Hi Andrew, On Fri, Mar 4, 2022 at 11:11 AM Andrew Lunn <andrew@xxxxxxx> wrote: > I suggest you look at the call sequences. When does phy_stop() and > phy_disconnect() get called? phylib has a work queue which runs once > per second to poll the PHY and get its status. That polling is stopped > by calling phy_stop(). It is also assumed you can still talk to the > PHY while performing phy_stop(). With this debug patch: --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -1034,6 +1034,8 @@ void phy_stop(struct phy_device *phydev) { struct net_device *dev = phydev->attached_dev; + pr_err("*************** %s\n", __func__); + if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) { WARN(1, "called from state %s\n", phy_state_to_str(phydev->state)); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index ce0bb5951b81..e26d9edf32f3 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1108,8 +1108,11 @@ EXPORT_SYMBOL(phy_connect); */ void phy_disconnect(struct phy_device *phydev) { - if (phy_is_started(phydev)) + pr_err("*********** %s: 1\n", __func__); + if (phy_is_started(phydev)) { + pr_err("*********** %s: 2\n", __func__); phy_stop(phydev); + } if (phy_interrupt_is_valid(phydev)) phy_free_interrupt(phydev); diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index bc1e3dd67c04..6ed674636961 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1190,6 +1190,7 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) { struct smsc95xx_priv *pdata = dev->driver_priv; + pr_err("*********** %s: calling phy_disconnect\n", __func__); phy_disconnect(dev->net->phydev); mdiobus_unregister(pdata->mdiobus); mdiobus_free(pdata->mdiobus); @@ -1206,6 +1207,7 @@ static int smsc95xx_start_phy(struct usbnet *dev) static int smsc95xx_stop(struct usbnet *dev) { + pr_err("*********** %s\n", __func__); if (dev->net->phydev) phy_stop(dev->net->phydev); The result is: # echo -n "2-1" > /sys/bus/usb/drivers/usb/unbind usb 2-1.1: USB disconnect, device number 3 smsc95xx 2-1.1:1.0 eth1: unregister 'smsc95xx' usb-ci_hdrc.1-1.1, smsc95xx USB 2.0 Ethernet smsc95xx 2-1.1:1.0 eth1: Failed to read reg index 0x00000114: -19 smsc95xx 2-1.1:1.0 eth1: Error reading MII_ACCESS *********** smsc95xx_unbind: calling phy_disconnect smsc95xx 2-1.1:1.0 eth1: __smsc95xx_mdio_read: MII is busy libphy: *********** phy_disconnect: 1 libphy: *********** phy_disconnect: 2 *************** phy_stop smsc95xx 2-1.1:1.0 eth1: Failed to read reg index 0x00000114: -19 smsc95xx 2-1.1:1.0 eth1: Error reading MII_ACCESS smsc95xx 2-1.1:1.0 eth1: __smsc95xx_mdio_read: MII is busy smsc95xx 2-1.1:1.0 eth1: Failed to read reg index 0x00000114: -19 smsc95xx 2-1.1:1.0 eth1: Error reading MII_ACCESS smsc95xx 2-1.1:1.0 eth1: __smsc95xx_mdio_read: MII is busy *********** smsc95xx_stop smsc95xx 2-1.1:1.0 eth1: hardware isn't capable of remote wakeup usb 2-1.4: USB disconnect, device number 4 Maybe the -19 errors should be ignored?