mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-12 06:57:57 +04:00
qualcommax: qca_ppe: add EEE support
EEE is disabled on every PPE port because the MAC side of LPI was never
programmed. The GMAC has an LPI enable per port, a wake and idle timer
per port and a microsecond prescaler at PPE offset 0x400, as the HPPE
code in qca-ssdk has it. Program them from mac_enable_tx_lpi, offer LPI
at 100 and 1000 Mbit/s on the QSGMII, PSGMII and SGMII ports, enable
EEE by default and add support_eee.
On IPQ8074 EEE negotiates on links whose partner offers it, a 10 minute
soak with bursty traffic loses 0 of 2939 pings, throughput is unchanged
(302 Mbit/s both ways, n=3) and idle ping latency rises from 0.16 to
0.22 ms (n=3). qca-ssdk uses the same LPI registers on IPQ60xx; no
IPQ60xx board was available to run it.
Fixes: a3a6679538 ("qualcommax: qca_ppe: disable EEE to prevent idle-port egress wedge")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Julius Bairaktaris <julius@bairaktaris.de>
Link: https://github.com/openwrt/openwrt/pull/25665
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
1 parent
ad77648ba7
commit
dd052b4594
2 files changed
+40
-6
No files matched your search
@@ -20,6 +20,16 @@
|
||||
|
||||
|
||||
/* --- Global --- */
|
||||
/* GMAC LPI: an enable bit per port from port 1, a wake and an idle timer per
|
||||
* port in microseconds, and the PPE clock cycles that make a microsecond.
|
||||
* qca-ssdk uses the same layout for IPQ807x and IPQ60xx.
|
||||
*/
|
||||
#define PPE_LPI_ENABLE 0x400
|
||||
#define PPE_LPI_PORT_TIMER(port) (0x400 + (port) * 0x4)
|
||||
#define PPE_LPI_WAKEUP_TIMER GENMASK(15, 0)
|
||||
#define PPE_LPI_SLEEP_TIMER GENMASK(31, 16)
|
||||
#define PPE_LPI_1US_CNT 0x430
|
||||
|
||||
#define PPE_PORT_MUX_CTRL 0x10
|
||||
|
||||
/* CPPE (IPQ60xx) PORT_MUX_CTRL bit layout */
|
||||
|
||||
@@ -968,6 +968,15 @@ static void qca_ppe_phylink_get_caps(struct dsa_switch *ds, int port,
|
||||
if (port != 0)
|
||||
phy_interface_copy(config->pcs_interfaces,
|
||||
config->supported_interfaces);
|
||||
|
||||
if (port != 0) {
|
||||
config->lpi_capabilities = MAC_100FD | MAC_1000FD;
|
||||
__set_bit(PHY_INTERFACE_MODE_QSGMII, config->lpi_interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_PSGMII, config->lpi_interfaces);
|
||||
__set_bit(PHY_INTERFACE_MODE_SGMII, config->lpi_interfaces);
|
||||
config->lpi_timer_default = 256;
|
||||
config->eee_enabled_default = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void ppe_pcs_set_mux_hppe(struct qca_ppe_priv *priv, int port,
|
||||
@@ -1408,20 +1417,34 @@ static void qca_ppe_mac_link_up(struct phylink_config *config,
|
||||
ppe_port_bridge_txmac_set(priv, port, true);
|
||||
}
|
||||
|
||||
/* qca_ppe implements no LPI. The stubs exist only to make
|
||||
* phylink_mac_implements_lpi() true with lpi_capabilities left at 0 -
|
||||
* phylink's "EEE always disabled" case, where phylink_bringup_phy() calls
|
||||
* phy_disable_eee(). Without that the PHYs negotiate 802.3az and egress into
|
||||
* a MAC waking from LPI wedges the port. Never called.
|
||||
*/
|
||||
/* Tw_sys for 100BASE-TX is 30 us, the longest of the speeds offered. */
|
||||
#define PPE_LPI_WAKE_US 32
|
||||
/* nss_ppe_clk runs at 300 MHz, as qca-ssdk's ADPT_HPPE_FREQUENCY has it. */
|
||||
#define PPE_LPI_CLK_MHZ 300
|
||||
|
||||
static int qca_ppe_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
|
||||
bool tx_clk_stop)
|
||||
{
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct qca_ppe_priv *priv = ds_to_priv(dp->ds);
|
||||
|
||||
regmap_write(priv->regmap, PPE_LPI_1US_CNT, PPE_LPI_CLK_MHZ);
|
||||
regmap_write(priv->regmap, PPE_LPI_PORT_TIMER(dp->index),
|
||||
FIELD_PREP(PPE_LPI_WAKEUP_TIMER, PPE_LPI_WAKE_US) |
|
||||
FIELD_PREP(PPE_LPI_SLEEP_TIMER,
|
||||
min_t(u32, timer,
|
||||
FIELD_MAX(PPE_LPI_SLEEP_TIMER))));
|
||||
regmap_set_bits(priv->regmap, PPE_LPI_ENABLE, BIT(dp->index - 1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qca_ppe_mac_disable_tx_lpi(struct phylink_config *config)
|
||||
{
|
||||
struct dsa_port *dp = dsa_phylink_to_port(config);
|
||||
struct qca_ppe_priv *priv = ds_to_priv(dp->ds);
|
||||
|
||||
regmap_clear_bits(priv->regmap, PPE_LPI_ENABLE, BIT(dp->index - 1));
|
||||
}
|
||||
|
||||
static const struct phylink_mac_ops qca_ppe_phylink_mac_ops = {
|
||||
@@ -1733,6 +1756,7 @@ static const struct dsa_switch_ops qca_ppe_ops = {
|
||||
.port_mdb_add = qca_ppe_port_mdb_add,
|
||||
.port_mdb_del = qca_ppe_port_mdb_del,
|
||||
.phylink_get_caps = qca_ppe_phylink_get_caps,
|
||||
.support_eee = dsa_supports_eee,
|
||||
.port_vlan_filtering = qca_ppe_port_vlan_filtering,
|
||||
.port_vlan_add = qca_ppe_port_vlan_add,
|
||||
.port_vlan_del = qca_ppe_port_vlan_del,
|
||||
|
||||
Reference in new issue
Block a user