Skip to content

Commit 13e6be2

Browse files
committed
Merge branch 'ravb-wol-magic-packet'
Niklas Söderlund says: ==================== ravb: add wake-on-lan support via magic packet WoL is enabled in the suspend callback by setting MagicPacket detection and disabling all interrupts expect MagicPacket. In the resume path the driver needs to reset the hardware to rearm the WoL logic, this prevents the driver from simply restoring the registers and to take advantage of that ravb was not suspended to reduce resume time. To reset the hardware the driver closes the device, sets it in reset mode and reopens the device just like it would do in a normal suspend/resume scenario without WoL enabled, but it both closes and opens the device in the resume callback since the device needs to be reset for WoL to work. One quirk needed for WoL is that the module clock needs to be prevented from being switched off by Runtime PM. To keep the clock alive the suspend callback need to call clk_enable() directly to increase the usage count of the clock. Then when Runtime PM decreases the clock usage count it won't reach 0 and be switched off. Changes since v2 - Only do the clock dance to workaround PSCI sleep when resuming if WoL is enabled. This was a bug in v2 which resulted in a WARN if resuming from PSCI sleep with WoL disabled, thanks Sergei for pointing this out! - Break out clock dance workaround in separate patch to make it easier to revert once a fix is upstream for the clock driver as suggested by Sergei. Changes since v1 - Fix issue where device would fail to resume from PSCI suspend if WoL was enabled, reported by Geert. The fault was that the clock driver thinks the clock is on, but PSCI have disabled it, added workaround for this in ravb driver which can be removed once the clock driver is aware of the PSCI behavior. - Only try to restore from wol wake up if netif is running, since this is a condition to enable wol in the first place this was a bug in v1. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 906a039 + fbf3d03 commit 13e6be2

File tree

2 files changed

+129
-4
lines changed

2 files changed

+129
-4
lines changed

drivers/net/ethernet/renesas/ravb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,7 @@ struct ravb_private {
991991
struct net_device *ndev;
992992
struct platform_device *pdev;
993993
void __iomem *addr;
994+
struct clk *clk;
994995
struct mdiobb_ctrl mdiobb;
995996
u32 num_rx_ring[NUM_RX_QUEUE];
996997
u32 num_tx_ring[NUM_TX_QUEUE];
@@ -1033,6 +1034,7 @@ struct ravb_private {
10331034

10341035
unsigned no_avb_link:1;
10351036
unsigned avb_link_active_low:1;
1037+
unsigned wol_enabled:1;
10361038
};
10371039

10381040
static inline u32 ravb_read(struct net_device *ndev, enum ravb_reg reg)

drivers/net/ethernet/renesas/ravb_main.c

Lines changed: 127 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,9 @@ static void ravb_emac_interrupt_unlocked(struct net_device *ndev)
680680

681681
ecsr = ravb_read(ndev, ECSR);
682682
ravb_write(ndev, ecsr, ECSR); /* clear interrupt */
683+
684+
if (ecsr & ECSR_MPD)
685+
pm_wakeup_event(&priv->pdev->dev, 0);
683686
if (ecsr & ECSR_ICD)
684687
ndev->stats.tx_carrier_errors++;
685688
if (ecsr & ECSR_LCHNG) {
@@ -1330,6 +1333,33 @@ static int ravb_get_ts_info(struct net_device *ndev,
13301333
return 0;
13311334
}
13321335

1336+
static void ravb_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
1337+
{
1338+
struct ravb_private *priv = netdev_priv(ndev);
1339+
1340+
wol->supported = 0;
1341+
wol->wolopts = 0;
1342+
1343+
if (priv->clk) {
1344+
wol->supported = WAKE_MAGIC;
1345+
wol->wolopts = priv->wol_enabled ? WAKE_MAGIC : 0;
1346+
}
1347+
}
1348+
1349+
static int ravb_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
1350+
{
1351+
struct ravb_private *priv = netdev_priv(ndev);
1352+
1353+
if (!priv->clk || wol->wolopts & ~WAKE_MAGIC)
1354+
return -EOPNOTSUPP;
1355+
1356+
priv->wol_enabled = !!(wol->wolopts & WAKE_MAGIC);
1357+
1358+
device_set_wakeup_enable(&priv->pdev->dev, priv->wol_enabled);
1359+
1360+
return 0;
1361+
}
1362+
13331363
static const struct ethtool_ops ravb_ethtool_ops = {
13341364
.nway_reset = ravb_nway_reset,
13351365
.get_msglevel = ravb_get_msglevel,
@@ -1343,6 +1373,8 @@ static const struct ethtool_ops ravb_ethtool_ops = {
13431373
.get_ts_info = ravb_get_ts_info,
13441374
.get_link_ksettings = ravb_get_link_ksettings,
13451375
.set_link_ksettings = ravb_set_link_ksettings,
1376+
.get_wol = ravb_get_wol,
1377+
.set_wol = ravb_set_wol,
13461378
};
13471379

13481380
static inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler,
@@ -2041,6 +2073,11 @@ static int ravb_probe(struct platform_device *pdev)
20412073

20422074
priv->chip_id = chip_id;
20432075

2076+
/* Get clock, if not found that's OK but Wake-On-Lan is unavailable */
2077+
priv->clk = devm_clk_get(&pdev->dev, NULL);
2078+
if (IS_ERR(priv->clk))
2079+
priv->clk = NULL;
2080+
20442081
/* Set function */
20452082
ndev->netdev_ops = &ravb_netdev_ops;
20462083
ndev->ethtool_ops = &ravb_ethtool_ops;
@@ -2107,6 +2144,9 @@ static int ravb_probe(struct platform_device *pdev)
21072144
if (error)
21082145
goto out_napi_del;
21092146

2147+
if (priv->clk)
2148+
device_set_wakeup_capable(&pdev->dev, 1);
2149+
21102150
/* Print device information */
21112151
netdev_info(ndev, "Base address at %#x, %pM, IRQ %d.\n",
21122152
(u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
@@ -2160,15 +2200,66 @@ static int ravb_remove(struct platform_device *pdev)
21602200
return 0;
21612201
}
21622202

2203+
static int ravb_wol_setup(struct net_device *ndev)
2204+
{
2205+
struct ravb_private *priv = netdev_priv(ndev);
2206+
2207+
/* Disable interrupts by clearing the interrupt masks. */
2208+
ravb_write(ndev, 0, RIC0);
2209+
ravb_write(ndev, 0, RIC2);
2210+
ravb_write(ndev, 0, TIC);
2211+
2212+
/* Only allow ECI interrupts */
2213+
synchronize_irq(priv->emac_irq);
2214+
napi_disable(&priv->napi[RAVB_NC]);
2215+
napi_disable(&priv->napi[RAVB_BE]);
2216+
ravb_write(ndev, ECSIPR_MPDIP, ECSIPR);
2217+
2218+
/* Enable MagicPacket */
2219+
ravb_modify(ndev, ECMR, ECMR_MPDE, ECMR_MPDE);
2220+
2221+
/* Increased clock usage so device won't be suspended */
2222+
clk_enable(priv->clk);
2223+
2224+
return enable_irq_wake(priv->emac_irq);
2225+
}
2226+
2227+
static int ravb_wol_restore(struct net_device *ndev)
2228+
{
2229+
struct ravb_private *priv = netdev_priv(ndev);
2230+
int ret;
2231+
2232+
napi_enable(&priv->napi[RAVB_NC]);
2233+
napi_enable(&priv->napi[RAVB_BE]);
2234+
2235+
/* Disable MagicPacket */
2236+
ravb_modify(ndev, ECMR, ECMR_MPDE, 0);
2237+
2238+
ret = ravb_close(ndev);
2239+
if (ret < 0)
2240+
return ret;
2241+
2242+
/* Restore clock usage count */
2243+
clk_disable(priv->clk);
2244+
2245+
return disable_irq_wake(priv->emac_irq);
2246+
}
2247+
21632248
static int __maybe_unused ravb_suspend(struct device *dev)
21642249
{
21652250
struct net_device *ndev = dev_get_drvdata(dev);
2166-
int ret = 0;
2251+
struct ravb_private *priv = netdev_priv(ndev);
2252+
int ret;
21672253

2168-
if (netif_running(ndev)) {
2169-
netif_device_detach(ndev);
2254+
if (!netif_running(ndev))
2255+
return 0;
2256+
2257+
netif_device_detach(ndev);
2258+
2259+
if (priv->wol_enabled)
2260+
ret = ravb_wol_setup(ndev);
2261+
else
21702262
ret = ravb_close(ndev);
2171-
}
21722263

21732264
return ret;
21742265
}
@@ -2179,6 +2270,33 @@ static int __maybe_unused ravb_resume(struct device *dev)
21792270
struct ravb_private *priv = netdev_priv(ndev);
21802271
int ret = 0;
21812272

2273+
if (priv->wol_enabled) {
2274+
/* Reduce the usecount of the clock to zero and then
2275+
* restore it to its original value. This is done to force
2276+
* the clock to be re-enabled which is a workaround
2277+
* for renesas-cpg-mssr driver which do not enable clocks
2278+
* when resuming from PSCI suspend/resume.
2279+
*
2280+
* Without this workaround the driver fails to communicate
2281+
* with the hardware if WoL was enabled when the system
2282+
* entered PSCI suspend. This is due to that if WoL is enabled
2283+
* we explicitly keep the clock from being turned off when
2284+
* suspending, but in PSCI sleep power is cut so the clock
2285+
* is disabled anyhow, the clock driver is not aware of this
2286+
* so the clock is not turned back on when resuming.
2287+
*
2288+
* TODO: once the renesas-cpg-mssr suspend/resume is working
2289+
* this clock dance should be removed.
2290+
*/
2291+
clk_disable(priv->clk);
2292+
clk_disable(priv->clk);
2293+
clk_enable(priv->clk);
2294+
clk_enable(priv->clk);
2295+
2296+
/* Set reset mode to rearm the WoL logic */
2297+
ravb_write(ndev, CCC_OPC_RESET, CCC);
2298+
}
2299+
21822300
/* All register have been reset to default values.
21832301
* Restore all registers which where setup at probe time and
21842302
* reopen device if it was running before system suspended.
@@ -2202,6 +2320,11 @@ static int __maybe_unused ravb_resume(struct device *dev)
22022320
ravb_write(ndev, priv->desc_bat_dma, DBAT);
22032321

22042322
if (netif_running(ndev)) {
2323+
if (priv->wol_enabled) {
2324+
ret = ravb_wol_restore(ndev);
2325+
if (ret)
2326+
return ret;
2327+
}
22052328
ret = ravb_open(ndev);
22062329
if (ret < 0)
22072330
return ret;

0 commit comments

Comments
 (0)