Loading drivers/net/ethernet/qualcomm/emac/emac.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -760,5 +760,6 @@ int emac_clk_set_rate(struct emac_adapter *adpt, enum emac_clk_id id, enum emac_clk_rate rate); void emac_task_schedule(struct emac_adapter *adpt); void emac_check_lsc(struct emac_adapter *adpt); void emac_wol_gpio_irq(struct emac_adapter *adpt, bool enable); #endif /* _QCOM_EMAC_H_ */ drivers/net/ethernet/qualcomm/emac/emac_ethtool.c +15 −3 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -322,6 +322,8 @@ static void emac_get_wol(struct net_device *netdev, static int emac_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct emac_adapter *adpt = netdev_priv(netdev); struct phy_device *phydev = netdev->phydev; u32 ret = 0; if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)) Loading @@ -330,13 +332,23 @@ static int emac_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) if (emac_wol_exclusion(adpt, wol)) return wol->wolopts ? -EOPNOTSUPP : 0; /* Enable WOL interrupt */ ret = phy_ethtool_set_wol(phydev, wol); if (ret) return ret; adpt->wol = 0; if (wol->wolopts & WAKE_MAGIC) if (wol->wolopts & WAKE_MAGIC) { adpt->wol |= EMAC_WOL_MAGIC; emac_wol_gpio_irq(adpt, true); /* Release wakelock */ __pm_relax(&adpt->link_wlock); } if (wol->wolopts & WAKE_PHY) adpt->wol |= EMAC_WOL_PHY; return 0; return ret; } static int emac_get_intr_coalesce(struct net_device *netdev, Loading drivers/net/ethernet/qualcomm/emac/emac_hw.h +1 −0 Original line number Diff line number Diff line Loading @@ -149,4 +149,5 @@ bool emac_hw_read_tx_tstamp(struct emac_hw *hw, struct emac_hwtxtstamp *ts); /* MII_INT_ENABLE/MII_INT_STATUS */ #define LINK_SUCCESS_INTERRUPT BIT(10) #define LINK_SUCCESS_BX BIT(7) #define WOL_INT BIT(0) #endif /*_EMAC_HW_H_*/ drivers/net/ethernet/qualcomm/emac/emac_main.c +17 −6 Original line number Diff line number Diff line Loading @@ -1132,7 +1132,7 @@ static int emac_start_xmit(struct sk_buff *skb, } /* This funciton aquire spin-lock so should not call from sleeping context */ static void emac_wol_gpio_irq(struct emac_adapter *adpt, bool enable) void emac_wol_gpio_irq(struct emac_adapter *adpt, bool enable) { struct emac_irq_per_dev *wol_irq = &adpt->irq[EMAC_WOL_IRQ]; struct emac_phy *phy = &adpt->phy; Loading Loading @@ -1174,6 +1174,8 @@ static irqreturn_t emac_wol_isr(int irq, void *data) if (!pm_runtime_status_suspended(adpt->netdev->dev.parent)) { if (val) emac_wol_gpio_irq(adpt, false); if (val & WOL_INT) __pm_stay_awake(&adpt->link_wlock); } return IRQ_HANDLED; } Loading Loading @@ -2035,9 +2037,10 @@ static int emac_open(struct net_device *netdev) if (irq->irq) { /* Register for EMAC WOL ISR */ retval = request_threaded_irq(irq->irq, NULL, irq_cmn->handler, IRQF_TRIGGER_FALLING IRQF_TRIGGER_LOW | IRQF_ONESHOT, irq_cmn->name, irq); enable_irq_wake(irq->irq); if (retval) { emac_err(adpt, "error:%d on request_irq(%d:%s flags:0x%lx)\n", Loading Loading @@ -2076,6 +2079,7 @@ static int emac_close(struct net_device *netdev) phy->is_wol_enabled = false; free_irq(adpt->irq[EMAC_WOL_IRQ].irq, &adpt->irq[EMAC_WOL_IRQ]); phy->is_wol_irq_reg = 0; disable_irq_wake(adpt->irq[EMAC_WOL_IRQ].irq); } if (!TEST_FLAG(adpt, ADPT_STATE_DOWN)) Loading Loading @@ -2452,7 +2456,7 @@ static void emac_init_adapter(struct emac_adapter *adpt) /* others */ hw->preamble = EMAC_PREAMBLE_DEF; adpt->wol = EMAC_WOL_MAGIC | EMAC_WOL_PHY; adpt->wol = EMAC_WOL_PHY; adpt->phy.is_ext_phy_connect = 0; } Loading Loading @@ -2812,7 +2816,7 @@ static int emac_pm_suspend(struct device *device, bool wol_enable) u32 wufc = adpt->wol; /* Check link state. Don't suspend if link is up */ if (netif_carrier_ok(adpt->netdev)) if (netif_carrier_ok(adpt->netdev) && !(adpt->wol & EMAC_WOL_MAGIC)) return -EPERM; /* cannot suspend if WOL interrupt is not enabled */ Loading @@ -2834,7 +2838,7 @@ static int emac_pm_suspend(struct device *device, bool wol_enable) flush_delayed_work(&adpt->phydev->state_queue); if (QCA8337_PHY_ID != adpt->phydev->phy_id) emac_hw_config_pow_save(hw, adpt->phydev->speed, !!wufc, !!(wufc & EMAC_WOL_MAGIC)); !!(wufc & EMAC_WOL_PHY)); if (!adpt->phydev->link && phy->is_wol_irq_reg) { int value, i; Loading Loading @@ -2936,17 +2940,24 @@ static int emac_pm_sys_suspend(struct device *device) if (!pm_runtime_enabled(device) || !pm_runtime_suspended(device)) { emac_pm_suspend(device, false); /* Synchronize runtime-pm and system-pm states: * at this point we are already suspended. However, the * runtime-PM framework still thinks that we are active. * The three calls below let the runtime-PM know that we are * suspended already without re-invoking the suspend callback */ if (adpt->wol & EMAC_WOL_MAGIC) { pm_runtime_mark_last_busy(netdev->dev.parent); pm_runtime_put_autosuspend(netdev->dev.parent); } pm_runtime_disable(netdev->dev.parent); pm_runtime_set_suspended(netdev->dev.parent); pm_runtime_enable(netdev->dev.parent); } /* Clear the Magic packet flag */ adpt->wol &= ~EMAC_WOL_MAGIC; } netif_device_detach(netdev); emac_disable_clks(adpt); emac_disable_regulator(adpt, EMAC_VREG1, EMAC_VREG2); Loading Loading
drivers/net/ethernet/qualcomm/emac/emac.h +2 −1 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -760,5 +760,6 @@ int emac_clk_set_rate(struct emac_adapter *adpt, enum emac_clk_id id, enum emac_clk_rate rate); void emac_task_schedule(struct emac_adapter *adpt); void emac_check_lsc(struct emac_adapter *adpt); void emac_wol_gpio_irq(struct emac_adapter *adpt, bool enable); #endif /* _QCOM_EMAC_H_ */
drivers/net/ethernet/qualcomm/emac/emac_ethtool.c +15 −3 Original line number Diff line number Diff line /* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -322,6 +322,8 @@ static void emac_get_wol(struct net_device *netdev, static int emac_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { struct emac_adapter *adpt = netdev_priv(netdev); struct phy_device *phydev = netdev->phydev; u32 ret = 0; if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)) Loading @@ -330,13 +332,23 @@ static int emac_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) if (emac_wol_exclusion(adpt, wol)) return wol->wolopts ? -EOPNOTSUPP : 0; /* Enable WOL interrupt */ ret = phy_ethtool_set_wol(phydev, wol); if (ret) return ret; adpt->wol = 0; if (wol->wolopts & WAKE_MAGIC) if (wol->wolopts & WAKE_MAGIC) { adpt->wol |= EMAC_WOL_MAGIC; emac_wol_gpio_irq(adpt, true); /* Release wakelock */ __pm_relax(&adpt->link_wlock); } if (wol->wolopts & WAKE_PHY) adpt->wol |= EMAC_WOL_PHY; return 0; return ret; } static int emac_get_intr_coalesce(struct net_device *netdev, Loading
drivers/net/ethernet/qualcomm/emac/emac_hw.h +1 −0 Original line number Diff line number Diff line Loading @@ -149,4 +149,5 @@ bool emac_hw_read_tx_tstamp(struct emac_hw *hw, struct emac_hwtxtstamp *ts); /* MII_INT_ENABLE/MII_INT_STATUS */ #define LINK_SUCCESS_INTERRUPT BIT(10) #define LINK_SUCCESS_BX BIT(7) #define WOL_INT BIT(0) #endif /*_EMAC_HW_H_*/
drivers/net/ethernet/qualcomm/emac/emac_main.c +17 −6 Original line number Diff line number Diff line Loading @@ -1132,7 +1132,7 @@ static int emac_start_xmit(struct sk_buff *skb, } /* This funciton aquire spin-lock so should not call from sleeping context */ static void emac_wol_gpio_irq(struct emac_adapter *adpt, bool enable) void emac_wol_gpio_irq(struct emac_adapter *adpt, bool enable) { struct emac_irq_per_dev *wol_irq = &adpt->irq[EMAC_WOL_IRQ]; struct emac_phy *phy = &adpt->phy; Loading Loading @@ -1174,6 +1174,8 @@ static irqreturn_t emac_wol_isr(int irq, void *data) if (!pm_runtime_status_suspended(adpt->netdev->dev.parent)) { if (val) emac_wol_gpio_irq(adpt, false); if (val & WOL_INT) __pm_stay_awake(&adpt->link_wlock); } return IRQ_HANDLED; } Loading Loading @@ -2035,9 +2037,10 @@ static int emac_open(struct net_device *netdev) if (irq->irq) { /* Register for EMAC WOL ISR */ retval = request_threaded_irq(irq->irq, NULL, irq_cmn->handler, IRQF_TRIGGER_FALLING IRQF_TRIGGER_LOW | IRQF_ONESHOT, irq_cmn->name, irq); enable_irq_wake(irq->irq); if (retval) { emac_err(adpt, "error:%d on request_irq(%d:%s flags:0x%lx)\n", Loading Loading @@ -2076,6 +2079,7 @@ static int emac_close(struct net_device *netdev) phy->is_wol_enabled = false; free_irq(adpt->irq[EMAC_WOL_IRQ].irq, &adpt->irq[EMAC_WOL_IRQ]); phy->is_wol_irq_reg = 0; disable_irq_wake(adpt->irq[EMAC_WOL_IRQ].irq); } if (!TEST_FLAG(adpt, ADPT_STATE_DOWN)) Loading Loading @@ -2452,7 +2456,7 @@ static void emac_init_adapter(struct emac_adapter *adpt) /* others */ hw->preamble = EMAC_PREAMBLE_DEF; adpt->wol = EMAC_WOL_MAGIC | EMAC_WOL_PHY; adpt->wol = EMAC_WOL_PHY; adpt->phy.is_ext_phy_connect = 0; } Loading Loading @@ -2812,7 +2816,7 @@ static int emac_pm_suspend(struct device *device, bool wol_enable) u32 wufc = adpt->wol; /* Check link state. Don't suspend if link is up */ if (netif_carrier_ok(adpt->netdev)) if (netif_carrier_ok(adpt->netdev) && !(adpt->wol & EMAC_WOL_MAGIC)) return -EPERM; /* cannot suspend if WOL interrupt is not enabled */ Loading @@ -2834,7 +2838,7 @@ static int emac_pm_suspend(struct device *device, bool wol_enable) flush_delayed_work(&adpt->phydev->state_queue); if (QCA8337_PHY_ID != adpt->phydev->phy_id) emac_hw_config_pow_save(hw, adpt->phydev->speed, !!wufc, !!(wufc & EMAC_WOL_MAGIC)); !!(wufc & EMAC_WOL_PHY)); if (!adpt->phydev->link && phy->is_wol_irq_reg) { int value, i; Loading Loading @@ -2936,17 +2940,24 @@ static int emac_pm_sys_suspend(struct device *device) if (!pm_runtime_enabled(device) || !pm_runtime_suspended(device)) { emac_pm_suspend(device, false); /* Synchronize runtime-pm and system-pm states: * at this point we are already suspended. However, the * runtime-PM framework still thinks that we are active. * The three calls below let the runtime-PM know that we are * suspended already without re-invoking the suspend callback */ if (adpt->wol & EMAC_WOL_MAGIC) { pm_runtime_mark_last_busy(netdev->dev.parent); pm_runtime_put_autosuspend(netdev->dev.parent); } pm_runtime_disable(netdev->dev.parent); pm_runtime_set_suspended(netdev->dev.parent); pm_runtime_enable(netdev->dev.parent); } /* Clear the Magic packet flag */ adpt->wol &= ~EMAC_WOL_MAGIC; } netif_device_detach(netdev); emac_disable_clks(adpt); emac_disable_regulator(adpt, EMAC_VREG1, EMAC_VREG2); Loading