Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os 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>

authored by

Clément Léger and committed by
David S. Miller
a08d6a6d 67f38b1c

+124
+2
include/net/dsa.h
··· 53 53 #define DSA_TAG_PROTO_SJA1110_VALUE 23 54 54 #define DSA_TAG_PROTO_RTL8_4_VALUE 24 55 55 #define DSA_TAG_PROTO_RTL8_4T_VALUE 25 56 + #define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26 56 57 57 58 enum dsa_tag_protocol { 58 59 DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, ··· 82 81 DSA_TAG_PROTO_SJA1110 = DSA_TAG_PROTO_SJA1110_VALUE, 83 82 DSA_TAG_PROTO_RTL8_4 = DSA_TAG_PROTO_RTL8_4_VALUE, 84 83 DSA_TAG_PROTO_RTL8_4T = DSA_TAG_PROTO_RTL8_4T_VALUE, 84 + DSA_TAG_PROTO_RZN1_A5PSW = DSA_TAG_PROTO_RZN1_A5PSW_VALUE, 85 85 }; 86 86 87 87 struct dsa_switch;
+1
include/uapi/linux/if_ether.h
··· 116 116 #define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ 117 117 #define ETH_P_EDSA 0xDADA /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ 118 118 #define ETH_P_DSA_8021Q 0xDADB /* Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] */ 119 + #define ETH_P_DSA_A5PSW 0xE001 /* A5PSW Tag Value [ NOT AN OFFICIALLY REGISTERED ID ] */ 119 120 #define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */ 120 121 #define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */ 121 122
+7
net/dsa/Kconfig
··· 132 132 Say Y or M if you want to enable support for tagging frames for Realtek 133 133 switches with 8 byte protocol 4 tags, such as the Realtek RTL8365MB-VC. 134 134 135 + config NET_DSA_TAG_RZN1_A5PSW 136 + tristate "Tag driver for Renesas RZ/N1 A5PSW switch" 137 + help 138 + Say Y or M if you want to enable support for tagging frames for 139 + Renesas RZ/N1 embedded switch that uses an 8 byte tag located after 140 + destination MAC address. 141 + 135 142 config NET_DSA_TAG_LAN9303 136 143 tristate "Tag driver for SMSC/Microchip LAN9303 family of switches" 137 144 help
+1
net/dsa/Makefile
··· 17 17 obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o 18 18 obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o 19 19 obj-$(CONFIG_NET_DSA_TAG_RTL8_4) += tag_rtl8_4.o 20 + obj-$(CONFIG_NET_DSA_TAG_RZN1_A5PSW) += tag_rzn1_a5psw.o 20 21 obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o 21 22 obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o 22 23 obj-$(CONFIG_NET_DSA_TAG_XRS700X) += tag_xrs700x.o
+113
net/dsa/tag_rzn1_a5psw.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2022 Schneider Electric 4 + * 5 + * Clément Léger <clement.leger@bootlin.com> 6 + */ 7 + 8 + #include <linux/bitfield.h> 9 + #include <linux/etherdevice.h> 10 + #include <linux/if_ether.h> 11 + #include <net/dsa.h> 12 + 13 + #include "dsa_priv.h" 14 + 15 + /* To define the outgoing port and to discover the incoming port a TAG is 16 + * inserted after Src MAC : 17 + * 18 + * Dest MAC Src MAC TAG Type 19 + * ...| 1 2 3 4 5 6 | 1 2 3 4 5 6 | 1 2 3 4 5 6 7 8 | 1 2 |... 20 + * |<--------------->| 21 + * 22 + * See struct a5psw_tag for layout 23 + */ 24 + 25 + #define ETH_P_DSA_A5PSW 0xE001 26 + #define A5PSW_TAG_LEN 8 27 + #define A5PSW_CTRL_DATA_FORCE_FORWARD BIT(0) 28 + /* This is both used for xmit tag and rcv tagging */ 29 + #define A5PSW_CTRL_DATA_PORT GENMASK(3, 0) 30 + 31 + struct a5psw_tag { 32 + __be16 ctrl_tag; 33 + __be16 ctrl_data; 34 + __be16 ctrl_data2_hi; 35 + __be16 ctrl_data2_lo; 36 + }; 37 + 38 + static struct sk_buff *a5psw_tag_xmit(struct sk_buff *skb, struct net_device *dev) 39 + { 40 + struct dsa_port *dp = dsa_slave_to_port(dev); 41 + struct a5psw_tag *ptag; 42 + u32 data2_val; 43 + 44 + BUILD_BUG_ON(sizeof(*ptag) != A5PSW_TAG_LEN); 45 + 46 + /* The Ethernet switch we are interfaced with needs packets to be at 47 + * least 60 bytes otherwise they will be discarded when they enter the 48 + * switch port logic. 49 + */ 50 + if (__skb_put_padto(skb, ETH_ZLEN, false)) 51 + return NULL; 52 + 53 + /* provide 'A5PSW_TAG_LEN' bytes additional space */ 54 + skb_push(skb, A5PSW_TAG_LEN); 55 + 56 + /* make room between MACs and Ether-Type to insert tag */ 57 + dsa_alloc_etype_header(skb, A5PSW_TAG_LEN); 58 + 59 + ptag = dsa_etype_header_pos_tx(skb); 60 + 61 + data2_val = FIELD_PREP(A5PSW_CTRL_DATA_PORT, BIT(dp->index)); 62 + ptag->ctrl_tag = htons(ETH_P_DSA_A5PSW); 63 + ptag->ctrl_data = htons(A5PSW_CTRL_DATA_FORCE_FORWARD); 64 + ptag->ctrl_data2_lo = htons(data2_val); 65 + ptag->ctrl_data2_hi = 0; 66 + 67 + return skb; 68 + } 69 + 70 + static struct sk_buff *a5psw_tag_rcv(struct sk_buff *skb, 71 + struct net_device *dev) 72 + { 73 + struct a5psw_tag *tag; 74 + int port; 75 + 76 + if (unlikely(!pskb_may_pull(skb, A5PSW_TAG_LEN))) { 77 + dev_warn_ratelimited(&dev->dev, 78 + "Dropping packet, cannot pull\n"); 79 + return NULL; 80 + } 81 + 82 + tag = dsa_etype_header_pos_rx(skb); 83 + 84 + if (tag->ctrl_tag != htons(ETH_P_DSA_A5PSW)) { 85 + dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid TAG marker\n"); 86 + return NULL; 87 + } 88 + 89 + port = FIELD_GET(A5PSW_CTRL_DATA_PORT, ntohs(tag->ctrl_data)); 90 + 91 + skb->dev = dsa_master_find_slave(dev, 0, port); 92 + if (!skb->dev) 93 + return NULL; 94 + 95 + skb_pull_rcsum(skb, A5PSW_TAG_LEN); 96 + dsa_strip_etype_header(skb, A5PSW_TAG_LEN); 97 + 98 + dsa_default_offload_fwd_mark(skb); 99 + 100 + return skb; 101 + } 102 + 103 + static const struct dsa_device_ops a5psw_netdev_ops = { 104 + .name = "a5psw", 105 + .proto = DSA_TAG_PROTO_RZN1_A5PSW, 106 + .xmit = a5psw_tag_xmit, 107 + .rcv = a5psw_tag_rcv, 108 + .needed_headroom = A5PSW_TAG_LEN, 109 + }; 110 + 111 + MODULE_LICENSE("GPL v2"); 112 + MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_A5PSW); 113 + module_dsa_tag_driver(a5psw_netdev_ops);