net: dsa: add Renesas RZ/N1 switch tag driver
The switch that is present on the Renesas RZ/N1 SoC uses a specific VLAN value followed by 6 bytes which contains forwarding configuration. Signed-off-by: Clément Léger <clement.leger@bootlin.com> Reviewed-by: Vladimir Oltean <olteanv@gmail.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
67f38b1c73
commit
a08d6a6dc8
@ -53,6 +53,7 @@ struct phylink_link_state;
|
|||||||
#define DSA_TAG_PROTO_SJA1110_VALUE 23
|
#define DSA_TAG_PROTO_SJA1110_VALUE 23
|
||||||
#define DSA_TAG_PROTO_RTL8_4_VALUE 24
|
#define DSA_TAG_PROTO_RTL8_4_VALUE 24
|
||||||
#define DSA_TAG_PROTO_RTL8_4T_VALUE 25
|
#define DSA_TAG_PROTO_RTL8_4T_VALUE 25
|
||||||
|
#define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26
|
||||||
|
|
||||||
enum dsa_tag_protocol {
|
enum dsa_tag_protocol {
|
||||||
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
|
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
|
||||||
@ -81,6 +82,7 @@ enum dsa_tag_protocol {
|
|||||||
DSA_TAG_PROTO_SJA1110 = DSA_TAG_PROTO_SJA1110_VALUE,
|
DSA_TAG_PROTO_SJA1110 = DSA_TAG_PROTO_SJA1110_VALUE,
|
||||||
DSA_TAG_PROTO_RTL8_4 = DSA_TAG_PROTO_RTL8_4_VALUE,
|
DSA_TAG_PROTO_RTL8_4 = DSA_TAG_PROTO_RTL8_4_VALUE,
|
||||||
DSA_TAG_PROTO_RTL8_4T = DSA_TAG_PROTO_RTL8_4T_VALUE,
|
DSA_TAG_PROTO_RTL8_4T = DSA_TAG_PROTO_RTL8_4T_VALUE,
|
||||||
|
DSA_TAG_PROTO_RZN1_A5PSW = DSA_TAG_PROTO_RZN1_A5PSW_VALUE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dsa_switch;
|
struct dsa_switch;
|
||||||
|
@ -116,6 +116,7 @@
|
|||||||
#define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
|
#define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
|
||||||
#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
|
#define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
|
||||||
#define ETH_P_DSA_8021Q 0xDADB /* Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
|
#define ETH_P_DSA_8021Q 0xDADB /* Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
|
||||||
|
#define ETH_P_DSA_A5PSW 0xE001 /* A5PSW Tag Value [ NOT AN OFFICIALLY REGISTERED ID ] */
|
||||||
#define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */
|
#define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */
|
||||||
#define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
|
#define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
|
||||||
|
|
||||||
|
@ -132,6 +132,13 @@ config NET_DSA_TAG_RTL8_4
|
|||||||
Say Y or M if you want to enable support for tagging frames for Realtek
|
Say Y or M if you want to enable support for tagging frames for Realtek
|
||||||
switches with 8 byte protocol 4 tags, such as the Realtek RTL8365MB-VC.
|
switches with 8 byte protocol 4 tags, such as the Realtek RTL8365MB-VC.
|
||||||
|
|
||||||
|
config NET_DSA_TAG_RZN1_A5PSW
|
||||||
|
tristate "Tag driver for Renesas RZ/N1 A5PSW switch"
|
||||||
|
help
|
||||||
|
Say Y or M if you want to enable support for tagging frames for
|
||||||
|
Renesas RZ/N1 embedded switch that uses an 8 byte tag located after
|
||||||
|
destination MAC address.
|
||||||
|
|
||||||
config NET_DSA_TAG_LAN9303
|
config NET_DSA_TAG_LAN9303
|
||||||
tristate "Tag driver for SMSC/Microchip LAN9303 family of switches"
|
tristate "Tag driver for SMSC/Microchip LAN9303 family of switches"
|
||||||
help
|
help
|
||||||
|
@ -17,6 +17,7 @@ obj-$(CONFIG_NET_DSA_TAG_OCELOT_8021Q) += tag_ocelot_8021q.o
|
|||||||
obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
|
obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
|
||||||
obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o
|
obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o
|
||||||
obj-$(CONFIG_NET_DSA_TAG_RTL8_4) += tag_rtl8_4.o
|
obj-$(CONFIG_NET_DSA_TAG_RTL8_4) += tag_rtl8_4.o
|
||||||
|
obj-$(CONFIG_NET_DSA_TAG_RZN1_A5PSW) += tag_rzn1_a5psw.o
|
||||||
obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o
|
obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o
|
||||||
obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
|
obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
|
||||||
obj-$(CONFIG_NET_DSA_TAG_XRS700X) += tag_xrs700x.o
|
obj-$(CONFIG_NET_DSA_TAG_XRS700X) += tag_xrs700x.o
|
||||||
|
113
net/dsa/tag_rzn1_a5psw.c
Normal file
113
net/dsa/tag_rzn1_a5psw.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Schneider Electric
|
||||||
|
*
|
||||||
|
* Clément Léger <clement.leger@bootlin.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <net/dsa.h>
|
||||||
|
|
||||||
|
#include "dsa_priv.h"
|
||||||
|
|
||||||
|
/* To define the outgoing port and to discover the incoming port a TAG is
|
||||||
|
* inserted after Src MAC :
|
||||||
|
*
|
||||||
|
* Dest MAC Src MAC TAG Type
|
||||||
|
* ...| 1 2 3 4 5 6 | 1 2 3 4 5 6 | 1 2 3 4 5 6 7 8 | 1 2 |...
|
||||||
|
* |<--------------->|
|
||||||
|
*
|
||||||
|
* See struct a5psw_tag for layout
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ETH_P_DSA_A5PSW 0xE001
|
||||||
|
#define A5PSW_TAG_LEN 8
|
||||||
|
#define A5PSW_CTRL_DATA_FORCE_FORWARD BIT(0)
|
||||||
|
/* This is both used for xmit tag and rcv tagging */
|
||||||
|
#define A5PSW_CTRL_DATA_PORT GENMASK(3, 0)
|
||||||
|
|
||||||
|
struct a5psw_tag {
|
||||||
|
__be16 ctrl_tag;
|
||||||
|
__be16 ctrl_data;
|
||||||
|
__be16 ctrl_data2_hi;
|
||||||
|
__be16 ctrl_data2_lo;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sk_buff *a5psw_tag_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct dsa_port *dp = dsa_slave_to_port(dev);
|
||||||
|
struct a5psw_tag *ptag;
|
||||||
|
u32 data2_val;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(sizeof(*ptag) != A5PSW_TAG_LEN);
|
||||||
|
|
||||||
|
/* The Ethernet switch we are interfaced with needs packets to be at
|
||||||
|
* least 60 bytes otherwise they will be discarded when they enter the
|
||||||
|
* switch port logic.
|
||||||
|
*/
|
||||||
|
if (__skb_put_padto(skb, ETH_ZLEN, false))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* provide 'A5PSW_TAG_LEN' bytes additional space */
|
||||||
|
skb_push(skb, A5PSW_TAG_LEN);
|
||||||
|
|
||||||
|
/* make room between MACs and Ether-Type to insert tag */
|
||||||
|
dsa_alloc_etype_header(skb, A5PSW_TAG_LEN);
|
||||||
|
|
||||||
|
ptag = dsa_etype_header_pos_tx(skb);
|
||||||
|
|
||||||
|
data2_val = FIELD_PREP(A5PSW_CTRL_DATA_PORT, BIT(dp->index));
|
||||||
|
ptag->ctrl_tag = htons(ETH_P_DSA_A5PSW);
|
||||||
|
ptag->ctrl_data = htons(A5PSW_CTRL_DATA_FORCE_FORWARD);
|
||||||
|
ptag->ctrl_data2_lo = htons(data2_val);
|
||||||
|
ptag->ctrl_data2_hi = 0;
|
||||||
|
|
||||||
|
return skb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sk_buff *a5psw_tag_rcv(struct sk_buff *skb,
|
||||||
|
struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct a5psw_tag *tag;
|
||||||
|
int port;
|
||||||
|
|
||||||
|
if (unlikely(!pskb_may_pull(skb, A5PSW_TAG_LEN))) {
|
||||||
|
dev_warn_ratelimited(&dev->dev,
|
||||||
|
"Dropping packet, cannot pull\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = dsa_etype_header_pos_rx(skb);
|
||||||
|
|
||||||
|
if (tag->ctrl_tag != htons(ETH_P_DSA_A5PSW)) {
|
||||||
|
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid TAG marker\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
port = FIELD_GET(A5PSW_CTRL_DATA_PORT, ntohs(tag->ctrl_data));
|
||||||
|
|
||||||
|
skb->dev = dsa_master_find_slave(dev, 0, port);
|
||||||
|
if (!skb->dev)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
skb_pull_rcsum(skb, A5PSW_TAG_LEN);
|
||||||
|
dsa_strip_etype_header(skb, A5PSW_TAG_LEN);
|
||||||
|
|
||||||
|
dsa_default_offload_fwd_mark(skb);
|
||||||
|
|
||||||
|
return skb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dsa_device_ops a5psw_netdev_ops = {
|
||||||
|
.name = "a5psw",
|
||||||
|
.proto = DSA_TAG_PROTO_RZN1_A5PSW,
|
||||||
|
.xmit = a5psw_tag_xmit,
|
||||||
|
.rcv = a5psw_tag_rcv,
|
||||||
|
.needed_headroom = A5PSW_TAG_LEN,
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_A5PSW);
|
||||||
|
module_dsa_tag_driver(a5psw_netdev_ops);
|
Loading…
Reference in New Issue
Block a user