2019-05-27 06:55:01 +00: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 13:44:02 +00: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 09:52:09 +00:00
|
|
|
* Copyright (c) 2008-2009 Marvell Semiconductor
|
2013-03-22 10:50:50 +00: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 13:44:02 +00:00
|
|
|
*/
|
|
|
|
|
2014-10-29 17:44:58 +00: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 13:44:02 +00: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 08:04:11 +00:00
|
|
|
#include <linux/slab.h>
|
2011-05-27 13:12:25 +00:00
|
|
|
#include <linux/module.h>
|
2017-10-11 17:57:48 +00:00
|
|
|
#include <linux/notifier.h>
|
2013-03-22 10:50:50 +00:00
|
|
|
#include <linux/of.h>
|
|
|
|
#include <linux/of_mdio.h>
|
|
|
|
#include <linux/of_platform.h>
|
2015-03-09 21:31:21 +00:00
|
|
|
#include <linux/of_net.h>
|
2017-03-28 21:45:06 +00:00
|
|
|
#include <linux/netdevice.h>
|
2014-10-29 17:44:58 +00:00
|
|
|
#include <linux/sysfs.h>
|
2015-10-06 14:40:32 +00:00
|
|
|
#include <linux/phy_fixed.h>
|
2018-02-14 00:07:49 +00:00
|
|
|
#include <linux/ptp_classify.h>
|
2017-04-08 15:55:23 +00:00
|
|
|
#include <linux/etherdevice.h>
|
2017-05-17 19:46:03 +00: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 13:44:02 +00:00
|
|
|
#include "dsa_priv.h"
|
|
|
|
|
2019-04-28 17:37:16 +00:00
|
|
|
static LIST_HEAD(dsa_tag_drivers_list);
|
|
|
|
static DEFINE_MUTEX(dsa_tag_drivers_lock);
|
|
|
|
|
2016-06-04 19:17:03 +00: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-28 17:37:11 +00:00
|
|
|
.name = "none",
|
2019-04-28 17:37:14 +00:00
|
|
|
.proto = DSA_TAG_PROTO_NONE,
|
2016-06-04 19:17:03 +00:00
|
|
|
.xmit = dsa_slave_notag_xmit,
|
|
|
|
.rcv = NULL,
|
|
|
|
};
|
|
|
|
|
2019-04-28 17:37:17 +00:00
|
|
|
DSA_TAG_DRIVER(none_ops);
|
|
|
|
|
2019-04-28 17:37:16 +00: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-28 17:37:15 +00:00
|
|
|
void dsa_tag_drivers_register(struct dsa_tag_driver *dsa_tag_driver_array[],
|
|
|
|
unsigned int count, struct module *owner)
|
|
|
|
{
|
2019-04-28 17:37:16 +00: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-28 17:37:15 +00: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-28 17:37:16 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
dsa_tag_driver_unregister(dsa_tag_driver_array[i]);
|
2019-04-28 17:37:15 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_tag_drivers_unregister);
|
|
|
|
|
2018-09-07 18:09:02 +00:00
|
|
|
const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops)
|
|
|
|
{
|
2019-04-28 17:37:11 +00:00
|
|
|
return ops->name;
|
2018-09-07 18:09:02 +00:00
|
|
|
};
|
|
|
|
|
2019-04-28 17:37:18 +00:00
|
|
|
const struct dsa_device_ops *dsa_tag_driver_get(int tag_protocol)
|
2016-06-04 19:17:03 +00:00
|
|
|
{
|
2019-04-28 17:37:20 +00:00
|
|
|
struct dsa_tag_driver *dsa_tag_driver;
|
2016-06-04 19:17:03 +00:00
|
|
|
const struct dsa_device_ops *ops;
|
2019-04-28 17:37:20 +00:00
|
|
|
bool found = false;
|
2016-06-04 19:17:03 +00:00
|
|
|
|
2020-03-28 09:53:09 +00:00
|
|
|
request_module("%s%d", DSA_TAG_DRIVER_ALIAS, tag_protocol);
|
2019-04-28 17:37:20 +00: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-04 19:17:03 +00:00
|
|
|
|
|
|
|
return ops;
|
|
|
|
}
|
|
|
|
|
2019-04-28 17:37:19 +00:00
|
|
|
void dsa_tag_driver_put(const struct dsa_device_ops *ops)
|
|
|
|
{
|
2019-04-28 17:37:20 +00: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-28 17:37:19 +00: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 13:44:02 +00: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-04 21:02:42 +00: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 13:44:02 +00: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-04 21:02:42 +00: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 13:44:02 +00:00
|
|
|
|
2018-02-14 00:07:49 +00: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 00:04:46 +00:00
|
|
|
static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
|
2017-08-17 14:47:00 +00:00
|
|
|
struct packet_type *pt, struct net_device *unused)
|
2014-08-28 00:04:46 +00:00
|
|
|
{
|
2017-09-29 21:19:20 +00:00
|
|
|
struct dsa_port *cpu_dp = dev->dsa_ptr;
|
2017-04-08 15:55:23 +00:00
|
|
|
struct sk_buff *nskb = NULL;
|
2017-08-01 22:00:36 +00:00
|
|
|
struct dsa_slave_priv *p;
|
2014-08-28 00:04:46 +00:00
|
|
|
|
2017-09-29 21:19:20 +00:00
|
|
|
if (unlikely(!cpu_dp)) {
|
2014-08-28 00:04:46 +00:00
|
|
|
kfree_skb(skb);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-08 15:55:22 +00:00
|
|
|
skb = skb_unshare(skb, GFP_ATOMIC);
|
|
|
|
if (!skb)
|
|
|
|
return 0;
|
|
|
|
|
2017-09-29 21:19:20 +00:00
|
|
|
nskb = cpu_dp->rcv(skb, dev, pt);
|
2017-04-08 15:55:23 +00:00
|
|
|
if (!nskb) {
|
|
|
|
kfree_skb(skb);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
skb = nskb;
|
2017-08-01 22:00:36 +00:00
|
|
|
p = netdev_priv(skb->dev);
|
2017-04-08 15:55:23 +00:00
|
|
|
skb_push(skb, ETH_HLEN);
|
|
|
|
skb->pkt_type = PACKET_HOST;
|
|
|
|
skb->protocol = eth_type_trans(skb, skb->dev);
|
|
|
|
|
2020-10-02 02:42:12 +00:00
|
|
|
if (unlikely(cpu_dp->ds->untag_bridge_pvid)) {
|
|
|
|
nskb = dsa_untag_bridge_pvid(skb);
|
|
|
|
if (!nskb) {
|
|
|
|
kfree_skb(skb);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
skb = nskb;
|
|
|
|
}
|
|
|
|
|
2020-11-07 20:49:46 +00:00
|
|
|
dev_sw_netstats_rx_add(skb->dev, skb->len);
|
2017-04-08 15:55:23 +00:00
|
|
|
|
2018-02-14 00:07:49 +00:00
|
|
|
if (dsa_skb_defer_rx_timestamp(p, skb))
|
|
|
|
return 0;
|
|
|
|
|
2020-04-21 13:41:08 +00:00
|
|
|
gro_cells_receive(&p->gcells, skb);
|
2017-04-08 15:55:23 +00:00
|
|
|
|
|
|
|
return 0;
|
2014-08-28 00:04:46 +00:00
|
|
|
}
|
|
|
|
|
2017-06-02 02:53:04 +00:00
|
|
|
#ifdef CONFIG_PM_SLEEP
|
2017-07-18 20:23:56 +00:00
|
|
|
static bool dsa_is_port_initialized(struct dsa_switch *ds, int p)
|
|
|
|
{
|
2019-10-21 20:51:15 +00:00
|
|
|
const struct dsa_port *dp = dsa_to_port(ds, p);
|
|
|
|
|
|
|
|
return dp->type == DSA_PORT_TYPE_USER && dp->slave;
|
2017-07-18 20:23:56 +00:00
|
|
|
}
|
|
|
|
|
2017-06-02 02:53:04 +00: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-21 20:51:15 +00:00
|
|
|
ret = dsa_slave_suspend(dsa_to_port(ds, i)->slave);
|
2017-06-02 02:53:04 +00: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-21 20:51:15 +00:00
|
|
|
ret = dsa_slave_resume(dsa_to_port(ds, i)->slave);
|
2017-06-02 02:53:04 +00:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_switch_resume);
|
|
|
|
#endif
|
|
|
|
|
2014-08-29 19:42:07 +00:00
|
|
|
static struct packet_type dsa_pack_type __read_mostly = {
|
2014-08-28 00:04:46 +00:00
|
|
|
.type = cpu_to_be16(ETH_P_XDSA),
|
|
|
|
.func = dsa_switch_rcv,
|
|
|
|
};
|
|
|
|
|
2017-08-06 13:15:42 +00:00
|
|
|
static struct workqueue_struct *dsa_owq;
|
|
|
|
|
|
|
|
bool dsa_schedule_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
return queue_work(dsa_owq, work);
|
|
|
|
}
|
|
|
|
|
2019-10-24 23:03:51 +00:00
|
|
|
int dsa_devlink_param_get(struct devlink *dl, u32 id,
|
|
|
|
struct devlink_param_gset_ctx *ctx)
|
|
|
|
{
|
2020-09-18 19:11:03 +00:00
|
|
|
struct dsa_switch *ds = dsa_devlink_to_ds(dl);
|
2019-10-24 23:03:51 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2020-09-18 19:11:03 +00:00
|
|
|
struct dsa_switch *ds = dsa_devlink_to_ds(dl);
|
2019-10-24 23:03:51 +00:00
|
|
|
|
|
|
|
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 00:12:57 +00: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);
|
|
|
|
|
2020-09-18 19:11:04 +00:00
|
|
|
struct devlink_region *
|
|
|
|
dsa_devlink_region_create(struct dsa_switch *ds,
|
|
|
|
const struct devlink_region_ops *ops,
|
|
|
|
u32 region_max_snapshots, u64 region_size)
|
|
|
|
{
|
|
|
|
return devlink_region_create(ds->devlink, ops, region_max_snapshots,
|
|
|
|
region_size);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_region_create);
|
|
|
|
|
2020-10-04 16:12:55 +00:00
|
|
|
struct devlink_region *
|
|
|
|
dsa_devlink_port_region_create(struct dsa_switch *ds,
|
|
|
|
int port,
|
|
|
|
const struct devlink_port_region_ops *ops,
|
|
|
|
u32 region_max_snapshots, u64 region_size)
|
|
|
|
{
|
|
|
|
struct dsa_port *dp = dsa_to_port(ds, port);
|
|
|
|
|
|
|
|
return devlink_port_region_create(&dp->devlink_port, ops,
|
|
|
|
region_max_snapshots,
|
|
|
|
region_size);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_port_region_create);
|
|
|
|
|
2020-09-18 19:11:04 +00:00
|
|
|
void dsa_devlink_region_destroy(struct devlink_region *region)
|
|
|
|
{
|
|
|
|
devlink_region_destroy(region);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_devlink_region_destroy);
|
|
|
|
|
net: dsa: introduce a dsa_port_from_netdev public helper
As its implementation shows, this is synonimous with calling
dsa_slave_dev_check followed by dsa_slave_to_port, so it is quite simple
already and provides functionality which is already there.
However there is now a need for these functions outside dsa_priv.h, for
example in drivers that perform mirroring and redirection through
tc-flower offloads (they are given raw access to the flow_cls_offload
structure), where they need to call this function on act->dev.
But simply exporting dsa_slave_to_port would make it non-inline and
would result in an extra function call in the hotpath, as can be seen
for example in sja1105:
Before:
000006dc <sja1105_xmit>:
{
6dc: e92d4ff0 push {r4, r5, r6, r7, r8, r9, sl, fp, lr}
6e0: e1a04000 mov r4, r0
6e4: e591958c ldr r9, [r1, #1420] ; 0x58c <- Inline dsa_slave_to_port
6e8: e1a05001 mov r5, r1
6ec: e24dd004 sub sp, sp, #4
u16 tx_vid = dsa_8021q_tx_vid(dp->ds, dp->index);
6f0: e1c901d8 ldrd r0, [r9, #24]
6f4: ebfffffe bl 0 <dsa_8021q_tx_vid>
6f4: R_ARM_CALL dsa_8021q_tx_vid
u8 pcp = netdev_txq_to_tc(netdev, queue_mapping);
6f8: e1d416b0 ldrh r1, [r4, #96] ; 0x60
u16 tx_vid = dsa_8021q_tx_vid(dp->ds, dp->index);
6fc: e1a08000 mov r8, r0
After:
000006e4 <sja1105_xmit>:
{
6e4: e92d4ff0 push {r4, r5, r6, r7, r8, r9, sl, fp, lr}
6e8: e1a04000 mov r4, r0
6ec: e24dd004 sub sp, sp, #4
struct dsa_port *dp = dsa_slave_to_port(netdev);
6f0: e1a00001 mov r0, r1
{
6f4: e1a05001 mov r5, r1
struct dsa_port *dp = dsa_slave_to_port(netdev);
6f8: ebfffffe bl 0 <dsa_slave_to_port>
6f8: R_ARM_CALL dsa_slave_to_port
6fc: e1a09000 mov r9, r0
u16 tx_vid = dsa_8021q_tx_vid(dp->ds, dp->index);
700: e1c001d8 ldrd r0, [r0, #24]
704: ebfffffe bl 0 <dsa_8021q_tx_vid>
704: R_ARM_CALL dsa_8021q_tx_vid
Because we want to avoid possible performance regressions, introduce
this new function which is designed to be public.
Suggested-by: Vivien Didelot <vivien.didelot@gmail.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Vivien Didelot <vivien.didelot@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-05-05 19:20:52 +00:00
|
|
|
struct dsa_port *dsa_port_from_netdev(struct net_device *netdev)
|
|
|
|
{
|
|
|
|
if (!netdev || !dsa_slave_dev_check(netdev))
|
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
|
|
|
|
return dsa_slave_to_port(netdev);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(dsa_port_from_netdev);
|
|
|
|
|
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 13:44:02 +00:00
|
|
|
static int __init dsa_init_module(void)
|
|
|
|
{
|
2011-11-25 14:35:02 +00:00
|
|
|
int rc;
|
|
|
|
|
2017-08-06 13:15:42 +00:00
|
|
|
dsa_owq = alloc_ordered_workqueue("dsa_ordered",
|
|
|
|
WQ_MEM_RECLAIM);
|
|
|
|
if (!dsa_owq)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2017-02-03 18:20:16 +00:00
|
|
|
rc = dsa_slave_register_notifier();
|
|
|
|
if (rc)
|
2019-05-06 15:25:29 +00:00
|
|
|
goto register_notifier_fail;
|
2015-02-24 21:15:33 +00:00
|
|
|
|
2014-08-28 00:04:46 +00:00
|
|
|
dev_add_pack(&dsa_pack_type);
|
|
|
|
|
2019-04-28 17:37:17 +00:00
|
|
|
dsa_tag_driver_register(&DSA_TAG_DRIVER_NAME(none_ops),
|
|
|
|
THIS_MODULE);
|
|
|
|
|
2011-11-25 14:35:02 +00:00
|
|
|
return 0;
|
2019-05-06 15:25:29 +00: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 13:44:02 +00:00
|
|
|
}
|
|
|
|
module_init(dsa_init_module);
|
|
|
|
|
|
|
|
static void __exit dsa_cleanup_module(void)
|
|
|
|
{
|
2019-04-28 17:37:17 +00:00
|
|
|
dsa_tag_driver_unregister(&DSA_TAG_DRIVER_NAME(none_ops));
|
|
|
|
|
2017-02-03 18:20:16 +00:00
|
|
|
dsa_slave_unregister_notifier();
|
2014-08-28 00:04:46 +00:00
|
|
|
dev_remove_pack(&dsa_pack_type);
|
2017-08-06 13:15:42 +00: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 13:44:02 +00:00
|
|
|
}
|
|
|
|
module_exit(dsa_cleanup_module);
|
|
|
|
|
2011-01-24 20:32:52 +00: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 13:44:02 +00:00
|
|
|
MODULE_DESCRIPTION("Driver for Distributed Switch Architecture switch chips");
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_ALIAS("platform:dsa");
|