mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 18:21:24 +02:00
net: bcmasp: Keep phy link during WoL sleep cycle
We currently more or less restart all the HW on resume. Since we also stop the PHY, it takes a while for the PHY link to be re-negotiated on resume. Instead of doing a full restart, we keep the HW state and the PHY link, that way we can resume network traffic with a much smaller delay. Signed-off-by: Justin Chen <justin.chen@broadcom.com> Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com> Link: https://patch.msgid.link/20260506213114.2002886-3-justin.chen@broadcom.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
e97ffa4e97
commit
e447b677bb
|
|
@ -923,7 +923,7 @@ static void bcmasp_phy_hw_unprepare(struct bcmasp_intf *intf)
|
|||
bcmasp_rgmii_mode_en_set(intf, false);
|
||||
}
|
||||
|
||||
static void bcmasp_netif_deinit(struct net_device *dev)
|
||||
static void bcmasp_netif_deinit(struct net_device *dev, bool stop_phy)
|
||||
{
|
||||
struct bcmasp_intf *intf = netdev_priv(dev);
|
||||
u32 reg, timeout = 1000;
|
||||
|
|
@ -946,7 +946,8 @@ static void bcmasp_netif_deinit(struct net_device *dev)
|
|||
|
||||
umac_enable_set(intf, UMC_CMD_TX_EN, 0);
|
||||
|
||||
phy_stop(dev->phydev);
|
||||
if (stop_phy)
|
||||
phy_stop(dev->phydev);
|
||||
|
||||
umac_enable_set(intf, UMC_CMD_RX_EN, 0);
|
||||
|
||||
|
|
@ -974,7 +975,7 @@ static int bcmasp_stop(struct net_device *dev)
|
|||
/* Stop tx from updating HW */
|
||||
netif_tx_disable(dev);
|
||||
|
||||
bcmasp_netif_deinit(dev);
|
||||
bcmasp_netif_deinit(dev, true);
|
||||
|
||||
bcmasp_reclaim_free_buffers(intf);
|
||||
|
||||
|
|
@ -1385,15 +1386,26 @@ int bcmasp_interface_suspend(struct bcmasp_intf *intf)
|
|||
{
|
||||
struct device *kdev = &intf->parent->pdev->dev;
|
||||
struct net_device *dev = intf->ndev;
|
||||
bool wake;
|
||||
|
||||
if (!netif_running(dev))
|
||||
return 0;
|
||||
|
||||
netif_device_detach(dev);
|
||||
|
||||
bcmasp_netif_deinit(dev);
|
||||
wake = device_may_wakeup(kdev) && intf->wolopts;
|
||||
|
||||
if (!intf->wolopts) {
|
||||
bcmasp_netif_deinit(dev, !wake);
|
||||
|
||||
if (wake) {
|
||||
/* Disable phy status updates while suspending */
|
||||
mutex_lock(&dev->phydev->lock);
|
||||
dev->phydev->state = PHY_READY;
|
||||
mutex_unlock(&dev->phydev->lock);
|
||||
cancel_delayed_work_sync(&dev->phydev->state_queue);
|
||||
|
||||
bcmasp_suspend_to_wol(intf);
|
||||
} else {
|
||||
bcmasp_phy_hw_unprepare(intf);
|
||||
|
||||
/* If Wake-on-LAN is disabled, we can safely
|
||||
|
|
@ -1402,9 +1414,6 @@ int bcmasp_interface_suspend(struct bcmasp_intf *intf)
|
|||
bcmasp_core_clock_set_intf(intf, false);
|
||||
}
|
||||
|
||||
if (device_may_wakeup(kdev) && intf->wolopts)
|
||||
bcmasp_suspend_to_wol(intf);
|
||||
|
||||
clk_disable_unprepare(intf->parent->clk);
|
||||
|
||||
return 0;
|
||||
|
|
@ -1428,8 +1437,11 @@ static void bcmasp_resume_from_wol(struct bcmasp_intf *intf)
|
|||
|
||||
int bcmasp_interface_resume(struct bcmasp_intf *intf)
|
||||
{
|
||||
struct device *kdev = &intf->parent->pdev->dev;
|
||||
struct net_device *dev = intf->ndev;
|
||||
bool wake;
|
||||
int ret;
|
||||
u32 reg;
|
||||
|
||||
if (!netif_running(dev))
|
||||
return 0;
|
||||
|
|
@ -1438,17 +1450,39 @@ int bcmasp_interface_resume(struct bcmasp_intf *intf)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
wake = device_may_wakeup(kdev) && intf->wolopts;
|
||||
|
||||
bcmasp_core_clock_set_intf(intf, true);
|
||||
|
||||
bcmasp_resume_from_wol(intf);
|
||||
|
||||
bcmasp_phy_hw_prepare(intf);
|
||||
|
||||
umac_reset_and_init(intf, dev->dev_addr);
|
||||
/* The interface might be HW reset in some suspend modes, so we may
|
||||
* need to restore the UNIMAC/PHY if that is the case.
|
||||
*/
|
||||
reg = umac_rl(intf, UMC_CMD);
|
||||
if (wake && (reg & UMC_CMD_RX_EN)) {
|
||||
umac_enable_set(intf, UMC_CMD_TX_EN, 1);
|
||||
bcmasp_resume_from_wol(intf);
|
||||
} else {
|
||||
bcmasp_phy_hw_prepare(intf);
|
||||
umac_reset_and_init(intf, dev->dev_addr);
|
||||
}
|
||||
|
||||
bcmasp_netif_init(dev);
|
||||
|
||||
phy_start(dev->phydev);
|
||||
if (wake) {
|
||||
/* If HW was reset, reprogram the unimac/PHY before resuming
|
||||
* link status tracking to avoid racing the state machine.
|
||||
*/
|
||||
if (!(reg & UMC_CMD_RX_EN))
|
||||
bcmasp_adj_link(dev);
|
||||
|
||||
/* Resume link status tracking */
|
||||
mutex_lock(&dev->phydev->lock);
|
||||
dev->phydev->state = dev->phydev->link ? PHY_RUNNING : PHY_NOLINK;
|
||||
mutex_unlock(&dev->phydev->lock);
|
||||
phy_trigger_machine(dev->phydev);
|
||||
} else {
|
||||
phy_start(dev->phydev);
|
||||
}
|
||||
|
||||
netif_device_attach(dev);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user