[PATCH net v3] r8152: Use BMSR to detect the link state

From: Linmao Li

Date: Sun Oct 25 2026 - 21:24:33 EST


r8152 detects carrier from PLA_PHYSTATUS without reading BMSR, so
BMSR_LSTATUS can remain latched low after link up. Since
commit f6f2e946aa4d ("net: mii: Fix the Speed display when the network
cable is not connected"), the first speed query can then report
SPEED_UNKNOWN, which applications such as NetworkManager may cache
until the next carrier change.

Use BMSR_LSTATUS in set_carrier() so a latched link down can turn
carrier off after the link has recovered. If BMSR reports down but
PLA_PHYSTATUS reports up, reschedule the link work to read the current
state without waiting for another notification.

Tested on an RTL8153B: NetworkManager reported 1000 Mb/s after 3 of 3
rebinds, instead of an unknown speed.

Fixes: f6f2e946aa4d ("net: mii: Fix the Speed display when the network cable is not connected")
Cc: stable@xxxxxxxxxxxxxxx
Suggested-by: Hayes Wang <hayeswang@xxxxxxxxxxx>
Signed-off-by: Linmao Li <lilinmao@xxxxxxxxxx>
---
v3:
- Use Hayes's approach: detect carrier from a single BMSR read, so a
latched link down can turn carrier off even after the link has
recovered (Andrew), and reschedule the link work while
PLA_PHYSTATUS still reports up, so carrier up does not depend on
another notification (Hayes).
- Drop the runtime resume change.
- Tested on a net/main based kernel instead of a 6.6-based one. With
intr_callback() filtered to pass only link status changes, and the
first link check delayed until after the down and up notifications
from ethtool -r, 5 of 5 runs showed NO-CARRIER then LOWER_UP about
8 ms apart. With the PHY powered down for 10 s, the carrier stayed
off and the speed was unknown.

v2: https://lore.kernel.org/netdev/20261005105249.1281648-1-lilinmao@xxxxxxxxxx/
v1: https://lore.kernel.org/netdev/20260930113842.2640928-1-lilinmao@xxxxxxxxxx/

drivers/net/usb/r8152.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index af3d7dcb2f14..ae861eb6d9a9 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -6958,11 +6958,8 @@ static void set_carrier(struct r8152 *tp)
{
struct net_device *netdev = tp->netdev;
struct napi_struct *napi = &tp->napi;
- u16 speed;
-
- speed = rtl8152_get_speed(tp);

- if (speed & LINK_STATUS) {
+ if (r8152_mdio_read(tp, MII_BMSR) & BMSR_LSTATUS) {
if (!netif_carrier_ok(netdev)) {
tp->rtl_ops.enable(tp);
netif_stop_queue(netdev);
@@ -6988,6 +6985,11 @@ static void set_carrier(struct r8152 *tp)
tasklet_enable(&tp->tx_tl);
netif_info(tp, link, netdev, "carrier off\n");
}
+
+ if (rtl8152_get_speed(tp) & LINK_STATUS) {
+ set_bit(RTL8152_LINK_CHG, &tp->flags);
+ schedule_delayed_work(&tp->schedule, 0);
+ }
}
}

--
2.25.1