mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-11 23:03:55 +08:00
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 <davem@davemloft.net>
This commit is contained in:
commit
d1bf73387b
@ -7123,8 +7123,6 @@ int stmmac_suspend(struct device *dev)
|
||||
if (!ndev || !netif_running(ndev))
|
||||
return 0;
|
||||
|
||||
phylink_mac_change(priv->phylink, false);
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
netif_device_detach(ndev);
|
||||
@ -7150,14 +7148,6 @@ int stmmac_suspend(struct device *dev)
|
||||
stmmac_pmt(priv, priv->hw, priv->wolopts);
|
||||
priv->irq_wake = 1;
|
||||
} else {
|
||||
mutex_unlock(&priv->lock);
|
||||
rtnl_lock();
|
||||
if (device_may_wakeup(priv->device))
|
||||
phylink_speed_down(priv->phylink, false);
|
||||
phylink_stop(priv->phylink);
|
||||
rtnl_unlock();
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
stmmac_mac_set(priv, priv->ioaddr, false);
|
||||
pinctrl_pm_select_sleep_state(priv->device);
|
||||
/* Disable clock in case of PWM is off */
|
||||
@ -7171,6 +7161,16 @@ int stmmac_suspend(struct device *dev)
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
rtnl_lock();
|
||||
if (device_may_wakeup(priv->device) && priv->plat->pmt) {
|
||||
phylink_suspend(priv->phylink, true);
|
||||
} else {
|
||||
if (device_may_wakeup(priv->device))
|
||||
phylink_speed_down(priv->phylink, false);
|
||||
phylink_suspend(priv->phylink, false);
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
if (priv->dma_cap.fpesel) {
|
||||
/* Disable FPE */
|
||||
stmmac_fpe_configure(priv, priv->ioaddr,
|
||||
@ -7261,13 +7261,15 @@ int stmmac_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!device_may_wakeup(priv->device) || !priv->plat->pmt) {
|
||||
rtnl_lock();
|
||||
phylink_start(priv->phylink);
|
||||
/* We may have called phylink_speed_down before */
|
||||
phylink_speed_up(priv->phylink);
|
||||
rtnl_unlock();
|
||||
rtnl_lock();
|
||||
if (device_may_wakeup(priv->device) && priv->plat->pmt) {
|
||||
phylink_resume(priv->phylink);
|
||||
} else {
|
||||
phylink_resume(priv->phylink);
|
||||
if (device_may_wakeup(priv->device))
|
||||
phylink_speed_up(priv->phylink);
|
||||
}
|
||||
rtnl_unlock();
|
||||
|
||||
rtnl_lock();
|
||||
mutex_lock(&priv->lock);
|
||||
@ -7288,8 +7290,6 @@ int stmmac_resume(struct device *dev)
|
||||
mutex_unlock(&priv->lock);
|
||||
rtnl_unlock();
|
||||
|
||||
phylink_mac_change(priv->phylink, true);
|
||||
|
||||
netif_device_attach(ndev);
|
||||
|
||||
return 0;
|
||||
|
@ -33,6 +33,7 @@
|
||||
enum {
|
||||
PHYLINK_DISABLE_STOPPED,
|
||||
PHYLINK_DISABLE_LINK,
|
||||
PHYLINK_DISABLE_MAC_WOL,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1282,6 +1283,9 @@ EXPORT_SYMBOL_GPL(phylink_start);
|
||||
* network device driver's &struct net_device_ops ndo_stop() method. The
|
||||
* network device's carrier state should not be changed prior to calling this
|
||||
* function.
|
||||
*
|
||||
* This will synchronously bring down the link if the link is not already
|
||||
* down (in other words, it will trigger a mac_link_down() method call.)
|
||||
*/
|
||||
void phylink_stop(struct phylink *pl)
|
||||
{
|
||||
@ -1301,6 +1305,84 @@ void phylink_stop(struct phylink *pl)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phylink_stop);
|
||||
|
||||
/**
|
||||
* phylink_suspend() - handle a network device suspend event
|
||||
* @pl: a pointer to a &struct phylink returned from phylink_create()
|
||||
* @mac_wol: true if the MAC needs to receive packets for Wake-on-Lan
|
||||
*
|
||||
* Handle a network device suspend event. There are several cases:
|
||||
* - If Wake-on-Lan is not active, we can bring down the link between
|
||||
* the MAC and PHY by calling phylink_stop().
|
||||
* - If Wake-on-Lan is active, and being handled only by the PHY, we
|
||||
* can also bring down the link between the MAC and PHY.
|
||||
* - If Wake-on-Lan is active, but being handled by the MAC, the MAC
|
||||
* still needs to receive packets, so we can not bring the link down.
|
||||
*/
|
||||
void phylink_suspend(struct phylink *pl, bool mac_wol)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (mac_wol && (!pl->netdev || pl->netdev->wol_enabled)) {
|
||||
/* Wake-on-Lan enabled, MAC handling */
|
||||
mutex_lock(&pl->state_mutex);
|
||||
|
||||
/* Stop the resolver bringing the link up */
|
||||
__set_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state);
|
||||
|
||||
/* Disable the carrier, to prevent transmit timeouts,
|
||||
* but one would hope all packets have been sent. This
|
||||
* also means phylink_resolve() will do nothing.
|
||||
*/
|
||||
netif_carrier_off(pl->netdev);
|
||||
|
||||
/* We do not call mac_link_down() here as we want the
|
||||
* link to remain up to receive the WoL packets.
|
||||
*/
|
||||
mutex_unlock(&pl->state_mutex);
|
||||
} else {
|
||||
phylink_stop(pl);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phylink_suspend);
|
||||
|
||||
/**
|
||||
* phylink_resume() - handle a network device resume event
|
||||
* @pl: a pointer to a &struct phylink returned from phylink_create()
|
||||
*
|
||||
* Undo the effects of phylink_suspend(), returning the link to an
|
||||
* operational state.
|
||||
*/
|
||||
void phylink_resume(struct phylink *pl)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (test_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state)) {
|
||||
/* Wake-on-Lan enabled, MAC handling */
|
||||
|
||||
/* Call mac_link_down() so we keep the overall state balanced.
|
||||
* Do this under the state_mutex lock for consistency. This
|
||||
* will cause a "Link Down" message to be printed during
|
||||
* resume, which is harmless - the true link state will be
|
||||
* printed when we run a resolve.
|
||||
*/
|
||||
mutex_lock(&pl->state_mutex);
|
||||
phylink_link_down(pl);
|
||||
mutex_unlock(&pl->state_mutex);
|
||||
|
||||
/* Re-apply the link parameters so that all the settings get
|
||||
* restored to the MAC.
|
||||
*/
|
||||
phylink_mac_initial_config(pl, true);
|
||||
|
||||
/* Re-enable and re-resolve the link parameters */
|
||||
clear_bit(PHYLINK_DISABLE_MAC_WOL, &pl->phylink_disable_state);
|
||||
phylink_run_resolve(pl);
|
||||
} else {
|
||||
phylink_start(pl);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phylink_resume);
|
||||
|
||||
/**
|
||||
* phylink_ethtool_get_wol() - get the wake on lan parameters for the PHY
|
||||
* @pl: a pointer to a &struct phylink returned from phylink_create()
|
||||
|
@ -451,6 +451,9 @@ void phylink_mac_change(struct phylink *, bool up);
|
||||
void phylink_start(struct phylink *);
|
||||
void phylink_stop(struct phylink *);
|
||||
|
||||
void phylink_suspend(struct phylink *pl, bool mac_wol);
|
||||
void phylink_resume(struct phylink *pl);
|
||||
|
||||
void phylink_ethtool_get_wol(struct phylink *, struct ethtool_wolinfo *);
|
||||
int phylink_ethtool_set_wol(struct phylink *, struct ethtool_wolinfo *);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user