Skip to content

Commit 4c0d2e9

Browse files
hkallweitdavem330
authored andcommitted
net: phy: consider that suspend2ram may cut off PHY power
Claudiu reported that on his system S2R cuts off power to the PHY and after resuming certain PHY settings are lost. The PM folks confirmed that cutting off power to selected components in S2R is a valid case. Therefore resuming from S2R, same as from hibernation, has to assume that the PHY has power-on defaults. As a consequence use the restore callback also as resume callback. In addition make sure that the interrupt configuration is restored. Let's do this in phy_init_hw() and ensure that after this call actual interrupt configuration is in sync with phydev->interrupts. Currently, if interrupt was enabled before hibernation, we would resume with interrupt disabled because that's the power-on default. This fix applies cleanly only after the commit marked as fixed. I don't have an affected system, therefore change is compile-tested only. [0] https://lore.kernel.org/netdev/[email protected]/ Fixes: 611d779 ("net: phy: fix MDIO bus PM PHY resuming") Reported-by: Claudiu Beznea <[email protected]> Signed-off-by: Heiner Kallweit <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e12be91 commit 4c0d2e9

File tree

1 file changed

+17
-36
lines changed

1 file changed

+17
-36
lines changed

drivers/net/phy/phy_device.c

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -300,50 +300,22 @@ static int mdio_bus_phy_resume(struct device *dev)
300300

301301
phydev->suspended_by_mdio_bus = 0;
302302

303-
ret = phy_resume(phydev);
303+
ret = phy_init_hw(phydev);
304304
if (ret < 0)
305305
return ret;
306306

307-
no_resume:
308-
if (phydev->attached_dev && phydev->adjust_link)
309-
phy_start_machine(phydev);
310-
311-
return 0;
312-
}
313-
314-
static int mdio_bus_phy_restore(struct device *dev)
315-
{
316-
struct phy_device *phydev = to_phy_device(dev);
317-
struct net_device *netdev = phydev->attached_dev;
318-
int ret;
319-
320-
if (!netdev)
321-
return 0;
322-
323-
ret = phy_init_hw(phydev);
307+
ret = phy_resume(phydev);
324308
if (ret < 0)
325309
return ret;
326-
310+
no_resume:
327311
if (phydev->attached_dev && phydev->adjust_link)
328312
phy_start_machine(phydev);
329313

330314
return 0;
331315
}
332316

333-
static const struct dev_pm_ops mdio_bus_phy_pm_ops = {
334-
.suspend = mdio_bus_phy_suspend,
335-
.resume = mdio_bus_phy_resume,
336-
.freeze = mdio_bus_phy_suspend,
337-
.thaw = mdio_bus_phy_resume,
338-
.restore = mdio_bus_phy_restore,
339-
};
340-
341-
#define MDIO_BUS_PHY_PM_OPS (&mdio_bus_phy_pm_ops)
342-
343-
#else
344-
345-
#define MDIO_BUS_PHY_PM_OPS NULL
346-
317+
static SIMPLE_DEV_PM_OPS(mdio_bus_phy_pm_ops, mdio_bus_phy_suspend,
318+
mdio_bus_phy_resume);
347319
#endif /* CONFIG_PM */
348320

349321
/**
@@ -554,7 +526,7 @@ static const struct device_type mdio_bus_phy_type = {
554526
.name = "PHY",
555527
.groups = phy_dev_groups,
556528
.release = phy_device_release,
557-
.pm = MDIO_BUS_PHY_PM_OPS,
529+
.pm = pm_ptr(&mdio_bus_phy_pm_ops),
558530
};
559531

560532
static int phy_request_driver_module(struct phy_device *dev, u32 phy_id)
@@ -1143,10 +1115,19 @@ int phy_init_hw(struct phy_device *phydev)
11431115
if (ret < 0)
11441116
return ret;
11451117

1146-
if (phydev->drv->config_init)
1118+
if (phydev->drv->config_init) {
11471119
ret = phydev->drv->config_init(phydev);
1120+
if (ret < 0)
1121+
return ret;
1122+
}
11481123

1149-
return ret;
1124+
if (phydev->drv->config_intr) {
1125+
ret = phydev->drv->config_intr(phydev);
1126+
if (ret < 0)
1127+
return ret;
1128+
}
1129+
1130+
return 0;
11501131
}
11511132
EXPORT_SYMBOL(phy_init_hw);
11521133

0 commit comments

Comments
 (0)