mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-23 15:32:33 +00:00
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:
parent
4c010932a5
commit
cd9c721124
@ -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(+)
|
@ -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(+)
|
@ -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:
|
File diff suppressed because it is too large
Load Diff
@ -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);
|
@ -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;
|
@ -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;
|
@ -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:
|
@ -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;
|
||||
+ };
|
||||
+ };
|
||||
+
|
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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);
|
Loading…
Reference in New Issue
Block a user