Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: spacemit: Check for netif_carrier_ok() in emac_stats_update()

Some PHYs stop the refclk for power saving, usually while link down.
This causes reading stats to time out.

Therefore, in emac_stats_update(), also don't update and reschedule if
!netif_carrier_ok(). But that means we could be missing later updates if
the link comes back up, so also reschedule when link up is detected in
emac_adjust_link().

While we're at it, improve the comments and error message prints around
this to reflect the better understanding of how this could happen.
Hopefully if this happens again on new hardware, these comments will
direct towards a solution.

Closes: https://lore.kernel.org/r/20260119141620.1318102-1-amadeus@jmu.edu.cn/
Fixes: bfec6d7f2001 ("net: spacemit: Add K1 Ethernet MAC")
Co-developed-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Signed-off-by: Vivian Wang <wangruikang@iscas.ac.cn>
Link: https://patch.msgid.link/20260123-k1-ethernet-clarify-stat-timeout-v3-1-93b9df627e87@iscas.ac.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Vivian Wang and committed by
Jakub Kicinski
2c849591 e2a9eeb6

+27 -7
+27 -7
drivers/net/ethernet/spacemit/k1_emac.c
··· 1099 1099 100, 10000); 1100 1100 1101 1101 if (ret) { 1102 - netdev_err(priv->ndev, "Read stat timeout\n"); 1102 + /* 1103 + * This could be caused by the PHY stopping its refclk even when 1104 + * the link is up, for power saving. See also comments in 1105 + * emac_stats_update(). 1106 + */ 1107 + dev_err_ratelimited(&priv->ndev->dev, 1108 + "Read stat timeout. PHY clock stopped?\n"); 1103 1109 return ret; 1104 1110 } 1105 1111 ··· 1153 1147 1154 1148 assert_spin_locked(&priv->stats_lock); 1155 1149 1156 - if (!netif_running(priv->ndev) || !netif_device_present(priv->ndev)) { 1157 - /* Not up, don't try to update */ 1150 + /* 1151 + * We can't read statistics if the interface is not up. Also, some PHYs 1152 + * stop their reference clocks for link down power saving, which also 1153 + * causes reading statistics to time out. Don't update and don't 1154 + * reschedule in these cases. 1155 + */ 1156 + if (!netif_running(priv->ndev) || 1157 + !netif_carrier_ok(priv->ndev) || 1158 + !netif_device_present(priv->ndev)) { 1158 1159 return; 1159 1160 } 1160 1161 1161 1162 for (i = 0; i < sizeof(priv->tx_stats) / sizeof(*tx_stats); i++) { 1162 1163 /* 1163 - * If reading stats times out, everything is broken and there's 1164 - * nothing we can do. Reading statistics also can't return an 1165 - * error, so just return without updating and without 1166 - * rescheduling. 1164 + * If reading stats times out anyway, the stat registers will be 1165 + * stuck, and we can't really recover from that. 1166 + * 1167 + * Reading statistics also can't return an error, so just return 1168 + * without updating and without rescheduling. 1167 1169 */ 1168 1170 if (emac_tx_read_stat_cnt(priv, i, &res)) 1169 1171 return; ··· 1650 1636 emac_wr(priv, MAC_GLOBAL_CONTROL, ctrl); 1651 1637 1652 1638 emac_set_fc_autoneg(priv); 1639 + 1640 + /* 1641 + * Reschedule stats updates now that link is up. See comments in 1642 + * emac_stats_update(). 1643 + */ 1644 + mod_timer(&priv->stats_timer, jiffies); 1653 1645 } 1654 1646 1655 1647 phy_print_status(phydev);