From nobody Sun Feb 8 18:39:23 2026 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 58F04221732 for ; Mon, 10 Mar 2025 11:57:48 +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=1741607874; cv=none; b=uYB9X3llDl4CHWw9McWRdKFj7cjp2LbFvwUicCcR4nFQgGzUmDQACz+c/2lAdN84/I2VPks9Pf//xPOlmYwDasJh9u5iuqAZvfTOxDeYyPJu/wF9pE2MA+tB5kBgDW1V+5EVLU6rZ4RYaQKCjB7xYo6qKpW155gocovtKTy8DNc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741607874; c=relaxed/simple; bh=rpdX7aj0HeoBb3Bkm8CI6Tb5jcJOsdsxyNnAtGWhUL8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ThqsDfWRM7GLi9hTUqEtevCvjOxEiVzYM6lp8OZ1i3Ak+XxFohujGl3CYE4pChU+4PDWcddIsmcyJJFAcCUAWPClCwSDQPEMxrV4t5Rv9Pkkd9msZtMCN0TsQJccELNYnogNEnKeL3OpXOfl014u6iNJUOljIere7Pv7jA/Mgp0= 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 1trblL-0000S4-Co; Mon, 10 Mar 2025 12:57:39 +0100 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 1trblK-004zZz-0E; Mon, 10 Mar 2025 12:57:38 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1trblK-003I1L-00; Mon, 10 Mar 2025 12:57:38 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Woojung Huh , Andrew Lunn , Russell King , Thangaraj Samynathan , Rengarajan Sundararajan Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, UNGLinuxDriver@microchip.com, Phil Elwell Subject: [PATCH net-next v3 1/7] net: usb: lan78xx: Convert to PHYlink for improved PHY and MAC management Date: Mon, 10 Mar 2025 12:57:31 +0100 Message-Id: <20250310115737.784047-2-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250310115737.784047-1-o.rempel@pengutronix.de> References: <20250310115737.784047-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-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 Content-Type: text/plain; charset="utf-8" Convert the LAN78xx driver to use the PHYlink framework for managing PHY and MAC interactions. Key changes include: - Replace direct PHY operations with phylink equivalents (e.g., phylink_start, phylink_stop). - Introduce lan78xx_phylink_setup for phylink initialization and configuration. - Add phylink MAC operations (lan78xx_mac_config, lan78xx_mac_link_down, lan78xx_mac_link_up) for managing link settings and flow control. - Remove redundant and now phylink-managed functions like `lan78xx_link_status_change`. Signed-off-by: Oleksij Rempel --- changes v3: - lan78xx_phy_init: drop phy_suspend() - lan78xx_phylink_setup: use phy_interface_set_rgmii() changes v2: - lan78xx_mac_config: remove unused rgmii_id - lan78xx_mac_config: PHY_INTERFACE_MODE_RGMII* variants - lan78xx_mac_config: remove auto-speed and duplex configuration - lan78xx_phylink_setup: set link_interface to PHY_INTERFACE_MODE_RGMII_ID instead of PHY_INTERFACE_MODE_NA. - lan78xx_phy_init: use phylink_set_fixed_link() instead of allocating fixed PHY. - lan78xx_configure_usb: move function values to separate variables --- drivers/net/usb/lan78xx.c | 559 ++++++++++++++++++++------------------ 1 file changed, 293 insertions(+), 266 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 137adf6d5b08..63b5406bfecb 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -384,7 +385,7 @@ struct skb_data { /* skb->cb is one of these */ #define EVENT_RX_HALT 1 #define EVENT_RX_MEMORY 2 #define EVENT_STS_SPLIT 3 -#define EVENT_LINK_RESET 4 +#define EVENT_PHY_INT_ACK 4 #define EVENT_RX_PAUSED 5 #define EVENT_DEV_WAKING 6 #define EVENT_DEV_ASLEEP 7 @@ -470,6 +471,9 @@ struct lan78xx_net { struct statstage stats; =20 struct irq_domain_data domain_data; + + struct phylink *phylink; + struct phylink_config phylink_config; }; =20 /* use ethtool to change the level for any given device */ @@ -1554,40 +1558,6 @@ static void lan78xx_set_multicast(struct net_device = *netdev) schedule_work(&pdata->set_multicast); } =20 -static int lan78xx_update_flowcontrol(struct lan78xx_net *dev, u8 duplex, - u16 lcladv, u16 rmtadv) -{ - u32 flow =3D 0, fct_flow =3D 0; - u8 cap; - - if (dev->fc_autoneg) - cap =3D mii_resolve_flowctrl_fdx(lcladv, rmtadv); - else - cap =3D dev->fc_request_control; - - if (cap & FLOW_CTRL_TX) - flow |=3D (FLOW_CR_TX_FCEN_ | 0xFFFF); - - if (cap & FLOW_CTRL_RX) - flow |=3D FLOW_CR_RX_FCEN_; - - if (dev->udev->speed =3D=3D USB_SPEED_SUPER) - fct_flow =3D FLOW_CTRL_THRESHOLD(FLOW_ON_SS, FLOW_OFF_SS); - else if (dev->udev->speed =3D=3D USB_SPEED_HIGH) - fct_flow =3D FLOW_CTRL_THRESHOLD(FLOW_ON_HS, FLOW_OFF_HS); - - netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s", - (cap & FLOW_CTRL_RX ? "enabled" : "disabled"), - (cap & FLOW_CTRL_TX ? "enabled" : "disabled")); - - lan78xx_write_reg(dev, FCT_FLOW, fct_flow); - - /* threshold value should be set before enabling flow */ - lan78xx_write_reg(dev, FLOW, flow); - - return 0; -} - static void lan78xx_rx_urb_submit_all(struct lan78xx_net *dev); =20 static int lan78xx_mac_reset(struct lan78xx_net *dev) @@ -1636,99 +1606,10 @@ static int lan78xx_mac_reset(struct lan78xx_net *de= v) return ret; } =20 -static int lan78xx_link_reset(struct lan78xx_net *dev) +static int lan78xx_phy_int_ack(struct lan78xx_net *dev) { - struct phy_device *phydev =3D dev->net->phydev; - struct ethtool_link_ksettings ecmd; - int ladv, radv, ret, link; - u32 buf; - /* clear LAN78xx interrupt status */ - ret =3D lan78xx_write_reg(dev, INT_STS, INT_STS_PHY_INT_); - if (unlikely(ret < 0)) - return ret; - - mutex_lock(&phydev->lock); - phy_read_status(phydev); - link =3D phydev->link; - mutex_unlock(&phydev->lock); - - if (!link && dev->link_on) { - dev->link_on =3D false; - - /* reset MAC */ - ret =3D lan78xx_mac_reset(dev); - if (ret < 0) - return ret; - - del_timer(&dev->stat_monitor); - } else if (link && !dev->link_on) { - dev->link_on =3D true; - - phy_ethtool_ksettings_get(phydev, &ecmd); - - if (dev->udev->speed =3D=3D USB_SPEED_SUPER) { - if (ecmd.base.speed =3D=3D 1000) { - /* disable U2 */ - ret =3D lan78xx_read_reg(dev, USB_CFG1, &buf); - if (ret < 0) - return ret; - buf &=3D ~USB_CFG1_DEV_U2_INIT_EN_; - ret =3D lan78xx_write_reg(dev, USB_CFG1, buf); - if (ret < 0) - return ret; - /* enable U1 */ - ret =3D lan78xx_read_reg(dev, USB_CFG1, &buf); - if (ret < 0) - return ret; - buf |=3D USB_CFG1_DEV_U1_INIT_EN_; - ret =3D lan78xx_write_reg(dev, USB_CFG1, buf); - if (ret < 0) - return ret; - } else { - /* enable U1 & U2 */ - ret =3D lan78xx_read_reg(dev, USB_CFG1, &buf); - if (ret < 0) - return ret; - buf |=3D USB_CFG1_DEV_U2_INIT_EN_; - buf |=3D USB_CFG1_DEV_U1_INIT_EN_; - ret =3D lan78xx_write_reg(dev, USB_CFG1, buf); - if (ret < 0) - return ret; - } - } - - ladv =3D phy_read(phydev, MII_ADVERTISE); - if (ladv < 0) - return ladv; - - radv =3D phy_read(phydev, MII_LPA); - if (radv < 0) - return radv; - - netif_dbg(dev, link, dev->net, - "speed: %u duplex: %d anadv: 0x%04x anlpa: 0x%04x", - ecmd.base.speed, ecmd.base.duplex, ladv, radv); - - ret =3D lan78xx_update_flowcontrol(dev, ecmd.base.duplex, ladv, - radv); - if (ret < 0) - return ret; - - if (!timer_pending(&dev->stat_monitor)) { - dev->delta =3D 1; - mod_timer(&dev->stat_monitor, - jiffies + STAT_UPDATE_TIMER); - } - - lan78xx_rx_urb_submit_all(dev); - - local_bh_disable(); - napi_schedule(&dev->napi); - local_bh_enable(); - } - - return 0; + return lan78xx_write_reg(dev, INT_STS, INT_STS_PHY_INT_); } =20 /* some work can't be done in tasklets, so we use keventd @@ -1757,7 +1638,7 @@ static void lan78xx_status(struct lan78xx_net *dev, s= truct urb *urb) =20 if (intdata & INT_ENP_PHY_INT) { netif_dbg(dev, link, dev->net, "PHY INTR: 0x%08x\n", intdata); - lan78xx_defer_kevent(dev, EVENT_LINK_RESET); + lan78xx_defer_kevent(dev, EVENT_PHY_INT_ACK); =20 if (dev->domain_data.phyirq > 0) generic_handle_irq_safe(dev->domain_data.phyirq); @@ -2356,26 +2237,6 @@ static void lan78xx_remove_mdio(struct lan78xx_net *= dev) mdiobus_free(dev->mdiobus); } =20 -static void lan78xx_link_status_change(struct net_device *net) -{ - struct lan78xx_net *dev =3D netdev_priv(net); - struct phy_device *phydev =3D net->phydev; - u32 data; - int ret; - - ret =3D lan78xx_read_reg(dev, MAC_CR, &data); - if (ret < 0) - return; - - if (phydev->enable_tx_lpi) - data |=3D MAC_CR_EEE_EN_; - else - data &=3D ~MAC_CR_EEE_EN_; - lan78xx_write_reg(dev, MAC_CR, data); - - phy_print_status(phydev); -} - static int irq_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { @@ -2508,27 +2369,211 @@ static void lan78xx_remove_irq_domain(struct lan78= xx_net *dev) dev->domain_data.irqdomain =3D NULL; } =20 -static struct phy_device *lan7801_phy_init(struct lan78xx_net *dev) +static void lan78xx_mac_config(struct phylink_config *config, unsigned int= mode, + const struct phylink_link_state *state) { - u32 buf; + struct net_device *net =3D to_net_dev(config->dev); + struct lan78xx_net *dev =3D netdev_priv(net); + u32 mac_cr =3D 0; + int ret; + + /* Check if the mode is supported */ + if (mode !=3D MLO_AN_FIXED && mode !=3D MLO_AN_PHY) { + netdev_err(net, "Unsupported negotiation mode: %u\n", mode); + return; + } + + switch (state->interface) { + case PHY_INTERFACE_MODE_INTERNAL: + case PHY_INTERFACE_MODE_GMII: + mac_cr |=3D MAC_CR_GMII_EN_; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_TXID: + case PHY_INTERFACE_MODE_RGMII_RXID: + break; + default: + netdev_warn(net, "Unsupported interface mode: %d\n", + state->interface); + return; + } + + ret =3D lan78xx_update_reg(dev, MAC_CR, MAC_CR_GMII_EN_, mac_cr); + if (ret < 0) + netdev_err(net, "Failed to config MAC with error %pe\n", + ERR_PTR(ret)); +} + +static void lan78xx_mac_link_down(struct phylink_config *config, + unsigned int mode, phy_interface_t interface) +{ + struct net_device *net =3D to_net_dev(config->dev); + struct lan78xx_net *dev =3D netdev_priv(net); + int ret; + + /* MAC reset will not de-assert TXEN/RXEN, we need to stop them + * manually before reset. TX and RX should be disabled before running + * link_up sequence. + */ + ret =3D lan78xx_stop_tx_path(dev); + if (ret < 0) + goto link_down_fail; + + ret =3D lan78xx_stop_rx_path(dev); + if (ret < 0) + goto link_down_fail; + + /* MAC reset seems to not affect MAC configuration, no idea if it is + * really needed, but it was done in previous driver version. So, leave + * it here. + */ + ret =3D lan78xx_mac_reset(dev); + if (ret < 0) + goto link_down_fail; + + return; + +link_down_fail: + netdev_err(dev->net, "Failed to set MAC down with error %pe\n", + ERR_PTR(ret)); +} + +static int lan78xx_configure_usb(struct lan78xx_net *dev, int speed) +{ + u32 mask, val; + int ret; + + /* Return early if USB speed is not SuperSpeed */ + if (dev->udev->speed !=3D USB_SPEED_SUPER) + return 0; + + /* Update U1 and U2 settings based on speed */ + if (speed !=3D SPEED_1000) { + mask =3D USB_CFG1_DEV_U2_INIT_EN_ | USB_CFG1_DEV_U1_INIT_EN_; + val =3D USB_CFG1_DEV_U2_INIT_EN_ | USB_CFG1_DEV_U1_INIT_EN_; + return lan78xx_update_reg(dev, USB_CFG1, mask, val); + } + + /* For 1000 Mbps: disable U2 and enable U1 */ + mask =3D USB_CFG1_DEV_U2_INIT_EN_; + val =3D 0; + ret =3D lan78xx_update_reg(dev, USB_CFG1, mask, val); + if (ret < 0) + return ret; + + mask =3D USB_CFG1_DEV_U1_INIT_EN_; + val =3D USB_CFG1_DEV_U1_INIT_EN_; + return lan78xx_update_reg(dev, USB_CFG1, mask, val); +} + +static int lan78xx_configure_flowcontrol(struct lan78xx_net *dev, + bool tx_pause, bool rx_pause) +{ + u32 flow =3D 0, fct_flow =3D 0; int ret; - struct fixed_phy_status fphy_status =3D { - .link =3D 1, - .speed =3D SPEED_1000, - .duplex =3D DUPLEX_FULL, - }; + + if (tx_pause) + flow |=3D (FLOW_CR_TX_FCEN_ | 0xFFFF); + + if (rx_pause) + flow |=3D FLOW_CR_RX_FCEN_; + + if (dev->udev->speed =3D=3D USB_SPEED_SUPER) + fct_flow =3D FLOW_CTRL_THRESHOLD(FLOW_ON_SS, FLOW_OFF_SS); + else if (dev->udev->speed =3D=3D USB_SPEED_HIGH) + fct_flow =3D FLOW_CTRL_THRESHOLD(FLOW_ON_HS, FLOW_OFF_HS); + + ret =3D lan78xx_write_reg(dev, FCT_FLOW, fct_flow); + if (ret < 0) + return ret; + + /* threshold value should be set before enabling flow */ + return lan78xx_write_reg(dev, FLOW, flow); +} + +static void lan78xx_mac_link_up(struct phylink_config *config, + struct phy_device *phy, + unsigned int mode, phy_interface_t interface, + int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + struct net_device *net =3D to_net_dev(config->dev); + struct lan78xx_net *dev =3D netdev_priv(net); + u32 mac_cr =3D 0; + int ret; + + switch (speed) { + case SPEED_1000: + mac_cr |=3D MAC_CR_SPEED_1000_; + break; + case SPEED_100: + mac_cr |=3D MAC_CR_SPEED_100_; + break; + case SPEED_10: + mac_cr |=3D MAC_CR_SPEED_10_; + break; + default: + netdev_err(dev->net, "Unsupported speed %d\n", speed); + return; + } + + if (duplex =3D=3D DUPLEX_FULL) + mac_cr |=3D MAC_CR_FULL_DUPLEX_; + + /* make sure TXEN and RXEN are disabled before reconfiguring MAC */ + ret =3D lan78xx_update_reg(dev, MAC_CR, MAC_CR_SPEED_MASK_ | + MAC_CR_FULL_DUPLEX_ | MAC_CR_EEE_EN_, mac_cr); + if (ret < 0) + goto link_up_fail; + + ret =3D lan78xx_configure_flowcontrol(dev, tx_pause, rx_pause); + if (ret < 0) + goto link_up_fail; + + ret =3D lan78xx_configure_usb(dev, speed); + if (ret < 0) + goto link_up_fail; + + lan78xx_rx_urb_submit_all(dev); + + ret =3D lan78xx_flush_rx_fifo(dev); + if (ret < 0) + goto link_up_fail; + + ret =3D lan78xx_flush_tx_fifo(dev); + if (ret < 0) + goto link_up_fail; + + ret =3D lan78xx_start_tx_path(dev); + if (ret < 0) + goto link_up_fail; + + ret =3D lan78xx_start_rx_path(dev); + if (ret < 0) + goto link_up_fail; + + return; +link_up_fail: + netdev_err(dev->net, "Failed to set MAC up with error %pe\n", + ERR_PTR(ret)); +} + +static const struct phylink_mac_ops lan78xx_phylink_mac_ops =3D { + .mac_config =3D lan78xx_mac_config, + .mac_link_down =3D lan78xx_mac_link_down, + .mac_link_up =3D lan78xx_mac_link_up, +}; + +static struct phy_device *lan7801_phy_init(struct lan78xx_net *dev) +{ struct phy_device *phydev; + int ret; + u32 buf; =20 phydev =3D phy_find_first(dev->mdiobus); if (!phydev) { - netdev_dbg(dev->net, "PHY Not Found!! Registering Fixed PHY\n"); - phydev =3D fixed_phy_register(PHY_POLL, &fphy_status, NULL); - if (IS_ERR(phydev)) { - netdev_err(dev->net, "No PHY/fixed_PHY found\n"); - return NULL; - } - netdev_dbg(dev->net, "Registered FIXED PHY\n"); - dev->interface =3D PHY_INTERFACE_MODE_RGMII; + netdev_dbg(dev->net, "PHY Not Found!! Forcing RGMII configuration\n"); ret =3D lan78xx_write_reg(dev, MAC_RGMII_ID, MAC_RGMII_ID_TXC_DELAY_EN_); ret =3D lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00); @@ -2541,7 +2586,7 @@ static struct phy_device *lan7801_phy_init(struct lan= 78xx_net *dev) netdev_err(dev->net, "no PHY driver found\n"); return NULL; } - dev->interface =3D PHY_INTERFACE_MODE_RGMII_ID; + phydev->interface =3D PHY_INTERFACE_MODE_RGMII_ID; /* The PHY driver is responsible to configure proper RGMII * interface delays. Disable RGMII delays on MAC side. */ @@ -2552,20 +2597,64 @@ static struct phy_device *lan7801_phy_init(struct l= an78xx_net *dev) return phydev; } =20 +static int lan78xx_phylink_setup(struct lan78xx_net *dev) +{ + struct phylink_config *pc =3D &dev->phylink_config; + phy_interface_t link_interface; + struct phylink *phylink; + + pc->dev =3D &dev->net->dev; + pc->type =3D PHYLINK_NETDEV; + pc->mac_capabilities =3D MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10 | + MAC_100 | MAC_1000FD; + pc->mac_managed_pm =3D true; + + if (dev->chipid =3D=3D ID_REV_CHIP_ID_7801_) { + phy_interface_set_rgmii(pc->supported_interfaces); + link_interface =3D PHY_INTERFACE_MODE_RGMII_ID; + } else { + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + pc->supported_interfaces); + link_interface =3D PHY_INTERFACE_MODE_INTERNAL; + } + + phylink =3D phylink_create(pc, dev->net->dev.fwnode, + link_interface, &lan78xx_phylink_mac_ops); + if (IS_ERR(phylink)) + return PTR_ERR(phylink); + + dev->phylink =3D phylink; + + return 0; +} + static int lan78xx_phy_init(struct lan78xx_net *dev) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(fc) =3D { 0, }; - int ret; - u32 mii_adv; struct phy_device *phydev; + int ret; =20 switch (dev->chipid) { case ID_REV_CHIP_ID_7801_: phydev =3D lan7801_phy_init(dev); + /* If no PHY found, set fixed link, probably there is no + * device or some kind of different device like switch. + * For example: EVB-KSZ9897-1 (KSZ9897 switch evaluation board + * with LAN7801 & KSZ9031) + */ if (!phydev) { - netdev_err(dev->net, "lan7801: PHY Init Failed"); - return -EIO; + struct phylink_link_state state =3D { + .speed =3D SPEED_1000, + .duplex =3D DUPLEX_FULL, + .interface =3D PHY_INTERFACE_MODE_RGMII, + }; + + ret =3D phylink_set_fixed_link(dev->phylink, &state); + if (ret) + netdev_err(dev->net, "Could not set fixed link\n"); + + return ret; } + break; =20 case ID_REV_CHIP_ID_7800_: @@ -2576,7 +2665,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) return -EIO; } phydev->is_internal =3D true; - dev->interface =3D PHY_INTERFACE_MODE_GMII; + phydev->interface =3D PHY_INTERFACE_MODE_GMII; break; =20 default: @@ -2591,37 +2680,13 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) phydev->irq =3D PHY_POLL; netdev_dbg(dev->net, "phydev->irq =3D %d\n", phydev->irq); =20 - /* set to AUTOMDIX */ - phydev->mdix =3D ETH_TP_MDI_AUTO; - - ret =3D phy_connect_direct(dev->net, phydev, - lan78xx_link_status_change, - dev->interface); + ret =3D phylink_connect_phy(dev->phylink, phydev); if (ret) { netdev_err(dev->net, "can't attach PHY to %s\n", dev->mdiobus->id); - if (dev->chipid =3D=3D ID_REV_CHIP_ID_7801_) { - if (phy_is_pseudo_fixed_link(phydev)) { - fixed_phy_unregister(phydev); - phy_device_free(phydev); - } - } return -EIO; } =20 - /* MAC doesn't support 1000T Half */ - phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); - - /* support both flow controls */ - dev->fc_request_control =3D (FLOW_CTRL_RX | FLOW_CTRL_TX); - linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, - phydev->advertising); - linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, - phydev->advertising); - mii_adv =3D (u32)mii_advertise_flowctrl(dev->fc_request_control); - mii_adv_to_linkmode_adv_t(fc, mii_adv); - linkmode_or(phydev->advertising, fc, phydev->advertising); - phy_support_eee(phydev); =20 if (phydev->mdio.dev.of_node) { @@ -2646,10 +2711,6 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) } } =20 - genphy_config_aneg(phydev); - - dev->fc_autoneg =3D phydev->autoneg; - return 0; } =20 @@ -2989,7 +3050,6 @@ static int lan78xx_reset(struct lan78xx_net *dev) unsigned long timeout; int ret; u32 buf; - u8 sig; =20 ret =3D lan78xx_read_reg(dev, HW_CFG, &buf); if (ret < 0) @@ -3146,22 +3206,12 @@ static int lan78xx_reset(struct lan78xx_net *dev) if (ret < 0) return ret; =20 + buf &=3D ~(MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_); + /* LAN7801 only has RGMII mode */ - if (dev->chipid =3D=3D ID_REV_CHIP_ID_7801_) { + if (dev->chipid =3D=3D ID_REV_CHIP_ID_7801_) buf &=3D ~MAC_CR_GMII_EN_; - /* Enable Auto Duplex and Auto speed */ - buf |=3D MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_; - } =20 - if (dev->chipid =3D=3D ID_REV_CHIP_ID_7800_ || - dev->chipid =3D=3D ID_REV_CHIP_ID_7850_) { - ret =3D lan78xx_read_raw_eeprom(dev, 0, 1, &sig); - if (!ret && sig !=3D EEPROM_INDICATOR) { - /* Implies there is no external eeprom. Set mac speed */ - netdev_info(dev->net, "No External EEPROM. Setting MAC Speed\n"); - buf |=3D MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_; - } - } ret =3D lan78xx_write_reg(dev, MAC_CR, buf); if (ret < 0) return ret; @@ -3211,9 +3261,11 @@ static int lan78xx_open(struct net_device *net) =20 mutex_lock(&dev->dev_mutex); =20 - phy_start(net->phydev); + lan78xx_init_stats(dev); + + napi_enable(&dev->napi); =20 - netif_dbg(dev, ifup, dev->net, "phy initialised successfully"); + set_bit(EVENT_DEV_OPEN, &dev->flags); =20 /* for Link Check */ if (dev->urb_intr) { @@ -3225,31 +3277,9 @@ static int lan78xx_open(struct net_device *net) } } =20 - ret =3D lan78xx_flush_rx_fifo(dev); - if (ret < 0) - goto done; - ret =3D lan78xx_flush_tx_fifo(dev); - if (ret < 0) - goto done; - - ret =3D lan78xx_start_tx_path(dev); - if (ret < 0) - goto done; - ret =3D lan78xx_start_rx_path(dev); - if (ret < 0) - goto done; - - lan78xx_init_stats(dev); - - set_bit(EVENT_DEV_OPEN, &dev->flags); + phylink_start(dev->phylink); =20 netif_start_queue(net); - - dev->link_on =3D false; - - napi_enable(&dev->napi); - - lan78xx_defer_kevent(dev, EVENT_LINK_RESET); done: mutex_unlock(&dev->dev_mutex); =20 @@ -3317,12 +3347,7 @@ static int lan78xx_stop(struct net_device *net) net->stats.rx_packets, net->stats.tx_packets, net->stats.rx_errors, net->stats.tx_errors); =20 - /* ignore errors that occur stopping the Tx and Rx data paths */ - lan78xx_stop_tx_path(dev); - lan78xx_stop_rx_path(dev); - - if (net->phydev) - phy_stop(net->phydev); + phylink_stop(dev->phylink); =20 usb_kill_urb(dev->urb_intr); =20 @@ -3332,7 +3357,7 @@ static int lan78xx_stop(struct net_device *net) */ clear_bit(EVENT_TX_HALT, &dev->flags); clear_bit(EVENT_RX_HALT, &dev->flags); - clear_bit(EVENT_LINK_RESET, &dev->flags); + clear_bit(EVENT_PHY_INT_ACK, &dev->flags); clear_bit(EVENT_STAT_UPDATE, &dev->flags); =20 cancel_delayed_work_sync(&dev->wq); @@ -4256,13 +4281,13 @@ static void lan78xx_delayedwork(struct work_struct = *work) } } =20 - if (test_bit(EVENT_LINK_RESET, &dev->flags)) { + if (test_bit(EVENT_PHY_INT_ACK, &dev->flags)) { int ret =3D 0; =20 - clear_bit(EVENT_LINK_RESET, &dev->flags); - if (lan78xx_link_reset(dev) < 0) { - netdev_info(dev->net, "link reset failed (%d)\n", - ret); + clear_bit(EVENT_PHY_INT_ACK, &dev->flags); + if (lan78xx_phy_int_ack(dev) < 0) { + netdev_info(dev->net, "PHY INT ack failed (%pe)\n", + ERR_PTR(ret)); } } =20 @@ -4337,32 +4362,29 @@ static void lan78xx_disconnect(struct usb_interface= *intf) struct lan78xx_net *dev; struct usb_device *udev; struct net_device *net; - struct phy_device *phydev; =20 dev =3D usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); if (!dev) return; =20 - netif_napi_del(&dev->napi); - udev =3D interface_to_usbdev(intf); net =3D dev->net; =20 + rtnl_lock(); + phylink_stop(dev->phylink); + phylink_disconnect_phy(dev->phylink); + rtnl_unlock(); + + netif_napi_del(&dev->napi); + unregister_netdev(net); =20 timer_shutdown_sync(&dev->stat_monitor); set_bit(EVENT_DEV_DISCONNECT, &dev->flags); cancel_delayed_work_sync(&dev->wq); =20 - phydev =3D net->phydev; - - phy_disconnect(net->phydev); - - if (phy_is_pseudo_fixed_link(phydev)) { - fixed_phy_unregister(phydev); - phy_device_free(phydev); - } + phylink_destroy(dev->phylink); =20 usb_scuttle_anchored_urbs(&dev->deferred); =20 @@ -4446,7 +4468,6 @@ static int lan78xx_probe(struct usb_interface *intf, goto out1; } =20 - /* netdev_printk() needs this */ SET_NETDEV_DEV(netdev, &intf->dev); =20 dev =3D netdev_priv(netdev); @@ -4558,14 +4579,18 @@ static int lan78xx_probe(struct usb_interface *intf, /* driver requires remote-wakeup capability during autosuspend. */ intf->needs_remote_wakeup =3D 1; =20 - ret =3D lan78xx_phy_init(dev); + ret =3D lan78xx_phylink_setup(dev); if (ret < 0) goto free_urbs; =20 + ret =3D lan78xx_phy_init(dev); + if (ret < 0) + goto destroy_phylink; + ret =3D register_netdev(netdev); if (ret !=3D 0) { netif_err(dev, probe, netdev, "couldn't register the device\n"); - goto out8; + goto disconnect_phy; } =20 usb_set_intfdata(intf, dev); @@ -4580,8 +4605,10 @@ static int lan78xx_probe(struct usb_interface *intf, =20 return 0; =20 -out8: - phy_disconnect(netdev->phydev); +disconnect_phy: + phylink_disconnect_phy(dev->phylink); +destroy_phylink: + phylink_destroy(dev->phylink); free_urbs: usb_free_urb(dev->urb_intr); out5: @@ -5143,7 +5170,7 @@ static int lan78xx_reset_resume(struct usb_interface = *intf) if (ret < 0) return ret; =20 - phy_start(dev->net->phydev); + phylink_start(dev->phylink); =20 ret =3D lan78xx_resume(intf); =20 --=20 2.39.5 From nobody Sun Feb 8 18:39:23 2026 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 7AEE9225798 for ; Mon, 10 Mar 2025 11:57:48 +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=1741607872; cv=none; b=PJxg83IiuCdJlDaZuVji1GAL2uTI6TDEUIPr8I6EGyEAiIvyHkZiCmoHF/3MF6Vl11xN+MUnTVE9Cigi6ynvFFCiiac4nNZgXI5u7T4W0XK5XXoV4xFyItJtgc377sXL60NwMVGIvAK4i9ddvYFmP2POEdcQmcgF5qH7i82AYAE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741607872; c=relaxed/simple; bh=z/z9oPKgEgmTzuJndfYToP13rdktD9p5abGLZ542iK8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=jYnWj48Uyyq1icraCISWzt9RkxPXbOZY1TQEtZCIoz0cfG1Iaq6TJWH4k+LNVlzfHTosDJz2196s6B6+6aBPB0w/ePbu1GtbKuigcSRQFA87AGOzeeLW+t1eg0raCHvoAF4wtvG3EmtGzQSA0lH/Tpwg6R04s46AWhnw8wkeBKw= 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 1trblL-0000S5-Cn; Mon, 10 Mar 2025 12:57:39 +0100 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 1trblK-004za0-0I; Mon, 10 Mar 2025 12:57:38 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1trblK-003I1b-03; Mon, 10 Mar 2025 12:57:38 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Woojung Huh , Andrew Lunn , Russell King , Thangaraj Samynathan , Rengarajan Sundararajan Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, UNGLinuxDriver@microchip.com, Phil Elwell Subject: [PATCH net-next v3 2/7] net: usb: lan78xx: improve error reporting on PHY attach failure Date: Mon, 10 Mar 2025 12:57:32 +0100 Message-Id: <20250310115737.784047-3-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250310115737.784047-1-o.rempel@pengutronix.de> References: <20250310115737.784047-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-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 Content-Type: text/plain; charset="utf-8" Include error code in the log message when PHY attachment fails, providing better debugging information. Signed-off-by: Oleksij Rempel --- changes v3: - update commit message --- drivers/net/usb/lan78xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 63b5406bfecb..dd55a9ba78fa 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -2682,8 +2682,8 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) =20 ret =3D phylink_connect_phy(dev->phylink, phydev); if (ret) { - netdev_err(dev->net, "can't attach PHY to %s\n", - dev->mdiobus->id); + netdev_err(dev->net, "can't attach PHY to %s, error %pe\n", + dev->mdiobus->id, ERR_PTR(ret)); return -EIO; } =20 --=20 2.39.5 From nobody Sun Feb 8 18:39:23 2026 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 3D98D22576A for ; Mon, 10 Mar 2025 11:57:48 +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=1741607871; cv=none; b=jEtH32mihKxPHTfhg0qGdzkzY3FmcGukX44LcVkJ/L0QZtC8b6nDIpXvNmKtq33tp4PPZLxF4YDznrQRVacq2B/zKuRxEAiIL9TmchHuEepsncypt8WXo+21yVc1zZekrmH453Nowa5OOZTlIbHAoiz3gxht7jKKz7UWX1O+Fr8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741607871; c=relaxed/simple; bh=agE0DgjvQ7Cvo+66vvgwpx9SrlSJ/iDfvgGrfiPMsqA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QI22M6cB5L6omjBLF/+JhOtYJtHzXBaWKkM+U3p/KojsKddbDQtHT1/rVpl0nNVIuO2cnQ3nI1PT/GQxWnywkg7mYBaLVGeOCaeOASt8xvaOATA1IkCa8oi05IBVEAEjyAQ7Zk9U7pNURHi0WvpH13KNPi6i1Tie5GLLaou7qxo= 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 1trblL-0000S6-Cl; Mon, 10 Mar 2025 12:57:39 +0100 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 1trblK-004za1-0M; Mon, 10 Mar 2025 12:57:38 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1trblK-003I1l-07; Mon, 10 Mar 2025 12:57:38 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Woojung Huh , Andrew Lunn , Russell King , Thangaraj Samynathan , Rengarajan Sundararajan Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, UNGLinuxDriver@microchip.com, Phil Elwell Subject: [PATCH net-next v3 3/7] net: usb: lan78xx: Improve error handling for PHY init path Date: Mon, 10 Mar 2025 12:57:33 +0100 Message-Id: <20250310115737.784047-4-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250310115737.784047-1-o.rempel@pengutronix.de> References: <20250310115737.784047-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-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 Content-Type: text/plain; charset="utf-8" Make sure existing return values are actually used. Signed-off-by: Oleksij Rempel --- drivers/net/usb/lan78xx.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index dd55a9ba78fa..465762c3efcf 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -2569,31 +2569,40 @@ static struct phy_device *lan7801_phy_init(struct l= an78xx_net *dev) { struct phy_device *phydev; int ret; - u32 buf; =20 phydev =3D phy_find_first(dev->mdiobus); if (!phydev) { netdev_dbg(dev->net, "PHY Not Found!! Forcing RGMII configuration\n"); ret =3D lan78xx_write_reg(dev, MAC_RGMII_ID, MAC_RGMII_ID_TXC_DELAY_EN_); + if (ret < 0) + return ERR_PTR(ret); + ret =3D lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00); - ret =3D lan78xx_read_reg(dev, HW_CFG, &buf); - buf |=3D HW_CFG_CLK125_EN_; - buf |=3D HW_CFG_REFCLK25_EN_; - ret =3D lan78xx_write_reg(dev, HW_CFG, buf); + if (ret < 0) + return ERR_PTR(ret); + + ret =3D lan78xx_update_reg(dev, HW_CFG, HW_CFG_CLK125_EN_ | + HW_CFG_REFCLK25_EN_, + HW_CFG_CLK125_EN_ | HW_CFG_REFCLK25_EN_); + if (ret < 0) + return ERR_PTR(ret); } else { if (!phydev->drv) { netdev_err(dev->net, "no PHY driver found\n"); - return NULL; + return ERR_PTR(-ENODEV); } phydev->interface =3D PHY_INTERFACE_MODE_RGMII_ID; /* The PHY driver is responsible to configure proper RGMII * interface delays. Disable RGMII delays on MAC side. */ - lan78xx_write_reg(dev, MAC_RGMII_ID, 0); + ret =3D lan78xx_write_reg(dev, MAC_RGMII_ID, 0); + if (ret < 0) + return ERR_PTR(ret); =20 phydev->is_internal =3D false; } + return phydev; } =20 @@ -2662,7 +2671,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) phydev =3D phy_find_first(dev->mdiobus); if (!phydev) { netdev_err(dev->net, "no PHY found\n"); - return -EIO; + return -ENODEV; } phydev->is_internal =3D true; phydev->interface =3D PHY_INTERFACE_MODE_GMII; @@ -2670,7 +2679,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) =20 default: netdev_err(dev->net, "Unknown CHIP ID found\n"); - return -EIO; + return -ENODEV; } =20 /* if phyirq is not set, use polling mode in phylib */ @@ -2684,7 +2693,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) if (ret) { netdev_err(dev->net, "can't attach PHY to %s, error %pe\n", dev->mdiobus->id, ERR_PTR(ret)); - return -EIO; + return ret; } =20 phy_support_eee(phydev); @@ -2698,7 +2707,10 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) sizeof(u32)); if (len >=3D 0) { /* Ensure the appropriate LEDs are enabled */ - lan78xx_read_reg(dev, HW_CFG, ®); + ret =3D lan78xx_read_reg(dev, HW_CFG, ®); + if (ret < 0) + return ret; + reg &=3D ~(HW_CFG_LED0_EN_ | HW_CFG_LED1_EN_ | HW_CFG_LED2_EN_ | @@ -2707,7 +2719,9 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) (len > 1) * HW_CFG_LED1_EN_ | (len > 2) * HW_CFG_LED2_EN_ | (len > 3) * HW_CFG_LED3_EN_; - lan78xx_write_reg(dev, HW_CFG, reg); + ret =3D lan78xx_write_reg(dev, HW_CFG, reg); + if (ret < 0) + return ret; } } =20 --=20 2.39.5 From nobody Sun Feb 8 18:39:23 2026 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 43A3822577C for ; Mon, 10 Mar 2025 11:57:48 +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=1741607871; cv=none; b=CAi62M/itOjl5S5t4w0EHl5yjyQrV6jSpdDWlj4fvSI8dkkIoCGz/Z+GHaohSwjeWQurEPM1k7lJk0LAbALGLX6mmbaCudz/RaoRiecjkoM+6OFGS8BOrVM0e51Uh3p/QKPf6I3ePnlboc2QEq5BEeUGTJWEexjmSmgcIF+nCSs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741607871; c=relaxed/simple; bh=R0D1y60vC+uBdp+6wIBczzW2cfEHCDuM5HyP0V9xITU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=UVbachSjnNRJbEPBdOp261ClX3BrsWgt0VLsbYAT0ryQNtEHBIx5JdySEhhaJxG7CxVoqfrbgPTYxL0WJQ9uutqBA6o92/O6hSy9SE4ZTSTHmfuqUBzQdDN2bItmw9BnZHSCClCQDNl++MiERbXNhEtPkfY6qoB/7hYA2duEndc= 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 1trblL-0000S7-Co; Mon, 10 Mar 2025 12:57:39 +0100 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 1trblK-004za2-0R; Mon, 10 Mar 2025 12:57:38 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1trblK-003I1v-0A; Mon, 10 Mar 2025 12:57:38 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Woojung Huh , Andrew Lunn , Russell King , Thangaraj Samynathan , Rengarajan Sundararajan Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, UNGLinuxDriver@microchip.com, Phil Elwell Subject: [PATCH net-next v3 4/7] net: usb: lan78xx: Use ethtool_op_get_link to reflect current link status Date: Mon, 10 Mar 2025 12:57:34 +0100 Message-Id: <20250310115737.784047-5-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250310115737.784047-1-o.rempel@pengutronix.de> References: <20250310115737.784047-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-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 Content-Type: text/plain; charset="utf-8" Replace the custom lan78xx_get_link implementation with the standard ethtool_op_get_link helper, which uses netif_carrier_ok to reflect the current link status accurately. Signed-off-by: Oleksij Rempel Reviewed-by: Maxime Chevallier --- drivers/net/usb/lan78xx.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 465762c3efcf..73f62c3e5c58 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1835,18 +1835,6 @@ static int lan78xx_set_eee(struct net_device *net, s= truct ethtool_keee *edata) return ret; } =20 -static u32 lan78xx_get_link(struct net_device *net) -{ - u32 link; - - mutex_lock(&net->phydev->lock); - phy_read_status(net->phydev); - link =3D net->phydev->link; - mutex_unlock(&net->phydev->lock); - - return link; -} - static void lan78xx_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) { @@ -2013,7 +2001,7 @@ lan78xx_get_regs(struct net_device *netdev, struct et= htool_regs *regs, } =20 static const struct ethtool_ops lan78xx_ethtool_ops =3D { - .get_link =3D lan78xx_get_link, + .get_link =3D ethtool_op_get_link, .nway_reset =3D phy_ethtool_nway_reset, .get_drvinfo =3D lan78xx_get_drvinfo, .get_msglevel =3D lan78xx_get_msglevel, --=20 2.39.5 From nobody Sun Feb 8 18:39:23 2026 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 3D89C225762 for ; Mon, 10 Mar 2025 11:57:48 +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=1741607873; cv=none; b=RLBdhk7yUtJh7eOujnDGT2jntfoKpBfqdQJp0C2gVy9q33hK0cq6V+pznv16Hd3912trefQhyX/bKG7RKT1K+SdPMc01QmjkgLjprsMT1/9enzF9lFCUFIZBepEds54Pqz3cHcAkQLCT3L63V20ETjHTSTDq2n7q9KrY9cGgIPA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741607873; c=relaxed/simple; bh=+eajRrOH/xNkg5/U26rvYo+W4vGukV/RaRL49tGEn70=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Jo8ILzdTZvm/tnGW+7YZczk2jbXsZH6wZqYt1Sy4t+IUFbOyqoIhL12Xbsqp23AxtqVec3t0178KzFeaDF6FawNkKE4cgA4ZY5xFnNh1Uf/wsMFIfRyK8wWKv6LUa+x/qytVaVEthJgI0LylRzXtHAh5DeityGAmEU68gNvhAjI= 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 1trblL-0000S8-Cn; Mon, 10 Mar 2025 12:57:39 +0100 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 1trblK-004za4-0W; Mon, 10 Mar 2025 12:57:38 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1trblK-003I25-0E; Mon, 10 Mar 2025 12:57:38 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Woojung Huh , Andrew Lunn , Russell King , Thangaraj Samynathan , Rengarajan Sundararajan Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, UNGLinuxDriver@microchip.com, Phil Elwell Subject: [PATCH net-next v3 5/7] net: usb: lan78xx: port link settings to phylink API Date: Mon, 10 Mar 2025 12:57:35 +0100 Message-Id: <20250310115737.784047-6-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250310115737.784047-1-o.rempel@pengutronix.de> References: <20250310115737.784047-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-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 Content-Type: text/plain; charset="utf-8" Refactor lan78xx_get_link_ksettings and lan78xx_set_link_ksettings to use the phylink API (phylink_ethtool_ksettings_get and phylink_ethtool_ksettings_set) instead of directly interfacing with the PHY. This change simplifies the code and ensures better integration with the phylink framework for link management. Signed-off-by: Oleksij Rempel Reviewed-by: Maxime Chevallier --- drivers/net/usb/lan78xx.c | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 73f62c3e5c58..7107eaa440e5 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1862,46 +1862,16 @@ static int lan78xx_get_link_ksettings(struct net_de= vice *net, struct ethtool_link_ksettings *cmd) { struct lan78xx_net *dev =3D netdev_priv(net); - struct phy_device *phydev =3D net->phydev; - int ret; - - ret =3D usb_autopm_get_interface(dev->intf); - if (ret < 0) - return ret; =20 - phy_ethtool_ksettings_get(phydev, cmd); - - usb_autopm_put_interface(dev->intf); - - return ret; + return phylink_ethtool_ksettings_get(dev->phylink, cmd); } =20 static int lan78xx_set_link_ksettings(struct net_device *net, const struct ethtool_link_ksettings *cmd) { struct lan78xx_net *dev =3D netdev_priv(net); - struct phy_device *phydev =3D net->phydev; - int ret =3D 0; - int temp; - - ret =3D usb_autopm_get_interface(dev->intf); - if (ret < 0) - return ret; - - /* change speed & duplex */ - ret =3D phy_ethtool_ksettings_set(phydev, cmd); =20 - if (!cmd->base.autoneg) { - /* force link down */ - temp =3D phy_read(phydev, MII_BMCR); - phy_write(phydev, MII_BMCR, temp | BMCR_LOOPBACK); - mdelay(1); - phy_write(phydev, MII_BMCR, temp); - } - - usb_autopm_put_interface(dev->intf); - - return ret; + return phylink_ethtool_ksettings_set(dev->phylink, cmd); } =20 static void lan78xx_get_pause(struct net_device *net, --=20 2.39.5 From nobody Sun Feb 8 18:39:23 2026 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 3D7CF22541D for ; Mon, 10 Mar 2025 11:57:48 +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=1741607871; cv=none; b=COmb6CzlhXv6ClBX5fzt3eE8UX1kxExoW638dtdjSu6kw4aqGZzsWjNRozK/tU1n1Hnn6lQi/HzsCcIhsYLDt2mfQamdMxdy6lu8XMI2fOsorNH+ZdPyVTWk+drcS+7xeuxRkPyF6LPsMmv1dDisZ1D/UgEcc4dwESt3nO72nm0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741607871; c=relaxed/simple; bh=mxRUnRtziyp0czycIlCjV5H1LD4H/a1NAVaWdseksaA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DT9MyShh567ZreqNJlM6PWiIufW6cZbmTJrdD0uZpNMUXAAEXzzDvSmZ2E/gMcb/TxQE/mIWLxBwGSqMAj+ub00rtd4SFPt/pzklX++96gnTr2xRePXeOji82z4/ZU+0/jT4atpG3DccGY8PMscuyJh9ygYPZ42wDLZEo5w5bYU= 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 1trblL-0000S9-Cm; Mon, 10 Mar 2025 12:57:39 +0100 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 1trblK-004za6-0e; Mon, 10 Mar 2025 12:57:38 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1trblK-003I2F-0H; Mon, 10 Mar 2025 12:57:38 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Woojung Huh , Andrew Lunn , Russell King , Thangaraj Samynathan , Rengarajan Sundararajan Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, UNGLinuxDriver@microchip.com, Phil Elwell Subject: [PATCH net-next v3 6/7] net: usb: lan78xx: Transition get/set_pause to phylink Date: Mon, 10 Mar 2025 12:57:36 +0100 Message-Id: <20250310115737.784047-7-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250310115737.784047-1-o.rempel@pengutronix.de> References: <20250310115737.784047-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-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 Content-Type: text/plain; charset="utf-8" Replace lan78xx_get_pause and lan78xx_set_pause implementations with phylink-based functions. This transition aligns pause parameter handling with the phylink API, simplifying the code and improving maintainability. Signed-off-by: Oleksij Rempel --- drivers/net/usb/lan78xx.c | 51 ++------------------------------------- 1 file changed, 2 insertions(+), 49 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 7107eaa440e5..3aa916a9ee0b 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1878,63 +1878,16 @@ static void lan78xx_get_pause(struct net_device *ne= t, struct ethtool_pauseparam *pause) { struct lan78xx_net *dev =3D netdev_priv(net); - struct phy_device *phydev =3D net->phydev; - struct ethtool_link_ksettings ecmd; - - phy_ethtool_ksettings_get(phydev, &ecmd); - - pause->autoneg =3D dev->fc_autoneg; =20 - if (dev->fc_request_control & FLOW_CTRL_TX) - pause->tx_pause =3D 1; - - if (dev->fc_request_control & FLOW_CTRL_RX) - pause->rx_pause =3D 1; + phylink_ethtool_get_pauseparam(dev->phylink, pause); } =20 static int lan78xx_set_pause(struct net_device *net, struct ethtool_pauseparam *pause) { struct lan78xx_net *dev =3D netdev_priv(net); - struct phy_device *phydev =3D net->phydev; - struct ethtool_link_ksettings ecmd; - int ret; - - phy_ethtool_ksettings_get(phydev, &ecmd); - - if (pause->autoneg && !ecmd.base.autoneg) { - ret =3D -EINVAL; - goto exit; - } =20 - dev->fc_request_control =3D 0; - if (pause->rx_pause) - dev->fc_request_control |=3D FLOW_CTRL_RX; - - if (pause->tx_pause) - dev->fc_request_control |=3D FLOW_CTRL_TX; - - if (ecmd.base.autoneg) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(fc) =3D { 0, }; - u32 mii_adv; - - linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT, - ecmd.link_modes.advertising); - linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, - ecmd.link_modes.advertising); - mii_adv =3D (u32)mii_advertise_flowctrl(dev->fc_request_control); - mii_adv_to_linkmode_adv_t(fc, mii_adv); - linkmode_or(ecmd.link_modes.advertising, fc, - ecmd.link_modes.advertising); - - phy_ethtool_ksettings_set(phydev, &ecmd); - } - - dev->fc_autoneg =3D pause->autoneg; - - ret =3D 0; -exit: - return ret; + return phylink_ethtool_set_pauseparam(dev->phylink, pause); } =20 static int lan78xx_get_regs_len(struct net_device *netdev) --=20 2.39.5 From nobody Sun Feb 8 18:39:23 2026 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 2E44D22423F for ; Mon, 10 Mar 2025 11:57:47 +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=1741607871; cv=none; b=UUml6NDOtwDvRGYIs9q4o7ztfk5Q31PtrlNWO1986W8hyWye70oqyZzlfYhalJYBBDFyJ/+mtCSFeJE4IehSV73TQD70TAXBqgztWgyg385lkeEgzhHN/SzLVDn9i3QEllNQenGN+8GaFv6h19IJY8J5e1/0K6vowMlsYTEsPds= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741607871; c=relaxed/simple; bh=Fuvdl0TGF9YX6waEmfb6eHtjb5Ubzg70XEPVxrTVx3E=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=Rb7EUfJNQa+joJ2JiUEdxn5RUPudO9HCDleyeHSkQVczbHb+wwGurjlbQtVAYDGj2Inbd2uuyXQ2GHnHTSTdF9KhYOgMfIGuMdmyEZoCMYBou+rsZqx8n6tfDCoT/P3franANwmD07D9II25Ndpk+mhfNggo3/vDnjC1xUg3A3E= 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 1trblL-0000SA-Cm; Mon, 10 Mar 2025 12:57:39 +0100 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 1trblK-004za9-0h; Mon, 10 Mar 2025 12:57:38 +0100 Received: from ore by dude04.red.stw.pengutronix.de with local (Exim 4.96) (envelope-from ) id 1trblK-003I2Q-0K; Mon, 10 Mar 2025 12:57:38 +0100 From: Oleksij Rempel To: "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Woojung Huh , Andrew Lunn , Russell King , Thangaraj Samynathan , Rengarajan Sundararajan Cc: Oleksij Rempel , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, UNGLinuxDriver@microchip.com, Phil Elwell Subject: [PATCH net-next v3 7/7] net: usb: lan78xx: Integrate EEE support with phylink LPI API Date: Mon, 10 Mar 2025 12:57:37 +0100 Message-Id: <20250310115737.784047-8-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250310115737.784047-1-o.rempel@pengutronix.de> References: <20250310115737.784047-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 Refactor Energy-Efficient Ethernet (EEE) support in the LAN78xx driver to fully integrate with the phylink Low Power Idle (LPI) API. This includes: - Replacing direct calls to `phy_ethtool_get_eee` and `phy_ethtool_set_eee` with `phylink_ethtool_get_eee` and `phylink_ethtool_set_eee`. - Implementing `.mac_enable_tx_lpi` and `.mac_disable_tx_lpi` to control LPI transitions via phylink. - Configuring `lpi_timer_default` to align with recommended values from LAN7800 documentation. - ensure EEE is disabled on controller reset Signed-off-by: Oleksij Rempel --- changes v2: - use latest PHYlink TX_LPI API --- drivers/net/usb/lan78xx.c | 120 ++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 44 deletions(-) diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 3aa916a9ee0b..0400616e1300 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -1785,54 +1785,15 @@ static int lan78xx_set_wol(struct net_device *netde= v, static int lan78xx_get_eee(struct net_device *net, struct ethtool_keee *ed= ata) { struct lan78xx_net *dev =3D netdev_priv(net); - struct phy_device *phydev =3D net->phydev; - int ret; - u32 buf; - - ret =3D usb_autopm_get_interface(dev->intf); - if (ret < 0) - return ret; - - ret =3D phy_ethtool_get_eee(phydev, edata); - if (ret < 0) - goto exit; =20 - ret =3D lan78xx_read_reg(dev, MAC_CR, &buf); - if (buf & MAC_CR_EEE_EN_) { - /* EEE_TX_LPI_REQ_DLY & tx_lpi_timer are same uSec unit */ - ret =3D lan78xx_read_reg(dev, EEE_TX_LPI_REQ_DLY, &buf); - edata->tx_lpi_timer =3D buf; - } else { - edata->tx_lpi_timer =3D 0; - } - - ret =3D 0; -exit: - usb_autopm_put_interface(dev->intf); - - return ret; + return phylink_ethtool_get_eee(dev->phylink, edata); } =20 static int lan78xx_set_eee(struct net_device *net, struct ethtool_keee *ed= ata) { struct lan78xx_net *dev =3D netdev_priv(net); - int ret; - u32 buf; - - ret =3D usb_autopm_get_interface(dev->intf); - if (ret < 0) - return ret; - - ret =3D phy_ethtool_set_eee(net->phydev, edata); - if (ret < 0) - goto out; - - buf =3D (u32)edata->tx_lpi_timer; - ret =3D lan78xx_write_reg(dev, EEE_TX_LPI_REQ_DLY, buf); -out: - usb_autopm_put_interface(dev->intf); =20 - return ret; + return phylink_ethtool_set_eee(dev->phylink, edata); } =20 static void lan78xx_get_drvinfo(struct net_device *net, @@ -2470,10 +2431,59 @@ static void lan78xx_mac_link_up(struct phylink_conf= ig *config, ERR_PTR(ret)); } =20 +static int lan78xx_mac_eee_enable(struct lan78xx_net *dev, bool enable) +{ + u32 mac_cr =3D 0; + + if (enable) + mac_cr |=3D MAC_CR_EEE_EN_; + + /* make sure TXEN and RXEN are disabled before reconfiguring MAC */ + return lan78xx_update_reg(dev, MAC_CR, MAC_CR_EEE_EN_, mac_cr); +} + +static void lan78xx_mac_disable_tx_lpi(struct phylink_config *config) +{ + struct net_device *net =3D to_net_dev(config->dev); + struct lan78xx_net *dev =3D netdev_priv(net); + + lan78xx_mac_eee_enable(dev, false); +} + +static int lan78xx_mac_enable_tx_lpi(struct phylink_config *config, u32 ti= mer, + bool tx_clk_stop) +{ + struct net_device *net =3D to_net_dev(config->dev); + struct lan78xx_net *dev =3D netdev_priv(net); + int ret; + + /* Software should only change this field when Energy Efficient + * Ethernet Enable (EEEEN) is cleared. We ensure that by clearing + * EEEEN during probe, and phylink itself guarantees that + * mac_disable_tx_lpi() will have been previously called. + */ + ret =3D lan78xx_write_reg(dev, EEE_TX_LPI_REQ_DLY, timer); + if (ret < 0) + goto tx_lpi_fail; + + ret =3D lan78xx_mac_eee_enable(dev, true); + if (ret < 0) + goto tx_lpi_fail; + + return 0; + +tx_lpi_fail: + netdev_err(dev->net, "Failed to enable TX LPI with error %pe\n", + ERR_PTR(ret)); + return ret; +} + static const struct phylink_mac_ops lan78xx_phylink_mac_ops =3D { .mac_config =3D lan78xx_mac_config, .mac_link_down =3D lan78xx_mac_link_down, .mac_link_up =3D lan78xx_mac_link_up, + .mac_disable_tx_lpi =3D lan78xx_mac_disable_tx_lpi, + .mac_enable_tx_lpi =3D lan78xx_mac_enable_tx_lpi, }; =20 static struct phy_device *lan7801_phy_init(struct lan78xx_net *dev) @@ -2528,6 +2538,26 @@ static int lan78xx_phylink_setup(struct lan78xx_net = *dev) pc->mac_capabilities =3D MAC_SYM_PAUSE | MAC_ASYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD; pc->mac_managed_pm =3D true; + pc->lpi_capabilities =3D MAC_100FD | MAC_1000FD; + /* + * Default TX LPI (Low Power Idle) request delay count is set to 50us. + * + * Source: LAN7800 Documentation, DS00001992H, Section 15.1.57, Page 204. + * + * Reasoning: + * According to the application note in the LAN7800 documentation, a + * zero delay may negatively impact the TX data path=E2=80=99s ability to + * support Gigabit operation. A value of 50us is recommended as a + * reasonable default when the part operates at Gigabit speeds, + * balancing stability and power efficiency in EEE mode. This delay can + * be increased based on performance testing, as EEE is designed for + * scenarios with mostly idle links and occasional bursts of full + * bandwidth transmission. The goal is to ensure reliable Gigabit + * performance without overly aggressive power optimization during + * inactive periods. + */ + pc->lpi_timer_default =3D 50; + pc->eee_enabled_default =3D true; =20 if (dev->chipid =3D=3D ID_REV_CHIP_ID_7801_) { phy_interface_set_rgmii(pc->supported_interfaces); @@ -2538,6 +2568,10 @@ static int lan78xx_phylink_setup(struct lan78xx_net = *dev) link_interface =3D PHY_INTERFACE_MODE_INTERNAL; } =20 + memcpy(dev->phylink_config.lpi_interfaces, + dev->phylink_config.supported_interfaces, + sizeof(dev->phylink_config.lpi_interfaces)); + phylink =3D phylink_create(pc, dev->net->dev.fwnode, link_interface, &lan78xx_phylink_mac_ops); if (IS_ERR(phylink)) @@ -2607,8 +2641,6 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) return ret; } =20 - phy_support_eee(phydev); - if (phydev->mdio.dev.of_node) { u32 reg; int len; @@ -3131,7 +3163,7 @@ static int lan78xx_reset(struct lan78xx_net *dev) if (ret < 0) return ret; =20 - buf &=3D ~(MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_); + buf &=3D ~(MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_ | MAC_CR_EEE_EN_); =20 /* LAN7801 only has RGMII mode */ if (dev->chipid =3D=3D ID_REV_CHIP_ID_7801_) --=20 2.39.5