From nobody Mon Dec 15 22:43:40 2025 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 166FF72610 for ; Mon, 7 Jul 2025 15:32:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751902367; cv=none; b=gc0mFcdjYw0NWSgen2lI0Yf7zVYDAy1/ne50XC/J9Illi9uMkZtM+dSWolTtix0jyuvEb9gQA4i+74ALGDCzJQ4Q6GJVpiSqvz99suDQqahQ1/xuTyg5AL94nIQfZh7hhIpqko/OqQN6X1BK48bOlqh2P7z3Nd/z3RBgtORa1/I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751902367; c=relaxed/simple; bh=5Echb8zj2aHQG67ZuO+XMw2fUTv38gNoRuoKlbYv9do=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=EZvXq9dHUSx7OC9VD8Qd6Inbeui9rRPeELAd7NxCR+PNI9iZioNhI1Y1zkfAy59jSZ/Oc3hCTIgDX+t/a1Em3tzcHOqXFmwrz8Vvfh4+c62zKIIlvTHugCf0ttTbRZf+9eKWj1V5oJmhW8rnC6kcsU1PnXo4ApuW1uwjm6zj7TI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1uYnpb-0007aJ-Qr; Mon, 07 Jul 2025 17:32:35 +0200 Received: from dude04.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::ac]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1uYnpa-007GvT-0R; Mon, 07 Jul 2025 17:32:34 +0200 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1uYnpZ-004YFN-36; Mon, 07 Jul 2025 17:32:33 +0200 From: Oleksij Rempel To: Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, Russell King , netdev@vger.kernel.org, Andre Edich , Lukas Wunner Subject: [PATCH net v1 1/2] net: phy: enable polling when driver implements get_next_update_time Date: Mon, 7 Jul 2025 17:32:31 +0200 Message-Id: <20250707153232.1082819-2-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250707153232.1082819-1-o.rempel@pengutronix.de> References: <20250707153232.1082819-1-o.rempel@pengutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Make phylib=E2=80=99s state-machine timer run for drivers that provide get_next_update_time() but not update_stats(). phy_polling_mode() currently switches to polling only when either - the PHY runs in interrupt-less mode, or - the driver exposes update_stats() (needed by several statistics-gathering drivers). Upcoming support for adaptive polling in the SMSC LAN9512/LAN8700 family relies on get_next_update_time() alone, so the helper must also trigger polling for that callback. No in-tree drivers have required this until now, so the change does not alter existing behaviour. Fixes: 8bf47e4d7b87 ("net: phy: Add support for driver-specific next update= time") Signed-off-by: Oleksij Rempel --- include/linux/phy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/phy.h b/include/linux/phy.h index 74c1bcf64b3c..b37b981fc9be 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -1628,7 +1628,7 @@ static inline bool phy_polling_mode(struct phy_device= *phydev) if (phydev->drv->flags & PHY_POLL_CABLE_TEST) return true; =20 - if (phydev->drv->update_stats) + if (phydev->drv->update_stats || phydev->drv->get_next_update_time) return true; =20 return phydev->irq =3D=3D PHY_POLL; --=20 2.39.5 From nobody Mon Dec 15 22:43:40 2025 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91C6F881E for ; Mon, 7 Jul 2025 15:32:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751902367; cv=none; b=hx5fvSUTuOJfHcTKNrc0ZNoHMtQEdZ+SwhdyLHpxx58DuDrd+znxCCzmynjHT6MHM+NVRFe/6H+hargIfkfwb1XE/fEIaow2jeyQ3bL5GxyAZEQBnRZpFFYzN4lIifv+OYAeS/enPjAsau5UE4yu7rLwBDZo+t/CSOWqZWylvVY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1751902367; c=relaxed/simple; bh=IibsQJ2N3+FhROMlUInFcPRwAna8EUl6stk82qwvWN4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=UCwSSN4bi4GbiJmu7hecdRp2GF4NSfYj3D9Gjdu7h+yta3c3d8zl0uhoc2x9rh9tDN/n7d5r0bh4+3PKQN9zIc/B4kVn4bx64afCQtGUJBNxZHd9KUAnXVjO9p8KKgKWeI6HVrC2Uoolglgv66yJIwowyqUin2LdlkeuuYqEVgc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1uYnpb-0007aK-Qn; Mon, 07 Jul 2025 17:32:35 +0200 Received: from dude04.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::ac]) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1uYnpa-007GvW-0Z; Mon, 07 Jul 2025 17:32:34 +0200 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1uYnpa-004YFk-0E; Mon, 07 Jul 2025 17:32:34 +0200 From: Oleksij Rempel To: Andrew Lunn , Heiner Kallweit , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: Oleksij Rempel , Lukas Wunner , kernel@pengutronix.de, linux-kernel@vger.kernel.org, Russell King , netdev@vger.kernel.org, Andre Edich Subject: [PATCH net v1 2/2] net: phy: smsc: add adaptive polling to recover missed link-up on LAN8700 Date: Mon, 7 Jul 2025 17:32:32 +0200 Message-Id: <20250707153232.1082819-3-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250707153232.1082819-1-o.rempel@pengutronix.de> References: <20250707153232.1082819-1-o.rempel@pengutronix.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Fixe unreliable link detection on LAN8700 configured for 10 Mbit / half- or full-duplex against an autonegotiating partner and similar scenarios. The LAN8700 PHY (build in to LAN9512 and similar adapters) can fail to report a link-up event when it is forced to a fixed speed/duplex and the link partner still advertises autonegotiation. During link establishment the PHY raises several interrupts while the link is not yet up; once the link finally comes up no further interrupt is generated, so phylib never observes the transition and the kernel keeps the interface down even though ethtool shows the link as up. Mitigate this by combining interrupts with adaptive polling: - When the driver is running in pure polling mode it continues to poll once per second (unchanged). - With an IRQ present we now - poll every 30 s while the link is up (low overhead); - switch to a 1 s poll for up to 30 s after the last IRQ and while the link is down, ensuring we catch the final silent link-up. This patch depends on: - commit 8bf47e4d7b87 ("net: phy: Add support for driver-specific next update time") - part of this patch set ("net: phy: enable polling when driver implements get_next_update_time") Fixes: 1ce8b37241ed ("usbnet: smsc95xx: Forward PHY interrupts to PHY drive= r to avoid polling") Signed-off-by: Oleksij Rempel Cc: Lukas Wunner --- drivers/net/phy/smsc.c | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c index b6489da5cfcd..118aee834094 100644 --- a/drivers/net/phy/smsc.c +++ b/drivers/net/phy/smsc.c @@ -39,6 +39,17 @@ /* interval between phylib state machine runs in ms */ #define PHY_STATE_MACH_MS 1000 =20 +/* Poll every 1 s when we have no IRQ line. + * Matches the default phylib state-machine cadence. + */ +#define SMSC_NOIRQ_POLLING_INTERVAL secs_to_jiffies(1) +/* When IRQs are present and the link is already up, + * fall back to a light 30 s poll: + * =E2=80=93 avoids needless wake-ups for power-management purposes + * =E2=80=93 still short enough to recover if the final link-up IRQ was l= ost + */ +#define SMSC_IRQ_POLLING_INTERVAL secs_to_jiffies(30) + struct smsc_hw_stat { const char *string; u8 reg; @@ -54,6 +65,7 @@ struct smsc_phy_priv { unsigned int edpd_mode_set_by_user:1; unsigned int edpd_max_wait_ms; bool wol_arp; + unsigned long last_irq; }; =20 static int smsc_phy_ack_interrupt(struct phy_device *phydev) @@ -100,6 +112,7 @@ static int smsc_phy_config_edpd(struct phy_device *phyd= ev) =20 irqreturn_t smsc_phy_handle_interrupt(struct phy_device *phydev) { + struct smsc_phy_priv *priv =3D phydev->priv; int irq_status; =20 irq_status =3D phy_read(phydev, MII_LAN83C185_ISF); @@ -113,6 +126,8 @@ irqreturn_t smsc_phy_handle_interrupt(struct phy_device= *phydev) if (!(irq_status & MII_LAN83C185_ISF_INT_PHYLIB_EVENTS)) return IRQ_NONE; =20 + priv->last_irq =3D jiffies; + phy_trigger_machine(phydev); =20 return IRQ_HANDLED; @@ -684,6 +699,33 @@ int smsc_phy_probe(struct phy_device *phydev) } EXPORT_SYMBOL_GPL(smsc_phy_probe); =20 +static unsigned int smsc_phy_get_next_update(struct phy_device *phydev) +{ + struct smsc_phy_priv *priv =3D phydev->priv; + + /* If interrupts are disabled, fall back to default polling */ + if (phydev->irq =3D=3D PHY_POLL) + return SMSC_NOIRQ_POLLING_INTERVAL; + + /* The PHY sometimes drops the *final* link-up IRQ when we run + * with autoneg OFF (10 Mbps HD/FD) against an autonegotiating + * partner: we see several =E2=80=9Clink down=E2=80=9D IRQs, none for =E2= =80=9Clink up=E2=80=9D. + * + * Work-around philosophy: + * - If the link is already up, the hazard is past, so we + * revert to a relaxed 30 s poll to save power. + * - Otherwise we stay in a tighter polling loop for up to one + * full interval after the last IRQ in case the crucial + * link-up IRQ was lost. Empirically 5 s is enough but we + * keep 30 s to be extra conservative. + */ + if (!priv->last_irq || phydev->link || + time_is_before_jiffies(priv->last_irq + SMSC_IRQ_POLLING_INTERVAL)) + return SMSC_IRQ_POLLING_INTERVAL; + + return SMSC_NOIRQ_POLLING_INTERVAL; +} + static struct phy_driver smsc_phy_driver[] =3D { { .phy_id =3D 0x0007c0a0, /* OUI=3D0x00800f, Model#=3D0x0a */ @@ -749,6 +791,7 @@ static struct phy_driver smsc_phy_driver[] =3D { /* IRQ related */ .config_intr =3D smsc_phy_config_intr, .handle_interrupt =3D smsc_phy_handle_interrupt, + .get_next_update_time =3D smsc_phy_get_next_update, =20 /* Statistics */ .get_sset_count =3D smsc_get_sset_count, --=20 2.39.5