kernel: backport RTL8366RB patches

These upstream patches makes the RTL8366RB DSA switch work
properly with OpenWrt, the D-Link DIR-685 gets network and
can be used as a router, and the same should be applicable
for any other device that want to enable the RTL8366RB
through Device Tree.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Linus Walleij 2020-08-11 13:11:08 +02:00 committed by Hauke Mehrtens
parent e742a31f07
commit 8735997686
3 changed files with 359 additions and 0 deletions

View File

@ -0,0 +1,27 @@
From 733993f502f254912b1415e13f73651d9f2e74ef Mon Sep 17 00:00:00 2001
From: Andrew Lunn <andrew@lunn.ch>
Date: Sun, 5 Jul 2020 22:42:27 +0200
Subject: [PATCH 1/5] net: dsa: rtl8366: Pass GENMASK() signed bits
Oddly, GENMASK() requires signed bit numbers, so that it can compare
them for < 0. If passed an unsigned type, we get warnings about the
test never being true.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/rtl8366.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/dsa/rtl8366.c
+++ b/drivers/net/dsa/rtl8366.c
@@ -285,7 +285,7 @@ int rtl8366_init_vlan(struct realtek_smi
/* For the CPU port, make all ports members of this
* VLAN.
*/
- mask = GENMASK(smi->num_ports - 1, 0);
+ mask = GENMASK((int)smi->num_ports - 1, 0);
else
/* For all other ports, enable itself plus the
* CPU port.

View File

@ -0,0 +1,232 @@
From 078ced30af696b52a450a016a16eb47499d68117 Mon Sep 17 00:00:00 2001
From: Linus Walleij <linus.walleij@linaro.org>
Date: Wed, 8 Jul 2020 14:25:36 +0200
Subject: [PATCH 2/5] net: dsa: tag_rtl4_a: Implement Realtek 4 byte A tag
This implements the known parts of the Realtek 4 byte
tag protocol version 0xA, as found in the RTL8366RB
DSA switch.
It is designated as protocol version 0xA as a
different Realtek 4 byte tag format with protocol
version 0x9 is known to exist in the Realtek RTL8306
chips.
The tag and switch chip lacks public documentation, so
the tag format has been reverse-engineered from
packet dumps. As only ingress traffic has been available
for analysis an egress tag has not been possible to
develop (even using educated guesses about bit fields)
so this is as far as it gets. It is not known if the
switch even supports egress tagging.
Excessive attempts to figure out the egress tag format
was made. When nothing else worked, I just tried all bit
combinations with 0xannp where a is protocol and p is
port. I looped through all values several times trying
to get a response from ping, without any positive
result.
Using just these ingress tags however, the switch
functionality is vastly improved and the packets find
their way into the destination port without any
tricky VLAN configuration. On the D-Link DIR-685 the
LAN ports now come up and respond to ping without
any command line configuration so this is a real
improvement for users.
Egress packets need to be restricted to the proper
target ports using VLAN, which the RTL8366RB DSA
switch driver already sets up.
Cc: DENG Qingfang <dqfext@gmail.com>
Cc: Mauri Sandberg <sandberg@mailfence.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
include/net/dsa.h | 2 +
net/dsa/Kconfig | 7 +++
net/dsa/Makefile | 1 +
net/dsa/tag_rtl4_a.c | 130 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 140 insertions(+)
create mode 100644 net/dsa/tag_rtl4_a.c
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -42,6 +42,7 @@ struct phylink_link_state;
#define DSA_TAG_PROTO_8021Q_VALUE 12
#define DSA_TAG_PROTO_SJA1105_VALUE 13
#define DSA_TAG_PROTO_KSZ8795_VALUE 14
+#define DSA_TAG_PROTO_RTL4_A_VALUE 17
enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
@@ -59,6 +60,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_8021Q = DSA_TAG_PROTO_8021Q_VALUE,
DSA_TAG_PROTO_SJA1105 = DSA_TAG_PROTO_SJA1105_VALUE,
DSA_TAG_PROTO_KSZ8795 = DSA_TAG_PROTO_KSZ8795_VALUE,
+ DSA_TAG_PROTO_RTL4_A = DSA_TAG_PROTO_RTL4_A_VALUE,
};
struct packet_type;
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -80,6 +80,13 @@ config NET_DSA_TAG_KSZ
Say Y if you want to enable support for tagging frames for the
Microchip 8795/9477/9893 families of switches.
+config NET_DSA_TAG_RTL4_A
+ tristate "Tag driver for Realtek 4 byte protocol A tags"
+ help
+ Say Y or M if you want to enable support for tagging frames for the
+ Realtek switches with 4 byte protocol A tags, sich as found in
+ the Realtek RTL8366RB.
+
config NET_DSA_TAG_QCA
tristate "Tag driver for Qualcomm Atheros QCA8K switches"
help
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa
obj-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o
obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
+obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o
obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag_lan9303.o
obj-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
obj-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
--- /dev/null
+++ b/net/dsa/tag_rtl4_a.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Handler for Realtek 4 byte DSA switch tags
+ * Currently only supports protocol "A" found in RTL8366RB
+ * Copyright (c) 2020 Linus Walleij <linus.walleij@linaro.org>
+ *
+ * This "proprietary tag" header looks like so:
+ *
+ * -------------------------------------------------
+ * | MAC DA | MAC SA | 0x8899 | 2 bytes tag | Type |
+ * -------------------------------------------------
+ *
+ * The 2 bytes tag form a 16 bit big endian word. The exact
+ * meaning has been guessed from packet dumps from ingress
+ * frames, as no working egress traffic has been available
+ * we do not know the format of the egress tags or if they
+ * are even supported.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/bits.h>
+
+#include "dsa_priv.h"
+
+#define RTL4_A_HDR_LEN 4
+#define RTL4_A_ETHERTYPE 0x8899
+#define RTL4_A_PROTOCOL_SHIFT 12
+/*
+ * 0x1 = Realtek Remote Control protocol (RRCP)
+ * 0x2/0x3 seems to be used for loopback testing
+ * 0x9 = RTL8306 DSA protocol
+ * 0xa = RTL8366RB DSA protocol
+ */
+#define RTL4_A_PROTOCOL_RTL8366RB 0xa
+
+static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ /*
+ * Just let it pass thru, we don't know if it is possible
+ * to tag a frame with the 0x8899 ethertype and direct it
+ * to a specific port, all attempts at reverse-engineering have
+ * ended up with the frames getting dropped.
+ *
+ * The VLAN set-up needs to restrict the frames to the right port.
+ *
+ * If you have documentation on the tagging format for RTL8366RB
+ * (tag type A) then please contribute.
+ */
+ return skb;
+}
+
+static struct sk_buff *rtl4a_tag_rcv(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt)
+{
+ u16 protport;
+ __be16 *p;
+ u16 etype;
+ u8 *tag;
+ u8 prot;
+ u8 port;
+
+ if (unlikely(!pskb_may_pull(skb, RTL4_A_HDR_LEN)))
+ return NULL;
+
+ /* The RTL4 header has its own custom Ethertype 0x8899 and that
+ * starts right at the beginning of the packet, after the src
+ * ethernet addr. Apparantly skb->data always points 2 bytes in,
+ * behind the Ethertype.
+ */
+ tag = skb->data - 2;
+ p = (__be16 *)tag;
+ etype = ntohs(*p);
+ if (etype != RTL4_A_ETHERTYPE) {
+ /* Not custom, just pass through */
+ netdev_dbg(dev, "non-realtek ethertype 0x%04x\n", etype);
+ return skb;
+ }
+ p = (__be16 *)(tag + 2);
+ protport = ntohs(*p);
+ /* The 4 upper bits are the protocol */
+ prot = (protport >> RTL4_A_PROTOCOL_SHIFT) & 0x0f;
+ if (prot != RTL4_A_PROTOCOL_RTL8366RB) {
+ netdev_err(dev, "unknown realtek protocol 0x%01x\n", prot);
+ return NULL;
+ }
+ port = protport & 0xff;
+
+ skb->dev = dsa_master_find_slave(dev, 0, port);
+ if (!skb->dev) {
+ netdev_dbg(dev, "could not find slave for port %d\n", port);
+ return NULL;
+ }
+
+ /* Remove RTL4 tag and recalculate checksum */
+ skb_pull_rcsum(skb, RTL4_A_HDR_LEN);
+
+ /* Move ethernet DA and SA in front of the data */
+ memmove(skb->data - ETH_HLEN,
+ skb->data - ETH_HLEN - RTL4_A_HDR_LEN,
+ 2 * ETH_ALEN);
+
+ skb->offload_fwd_mark = 1;
+
+ return skb;
+}
+
+static int rtl4a_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto,
+ int *offset)
+{
+ *offset = RTL4_A_HDR_LEN;
+ /* Skip past the tag and fetch the encapsulated Ethertype */
+ *proto = ((__be16 *)skb->data)[1];
+
+ return 0;
+}
+
+static const struct dsa_device_ops rtl4a_netdev_ops = {
+ .name = "rtl4a",
+ .proto = DSA_TAG_PROTO_RTL4_A,
+ .xmit = rtl4a_tag_xmit,
+ .rcv = rtl4a_tag_rcv,
+ .flow_dissect = rtl4a_tag_flow_dissect,
+ .overhead = RTL4_A_HDR_LEN,
+};
+module_dsa_tag_driver(rtl4a_netdev_ops);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_RTL4_A);

View File

@ -0,0 +1,100 @@
From c633ba43b7a9c2bfdb992ffd198d4c661520466f Mon Sep 17 00:00:00 2001
From: Linus Walleij <linus.walleij@linaro.org>
Date: Wed, 8 Jul 2020 14:25:37 +0200
Subject: [PATCH 3/5] net: dsa: rtl8366rb: Support the CPU DSA tag
This activates the support to use the CPU tag to properly
direct ingress traffic to the right port.
Bit 15 in register RTL8368RB_CPU_CTRL_REG can be set to
1 to disable the insertion of the CPU tag which is what
the code currently does. The bit 15 define calls this
setting RTL8368RB_CPU_INSTAG which is confusing since the
inverse meaning is implied: programmers may think that
setting this bit to 1 will *enable* inserting the tag
rather than disabling it, so rename this setting in
bit 15 to RTL8368RB_CPU_NO_TAG which is more to the
point.
After this e.g. ping works out-of-the-box with the
RTL8366RB.
Cc: DENG Qingfang <dqfext@gmail.com>
Cc: Mauri Sandberg <sandberg@mailfence.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/Kconfig | 1 +
drivers/net/dsa/rtl8366rb.c | 31 ++++++++-----------------------
2 files changed, 9 insertions(+), 23 deletions(-)
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -66,6 +66,7 @@ config NET_DSA_QCA8K
config NET_DSA_REALTEK_SMI
tristate "Realtek SMI Ethernet switch family support"
depends on NET_DSA
+ select NET_DSA_TAG_RTL4_A
select FIXED_PHY
select IRQ_DOMAIN
select REALTEK_PHY
--- a/drivers/net/dsa/rtl8366rb.c
+++ b/drivers/net/dsa/rtl8366rb.c
@@ -109,8 +109,8 @@
/* CPU port control reg */
#define RTL8368RB_CPU_CTRL_REG 0x0061
#define RTL8368RB_CPU_PORTS_MSK 0x00FF
-/* Enables inserting custom tag length/type 0x8899 */
-#define RTL8368RB_CPU_INSTAG BIT(15)
+/* Disables inserting custom tag length/type 0x8899 */
+#define RTL8368RB_CPU_NO_TAG BIT(15)
#define RTL8366RB_SMAR0 0x0070 /* bits 0..15 */
#define RTL8366RB_SMAR1 0x0071 /* bits 16..31 */
@@ -844,16 +844,14 @@ static int rtl8366rb_setup(struct dsa_sw
if (ret)
return ret;
- /* Enable CPU port and enable inserting CPU tag
+ /* Enable CPU port with custom DSA tag 8899.
*
- * Disabling RTL8368RB_CPU_INSTAG here will change the behaviour
- * of the switch totally and it will start talking Realtek RRCP
- * internally. It is probably possible to experiment with this,
- * but then the kernel needs to understand and handle RRCP first.
+ * If you set RTL8368RB_CPU_NO_TAG (bit 15) in this registers
+ * the custom tag is turned off.
*/
ret = regmap_update_bits(smi->map, RTL8368RB_CPU_CTRL_REG,
0xFFFF,
- RTL8368RB_CPU_INSTAG | BIT(smi->cpu_port));
+ BIT(smi->cpu_port));
if (ret)
return ret;
@@ -966,21 +964,8 @@ static int rtl8366rb_setup(struct dsa_sw
static enum dsa_tag_protocol rtl8366_get_tag_protocol(struct dsa_switch *ds,
int port)
{
- /* For now, the RTL switches are handled without any custom tags.
- *
- * It is possible to turn on "custom tags" by removing the
- * RTL8368RB_CPU_INSTAG flag when enabling the port but what it
- * does is unfamiliar to DSA: ethernet frames of type 8899, the Realtek
- * Remote Control Protocol (RRCP) start to appear on the CPU port of
- * the device. So this is not the ordinary few extra bytes in the
- * frame. Instead it appears that the switch starts to talk Realtek
- * RRCP internally which means a pretty complex RRCP implementation
- * decoding and responding the RRCP protocol is needed to exploit this.
- *
- * The OpenRRCP project (dormant since 2009) have reverse-egineered
- * parts of the protocol.
- */
- return DSA_TAG_PROTO_NONE;
+ /* This switch uses the 4 byte protocol A Realtek DSA tag */
+ return DSA_TAG_PROTO_RTL4_A;
}
static void rtl8366rb_adjust_link(struct dsa_switch *ds, int port,