[net,PATCH v2] net: ks8851: Fix receiver error in 100BASE-TX mode following software power-down
From: Marek Vasut <hidden>
Date: 2026-09-05 13:03:35
Also in:
lkml
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
KSZ8851 errata sheet DS80000716D-page 4 Module 3 [1] states that, when issuing a software power-down (PMECR[1:0] = 10) followed by a power-on (PMECR[1:0] = 00), the receiver circuit can fail to start properly preventing communication. The Transmitter will still send data, but no data will be received. The errata sheet also includes a workaround, which states that, it is recommended that the software power-down feature not be used. Implement that workaround and drop the entry into software power-down mode. The ks8851_write_mac_addr() calls entry into normal power-on mode at the very beginning of the function, therefore dropping the second call to enter software power-down mode is sufficient here. The ks8851_net_stop() can only be called after ks8851_net_start() was already called, and ks8851_net_start() also makes the MAC enter normal power-on mode, therefore it is also fine to drop the call to enter software power-down mode from ks8851_net_stop(). This will lead to a slight increase in power consumption, but it also fixes a sporadic reliability problem on at least KSZ8851-16MLL, which is where the problem was reported and this fix was tested. [1] https://ww1.microchip.com/downloads/en/DeviceDoc/80000716D.pdf Fixes: 3ba81f3ece3c ("net: Micrel KS8851 SPI network driver") Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Marek Vasut <redacted> --- Cc: "David S. Miller" <davem@davemloft.net> Cc: Andrew Lunn <andrew+netdev@lunn.ch> Cc: Eric Dumazet <edumazet@google.com> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Paolo Abeni <pabeni@redhat.com> Cc: Ronald Wahl <redacted> Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Yicong Hui <redacted> Cc: kernel@dh-electronics.com Cc: linux-kernel@vger.kernel.org Cc: netdev@vger.kernel.org --- V2: - Add RB from Sebastian - Update ks8851_net_stop() description based on input from Jakub --- drivers/net/ethernet/micrel/ks8851_common.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c
index 4afbb40bc0e4a..d49f281c78676 100644
--- a/drivers/net/ethernet/micrel/ks8851_common.c
+++ b/drivers/net/ethernet/micrel/ks8851_common.c@@ -139,17 +139,14 @@ static int ks8851_write_mac_addr(struct net_device *dev) ks8851_set_powermode(ks, PMECR_PM_NORMAL); for (i = 0; i < ETH_ALEN; i += 2) { val = (dev->dev_addr[i] << 8) | dev->dev_addr[i + 1]; ks8851_wrreg16(ks, KS_MAR(i), val); } - if (!netif_running(dev)) - ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); - ks8851_unlock(ks); return 0; } /** * ks8851_read_mac_addr - read mac address from device registers
@@ -474,16 +471,15 @@ static int ks8851_net_open(struct net_device *dev) } /** * ks8851_net_stop - close network device * @dev: The device being closed. * * Called to close down a network device which has been active. Cancel any - * work, shutdown the RX and TX process and then place the chip into a low - * power state whilst it is not being used. + * work and shutdown the RX and TX process. */ static int ks8851_net_stop(struct net_device *dev) { struct ks8851_net *ks = netdev_priv(dev); netif_info(ks, ifdown, dev, "shutting down\n");
@@ -502,16 +498,14 @@ static int ks8851_net_stop(struct net_device *dev) ks8851_lock(ks); /* shutdown RX process */ ks8851_wrreg16(ks, KS_RXCR1, 0x0000); /* shutdown TX process */ ks8851_wrreg16(ks, KS_TXCR, 0x0000); - /* set powermode to soft power down to save power */ - ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); ks8851_unlock(ks); /* ensure any queued tx buffers are dumped */ while (!skb_queue_empty(&ks->txq)) { struct sk_buff *txb = skb_dequeue(&ks->txq); netif_dbg(ks, ifdown, ks->netdev,
--
2.53.0