2019-05-27 13:55:01 +07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
/*
|
|
|
|
* net/dsa/dsa.c - Hardware switch handling
|
dsa: add switch chip cascading support
The initial version of the DSA driver only supported a single switch
chip per network interface, while DSA-capable switch chips can be
interconnected to form a tree of switch chips. This patch adds support
for multiple switch chips on a network interface.
An example topology for a 16-port device with an embedded CPU is as
follows:
+-----+ +--------+ +--------+
| |eth0 10| switch |9 10| switch |
| CPU +----------+ +-------+ |
| | | chip 0 | | chip 1 |
+-----+ +---++---+ +---++---+
|| ||
|| ||
||1000baseT ||1000baseT
||ports 1-8 ||ports 9-16
This requires a couple of interdependent changes in the DSA layer:
- The dsa platform driver data needs to be extended: there is still
only one netdevice per DSA driver instance (eth0 in the example
above), but each of the switch chips in the tree needs its own
mii_bus device pointer, MII management bus address, and port name
array. (include/net/dsa.h) The existing in-tree dsa users need
some small changes to deal with this. (arch/arm)
- The DSA and Ethertype DSA tagging modules need to be extended to
use the DSA device ID field on receive and demultiplex the packet
accordingly, and fill in the DSA device ID field on transmit
according to which switch chip the packet is heading to.
(net/dsa/tag_{dsa,edsa}.c)
- The concept of "CPU port", which is the switch chip port that the
CPU is connected to (port 10 on switch chip 0 in the example), needs
to be extended with the concept of "upstream port", which is the
port on the switch chip that will bring us one hop closer to the CPU
(port 10 for both switch chips in the example above).
- The dsa platform data needs to specify which ports on which switch
chips are links to other switch chips, so that we can enable DSA
tagging mode on them. (For inter-switch links, we always use
non-EtherType DSA tagging, since it has lower overhead. The CPU
link uses dsa or edsa tagging depending on what the 'root' switch
chip supports.) This is done by specifying "dsa" for the given
port in the port array.
- The dsa platform data needs to be extended with information on via
which port to reach any given switch chip from any given switch chip.
This info is specified via the per-switch chip data struct ->rtable[]
array, which gives the nexthop ports for each of the other switches
in the tree.
For the example topology above, the dsa platform data would look
something like this:
static struct dsa_chip_data sw[2] = {
{
.mii_bus = &foo,
.sw_addr = 1,
.port_names[0] = "p1",
.port_names[1] = "p2",
.port_names[2] = "p3",
.port_names[3] = "p4",
.port_names[4] = "p5",
.port_names[5] = "p6",
.port_names[6] = "p7",
.port_names[7] = "p8",
.port_names[9] = "dsa",
.port_names[10] = "cpu",
.rtable = (s8 []){ -1, 9, },
}, {
.mii_bus = &foo,
.sw_addr = 2,
.port_names[0] = "p9",
.port_names[1] = "p10",
.port_names[2] = "p11",
.port_names[3] = "p12",
.port_names[4] = "p13",
.port_names[5] = "p14",
.port_names[6] = "p15",
.port_names[7] = "p16",
.port_names[10] = "dsa",
.rtable = (s8 []){ 10, -1, },
},
},
static struct dsa_platform_data pd = {
.netdev = &foo,
.nr_switches = 2,
.sw = sw,
};
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Gary Thomas <gary@mlbassoc.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2009-03-20 16:52:09 +07:00
|
|
|
* Copyright (c) 2008-2009 Marvell Semiconductor
|
2013-03-22 17:50:50 +07:00
|
|
|
* Copyright (c) 2013 Florian Fainelli <florian@openwrt.org>
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
*/
|
|
|
|
|
2014-10-30 00:44:58 +07:00
|
|
|
#include <linux/device.h>
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
#include <linux/list.h>
|
|
|
|
#include <linux/platform_device.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 15:04:11 +07:00
|
|
|
#include <linux/slab.h>
|
2011-05-27 20:12:25 +07:00
|
|
|
#include <linux/module.h>
|
2017-10-12 00:57:48 +07:00
|
|
|
#include <linux/notifier.h>
|
2013-03-22 17:50:50 +07:00
|
|
|
#include <linux/of.h>
|
|
|
|
#include <linux/of_mdio.h>
|
|
|
|
#include <linux/of_platform.h>
|
2015-03-10 04:31:21 +07:00
|
|
|
#include <linux/of_net.h>
|
2017-03-29 04:45:06 +07:00
|
|
|
#include <linux/netdevice.h>
|
2014-10-30 00:44:58 +07:00
|
|
|
#include <linux/sysfs.h>
|
2015-10-06 21:40:32 +07:00
|
|
|
#include <linux/phy_fixed.h>
|
2018-02-14 07:07:49 +07:00
|
|
|
#include <linux/ptp_classify.h>
|
2017-04-08 22:55:23 +07:00
|
|
|
#include <linux/etherdevice.h>
|
2017-05-18 02:46:03 +07:00
|
|
|
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
#include "dsa_priv.h"
|
|
|
|
|
2019-04-29 00:37:16 +07:00
|
|
|
static LIST_HEAD(dsa_tag_drivers_list);
|
|
|
|
static DEFINE_MUTEX(dsa_tag_drivers_lock);
|
|
|
|
|
2016-06-05 02:17:03 +07:00
|
|
|
static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff *skb,
|
|
|
|
struct net_device *dev)
|
|
|
|
{
|
|
|
|
/* Just return the original SKB */
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct dsa_device_ops none_ops = {
|
2019-04-29 00:37:11 +07:00
|
|
|
.name = "none",
|
2019-04-29 00:37:14 +07:00
|
|
|
.proto = DSA_TAG_PROTO_NONE,
|
2016-06-05 02:17:03 +07:00
|
|
|
.xmit = dsa_slave_notag_xmit,
|
|
|
|
.rcv = NULL,
|
|
|
|
};
|
|
|
|
|
2019-04-29 00:37:17 +07:00
|
|
|
DSA_TAG_DRIVER(none_ops);
|
|
|
|
|
2019-04-29 00:37:16 +07:00
|
|
|
static void dsa_tag_driver_register(struct dsa_tag_driver *dsa_tag_driver,
|
|
|
|
struct module *owner)
|
|
|
|
{
|
|
|
|
dsa_tag_driver->owner = owner;
|
|
|
|
|
|
|
|
mutex_lock(&dsa_tag_drivers_lock);
|
|
|
|
list_add_tail(&dsa_tag_driver->list, &dsa_tag_drivers_list);
|
|
|
|
mutex_unlock(&dsa_tag_drivers_lock);
|
|
|
|
}
|
|
|
|
|
2019-04-29 00:37:15 +07:00
|
|
|
void dsa_tag_drivers_register(struct dsa_tag_driver *dsa_tag_driver_array[],
|
|
|
|
unsigned int count, struct module *owner)
|
|
|
|
{
|
2019-04-29 00:37:16 +07:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
dsa_tag_driver_register(dsa_tag_driver_array[i], owner);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dsa_tag_driver_unregister(struct dsa_tag_driver *dsa_tag_driver)
|
|
|
|
{
|
|
|
|
mutex_lock(&dsa_tag_drivers_lock);
|
|
|
|
list_del(&dsa_tag_driver->list);
|
|
|
|
mutex_unlock(&dsa_tag_drivers_lock);
|
2019-04-29 00:37:15 +07:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_tag_drivers_register);
|
|
|
|
|
|
|
|
void dsa_tag_drivers_unregister(struct dsa_tag_driver *dsa_tag_driver_array[],
|
|
|
|
unsigned int count)
|
|
|
|
{
|
2019-04-29 00:37:16 +07:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
dsa_tag_driver_unregister(dsa_tag_driver_array[i]);
|
2019-04-29 00:37:15 +07:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_tag_drivers_unregister);
|
|
|
|
|
2018-09-08 01:09:02 +07:00
|
|
|
const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops)
|
|
|
|
{
|
2019-04-29 00:37:11 +07:00
|
|
|
return ops->name;
|
2018-09-08 01:09:02 +07:00
|
|
|
};
|
|
|
|
|
2019-04-29 00:37:18 +07:00
|
|
|
const struct dsa_device_ops *dsa_tag_driver_get(int tag_protocol)
|
2016-06-05 02:17:03 +07:00
|
|
|
{
|
2019-04-29 00:37:20 +07:00
|
|
|
struct dsa_tag_driver *dsa_tag_driver;
|
2016-06-05 02:17:03 +07:00
|
|
|
const struct dsa_device_ops *ops;
|
2019-04-29 00:37:20 +07:00
|
|
|
bool found = false;
|
2016-06-05 02:17:03 +07:00
|
|
|
|
2020-03-28 16:53:09 +07:00
|
|
|
request_module("%s%d", DSA_TAG_DRIVER_ALIAS, tag_protocol);
|
2019-04-29 00:37:20 +07:00
|
|
|
|
|
|
|
mutex_lock(&dsa_tag_drivers_lock);
|
|
|
|
list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) {
|
|
|
|
ops = dsa_tag_driver->ops;
|
|
|
|
if (ops->proto == tag_protocol) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found) {
|
|
|
|
if (!try_module_get(dsa_tag_driver->owner))
|
|
|
|
ops = ERR_PTR(-ENOPROTOOPT);
|
|
|
|
} else {
|
|
|
|
ops = ERR_PTR(-ENOPROTOOPT);
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_unlock(&dsa_tag_drivers_lock);
|
2016-06-05 02:17:03 +07:00
|
|
|
|
|
|
|
return ops;
|
|
|
|
}
|
|
|
|
|
2019-04-29 00:37:19 +07:00
|
|
|
void dsa_tag_driver_put(const struct dsa_device_ops *ops)
|
|
|
|
{
|
2019-04-29 00:37:20 +07:00
|
|
|
struct dsa_tag_driver *dsa_tag_driver;
|
|
|
|
|
|
|
|
mutex_lock(&dsa_tag_drivers_lock);
|
|
|
|
list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) {
|
|
|
|
if (dsa_tag_driver->ops == ops) {
|
|
|
|
module_put(dsa_tag_driver->owner);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mutex_unlock(&dsa_tag_drivers_lock);
|
2019-04-29 00:37:19 +07:00
|
|
|
}
|
|
|
|
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
static int dev_is_class(struct device *dev, void *class)
|
|
|
|
{
|
|
|
|
if (dev->class != NULL && !strcmp(dev->class->name, class))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct device *dev_find_class(struct device *parent, char *class)
|
|
|
|
{
|
|
|
|
if (dev_is_class(parent, class)) {
|
|
|
|
get_device(parent);
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
return device_find_child(parent, class, dev_is_class);
|
|
|
|
}
|
|
|
|
|
2017-02-05 04:02:42 +07:00
|
|
|
struct net_device *dsa_dev_to_net_device(struct device *dev)
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
{
|
|
|
|
struct device *d;
|
|
|
|
|
|
|
|
d = dev_find_class(dev, "net");
|
|
|
|
if (d != NULL) {
|
|
|
|
struct net_device *nd;
|
|
|
|
|
|
|
|
nd = to_net_dev(d);
|
|
|
|
dev_hold(nd);
|
|
|
|
put_device(d);
|
|
|
|
|
|
|
|
return nd;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-02-05 04:02:42 +07:00
|
|
|
EXPORT_SYMBOL_GPL(dsa_dev_to_net_device);
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
|
2018-02-14 07:07:49 +07:00
|
|
|
/* Determine if we should defer delivery of skb until we have a rx timestamp.
|
|
|
|
*
|
|
|
|
* Called from dsa_switch_rcv. For now, this will only work if tagging is
|
|
|
|
* enabled on the switch. Normally the MAC driver would retrieve the hardware
|
|
|
|
* timestamp when it reads the packet out of the hardware. However in a DSA
|
|
|
|
* switch, the DSA driver owning the interface to which the packet is
|
|
|
|
* delivered is never notified unless we do so here.
|
|
|
|
*/
|
|
|
|
static bool dsa_skb_defer_rx_timestamp(struct dsa_slave_priv *p,
|
|
|
|
struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct dsa_switch *ds = p->dp->ds;
|
|
|
|
unsigned int type;
|
|
|
|
|
|
|
|
if (skb_headroom(skb) < ETH_HLEN)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
__skb_push(skb, ETH_HLEN);
|
|
|
|
|
|
|
|
type = ptp_classify_raw(skb);
|
|
|
|
|
|
|
|
__skb_pull(skb, ETH_HLEN);
|
|
|
|
|
|
|
|
if (type == PTP_CLASS_NONE)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (likely(ds->ops->port_rxtstamp))
|
|
|
|
return ds->ops->port_rxtstamp(ds, p->dp->index, skb, type);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-08-28 07:04:46 +07:00
|
|
|
static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
|
2017-08-17 21:47:00 +07:00
|
|
|
struct packet_type *pt, struct net_device *unused)
|
2014-08-28 07:04:46 +07:00
|
|
|
{
|
2017-09-30 04:19:20 +07:00
|
|
|
struct dsa_port *cpu_dp = dev->dsa_ptr;
|
2017-04-08 22:55:23 +07:00
|
|
|
struct sk_buff *nskb = NULL;
|
2017-08-04 11:33:27 +07:00
|
|
|
struct pcpu_sw_netstats *s;
|
2017-08-02 05:00:36 +07:00
|
|
|
struct dsa_slave_priv *p;
|
2014-08-28 07:04:46 +07:00
|
|
|
|
2017-09-30 04:19:20 +07:00
|
|
|
if (unlikely(!cpu_dp)) {
|
2014-08-28 07:04:46 +07:00
|
|
|
kfree_skb(skb);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-08 22:55:22 +07:00
|
|
|
skb = skb_unshare(skb, GFP_ATOMIC);
|
|
|
|
if (!skb)
|
|
|
|
return 0;
|
|
|
|
|
2017-09-30 04:19:20 +07:00
|
|
|
nskb = cpu_dp->rcv(skb, dev, pt);
|
2017-04-08 22:55:23 +07:00
|
|
|
if (!nskb) {
|
|
|
|
kfree_skb(skb);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb = nskb;
|
2017-08-02 05:00:36 +07:00
|
|
|
p = netdev_priv(skb->dev);
|
2017-04-08 22:55:23 +07:00
|
|
|
skb_push(skb, ETH_HLEN);
|
|
|
|
skb->pkt_type = PACKET_HOST;
|
|
|
|
skb->protocol = eth_type_trans(skb, skb->dev);
|
|
|
|
|
2017-08-04 11:33:27 +07:00
|
|
|
s = this_cpu_ptr(p->stats64);
|
|
|
|
u64_stats_update_begin(&s->syncp);
|
|
|
|
s->rx_packets++;
|
|
|
|
s->rx_bytes += skb->len;
|
|
|
|
u64_stats_update_end(&s->syncp);
|
2017-04-08 22:55:23 +07:00
|
|
|
|
2018-02-14 07:07:49 +07:00
|
|
|
if (dsa_skb_defer_rx_timestamp(p, skb))
|
|
|
|
return 0;
|
|
|
|
|
2020-04-21 20:41:08 +07:00
|
|
|
gro_cells_receive(&p->gcells, skb);
|
2017-04-08 22:55:23 +07:00
|
|
|
|
|
|
|
return 0;
|
2014-08-28 07:04:46 +07:00
|
|
|
}
|
|
|
|
|
2017-06-02 09:53:04 +07:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
2017-07-19 03:23:56 +07:00
|
|
|
static bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
|
|
|
|
{
|
2019-10-22 03:51:15 +07:00
|
|
|
const struct dsa_port *dp = dsa_to_port(ds, p);
|
|
|
|
|
|
|
|
return dp->type == DSA_PORT_TYPE_USER && dp->slave;
|
2017-07-19 03:23:56 +07:00
|
|
|
}
|
|
|
|
|
2017-06-02 09:53:04 +07:00
|
|
|
int dsa_switch_suspend(struct dsa_switch *ds)
|
|
|
|
{
|
|
|
|
int i, ret = 0;
|
|
|
|
|
|
|
|
/* Suspend slave network devices */
|
|
|
|
for (i = 0; i < ds->num_ports; i++) {
|
|
|
|
if (!dsa_is_port_initialized(ds, i))
|
|
|
|
continue;
|
|
|
|
|
2019-10-22 03:51:15 +07:00
|
|
|
ret = dsa_slave_suspend(dsa_to_port(ds, i)->slave);
|
2017-06-02 09:53:04 +07:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ds->ops->suspend)
|
|
|
|
ret = ds->ops->suspend(ds);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_switch_suspend);
|
|
|
|
|
|
|
|
int dsa_switch_resume(struct dsa_switch *ds)
|
|
|
|
{
|
|
|
|
int i, ret = 0;
|
|
|
|
|
|
|
|
if (ds->ops->resume)
|
|
|
|
ret = ds->ops->resume(ds);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
/* Resume slave network devices */
|
|
|
|
for (i = 0; i < ds->num_ports; i++) {
|
|
|
|
if (!dsa_is_port_initialized(ds, i))
|
|
|
|
continue;
|
|
|
|
|
2019-10-22 03:51:15 +07:00
|
|
|
ret = dsa_slave_resume(dsa_to_port(ds, i)->slave);
|
2017-06-02 09:53:04 +07:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_switch_resume);
|
|
|
|
#endif
|
|
|
|
|
2014-08-30 02:42:07 +07:00
|
|
|
static struct packet_type dsa_pack_type __read_mostly = {
|
2014-08-28 07:04:46 +07:00
|
|
|
.type = cpu_to_be16(ETH_P_XDSA),
|
|
|
|
.func = dsa_switch_rcv,
|
|
|
|
};
|
|
|
|
|
2017-08-06 20:15:42 +07:00
|
|
|
static struct workqueue_struct *dsa_owq;
|
|
|
|
|
|
|
|
bool dsa_schedule_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
return queue_work(dsa_owq, work);
|
|
|
|
}
|
|
|
|
|
2017-10-12 00:57:48 +07:00
|
|
|
static ATOMIC_NOTIFIER_HEAD(dsa_notif_chain);
|
|
|
|
|
|
|
|
int register_dsa_notifier(struct notifier_block *nb)
|
|
|
|
{
|
|
|
|
return atomic_notifier_chain_register(&dsa_notif_chain, nb);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(register_dsa_notifier);
|
|
|
|
|
|
|
|
int unregister_dsa_notifier(struct notifier_block *nb)
|
|
|
|
{
|
|
|
|
return atomic_notifier_chain_unregister(&dsa_notif_chain, nb);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(unregister_dsa_notifier);
|
|
|
|
|
|
|
|
int call_dsa_notifiers(unsigned long val, struct net_device *dev,
|
|
|
|
struct dsa_notifier_info *info)
|
|
|
|
{
|
|
|
|
info->dev = dev;
|
|
|
|
return atomic_notifier_call_chain(&dsa_notif_chain, val, info);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(call_dsa_notifiers);
|
|
|
|
|
2019-10-25 06:03:51 +07:00
|
|
|
int dsa_devlink_param_get(struct devlink *dl, u32 id,
|
|
|
|
struct devlink_param_gset_ctx *ctx)
|
|
|
|
{
|
|
|
|
struct dsa_devlink_priv *dl_priv;
|
|
|
|
struct dsa_switch *ds;
|
|
|
|
|
|
|
|
dl_priv = devlink_priv(dl);
|
|
|
|
ds = dl_priv->ds;
|
|
|
|
|
|
|
|
if (!ds->ops->devlink_param_get)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
return ds->ops->devlink_param_get(ds, id, ctx);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_param_get);
|
|
|
|
|
|
|
|
int dsa_devlink_param_set(struct devlink *dl, u32 id,
|
|
|
|
struct devlink_param_gset_ctx *ctx)
|
|
|
|
{
|
|
|
|
struct dsa_devlink_priv *dl_priv;
|
|
|
|
struct dsa_switch *ds;
|
|
|
|
|
|
|
|
dl_priv = devlink_priv(dl);
|
|
|
|
ds = dl_priv->ds;
|
|
|
|
|
|
|
|
if (!ds->ops->devlink_param_set)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
return ds->ops->devlink_param_set(ds, id, ctx);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_param_set);
|
|
|
|
|
|
|
|
int dsa_devlink_params_register(struct dsa_switch *ds,
|
|
|
|
const struct devlink_param *params,
|
|
|
|
size_t params_count)
|
|
|
|
{
|
|
|
|
return devlink_params_register(ds->devlink, params, params_count);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_params_register);
|
|
|
|
|
|
|
|
void dsa_devlink_params_unregister(struct dsa_switch *ds,
|
|
|
|
const struct devlink_param *params,
|
|
|
|
size_t params_count)
|
|
|
|
{
|
|
|
|
devlink_params_unregister(ds->devlink, params, params_count);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_params_unregister);
|
|
|
|
|
2019-11-05 07:12:57 +07:00
|
|
|
int dsa_devlink_resource_register(struct dsa_switch *ds,
|
|
|
|
const char *resource_name,
|
|
|
|
u64 resource_size,
|
|
|
|
u64 resource_id,
|
|
|
|
u64 parent_resource_id,
|
|
|
|
const struct devlink_resource_size_params *size_params)
|
|
|
|
{
|
|
|
|
return devlink_resource_register(ds->devlink, resource_name,
|
|
|
|
resource_size, resource_id,
|
|
|
|
parent_resource_id,
|
|
|
|
size_params);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_resource_register);
|
|
|
|
|
|
|
|
void dsa_devlink_resources_unregister(struct dsa_switch *ds)
|
|
|
|
{
|
|
|
|
devlink_resources_unregister(ds->devlink, NULL);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_resources_unregister);
|
|
|
|
|
|
|
|
void dsa_devlink_resource_occ_get_register(struct dsa_switch *ds,
|
|
|
|
u64 resource_id,
|
|
|
|
devlink_resource_occ_get_t *occ_get,
|
|
|
|
void *occ_get_priv)
|
|
|
|
{
|
|
|
|
return devlink_resource_occ_get_register(ds->devlink, resource_id,
|
|
|
|
occ_get, occ_get_priv);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_resource_occ_get_register);
|
|
|
|
|
|
|
|
void dsa_devlink_resource_occ_get_unregister(struct dsa_switch *ds,
|
|
|
|
u64 resource_id)
|
|
|
|
{
|
|
|
|
devlink_resource_occ_get_unregister(ds->devlink, resource_id);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_resource_occ_get_unregister);
|
|
|
|
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
static int __init dsa_init_module(void)
|
|
|
|
{
|
2011-11-25 21:35:02 +07:00
|
|
|
int rc;
|
|
|
|
|
2017-08-06 20:15:42 +07:00
|
|
|
dsa_owq = alloc_ordered_workqueue("dsa_ordered",
|
|
|
|
WQ_MEM_RECLAIM);
|
|
|
|
if (!dsa_owq)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2017-02-04 01:20:16 +07:00
|
|
|
rc = dsa_slave_register_notifier();
|
|
|
|
if (rc)
|
2019-05-06 22:25:29 +07:00
|
|
|
goto register_notifier_fail;
|
2015-02-25 04:15:33 +07:00
|
|
|
|
2014-08-28 07:04:46 +07:00
|
|
|
dev_add_pack(&dsa_pack_type);
|
|
|
|
|
2019-04-29 00:37:17 +07:00
|
|
|
dsa_tag_driver_register(&DSA_TAG_DRIVER_NAME(none_ops),
|
|
|
|
THIS_MODULE);
|
|
|
|
|
2011-11-25 21:35:02 +07:00
|
|
|
return 0;
|
2019-05-06 22:25:29 +07:00
|
|
|
|
|
|
|
register_notifier_fail:
|
|
|
|
destroy_workqueue(dsa_owq);
|
|
|
|
|
|
|
|
return rc;
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
}
|
|
|
|
module_init(dsa_init_module);
|
|
|
|
|
|
|
|
static void __exit dsa_cleanup_module(void)
|
|
|
|
{
|
2019-04-29 00:37:17 +07:00
|
|
|
dsa_tag_driver_unregister(&DSA_TAG_DRIVER_NAME(none_ops));
|
|
|
|
|
2017-02-04 01:20:16 +07:00
|
|
|
dsa_slave_unregister_notifier();
|
2014-08-28 07:04:46 +07:00
|
|
|
dev_remove_pack(&dsa_pack_type);
|
2017-08-06 20:15:42 +07:00
|
|
|
destroy_workqueue(dsa_owq);
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
}
|
|
|
|
module_exit(dsa_cleanup_module);
|
|
|
|
|
2011-01-25 03:32:52 +07:00
|
|
|
MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
|
net: Distributed Switch Architecture protocol support
Distributed Switch Architecture is a protocol for managing hardware
switch chips. It consists of a set of MII management registers and
commands to configure the switch, and an ethernet header format to
signal which of the ports of the switch a packet was received from
or is intended to be sent to.
The switches that this driver supports are typically embedded in
access points and routers, and a typical setup with a DSA switch
looks something like this:
+-----------+ +-----------+
| | RGMII | |
| +-------+ +------ 1000baseT MDI ("WAN")
| | | 6-port +------ 1000baseT MDI ("LAN1")
| CPU | | ethernet +------ 1000baseT MDI ("LAN2")
| |MIImgmt| switch +------ 1000baseT MDI ("LAN3")
| +-------+ w/5 PHYs +------ 1000baseT MDI ("LAN4")
| | | |
+-----------+ +-----------+
The switch driver presents each port on the switch as a separate
network interface to Linux, polls the switch to maintain software
link state of those ports, forwards MII management interface
accesses to those network interfaces (e.g. as done by ethtool) to
the switch, and exposes the switch's hardware statistics counters
via the appropriate Linux kernel interfaces.
This initial patch supports the MII management interface register
layout of the Marvell 88E6123, 88E6161 and 88E6165 switch chips, and
supports the "Ethertype DSA" packet tagging format.
(There is no officially registered ethertype for the Ethertype DSA
packet format, so we just grab a random one. The ethertype to use
is programmed into the switch, and the switch driver uses the value
of ETH_P_EDSA for this, so this define can be changed at any time in
the future if the one we chose is allocated to another protocol or
if Ethertype DSA gets its own officially registered ethertype, and
everything will continue to work.)
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Tested-by: Nicolas Pitre <nico@marvell.com>
Tested-by: Byron Bradley <byron.bbradley@gmail.com>
Tested-by: Tim Ellis <tim.ellis@mac.com>
Tested-by: Peter van Valderen <linux@ddcrew.com>
Tested-by: Dirk Teurlings <dirk@upexia.nl>
Signed-off-by: David S. Miller <davem@davemloft.net>
2008-10-07 20:44:02 +07:00
|
|
|
MODULE_DESCRIPTION("Driver for Distributed Switch Architecture switch chips");
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_ALIAS("platform:dsa");
|