forked from Minki/linux
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_RTL8_4_VALUE 24
|
||||
#define DSA_TAG_PROTO_RTL8_4T_VALUE 25
|
||||
#define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26
|
||||
|
||||
enum dsa_tag_protocol {
|
||||
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_RTL8_4 = DSA_TAG_PROTO_RTL8_4_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;
|
||||
|
@ -116,6 +116,7 @@
|
||||
#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_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_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
|
||||
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
|
||||
tristate "Tag driver for SMSC/Microchip LAN9303 family of switches"
|
||||
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_RTL4_A) += tag_rtl4_a.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_TRAILER) += tag_trailer.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