|
@@ -1,187 +0,0 @@
|
|
|
-From 29a0c2fae991cab142575c92276c0afdeb260ebe Mon Sep 17 00:00:00 2001
|
|
|
-From: Gabor Juhos <[email protected]>
|
|
|
-Date: Thu, 28 Oct 2021 21:44:52 +0200
|
|
|
-Subject: [PATCH] net: dsa: tag_ipq4019: add shinfo based tagging driver for
|
|
|
- IPQ40xx
|
|
|
-
|
|
|
-This change adds a tagging protocol driver for the built-in
|
|
|
-ethernet switch of the Qualcomm Atheros IPQ4019 SoCs.
|
|
|
-
|
|
|
-In comparison to the existing tagging protocols this hardware
|
|
|
-requires a slightly different approach because the switch does
|
|
|
-not use in-band tags.
|
|
|
-
|
|
|
-On the receive path, the source port information is embedded
|
|
|
-into the RX descriptors of the ethernet MAC hardware. Similarly,
|
|
|
-the destination port mask must be sent via the TX descriptors
|
|
|
-of the ethernet MAC when a packet is sent towards the switch.
|
|
|
-
|
|
|
-In order to support this special requirements, this patch
|
|
|
-adds a new tagging protocol driver.
|
|
|
-
|
|
|
-The driver extracts the source port information directly
|
|
|
-from the 'receive return descriptor' of the ethernet MAC.
|
|
|
-It is possible because that descriptor is part of the skb
|
|
|
-received from the ethernet driver.
|
|
|
-
|
|
|
-Unfortunatley, it is not possible to put the destination
|
|
|
-port information directly to the TX descriptors, because
|
|
|
-those are handled internally by the driver of the ethernet
|
|
|
-hardware.
|
|
|
-
|
|
|
-To overcome this limitation, this tagging driver uses the
|
|
|
-DSA specific fields in skb->shinfo to send the destination
|
|
|
-port information to the ethernet driver.
|
|
|
-
|
|
|
-A similar tagging driver is exist but that uses skb
|
|
|
-extensions which causes unnecessary overhead.
|
|
|
-
|
|
|
-Signed-off-by: Gabor Juhos <[email protected]>
|
|
|
----
|
|
|
- include/linux/dsa/ipq4019.h | 11 ++++++
|
|
|
- include/net/dsa.h | 2 +
|
|
|
- net/dsa/Kconfig | 6 +++
|
|
|
- net/dsa/Makefile | 1 +
|
|
|
- net/dsa/tag_ipq4019.c | 79 +++++++++++++++++++++++++++++++++++++
|
|
|
- 5 files changed, 99 insertions(+)
|
|
|
- create mode 100644 include/linux/dsa/ipq4019.h
|
|
|
- create mode 100644 net/dsa/tag_ipq4019.c
|
|
|
-
|
|
|
---- /dev/null
|
|
|
-+++ b/include/linux/dsa/ipq4019.h
|
|
|
-@@ -0,0 +1,11 @@
|
|
|
-+/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
-+
|
|
|
-+#ifndef DSA_IPQ40XX_H
|
|
|
-+#define DSA_IPQ40XX_H
|
|
|
-+
|
|
|
-+struct ipq40xx_dsa_tag_data {
|
|
|
-+ u8 from_cpu;
|
|
|
-+ u8 dp;
|
|
|
-+};
|
|
|
-+
|
|
|
-+#endif /* DSA_IPQ40XX_H */
|
|
|
---- a/include/net/dsa.h
|
|
|
-+++ b/include/net/dsa.h
|
|
|
-@@ -51,6 +51,7 @@ struct phylink_link_state;
|
|
|
- #define DSA_TAG_PROTO_SEVILLE_VALUE 21
|
|
|
- #define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22
|
|
|
- #define DSA_TAG_PROTO_SJA1110_VALUE 23
|
|
|
-+#define DSA_TAG_PROTO_IPQ4019_VALUE 24
|
|
|
-
|
|
|
- enum dsa_tag_protocol {
|
|
|
- DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
|
|
|
-@@ -77,6 +78,7 @@ enum dsa_tag_protocol {
|
|
|
- DSA_TAG_PROTO_OCELOT_8021Q = DSA_TAG_PROTO_OCELOT_8021Q_VALUE,
|
|
|
- DSA_TAG_PROTO_SEVILLE = DSA_TAG_PROTO_SEVILLE_VALUE,
|
|
|
- DSA_TAG_PROTO_SJA1110 = DSA_TAG_PROTO_SJA1110_VALUE,
|
|
|
-+ DSA_TAG_PROTO_IPQ4019 = DSA_TAG_PROTO_IPQ4019_VALUE,
|
|
|
- };
|
|
|
-
|
|
|
- struct dsa_switch;
|
|
|
---- a/net/dsa/Kconfig
|
|
|
-+++ b/net/dsa/Kconfig
|
|
|
-@@ -57,6 +57,12 @@ config NET_DSA_TAG_HELLCREEK
|
|
|
- Say Y or M if you want to enable support for tagging frames
|
|
|
- for the Hirschmann Hellcreek TSN switches.
|
|
|
-
|
|
|
-+config NET_DSA_TAG_IPQ4019
|
|
|
-+ tristate "Tag driver for Qualcomm Atheros IPQ4019 SoC built-in switch"
|
|
|
-+ help
|
|
|
-+ Say Y or M if you want to enable support for tagging frames for
|
|
|
-+ the built-in switch of the Qualcomm Atheros IPQ4019 SoC-s.
|
|
|
-+
|
|
|
- config NET_DSA_TAG_GSWIP
|
|
|
- tristate "Tag driver for Lantiq / Intel GSWIP switches"
|
|
|
- help
|
|
|
---- a/net/dsa/Makefile
|
|
|
-+++ b/net/dsa/Makefile
|
|
|
-@@ -8,6 +8,7 @@ obj-$(CONFIG_NET_DSA_TAG_AR9331) += tag_
|
|
|
- obj-$(CONFIG_NET_DSA_TAG_BRCM_COMMON) += tag_brcm.o
|
|
|
- obj-$(CONFIG_NET_DSA_TAG_DSA_COMMON) += tag_dsa.o
|
|
|
- obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o
|
|
|
-+obj-$(CONFIG_NET_DSA_TAG_IPQ4019) += tag_ipq4019.o
|
|
|
- obj-$(CONFIG_NET_DSA_TAG_HELLCREEK) += tag_hellcreek.o
|
|
|
- obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
|
|
|
- obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o
|
|
|
---- /dev/null
|
|
|
-+++ b/net/dsa/tag_ipq4019.c
|
|
|
-@@ -0,0 +1,78 @@
|
|
|
-+// SPDX-License-Identifier: GPL-2.0-only
|
|
|
-+
|
|
|
-+/* Copyright (c) 2021, Gabor Juhos <[email protected]> */
|
|
|
-+
|
|
|
-+#include <linux/bitfield.h>
|
|
|
-+#include <linux/dsa/ipq4019.h>
|
|
|
-+
|
|
|
-+#include "dsa_priv.h"
|
|
|
-+
|
|
|
-+/* Receive Return Descriptor */
|
|
|
-+struct edma_rrd {
|
|
|
-+ u16 rrd0;
|
|
|
-+ u16 rrd1;
|
|
|
-+ u16 rrd2;
|
|
|
-+ u16 rrd3;
|
|
|
-+ u16 rrd4;
|
|
|
-+ u16 rrd5;
|
|
|
-+ u16 rrd6;
|
|
|
-+ u16 rrd7;
|
|
|
-+} __packed;
|
|
|
-+
|
|
|
-+#define EDMA_RRD_SIZE sizeof(struct edma_rrd)
|
|
|
-+
|
|
|
-+#define EDMA_RRD1_PORT_ID_MASK GENMASK(14, 12)
|
|
|
-+
|
|
|
-+static struct sk_buff *ipq4019_sh_tag_xmit(struct sk_buff *skb,
|
|
|
-+ struct net_device *dev)
|
|
|
-+{
|
|
|
-+ struct dsa_port *dp = dsa_slave_to_port(dev);
|
|
|
-+ struct ipq40xx_dsa_tag_data *tag_data;
|
|
|
-+
|
|
|
-+ BUILD_BUG_ON(sizeof_field(struct skb_shared_info, dsa_tag_data) <
|
|
|
-+ sizeof(struct ipq40xx_dsa_tag_data));
|
|
|
-+
|
|
|
-+ skb_shinfo(skb)->dsa_tag_proto = DSA_TAG_PROTO_IPQ4019;
|
|
|
-+ tag_data = (struct ipq40xx_dsa_tag_data *)skb_shinfo(skb)->dsa_tag_data;
|
|
|
-+
|
|
|
-+ tag_data->from_cpu = 1;
|
|
|
-+ /* set the destination port information */
|
|
|
-+ tag_data->dp = BIT(dp->index);
|
|
|
-+
|
|
|
-+ return skb;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static struct sk_buff *ipq4019_sh_tag_rcv(struct sk_buff *skb,
|
|
|
-+ struct net_device *dev)
|
|
|
-+{
|
|
|
-+ struct edma_rrd *rrd;
|
|
|
-+ int offset;
|
|
|
-+ int port;
|
|
|
-+
|
|
|
-+ offset = EDMA_RRD_SIZE + ETH_HLEN;
|
|
|
-+ if (unlikely(skb_headroom(skb) < offset))
|
|
|
-+ return NULL;
|
|
|
-+
|
|
|
-+ rrd = (struct edma_rrd *)(skb->data - offset);
|
|
|
-+ port = FIELD_GET(EDMA_RRD1_PORT_ID_MASK, rrd->rrd1);
|
|
|
-+
|
|
|
-+ skb->dev = dsa_master_find_slave(dev, 0, port);
|
|
|
-+ if (!skb->dev)
|
|
|
-+ return NULL;
|
|
|
-+
|
|
|
-+ return skb;
|
|
|
-+}
|
|
|
-+
|
|
|
-+const struct dsa_device_ops ipq4019_sh_tag_dsa_ops = {
|
|
|
-+ .name = "ipq4019-sh",
|
|
|
-+ .proto = DSA_TAG_PROTO_IPQ4019,
|
|
|
-+ .xmit = ipq4019_sh_tag_xmit,
|
|
|
-+ .rcv = ipq4019_sh_tag_rcv,
|
|
|
-+};
|
|
|
-+
|
|
|
-+MODULE_LICENSE("GPL v2");
|
|
|
-+MODULE_DESCRIPTION("DSA tag driver for the IPQ4019 SoC built-in ethernet switch");
|
|
|
-+MODULE_AUTHOR("Gabor Juhos <[email protected]>");
|
|
|
-+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_IPQ4019);
|
|
|
-+
|
|
|
-+module_dsa_tag_driver(ipq4019_sh_tag_dsa_ops);
|