Skip to content

Commit 6eeceb3

Browse files
author
Paolo Abeni
committed
Merge branch 'address-eee-regressions-on-ksz-switches-since-v6-9-v6-14'
Oleksij Rempel says: ==================== address EEE regressions on KSZ switches since v6.9 (v6.14+) This patch series addresses a regression in Energy Efficient Ethernet (EEE) handling for KSZ switches with integrated PHYs, introduced in kernel v6.9 by commit fe0d4fd ("net: phy: Keep track of EEE configuration"). The first patch updates the DSA driver to allow phylink to properly manage PHY EEE configuration. Since integrated PHYs handle LPI internally and ports without integrated PHYs do not document MAC-level LPI support, dummy MAC LPI callbacks are provided. The second patch removes outdated EEE workarounds from the micrel PHY driver, as they are no longer needed with correct phylink handling. This series addresses the regression for mainline and kernels starting from v6.14. It is not easily possible to fully fix older kernels due to missing infrastructure changes. Tested on KSZ9893 hardware. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 498625a + 8c619eb commit 6eeceb3

File tree

3 files changed

+107
-36
lines changed

3 files changed

+107
-36
lines changed

drivers/net/dsa/microchip/ksz_common.c

Lines changed: 107 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -265,16 +265,70 @@ static void ksz_phylink_mac_link_down(struct phylink_config *config,
265265
unsigned int mode,
266266
phy_interface_t interface);
267267

268+
/**
269+
* ksz_phylink_mac_disable_tx_lpi() - Callback to signal LPI support (Dummy)
270+
* @config: phylink config structure
271+
*
272+
* This function is a dummy handler. See ksz_phylink_mac_enable_tx_lpi() for
273+
* a detailed explanation of EEE/LPI handling in KSZ switches.
274+
*/
275+
static void ksz_phylink_mac_disable_tx_lpi(struct phylink_config *config)
276+
{
277+
}
278+
279+
/**
280+
* ksz_phylink_mac_enable_tx_lpi() - Callback to signal LPI support (Dummy)
281+
* @config: phylink config structure
282+
* @timer: timer value before entering LPI (unused)
283+
* @tx_clock_stop: whether to stop the TX clock in LPI mode (unused)
284+
*
285+
* This function signals to phylink that the driver architecture supports
286+
* LPI management, enabling phylink to control EEE advertisement during
287+
* negotiation according to IEEE Std 802.3 (Clause 78).
288+
*
289+
* Hardware Management of EEE/LPI State:
290+
* For KSZ switch ports with integrated PHYs (e.g., KSZ9893R ports 1-2),
291+
* observation and testing suggest that the actual EEE / Low Power Idle (LPI)
292+
* state transitions are managed autonomously by the hardware based on
293+
* the auto-negotiation results. (Note: While the datasheet describes EEE
294+
* operation based on negotiation, it doesn't explicitly detail the internal
295+
* MAC/PHY interaction, so autonomous hardware management of the MAC state
296+
* for LPI is inferred from observed behavior).
297+
* This hardware control, consistent with the switch's ability to operate
298+
* autonomously via strapping, means MAC-level software intervention is not
299+
* required or exposed for managing the LPI state once EEE is negotiated.
300+
* (Ref: KSZ9893R Data Sheet DS00002420D, primarily Section 4.7.5 explaining
301+
* EEE, also Sections 4.1.7 on Auto-Negotiation and 3.2.1 on Configuration
302+
* Straps).
303+
*
304+
* Additionally, ports configured as MAC interfaces (e.g., KSZ9893R port 3)
305+
* lack documented MAC-level LPI control.
306+
*
307+
* Therefore, this callback performs no action and serves primarily to inform
308+
* phylink of LPI awareness and to document the inferred hardware behavior.
309+
*
310+
* Returns: 0 (Always success)
311+
*/
312+
static int ksz_phylink_mac_enable_tx_lpi(struct phylink_config *config,
313+
u32 timer, bool tx_clock_stop)
314+
{
315+
return 0;
316+
}
317+
268318
static const struct phylink_mac_ops ksz88x3_phylink_mac_ops = {
269319
.mac_config = ksz88x3_phylink_mac_config,
270320
.mac_link_down = ksz_phylink_mac_link_down,
271321
.mac_link_up = ksz8_phylink_mac_link_up,
322+
.mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
323+
.mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
272324
};
273325

274326
static const struct phylink_mac_ops ksz8_phylink_mac_ops = {
275327
.mac_config = ksz_phylink_mac_config,
276328
.mac_link_down = ksz_phylink_mac_link_down,
277329
.mac_link_up = ksz8_phylink_mac_link_up,
330+
.mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
331+
.mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
278332
};
279333

280334
static const struct ksz_dev_ops ksz88xx_dev_ops = {
@@ -358,6 +412,8 @@ static const struct phylink_mac_ops ksz9477_phylink_mac_ops = {
358412
.mac_config = ksz_phylink_mac_config,
359413
.mac_link_down = ksz_phylink_mac_link_down,
360414
.mac_link_up = ksz9477_phylink_mac_link_up,
415+
.mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
416+
.mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
361417
};
362418

363419
static const struct ksz_dev_ops ksz9477_dev_ops = {
@@ -401,6 +457,8 @@ static const struct phylink_mac_ops lan937x_phylink_mac_ops = {
401457
.mac_config = ksz_phylink_mac_config,
402458
.mac_link_down = ksz_phylink_mac_link_down,
403459
.mac_link_up = ksz9477_phylink_mac_link_up,
460+
.mac_disable_tx_lpi = ksz_phylink_mac_disable_tx_lpi,
461+
.mac_enable_tx_lpi = ksz_phylink_mac_enable_tx_lpi,
404462
};
405463

406464
static const struct ksz_dev_ops lan937x_dev_ops = {
@@ -2016,6 +2074,18 @@ static void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
20162074

20172075
if (dev->dev_ops->get_caps)
20182076
dev->dev_ops->get_caps(dev, port, config);
2077+
2078+
if (ds->ops->support_eee && ds->ops->support_eee(ds, port)) {
2079+
memcpy(config->lpi_interfaces, config->supported_interfaces,
2080+
sizeof(config->lpi_interfaces));
2081+
2082+
config->lpi_capabilities = MAC_100FD;
2083+
if (dev->info->gbit_capable[port])
2084+
config->lpi_capabilities |= MAC_1000FD;
2085+
2086+
/* EEE is fully operational */
2087+
config->eee_enabled_default = true;
2088+
}
20192089
}
20202090

20212091
void ksz_r_mib_stats64(struct ksz_device *dev, int port)
@@ -3008,31 +3078,6 @@ static u32 ksz_get_phy_flags(struct dsa_switch *ds, int port)
30083078
if (!port)
30093079
return MICREL_KSZ8_P1_ERRATA;
30103080
break;
3011-
case KSZ8567_CHIP_ID:
3012-
/* KSZ8567R Errata DS80000752C Module 4 */
3013-
case KSZ8765_CHIP_ID:
3014-
case KSZ8794_CHIP_ID:
3015-
case KSZ8795_CHIP_ID:
3016-
/* KSZ879x/KSZ877x/KSZ876x Errata DS80000687C Module 2 */
3017-
case KSZ9477_CHIP_ID:
3018-
/* KSZ9477S Errata DS80000754A Module 4 */
3019-
case KSZ9567_CHIP_ID:
3020-
/* KSZ9567S Errata DS80000756A Module 4 */
3021-
case KSZ9896_CHIP_ID:
3022-
/* KSZ9896C Errata DS80000757A Module 3 */
3023-
case KSZ9897_CHIP_ID:
3024-
case LAN9646_CHIP_ID:
3025-
/* KSZ9897R Errata DS80000758C Module 4 */
3026-
/* Energy Efficient Ethernet (EEE) feature select must be manually disabled
3027-
* The EEE feature is enabled by default, but it is not fully
3028-
* operational. It must be manually disabled through register
3029-
* controls. If not disabled, the PHY ports can auto-negotiate
3030-
* to enable EEE, and this feature can cause link drops when
3031-
* linked to another device supporting EEE.
3032-
*
3033-
* The same item appears in the errata for all switches above.
3034-
*/
3035-
return MICREL_NO_EEE;
30363081
}
30373082

30383083
return 0;
@@ -3466,6 +3511,20 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
34663511
return -EOPNOTSUPP;
34673512
}
34683513

3514+
/**
3515+
* ksz_support_eee - Determine Energy Efficient Ethernet (EEE) support for a
3516+
* port
3517+
* @ds: Pointer to the DSA switch structure
3518+
* @port: Port number to check
3519+
*
3520+
* This function also documents devices where EEE was initially advertised but
3521+
* later withdrawn due to reliability issues, as described in official errata
3522+
* documents. These devices are explicitly listed to record known limitations,
3523+
* even if there is no technical necessity for runtime checks.
3524+
*
3525+
* Returns: true if the internal PHY on the given port supports fully
3526+
* operational EEE, false otherwise.
3527+
*/
34693528
static bool ksz_support_eee(struct dsa_switch *ds, int port)
34703529
{
34713530
struct ksz_device *dev = ds->priv;
@@ -3475,15 +3534,35 @@ static bool ksz_support_eee(struct dsa_switch *ds, int port)
34753534

34763535
switch (dev->chip_id) {
34773536
case KSZ8563_CHIP_ID:
3537+
case KSZ9563_CHIP_ID:
3538+
case KSZ9893_CHIP_ID:
3539+
return true;
34783540
case KSZ8567_CHIP_ID:
3541+
/* KSZ8567R Errata DS80000752C Module 4 */
3542+
case KSZ8765_CHIP_ID:
3543+
case KSZ8794_CHIP_ID:
3544+
case KSZ8795_CHIP_ID:
3545+
/* KSZ879x/KSZ877x/KSZ876x Errata DS80000687C Module 2 */
34793546
case KSZ9477_CHIP_ID:
3480-
case KSZ9563_CHIP_ID:
3547+
/* KSZ9477S Errata DS80000754A Module 4 */
34813548
case KSZ9567_CHIP_ID:
3482-
case KSZ9893_CHIP_ID:
3549+
/* KSZ9567S Errata DS80000756A Module 4 */
34833550
case KSZ9896_CHIP_ID:
3551+
/* KSZ9896C Errata DS80000757A Module 3 */
34843552
case KSZ9897_CHIP_ID:
34853553
case LAN9646_CHIP_ID:
3486-
return true;
3554+
/* KSZ9897R Errata DS80000758C Module 4 */
3555+
/* Energy Efficient Ethernet (EEE) feature select must be
3556+
* manually disabled
3557+
* The EEE feature is enabled by default, but it is not fully
3558+
* operational. It must be manually disabled through register
3559+
* controls. If not disabled, the PHY ports can auto-negotiate
3560+
* to enable EEE, and this feature can cause link drops when
3561+
* linked to another device supporting EEE.
3562+
*
3563+
* The same item appears in the errata for all switches above.
3564+
*/
3565+
break;
34873566
}
34883567

34893568
return false;

drivers/net/phy/micrel.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,12 +2027,6 @@ static int ksz9477_config_init(struct phy_device *phydev)
20272027
return err;
20282028
}
20292029

2030-
/* According to KSZ9477 Errata DS80000754C (Module 4) all EEE modes
2031-
* in this switch shall be regarded as broken.
2032-
*/
2033-
if (phydev->dev_flags & MICREL_NO_EEE)
2034-
phy_disable_eee(phydev);
2035-
20362030
return kszphy_config_init(phydev);
20372031
}
20382032

@@ -5705,7 +5699,6 @@ static struct phy_driver ksphy_driver[] = {
57055699
.handle_interrupt = kszphy_handle_interrupt,
57065700
.suspend = genphy_suspend,
57075701
.resume = ksz9477_resume,
5708-
.get_features = ksz9477_get_features,
57095702
} };
57105703

57115704
module_phy_driver(ksphy_driver);

include/linux/micrel_phy.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
#define MICREL_PHY_50MHZ_CLK BIT(0)
4545
#define MICREL_PHY_FXEN BIT(1)
4646
#define MICREL_KSZ8_P1_ERRATA BIT(2)
47-
#define MICREL_NO_EEE BIT(3)
4847

4948
#define MICREL_KSZ9021_EXTREG_CTRL 0xB
5049
#define MICREL_KSZ9021_EXTREG_DATA_WRITE 0xC

0 commit comments

Comments
 (0)