Skip to content

Commit d1bf733

Browse files
committed
Merge branch 'stmmac-wol-fix'
Joakim Zhang says: ==================== net: stmmac: fix WoL issue This patch set fixes stmmac not working after system resume back with WoL active. Thanks a lot for Russell King keeps looking into this issue. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 0341d5e + 90702dc commit d1bf733

File tree

3 files changed

+103
-18
lines changed

3 files changed

+103
-18
lines changed

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7123,8 +7123,6 @@ int stmmac_suspend(struct device *dev)
71237123
if (!ndev || !netif_running(ndev))
71247124
return 0;
71257125

7126-
phylink_mac_change(priv->phylink, false);
7127-
71287126
mutex_lock(&priv->lock);
71297127

71307128
netif_device_detach(ndev);
@@ -7150,14 +7148,6 @@ int stmmac_suspend(struct device *dev)
71507148
stmmac_pmt(priv, priv->hw, priv->wolopts);
71517149
priv->irq_wake = 1;
71527150
} else {
7153-
mutex_unlock(&priv->lock);
7154-
rtnl_lock();
7155-
if (device_may_wakeup(priv->device))
7156-
phylink_speed_down(priv->phylink, false);
7157-
phylink_stop(priv->phylink);
7158-
rtnl_unlock();
7159-
mutex_lock(&priv->lock);
7160-
71617151
stmmac_mac_set(priv, priv->ioaddr, false);
71627152
pinctrl_pm_select_sleep_state(priv->device);
71637153
/* Disable clock in case of PWM is off */
@@ -7171,6 +7161,16 @@ int stmmac_suspend(struct device *dev)
71717161

71727162
mutex_unlock(&priv->lock);
71737163

7164+
rtnl_lock();
7165+
if (device_may_wakeup(priv->device) && priv->plat->pmt) {
7166+
phylink_suspend(priv->phylink, true);
7167+
} else {
7168+
if (device_may_wakeup(priv->device))
7169+
phylink_speed_down(priv->phylink, false);
7170+
phylink_suspend(priv->phylink, false);
7171+
}
7172+
rtnl_unlock();
7173+
71747174
if (priv->dma_cap.fpesel) {
71757175
/* Disable FPE */
71767176
stmmac_fpe_configure(priv, priv->ioaddr,
@@ -7261,13 +7261,15 @@ int stmmac_resume(struct device *dev)
72617261
return ret;
72627262
}
72637263

7264-
if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
7265-
rtnl_lock();
7266-
phylink_start(priv->phylink);
7267-
/* We may have called phylink_speed_down before */
7268-
phylink_speed_up(priv->phylink);
7269-
rtnl_unlock();
7264+
rtnl_lock();
7265+
if (device_may_wakeup(priv->device) && priv->plat->pmt) {
7266+
phylink_resume(priv->phylink);
7267+
} else {
7268+
phylink_resume(priv->phylink);
7269+
if (device_may_wakeup(priv->device))
7270+
phylink_speed_up(priv->phylink);
72707271
}
7272+
rtnl_unlock();
72717273

72727274
rtnl_lock();
72737275
mutex_lock(&priv->lock);
@@ -7288,8 +7290,6 @@ int stmmac_resume(struct device *dev)
72887290
mutex_unlock(&priv->lock);
72897291
rtnl_unlock();
72907292

7291-
phylink_mac_change(priv->phylink, true);
7292-
72937293
netif_device_attach(ndev);
72947294

72957295
return 0;

drivers/net/phy/phylink.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
enum {
3434
PHYLINK_DISABLE_STOPPED,
3535
PHYLINK_DISABLE_LINK,
36+
PHYLINK_DISABLE_MAC_WOL,
3637
};
3738

3839
/**
@@ -1282,6 +1283,9 @@ EXPORT_SYMBOL_GPL(phylink_start);
12821283
* network device driver's &struct net_device_ops ndo_stop() method. The
12831284
* network device's carrier state should not be changed prior to calling this
12841285
* function.
1286+
*
1287+
* This will synchronously bring down the link if the link is not already
1288+
* down (in other words, it will trigger a mac_link_down() method call.)
12851289
*/
12861290
void phylink_stop(struct phylink *pl)
12871291
{
@@ -1301,6 +1305,84 @@ void phylink_stop(struct phylink *pl)
13011305
}
13021306
EXPORT_SYMBOL_GPL(phylink_stop);
13031307

1308+
/**
1309+
* phylink_suspend() - handle a network device suspend event
1310+
* @pl: a pointer to a &struct phylink returned from phylink_create()
1311+
* @mac_wol: true if the MAC needs to receive packets for Wake-on-Lan
1312+
*
1313+
* Handle a network device suspend event. There are several cases:
1314+
* - If Wake-on-Lan is not active, we can bring down the link between
1315+
* the MAC and PHY by calling phylink_stop().
1316+
* - If Wake-on-Lan is active, and being handled only by the PHY, we
1317+
* can also bring down the link between the MAC and PHY.
1318+
* - If Wake-on-Lan is active, but being handled by the MAC, the MAC
1319+
* still needs to receive packets, so we can not bring the link down.
1320+
*/
1321+
void phylink_suspend(struct phylink *pl, bool mac_wol)
1322+
{
1323+
ASSERT_RTNL();
1324+
1325+
if (mac_wol && (!pl->netdev || pl->netdev->wol_enabled)) {
1326+
/* Wake-on-Lan enabled, MAC handling */
1327+
mutex_lock(&pl->state_mutex);
1328+
1329+
/* Stop the resolver bringing the link up */
1330+
__set_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state);
1331+
1332+
/* Disable the carrier, to prevent transmit timeouts,
1333+
* but one would hope all packets have been sent. This
1334+
* also means phylink_resolve() will do nothing.
1335+
*/
1336+
netif_carrier_off(pl->netdev);
1337+
1338+
/* We do not call mac_link_down() here as we want the
1339+
* link to remain up to receive the WoL packets.
1340+
*/
1341+
mutex_unlock(&pl->state_mutex);
1342+
} else {
1343+
phylink_stop(pl);
1344+
}
1345+
}
1346+
EXPORT_SYMBOL_GPL(phylink_suspend);
1347+
1348+
/**
1349+
* phylink_resume() - handle a network device resume event
1350+
* @pl: a pointer to a &struct phylink returned from phylink_create()
1351+
*
1352+
* Undo the effects of phylink_suspend(), returning the link to an
1353+
* operational state.
1354+
*/
1355+
void phylink_resume(struct phylink *pl)
1356+
{
1357+
ASSERT_RTNL();
1358+
1359+
if (test_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state)) {
1360+
/* Wake-on-Lan enabled, MAC handling */
1361+
1362+
/* Call mac_link_down() so we keep the overall state balanced.
1363+
* Do this under the state_mutex lock for consistency. This
1364+
* will cause a "Link Down" message to be printed during
1365+
* resume, which is harmless - the true link state will be
1366+
* printed when we run a resolve.
1367+
*/
1368+
mutex_lock(&pl->state_mutex);
1369+
phylink_link_down(pl);
1370+
mutex_unlock(&pl->state_mutex);
1371+
1372+
/* Re-apply the link parameters so that all the settings get
1373+
* restored to the MAC.
1374+
*/
1375+
phylink_mac_initial_config(pl, true);
1376+
1377+
/* Re-enable and re-resolve the link parameters */
1378+
clear_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state);
1379+
phylink_run_resolve(pl);
1380+
} else {
1381+
phylink_start(pl);
1382+
}
1383+
}
1384+
EXPORT_SYMBOL_GPL(phylink_resume);
1385+
13041386
/**
13051387
* phylink_ethtool_get_wol() - get the wake on lan parameters for the PHY
13061388
* @pl: a pointer to a &struct phylink returned from phylink_create()

include/linux/phylink.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,9 @@ void phylink_mac_change(struct phylink *, bool up);
451451
void phylink_start(struct phylink *);
452452
void phylink_stop(struct phylink *);
453453

454+
void phylink_suspend(struct phylink *pl, bool mac_wol);
455+
void phylink_resume(struct phylink *pl);
456+
454457
void phylink_ethtool_get_wol(struct phylink *, struct ethtool_wolinfo *);
455458
int phylink_ethtool_set_wol(struct phylink *, struct ethtool_wolinfo *);
456459

0 commit comments

Comments
 (0)