mirror of
git://git.openwrt.org/openwrt/openwrt.git
synced 2025-12-12 07:32:10 -05:00
After booting, a "transmit queue 0 timed out" warning followed by a register dump was observed. The dump indicates that mtk_hw_init() does not initialize the EEECR during probe. This occurs because the netdev is allocated in mtk_add_mac(), which is called after mtk_hw_init(). Consequently, the EEECR register remains uninitialized until a reset is triggered, causing mtk_hw_init() to run again with a valid netdev, at which point the register is finally set. To address this, instead of modifying the probe sequence, latch the Tx LPI enable state and timer value, and move the EEECR register initialization to mtk_mac_link_up() to ensure proper setup when the interface comes up. Additionally, the splat reveals that LPI functionality is controlled by the MAC_MCR_EEE bits in the MCR register. Update mtk_set_eee() to modify these bits accordingly. Fixes:d8315d5358("kernel: backport Mediatek SoC EEE support") Fixes:edddbaf79c("kernel: Mediatek: set default EEE Tx LPI timer") Signed-off-by: Qingfang Deng <dqfext@gmail.com>
158 lines
4.9 KiB
Diff
158 lines
4.9 KiB
Diff
From 952d7325362ffbefa6ce5619fb4e53c2159ec7a7 Mon Sep 17 00:00:00 2001
|
|
From: Qingfang Deng <dqfext@gmail.com>
|
|
Date: Mon, 17 Feb 2025 17:40:21 +0800
|
|
Subject: [PATCH] net: ethernet: mediatek: add EEE support
|
|
|
|
Add EEE support to MediaTek SoC Ethernet. The register fields are
|
|
similar to the ones in MT7531, except that the LPI threshold is in
|
|
milliseconds.
|
|
|
|
Signed-off-by: Qingfang Deng <dqfext@gmail.com>
|
|
---
|
|
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 64 +++++++++++++++++++++
|
|
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 11 ++++
|
|
2 files changed, 75 insertions(+)
|
|
|
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
|
@@ -786,6 +786,7 @@ static void mtk_mac_link_up(struct phyli
|
|
|
|
mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
|
|
mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 |
|
|
+ MAC_MCR_EEE100M | MAC_MCR_EEE1G |
|
|
MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC |
|
|
MAC_MCR_FORCE_RX_FC);
|
|
|
|
@@ -811,6 +812,15 @@ static void mtk_mac_link_up(struct phyli
|
|
if (rx_pause)
|
|
mcr |= MAC_MCR_FORCE_RX_FC;
|
|
|
|
+ if (mode == MLO_AN_PHY && phy && mac->tx_lpi_enabled && phy_init_eee(phy, false) >= 0) {
|
|
+ mcr |= MAC_MCR_EEE100M | MAC_MCR_EEE1G;
|
|
+ mtk_w32(mac->hw,
|
|
+ FIELD_PREP(MAC_EEE_WAKEUP_TIME_1000, 17) |
|
|
+ FIELD_PREP(MAC_EEE_WAKEUP_TIME_100, 36) |
|
|
+ FIELD_PREP(MAC_EEE_LPI_TXIDLE_THD, mac->txidle_thd_ms),
|
|
+ MTK_MAC_EEECR(mac->id));
|
|
+ }
|
|
+
|
|
mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK;
|
|
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
|
|
}
|
|
@@ -4476,6 +4486,61 @@ static int mtk_set_pauseparam(struct net
|
|
return phylink_ethtool_set_pauseparam(mac->phylink, pause);
|
|
}
|
|
|
|
+static int mtk_get_eee(struct net_device *dev, struct ethtool_eee *eee)
|
|
+{
|
|
+ struct mtk_mac *mac = netdev_priv(dev);
|
|
+ u32 reg;
|
|
+ int ret;
|
|
+
|
|
+ ret = phylink_ethtool_get_eee(mac->phylink, eee);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ reg = mtk_r32(mac->hw, MTK_MAC_EEECR(mac->id));
|
|
+ eee->tx_lpi_enabled = mac->tx_lpi_enabled;
|
|
+ eee->tx_lpi_timer = FIELD_GET(MAC_EEE_LPI_TXIDLE_THD, reg) * 1000;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int mtk_set_eee(struct net_device *dev, struct ethtool_eee *eee)
|
|
+{
|
|
+ struct mtk_mac *mac = netdev_priv(dev);
|
|
+ u32 txidle_thd_ms, reg;
|
|
+ int ret;
|
|
+
|
|
+ /* Tx idle timer in ms */
|
|
+ txidle_thd_ms = DIV_ROUND_UP(eee->tx_lpi_timer, 1000);
|
|
+ if (!FIELD_FIT(MAC_EEE_LPI_TXIDLE_THD, txidle_thd_ms))
|
|
+ return -EINVAL;
|
|
+
|
|
+ reg = FIELD_PREP(MAC_EEE_LPI_TXIDLE_THD, txidle_thd_ms);
|
|
+
|
|
+ /* PHY Wake-up time, this field does not have a reset value, so use the
|
|
+ * reset value from MT7531 (36us for 100BaseT and 17us for 1000BaseT).
|
|
+ */
|
|
+ reg |= FIELD_PREP(MAC_EEE_WAKEUP_TIME_1000, 17) |
|
|
+ FIELD_PREP(MAC_EEE_WAKEUP_TIME_100, 36);
|
|
+
|
|
+ if (!txidle_thd_ms)
|
|
+ /* Force LPI Mode without a delay */
|
|
+ reg |= MAC_EEE_LPI_MODE;
|
|
+
|
|
+ ret = phylink_ethtool_set_eee(mac->phylink, eee);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ mac->tx_lpi_enabled = eee->tx_lpi_enabled;
|
|
+ mac->txidle_thd_ms = txidle_thd_ms;
|
|
+ mtk_w32(mac->hw, reg, MTK_MAC_EEECR(mac->id));
|
|
+ if (eee->eee_enabled && eee->eee_active && eee->tx_lpi_enabled)
|
|
+ mtk_m32(mac->hw, 0, MAC_MCR_EEE100M | MAC_MCR_EEE1G, MTK_MAC_MCR(mac->id));
|
|
+ else
|
|
+ mtk_m32(mac->hw, MAC_MCR_EEE100M | MAC_MCR_EEE1G, 0, MTK_MAC_MCR(mac->id));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static u16 mtk_select_queue(struct net_device *dev, struct sk_buff *skb,
|
|
struct net_device *sb_dev)
|
|
{
|
|
@@ -4508,6 +4573,8 @@ static const struct ethtool_ops mtk_etht
|
|
.set_pauseparam = mtk_set_pauseparam,
|
|
.get_rxnfc = mtk_get_rxnfc,
|
|
.set_rxnfc = mtk_set_rxnfc,
|
|
+ .get_eee = mtk_get_eee,
|
|
+ .set_eee = mtk_set_eee,
|
|
};
|
|
|
|
static const struct net_device_ops mtk_netdev_ops = {
|
|
@@ -4568,6 +4635,8 @@ static int mtk_add_mac(struct mtk_eth *e
|
|
}
|
|
mac = netdev_priv(eth->netdev[id]);
|
|
eth->mac[id] = mac;
|
|
+ mac->tx_lpi_enabled = true;
|
|
+ mac->txidle_thd_ms = 1;
|
|
mac->id = id;
|
|
mac->hw = eth;
|
|
mac->of_node = np;
|
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
|
@@ -453,6 +453,8 @@
|
|
#define MAC_MCR_RX_FIFO_CLR_DIS BIT(12)
|
|
#define MAC_MCR_BACKOFF_EN BIT(9)
|
|
#define MAC_MCR_BACKPR_EN BIT(8)
|
|
+#define MAC_MCR_EEE1G BIT(7)
|
|
+#define MAC_MCR_EEE100M BIT(6)
|
|
#define MAC_MCR_FORCE_RX_FC BIT(5)
|
|
#define MAC_MCR_FORCE_TX_FC BIT(4)
|
|
#define MAC_MCR_SPEED_1000 BIT(3)
|
|
@@ -461,6 +463,15 @@
|
|
#define MAC_MCR_FORCE_LINK BIT(0)
|
|
#define MAC_MCR_FORCE_LINK_DOWN (MAC_MCR_FORCE_MODE)
|
|
|
|
+/* Mac EEE control registers */
|
|
+#define MTK_MAC_EEECR(x) (0x10104 + (x * 0x100))
|
|
+#define MAC_EEE_WAKEUP_TIME_1000 GENMASK(31, 24)
|
|
+#define MAC_EEE_WAKEUP_TIME_100 GENMASK(23, 16)
|
|
+#define MAC_EEE_LPI_TXIDLE_THD GENMASK(15, 8)
|
|
+#define MAC_EEE_CKG_TXIDLE BIT(3)
|
|
+#define MAC_EEE_CKG_RXLPI BIT(2)
|
|
+#define MAC_EEE_LPI_MODE BIT(0)
|
|
+
|
|
/* Mac status registers */
|
|
#define MTK_MAC_MSR(x) (0x10108 + (x * 0x100))
|
|
#define MAC_MSR_EEE1G BIT(7)
|
|
@@ -1321,6 +1332,8 @@ struct mtk_mac {
|
|
int id;
|
|
phy_interface_t interface;
|
|
u8 ppe_idx;
|
|
+ bool tx_lpi_enabled;
|
|
+ u8 txidle_thd_ms;
|
|
int speed;
|
|
struct device_node *of_node;
|
|
struct phylink *phylink;
|