ipq40xx: 6.1: use latest DSA and ethernet patches

This pulls-in the latest version of qca8k based IPQ4019 driver as well as
the latest version of IPQESS that was sent upstream.

Both qca8k and IPQESS have been improved and cleaned up compared to current
version of patches.

PSGMII PHY mode and missing reset have been upstreamed and will be in
the kernel 6.6.

Signed-off-by: Robert Marko <robimarko@gmail.com>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
Robert Marko 2023-08-21 23:42:54 +02:00 committed by Christian Marangi
parent 4c010932a5
commit cd9c721124
No known key found for this signature in database
GPG Key ID: AC001D09ADBFEAD7
15 changed files with 3896 additions and 33 deletions

View File

@ -1,12 +1,15 @@
From 53cac0823f86c39eb4b00e2c9a7b2483a4182008 Mon Sep 17 00:00:00 2001
From be59072c6eeb7535bf9a339fb9d5a8bfae17ac22 Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Mon, 14 Aug 2023 12:37:58 +0200
Subject: [PATCH 1/2] dt-bindings: clock: qcom: ipq4019: add missing networking
Date: Mon, 14 Aug 2023 12:40:23 +0200
Subject: [PATCH] dt-bindings: clock: qcom: ipq4019: add missing networking
resets
Add bindings for the missing networking resets found in IPQ4019 GCC.
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20230814104119.96858-1-robert.marko@sartura.hr
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
include/dt-bindings/clock/qcom,gcc-ipq4019.h | 6 ++++++
1 file changed, 6 insertions(+)

View File

@ -1,12 +1,14 @@
From 6038ba75e2aa8e57d4eaf20a90c8061c43b1117f Mon Sep 17 00:00:00 2001
From 20014461691efc9e274c3870357152db7f091820 Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Mon, 14 Aug 2023 12:39:04 +0200
Subject: [PATCH 2/2] clk: qcom: gcc-ipq4019: add missing networking resets
Date: Mon, 14 Aug 2023 12:40:24 +0200
Subject: [PATCH] clk: qcom: gcc-ipq4019: add missing networking resets
IPQ4019 has more networking related resets that will be required for future
wired networking support, so lets add them.
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
Link: https://lore.kernel.org/r/20230814104119.96858-2-robert.marko@sartura.hr
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
drivers/clk/qcom/gcc-ipq4019.c | 6 ++++++
1 file changed, 6 insertions(+)

View File

@ -0,0 +1,105 @@
From 9a0e95e34e9c0a713ddfd48c3a88a20d2bdfd514 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <j4g8y7@gmail.com>
Date: Fri, 11 Aug 2023 13:10:07 +0200
Subject: [PATCH] net: phy: Introduce PSGMII PHY interface mode
The PSGMII interface is similar to QSGMII. The main difference
is that the PSGMII interface combines five SGMII lines into a
single link while in QSGMII only four lines are combined.
Similarly to the QSGMII, this interface mode might also needs
special handling within the MAC driver.
It is commonly used by Qualcomm with their QCA807x PHY series and
modern WiSoC-s.
Add definitions for the PHY layer to allow to express this type
of connection between the MAC and PHY.
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
Documentation/networking/phy.rst | 4 ++++
drivers/net/phy/phy-core.c | 2 ++
drivers/net/phy/phylink.c | 3 +++
include/linux/phy.h | 4 ++++
4 files changed, 13 insertions(+)
--- a/Documentation/networking/phy.rst
+++ b/Documentation/networking/phy.rst
@@ -323,6 +323,10 @@ Some of the interface modes are describe
contrast with the 1000BASE-X phy mode used for Clause 38 and 39 PMDs, this
interface mode has different autonegotiation and only supports full duplex.
+``PHY_INTERFACE_MODE_PSGMII``
+ This is the Penta SGMII mode, it is similar to QSGMII but it combines 5
+ SGMII lines into a single link compared to 4 on QSGMII.
+
Pause frames / flow control
===========================
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -140,6 +140,8 @@ int phy_interface_num_ports(phy_interfac
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
return 4;
+ case PHY_INTERFACE_MODE_PSGMII:
+ return 5;
case PHY_INTERFACE_MODE_MAX:
WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode");
return 0;
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -187,6 +187,7 @@ static int phylink_interface_max_speed(p
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_PSGMII:
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
case PHY_INTERFACE_MODE_SGMII:
@@ -448,6 +449,7 @@ unsigned long phylink_get_capabilities(p
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_PSGMII:
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
case PHY_INTERFACE_MODE_SGMII:
@@ -814,6 +816,7 @@ static int phylink_parse_mode(struct phy
switch (pl->link_config.interface) {
case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_PSGMII:
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
case PHY_INTERFACE_MODE_RGMII:
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -104,6 +104,7 @@ extern const int phy_10gbit_features_arr
* @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface
* @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface
* @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax
+ * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII
* @PHY_INTERFACE_MODE_QSGMII: Quad SGMII
* @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII
* @PHY_INTERFACE_MODE_100BASEX: 100 BaseX
@@ -141,6 +142,7 @@ typedef enum {
PHY_INTERFACE_MODE_XGMII,
PHY_INTERFACE_MODE_XLGMII,
PHY_INTERFACE_MODE_MOCA,
+ PHY_INTERFACE_MODE_PSGMII,
PHY_INTERFACE_MODE_QSGMII,
PHY_INTERFACE_MODE_TRGMII,
PHY_INTERFACE_MODE_100BASEX,
@@ -248,6 +250,8 @@ static inline const char *phy_modes(phy_
return "xlgmii";
case PHY_INTERFACE_MODE_MOCA:
return "moca";
+ case PHY_INTERFACE_MODE_PSGMII:
+ return "psgmii";
case PHY_INTERFACE_MODE_QSGMII:
return "qsgmii";
case PHY_INTERFACE_MODE_TRGMII:

View File

@ -0,0 +1,238 @@
From a32e16b3c2fc1954ad6e09737439f60e5890278e Mon Sep 17 00:00:00 2001
From: Maxime Chevallier <maxime.chevallier@bootlin.com>
Date: Fri, 4 Nov 2022 18:41:49 +0100
Subject: [PATCH] net: dsa: add out-of-band tagging protocol
This tagging protocol is designed for the situation where the link
between the MAC and the Switch is designed such that the Destination
Port, which is usually embedded in some part of the Ethernet Header, is
sent out-of-band, and isn't present at all in the Ethernet frame.
This can happen when the MAC and Switch are tightly integrated on an
SoC, as is the case with the Qualcomm IPQ4019 for example, where the DSA
tag is inserted directly into the DMA descriptors. In that case,
the MAC driver is responsible for sending the tag to the switch using
the out-of-band medium. To do so, the MAC driver needs to have the
information of the destination port for that skb.
Add a new tagging protocol based on SKB extensions to convey the
information about the destination port to the MAC driver
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
Documentation/networking/dsa/dsa.rst | 13 +++++++-
MAINTAINERS | 1 +
include/linux/dsa/oob.h | 16 +++++++++
include/linux/skbuff.h | 3 ++
include/net/dsa.h | 2 ++
net/core/skbuff.c | 10 ++++++
net/dsa/Kconfig | 9 +++++
net/dsa/Makefile | 1 +
net/dsa/tag_oob.c | 49 ++++++++++++++++++++++++++++
9 files changed, 103 insertions(+), 1 deletion(-)
create mode 100644 include/linux/dsa/oob.h
create mode 100644 net/dsa/tag_oob.c
--- a/Documentation/networking/dsa/dsa.rst
+++ b/Documentation/networking/dsa/dsa.rst
@@ -66,7 +66,8 @@ Switch tagging protocols
------------------------
DSA supports many vendor-specific tagging protocols, one software-defined
-tagging protocol, and a tag-less mode as well (``DSA_TAG_PROTO_NONE``).
+tagging protocol, a tag-less mode as well (``DSA_TAG_PROTO_NONE``) and an
+out-of-band tagging protocol (``DSA_TAG_PROTO_OOB``).
The exact format of the tag protocol is vendor specific, but in general, they
all contain something which:
@@ -217,6 +218,16 @@ receive all frames regardless of the val
setting the ``promisc_on_master`` property of the ``struct dsa_device_ops``.
Note that this assumes a DSA-unaware master driver, which is the norm.
+Some SoCs have a tight integration between the conduit network interface and the
+embedded switch, such that the DSA tag isn't transmitted in the packet data,
+but through another media, using so-called out-of-band tagging. In that case,
+the host MAC driver is in charge of transmitting the tag to the switch.
+An example is the IPQ4019 SoC, that transmits the tag between the ipqess
+ethernet controller and the qca8k switch using the DMA descriptor. In that
+configuration, tag-chaining is permitted, but the OOB tag will always be the
+top-most switch in the tree. The tagger (``DSA_TAG_PROTO_OOB``) uses skb
+extensions to transmit the tag to and from the MAC driver.
+
Master network devices
----------------------
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17070,6 +17070,7 @@ L: netdev@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/net/qcom,ipq4019-ess-edma.yaml
F: drivers/net/ethernet/qualcomm/ipqess/
+F: net/dsa/tag_oob.c
QUALCOMM ETHQOS ETHERNET DRIVER
M: Vinod Koul <vkoul@kernel.org>
--- /dev/null
+++ b/include/linux/dsa/oob.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ * Copyright (C) 2022 Maxime Chevallier <maxime.chevallier@bootlin.com>
+ */
+
+#ifndef _NET_DSA_OOB_H
+#define _NET_DSA_OOB_H
+
+#include <linux/skbuff.h>
+
+struct dsa_oob_tag_info {
+ u16 port;
+};
+
+int dsa_oob_tag_push(struct sk_buff *skb, struct dsa_oob_tag_info *ti);
+int dsa_oob_tag_pop(struct sk_buff *skb, struct dsa_oob_tag_info *ti);
+#endif
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -4580,6 +4580,9 @@ enum skb_ext_id {
#if IS_ENABLED(CONFIG_MCTP_FLOWS)
SKB_EXT_MCTP,
#endif
+#if IS_ENABLED(CONFIG_NET_DSA_TAG_OOB)
+ SKB_EXT_DSA_OOB,
+#endif
SKB_EXT_NUM, /* must be last */
};
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -55,6 +55,7 @@ struct phylink_link_state;
#define DSA_TAG_PROTO_RTL8_4T_VALUE 25
#define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 26
#define DSA_TAG_PROTO_LAN937X_VALUE 27
+#define DSA_TAG_PROTO_OOB_VALUE 28
enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
@@ -85,6 +86,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_RTL8_4T = DSA_TAG_PROTO_RTL8_4T_VALUE,
DSA_TAG_PROTO_RZN1_A5PSW = DSA_TAG_PROTO_RZN1_A5PSW_VALUE,
DSA_TAG_PROTO_LAN937X = DSA_TAG_PROTO_LAN937X_VALUE,
+ DSA_TAG_PROTO_OOB = DSA_TAG_PROTO_OOB_VALUE,
};
struct dsa_switch;
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -62,8 +62,12 @@
#include <linux/mpls.h>
#include <linux/kcov.h>
#include <linux/if.h>
+#ifdef CONFIG_NET_DSA_TAG_OOB
+#include <linux/dsa/oob.h>
+#endif
#include <net/protocol.h>
+#include <net/dsa.h>
#include <net/dst.h>
#include <net/sock.h>
#include <net/checksum.h>
@@ -4510,6 +4514,9 @@ static const u8 skb_ext_type_len[] = {
#if IS_ENABLED(CONFIG_MCTP_FLOWS)
[SKB_EXT_MCTP] = SKB_EXT_CHUNKSIZEOF(struct mctp_flow),
#endif
+#if IS_ENABLED(CONFIG_NET_DSA_TAG_OOB)
+ [SKB_EXT_DSA_OOB] = SKB_EXT_CHUNKSIZEOF(struct dsa_oob_tag_info),
+#endif
};
static __always_inline unsigned int skb_ext_total_length(void)
@@ -4530,6 +4537,9 @@ static __always_inline unsigned int skb_
#if IS_ENABLED(CONFIG_MCTP_FLOWS)
skb_ext_type_len[SKB_EXT_MCTP] +
#endif
+#if IS_ENABLED(CONFIG_NET_DSA_TAG_OOB)
+ skb_ext_type_len[SKB_EXT_DSA_OOB] +
+#endif
0;
}
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -113,6 +113,15 @@ config NET_DSA_TAG_OCELOT_8021Q
this mode, less TCAM resources (VCAP IS1, IS2, ES0) are available for
use with tc-flower.
+config NET_DSA_TAG_OOB
+ select SKB_EXTENSIONS
+ tristate "Tag driver for Out-of-band tagging drivers"
+ help
+ Say Y or M if you want to enable support for pairs of embedded
+ switches and host MAC drivers which perform demultiplexing and
+ packet steering to ports using out of band metadata processed
+ by the DSA master, rather than tags present in the packets.
+
config NET_DSA_TAG_QCA
tristate "Tag driver for Qualcomm Atheros QCA8K switches"
help
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_NET_DSA_TAG_LAN9303) += tag
obj-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
obj-$(CONFIG_NET_DSA_TAG_OCELOT) += tag_ocelot.o
obj-$(CONFIG_NET_DSA_TAG_OCELOT_8021Q) += tag_ocelot_8021q.o
+obj-$(CONFIG_NET_DSA_TAG_OOB) += tag_oob.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
--- /dev/null
+++ b/net/dsa/tag_oob.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/* Copyright (c) 2022, Maxime Chevallier <maxime.chevallier@bootlin.com> */
+
+#include <linux/bitfield.h>
+#include <linux/dsa/oob.h>
+#include <linux/skbuff.h>
+
+#include "dsa_priv.h"
+
+static struct sk_buff *oob_tag_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct dsa_oob_tag_info *tag_info = skb_ext_add(skb, SKB_EXT_DSA_OOB);
+ struct dsa_port *dp = dsa_slave_to_port(dev);
+
+ tag_info->port = dp->index;
+
+ return skb;
+}
+
+static struct sk_buff *oob_tag_rcv(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct dsa_oob_tag_info *tag_info = skb_ext_find(skb, SKB_EXT_DSA_OOB);
+
+ if (!tag_info)
+ return NULL;
+
+ skb->dev = dsa_master_find_slave(dev, 0, tag_info->port);
+ if (!skb->dev)
+ return NULL;
+
+ return skb;
+}
+
+static const struct dsa_device_ops oob_tag_dsa_ops = {
+ .name = "oob",
+ .proto = DSA_TAG_PROTO_OOB,
+ .xmit = oob_tag_xmit,
+ .rcv = oob_tag_rcv,
+};
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DSA tag driver for out-of-band tagging");
+MODULE_AUTHOR("Maxime Chevallier <maxime.chevallier@bootlin.com>");
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_OOB);
+
+module_dsa_tag_driver(oob_tag_dsa_ops);

View File

@ -0,0 +1,173 @@
From 4975e2b3f1d37bba04f262784cef0d5b7e0a30a4 Mon Sep 17 00:00:00 2001
From: Maxime Chevallier <maxime.chevallier@bootlin.com>
Date: Fri, 4 Nov 2022 18:41:50 +0100
Subject: [PATCH] net: ipqess: Add out-of-band DSA tagging support
On the IPQ4019, there's an 5 ports switch connected to the CPU through
the IPQESS Ethernet controller. The way the DSA tag is sent-out to that
switch is through the DMA descriptor, due to how tightly it is
integrated with the switch.
We use the out-of-band tagging protocol by getting the source
port from the descriptor, push it into the skb extensions, and have the
tagger pull it to infer the destination netdev. The reverse process is
done on the TX side, where the driver pulls the tag from the skb and
builds the descriptor accordingly.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
drivers/net/ethernet/qualcomm/Kconfig | 1 +
drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 64 ++++++++++++++++++-
drivers/net/ethernet/qualcomm/ipqess/ipqess.h | 4 ++
3 files changed, 68 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/qualcomm/Kconfig
+++ b/drivers/net/ethernet/qualcomm/Kconfig
@@ -64,6 +64,7 @@ config QCOM_IPQ4019_ESS_EDMA
tristate "Qualcomm Atheros IPQ4019 ESS EDMA support"
depends on (OF && ARCH_QCOM) || COMPILE_TEST
select PHYLINK
+ select NET_DSA_TAG_OOB
help
This driver supports the Qualcomm Atheros IPQ40xx built-in
ESS EDMA ethernet controller.
--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
+++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
@@ -9,6 +9,7 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
+#include <linux/dsa/oob.h>
#include <linux/if_vlan.h>
#include <linux/interrupt.h>
#include <linux/module.h>
@@ -22,6 +23,7 @@
#include <linux/skbuff.h>
#include <linux/vmalloc.h>
#include <net/checksum.h>
+#include <net/dsa.h>
#include <net/ip6_checksum.h>
#include "ipqess.h"
@@ -327,6 +329,7 @@ static int ipqess_rx_poll(struct ipqess_
tail &= IPQESS_RFD_CONS_IDX_MASK;
while (done < budget) {
+ struct dsa_oob_tag_info *tag_info;
struct ipqess_rx_desc *rd;
struct sk_buff *skb;
@@ -406,6 +409,12 @@ static int ipqess_rx_poll(struct ipqess_
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021AD),
le16_to_cpu(rd->rrd4));
+ if (likely(rx_ring->ess->dsa_ports)) {
+ tag_info = skb_ext_add(skb, SKB_EXT_DSA_OOB);
+ tag_info->port = FIELD_GET(IPQESS_RRD_PORT_ID_MASK,
+ le16_to_cpu(rd->rrd1));
+ }
+
napi_gro_receive(&rx_ring->napi_rx, skb);
rx_ring->ess->stats.rx_packets++;
@@ -706,6 +715,23 @@ static void ipqess_rollback_tx(struct ip
tx_ring->head = start_index;
}
+static void ipqess_process_dsa_tag_sh(struct ipqess *ess, struct sk_buff *skb,
+ u32 *word3)
+{
+ struct dsa_oob_tag_info *tag_info;
+
+ if (unlikely(!ess->dsa_ports))
+ return;
+
+ tag_info = skb_ext_find(skb, SKB_EXT_DSA_OOB);
+ if (!tag_info)
+ return;
+
+ *word3 |= tag_info->port << IPQESS_TPD_PORT_BITMAP_SHIFT;
+ *word3 |= BIT(IPQESS_TPD_FROM_CPU_SHIFT);
+ *word3 |= 0x3e << IPQESS_TPD_PORT_BITMAP_SHIFT;
+}
+
static int ipqess_tx_map_and_fill(struct ipqess_tx_ring *tx_ring,
struct sk_buff *skb)
{
@@ -716,6 +742,8 @@ static int ipqess_tx_map_and_fill(struct
u16 len;
int i;
+ ipqess_process_dsa_tag_sh(tx_ring->ess, skb, &word3);
+
if (skb_is_gso(skb)) {
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) {
lso_word1 |= IPQESS_TPD_IPV4_EN;
@@ -917,6 +945,33 @@ static const struct net_device_ops ipqes
.ndo_tx_timeout = ipqess_tx_timeout,
};
+static int ipqess_netdevice_event(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct ipqess *ess = container_of(nb, struct ipqess, netdev_notifier);
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+ struct netdev_notifier_changeupper_info *info;
+
+ if (dev != ess->netdev)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_CHANGEUPPER:
+ info = ptr;
+
+ if (!dsa_slave_dev_check(info->upper_dev))
+ return NOTIFY_DONE;
+
+ if (info->linking)
+ ess->dsa_ports++;
+ else
+ ess->dsa_ports--;
+
+ return NOTIFY_DONE;
+ }
+ return NOTIFY_OK;
+}
+
static void ipqess_hw_stop(struct ipqess *ess)
{
int i;
@@ -1184,12 +1239,19 @@ static int ipqess_axi_probe(struct platf
netif_napi_add(netdev, &ess->rx_ring[i].napi_rx, ipqess_rx_napi);
}
- err = register_netdev(netdev);
+ ess->netdev_notifier.notifier_call = ipqess_netdevice_event;
+ err = register_netdevice_notifier(&ess->netdev_notifier);
if (err)
goto err_hw_stop;
+ err = register_netdev(netdev);
+ if (err)
+ goto err_notifier_unregister;
+
return 0;
+err_notifier_unregister:
+ unregister_netdevice_notifier(&ess->netdev_notifier);
err_hw_stop:
ipqess_hw_stop(ess);
--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.h
+++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.h
@@ -171,6 +171,10 @@ struct ipqess {
struct platform_device *pdev;
struct phylink *phylink;
struct phylink_config phylink_config;
+
+ struct notifier_block netdev_notifier;
+ int dsa_ports;
+
struct ipqess_tx_ring tx_ring[IPQESS_NETDEV_QUEUES];
struct ipqess_statistics ipqess_stats;

View File

@ -0,0 +1,75 @@
From 5f15f7f170c76220dfd36cb9037d7848d1fc4aaf Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Tue, 15 Aug 2023 14:30:50 +0200
Subject: [PATCH] net: qualcomm: ipqess: release IRQ-s on network device stop
Currently, IPQESS driver is obtaining the IRQ-s during ndo_open, but they
are never freed as they are device managed.
However, it is not enough for them to be released when device is removed
as the same network device can be stopped and started multiple times which
on the second start would lead to IRQ request to fail with -EBUSY as they
have already been requested before and are not of the shared type with:
[ 34.480769] ipqess-edma c080000.ethernet eth0: Link is Down
[ 34.488070] ipqess-edma c080000.ethernet eth0: ipqess_open
[ 34.488131] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0)
[ 34.494527] ipqess-edma c080000.ethernet eth0: ipqess_open
[ 34.502892] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0)
[ 34.508137] qca8k-ipq4019 c000000.switch lan1: failed to open master eth0
[ 34.518966] br-lan: port 1(lan1) entered blocking state
[ 34.525165] br-lan: port 1(lan1) entered disabled state
[ 34.530633] device lan1 entered promiscuous mode
[ 34.548598] ipqess-edma c080000.ethernet eth0: ipqess_open
[ 34.548660] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0)
[ 34.553111] qca8k-ipq4019 c000000.switch lan2: failed to open master eth0
[ 34.563841] br-lan: port 2(lan2) entered blocking state
[ 34.570083] br-lan: port 2(lan2) entered disabled state
[ 34.575530] device lan2 entered promiscuous mode
[ 34.587067] ipqess-edma c080000.ethernet eth0: ipqess_open
[ 34.587132] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0)
[ 34.591579] qca8k-ipq4019 c000000.switch lan3: failed to open master eth0
[ 34.602451] br-lan: port 3(lan3) entered blocking state
[ 34.608496] br-lan: port 3(lan3) entered disabled state
[ 34.614084] device lan3 entered promiscuous mode
[ 34.626405] ipqess-edma c080000.ethernet eth0: ipqess_open
[ 34.626468] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0)
[ 34.630871] qca8k-ipq4019 c000000.switch lan4: failed to open master eth0
[ 34.641689] br-lan: port 4(lan4) entered blocking state
[ 34.647834] br-lan: port 4(lan4) entered disabled state
[ 34.653455] device lan4 entered promiscuous mode
[ 34.667282] ipqess-edma c080000.ethernet eth0: ipqess_open
[ 34.667364] genirq: Flags mismatch irq 37. 00000001 (c080000.ethernet:txq0) vs. 00000001 (c080000.ethernet:txq0)
[ 34.671830] qca8k-ipq4019 c000000.switch wan: failed to open master eth0
So, lets free the IRQ-s on ndo_stop after stopping NAPI and HW IRQ-s.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
+++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
@@ -636,9 +636,22 @@ static int ipqess_stop(struct net_device
netif_tx_stop_all_queues(netdev);
phylink_stop(ess->phylink);
ipqess_irq_disable(ess);
+
for (i = 0; i < IPQESS_NETDEV_QUEUES; i++) {
+ int qid;
+
napi_disable(&ess->tx_ring[i].napi_tx);
napi_disable(&ess->rx_ring[i].napi_rx);
+
+ qid = ess->tx_ring[i].idx;
+ devm_free_irq(&netdev->dev,
+ ess->tx_irq[qid],
+ &ess->tx_ring[i]);
+
+ qid = ess->rx_ring[i].idx;
+ devm_free_irq(&netdev->dev,
+ ess->rx_irq[qid],
+ &ess->rx_ring[i]);
}
return 0;

View File

@ -0,0 +1,49 @@
From 9fa4a57a65e270e4d579cace4de5c438f46c7d12 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Tue, 15 Aug 2023 14:38:44 +0200
Subject: [PATCH] net: qualcomm: ipqess: enable threaded NAPI by default
Threaded NAPI provides a nice performance boost, so lets enable it by
default.
We do however need to move the __napi_schedule() after HW IRQ has been
cleared in order to avoid concurency issues.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
+++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
@@ -530,9 +530,9 @@ static irqreturn_t ipqess_interrupt_tx(i
struct ipqess_tx_ring *tx_ring = (struct ipqess_tx_ring *)priv;
if (likely(napi_schedule_prep(&tx_ring->napi_tx))) {
- __napi_schedule(&tx_ring->napi_tx);
ipqess_w32(tx_ring->ess, IPQESS_REG_TX_INT_MASK_Q(tx_ring->idx),
0x0);
+ __napi_schedule(&tx_ring->napi_tx);
}
return IRQ_HANDLED;
@@ -543,9 +543,9 @@ static irqreturn_t ipqess_interrupt_rx(i
struct ipqess_rx_ring *rx_ring = (struct ipqess_rx_ring *)priv;
if (likely(napi_schedule_prep(&rx_ring->napi_rx))) {
- __napi_schedule(&rx_ring->napi_rx);
ipqess_w32(rx_ring->ess, IPQESS_REG_RX_INT_MASK_Q(rx_ring->idx),
0x0);
+ __napi_schedule(&rx_ring->napi_rx);
}
return IRQ_HANDLED;
@@ -1261,6 +1261,8 @@ static int ipqess_axi_probe(struct platf
if (err)
goto err_notifier_unregister;
+ dev_set_threaded(netdev, true);
+
return 0;
err_notifier_unregister:

View File

@ -1,27 +1,27 @@
From 44327d7098d4f32c24ec8c528e5aff6e030956bc Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Wed, 20 Oct 2021 13:21:45 +0200
Subject: [PATCH] arm: dts: ipq4019: add ethernet controller DT node
From 5b71dbb867680887d47954ce1cc145cb747cbce6 Mon Sep 17 00:00:00 2001
From: Maxime Chevallier <maxime.chevallier@bootlin.com>
Date: Fri, 4 Nov 2022 18:41:51 +0100
Subject: [PATCH] ARM: dts: qcom: ipq4019: Add description for the IPQESS
Ethernet controller
Since IPQ40xx SoC built-in ethernet controller now has a driver,
add its DT node so it can be used.
The Qualcomm IPQ4019 includes an internal 5 ports switch, which is
connected to the CPU through the internal IPQESS Ethernet controller.
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
Add support for this internal interface, which is internally connected to a
modified version of the QCA8K Ethernet switch.
This Ethernet controller only support a specific internal interface mode
for connection to the switch.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
arch/arm/boot/dts/qcom-ipq4019.dtsi | 48 +++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
@@ -38,6 +38,7 @@
spi1 = &blsp1_spi2;
i2c0 = &blsp1_i2c3;
i2c1 = &blsp1_i2c4;
+ ethernet0 = &gmac;
};
cpus {
@@ -589,6 +590,57 @@
@@ -591,6 +591,54 @@
status = "disabled";
};
@ -29,9 +29,9 @@ Signed-off-by: Robert Marko <robert.marko@sartura.hr>
+ compatible = "qcom,ipq4019-ess-edma";
+ reg = <0xc080000 0x8000>;
+ resets = <&gcc ESS_RESET>;
+ reset-names = "ess_rst";
+ reset-names = "ess";
+ clocks = <&gcc GCC_ESS_CLK>;
+ clock-names = "ess_clk";
+ clock-names = "ess";
+ interrupts = <GIC_SPI 65 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 66 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 67 IRQ_TYPE_EDGE_RISING>,
@ -64,15 +64,12 @@ Signed-off-by: Robert Marko <robert.marko@sartura.hr>
+ <GIC_SPI 253 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 254 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 255 IRQ_TYPE_EDGE_RISING>;
+
+ status = "disabled";
+
+ phy-mode = "internal";
+ status = "disabled";
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ pause;
+ asym-pause;
+ };
+ };
+

View File

@ -1,4 +1,4 @@
From 8cbdb2526c3d7ba2e0c8c771773595f195135f54 Mon Sep 17 00:00:00 2001
From 19c507c3fe4a6fc60317dcae2c55de452aecb7d5 Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Mon, 1 Nov 2021 18:15:04 +0100
Subject: [PATCH] arm: dts: ipq4019: add switch node

View File

@ -1,4 +1,4 @@
From dfba344da3657ee4d91e7ebd1217e93423d03624 Mon Sep 17 00:00:00 2001
From 96eb388c082bd0086b128d82def9daaab1617951 Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Thu, 1 Oct 2020 15:05:35 +0200
Subject: [PATCH] dt-bindings: net: add QCA807x PHY

View File

@ -1,4 +1,4 @@
From 95179775debad6b0bdab241d4a305135fc5e67dc Mon Sep 17 00:00:00 2001
From 876bb5b69c1e083be526c0ea261982d5eb78556f Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Fri, 9 Sep 2022 23:44:42 +0200
Subject: [PATCH] net: phy: Add Qualcom QCA807x driver
@ -25,7 +25,7 @@ Signed-off-by: Robert Marko <robert.marko@sartura.hr>
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -362,6 +362,13 @@ config AT803X_PHY
@@ -369,6 +369,13 @@ config AT803X_PHY
Currently supports the AR8030, AR8031, AR8033, AR8035 and internal
QCA8337(Internal qca8k PHY) model

View File

@ -1,4 +1,4 @@
From 03ebcd291974e4ca5d77026111f63309bc708326 Mon Sep 17 00:00:00 2001
From 79b38b9f85da868ca59b66715c20aa55104b640b Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Fri, 2 Oct 2020 10:43:26 +0200
Subject: [PATCH] arm: dts: ipq4019: QCA807x properties

View File

@ -0,0 +1,64 @@
From d0055b03d9c8d48ad2b971821989b09ba95c39f8 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Sun, 17 Sep 2023 20:18:31 +0200
Subject: [PATCH] net: qualcomm: ipqess: fix TX timeout errors
Currently logic to handle napi tx completion is flawed and on the long
run on loaded condition cause TX timeout error with the queue not being
able to handle any new packet.
There are 2 main cause of this:
- incrementing the packet done value wrongly
- handling 2 times the tx_ring tail
ipqess_tx_unmap_and_free may return 2 kind values:
- 0: we are handling first and middle descriptor for the packet
- packet len: we are at the last descriptor for the packet
Done value was wrongly incremented also for first and intermediate
descriptor for the packet resulting causing panic and TX timeouts by
comunicating to the kernel an inconsistent value of packet handling not
matching the expected ones.
Tx_ring tail was handled twice for ipqess_tx_complete run resulting in
again done value incremented wrongly and also problem with idx handling
by actually skipping descriptor for some packets.
Rework the loop logic to fix these 2 problem and also add some comments
to make sure ipqess_tx_unmap_and_free ret value is better
understandable.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/net/ethernet/qualcomm/ipqess/ipqess.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
--- a/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
+++ b/drivers/net/ethernet/qualcomm/ipqess/ipqess.c
@@ -453,13 +453,22 @@ static int ipqess_tx_complete(struct ipq
tail >>= IPQESS_TPD_CONS_IDX_SHIFT;
tail &= IPQESS_TPD_CONS_IDX_MASK;
- do {
+ while ((tx_ring->tail != tail) && (done < budget)) {
ret = ipqess_tx_unmap_and_free(&tx_ring->ess->pdev->dev,
&tx_ring->buf[tx_ring->tail]);
- tx_ring->tail = IPQESS_NEXT_IDX(tx_ring->tail, tx_ring->count);
+ /* ipqess_tx_unmap_and_free may return 2 kind values:
+ * - 0: we are handling first and middle descriptor for the packet
+ * - packet len: we are at the last descriptor for the packet
+ * Increment total bytes handled and packet done only if we are
+ * handling the last descriptor for the packet.
+ */
+ if (ret) {
+ total += ret;
+ done++;
+ }
- total += ret;
- } while ((++done < budget) && (tx_ring->tail != tail));
+ tx_ring->tail = IPQESS_NEXT_IDX(tx_ring->tail, tx_ring->count);
+ };
ipqess_w32(tx_ring->ess, IPQESS_REG_TX_SW_CONS_IDX_Q(tx_ring->idx),
tx_ring->tail);