Added Wake on LAN
This commit is contained in:
parent
3eb8494c5e
commit
c751e1d121
5 changed files with 261 additions and 0 deletions
23
docs/files/wol/helios4-dts-add-wake-on-lan-support.patch
Normal file
23
docs/files/wol/helios4-dts-add-wake-on-lan-support.patch
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/armada-388-helios4.dts
|
||||||
|
index 705adfa8c..d5afbfc53 100644
|
||||||
|
--- a/arch/arm/boot/dts/armada-388-helios4.dts
|
||||||
|
+++ b/arch/arm/boot/dts/armada-388-helios4.dts
|
||||||
|
@@ -84,6 +84,18 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
+ gpio-keys {
|
||||||
|
+ compatible = "gpio-keys";
|
||||||
|
+ pinctrl-0 = <µsom_phy0_int_pins>;
|
||||||
|
+
|
||||||
|
+ wol {
|
||||||
|
+ label = "Wake-On-LAN";
|
||||||
|
+ linux,code = <KEY_WAKEUP>;
|
||||||
|
+ gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
|
||||||
|
+ wakeup-source;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
io-leds {
|
||||||
|
compatible = "gpio-leds";
|
||||||
|
sata1-led {
|
|
@ -0,0 +1,90 @@
|
||||||
|
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
|
||||||
|
index 661c5a38f..a25d61d54 100644
|
||||||
|
--- a/drivers/gpio/gpio-mvebu.c
|
||||||
|
+++ b/drivers/gpio/gpio-mvebu.c
|
||||||
|
@@ -38,6 +38,7 @@
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
+#include <linux/interrupt.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
#include <linux/irqchip/chained_irq.h>
|
||||||
|
@@ -133,7 +134,7 @@ struct mvebu_gpio_chip {
|
||||||
|
struct regmap *regs;
|
||||||
|
u32 offset;
|
||||||
|
struct regmap *percpu_regs;
|
||||||
|
- int irqbase;
|
||||||
|
+ int bank_irq[4];
|
||||||
|
struct irq_domain *domain;
|
||||||
|
int soc_variant;
|
||||||
|
|
||||||
|
@@ -608,6 +609,33 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
|
||||||
|
chained_irq_exit(chip, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Set interrupt number "irq" in the GPIO as a wake-up source.
|
||||||
|
+ * While system is running, all registered GPIO interrupts need to have
|
||||||
|
+ * wake-up enabled. When system is suspended, only selected GPIO interrupts
|
||||||
|
+ * need to have wake-up enabled.
|
||||||
|
+ * @param irq interrupt source number
|
||||||
|
+ * @param enable enable as wake-up if equal to non-zero
|
||||||
|
+ * @return This function returns 0 on success.
|
||||||
|
+ */
|
||||||
|
+static int mvebu_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
|
||||||
|
+{
|
||||||
|
+ struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
|
||||||
|
+ struct mvebu_gpio_chip *mvchip = gc->private;
|
||||||
|
+ int irq;
|
||||||
|
+ int bank;
|
||||||
|
+
|
||||||
|
+ bank = d->hwirq % 8;
|
||||||
|
+ irq = mvchip->bank_irq[bank];
|
||||||
|
+
|
||||||
|
+ if (enable)
|
||||||
|
+ enable_irq_wake(irq);
|
||||||
|
+ else
|
||||||
|
+ disable_irq_wake(irq);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Functions implementing the pwm_chip methods
|
||||||
|
*/
|
||||||
|
@@ -1277,7 +1305,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
|
err = irq_alloc_domain_generic_chips(
|
||||||
|
mvchip->domain, ngpios, 2, np->name, handle_level_irq,
|
||||||
|
- IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0);
|
||||||
|
+ IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, IRQ_GC_INIT_NESTED_LOCK);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n",
|
||||||
|
mvchip->chip.label);
|
||||||
|
@@ -1295,6 +1323,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
||||||
|
ct->chip.irq_mask = mvebu_gpio_level_irq_mask;
|
||||||
|
ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask;
|
||||||
|
ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
|
||||||
|
+ ct->chip.irq_set_wake = mvebu_gpio_set_wake_irq;
|
||||||
|
+ ct->chip.flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
|
||||||
|
ct->chip.name = mvchip->chip.label;
|
||||||
|
|
||||||
|
ct = &gc->chip_types[1];
|
||||||
|
@@ -1303,6 +1333,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
||||||
|
ct->chip.irq_mask = mvebu_gpio_edge_irq_mask;
|
||||||
|
ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask;
|
||||||
|
ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
|
||||||
|
+ ct->chip.irq_set_wake = mvebu_gpio_set_wake_irq;
|
||||||
|
+ ct->chip.flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_MASK_ON_SUSPEND;
|
||||||
|
ct->handler = handle_edge_irq;
|
||||||
|
ct->chip.name = mvchip->chip.label;
|
||||||
|
|
||||||
|
@@ -1318,6 +1350,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
|
||||||
|
continue;
|
||||||
|
irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler,
|
||||||
|
mvchip);
|
||||||
|
+ mvchip->bank_irq[i] = irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some MVEBU SoCs have simple PWM support for GPIO lines */
|
BIN
docs/img/wol/schematic.png
Normal file
BIN
docs/img/wol/schematic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
147
docs/wol.md
Normal file
147
docs/wol.md
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
|
||||||
|
![Ethernet PHY](/img/wol/schematic.png)
|
||||||
|
|
||||||
|
The ARMADA 388 provides several waking options sourced by different peripherals to take the system out of power save modes. Some of the options are
|
||||||
|
|
||||||
|
* Wake on GPIO
|
||||||
|
|
||||||
|
* Wake on LAN
|
||||||
|
|
||||||
|
Currently Helios4 use PHY interrupt and Wake on GPIO event to implement Wake on LAN.
|
||||||
|
|
||||||
|
## Device Tree Support
|
||||||
|
|
||||||
|
Linux provides gpio-keys driver to handle GPIO event and can be configured as wakeup source.
|
||||||
|
|
||||||
|
```
|
||||||
|
gpio-keys {
|
||||||
|
compatible = "gpio-keys";
|
||||||
|
pinctrl-0 = <µsom_phy0_int_pins>;
|
||||||
|
|
||||||
|
wol {
|
||||||
|
label = "Wake-On-LAN";
|
||||||
|
linux,code = <KEY_WAKEUP>;
|
||||||
|
gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
|
||||||
|
wakeup-source;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Device Tree Patch can be found [here](/files/wol/helios4-dts-add-wake-on-lan-support.patch)
|
||||||
|
|
||||||
|
## Kernel Patch
|
||||||
|
|
||||||
|
Current gpio-mvebu driver does not implement [irq_set_wake()](https://www.kernel.org/doc/html/v4.14/core-api/genericirq.html?highlight=irq_set_wake#c.irq_chip)
|
||||||
|
to support GPIO as wakeup source and properly route it to upper interrupt controller (Arm GIC).
|
||||||
|
|
||||||
|
This will raise following issues:
|
||||||
|
|
||||||
|
- System unable to wake up from Suspend-to-RAM
|
||||||
|
|
||||||
|
- Kernel crash during wakeup from standby
|
||||||
|
|
||||||
|
```
|
||||||
|
[ 59.169436] ------------[ cut here ]------------
|
||||||
|
[ 59.174075] WARNING: CPU: 0 PID: 1535 at kernel/irq/manage.c:623 irq_set_irq_wake+0xe4/0x11c
|
||||||
|
[ 59.182533] Unbalanced IRQ 50 wake disable
|
||||||
|
[ 59.186638] Modules linked in: lz4hc lz4hc_compress marvell_cesa zram zsmalloc lm75 pwm_fan ip_tables x_tables
|
||||||
|
[ 59.196690] CPU: 0 PID: 1535 Comm: bash Not tainted 4.14.94-mvebu+ #14
|
||||||
|
[ 59.203234] Hardware name: Marvell Armada 380/385 (Device Tree)
|
||||||
|
[ 59.209183] [<c01118d0>] (unwind_backtrace) from [<c010c7cc>] (show_stack+0x10/0x14)
|
||||||
|
[ 59.216955] [<c010c7cc>] (show_stack) from [<c095091c>] (dump_stack+0x88/0x9c)
|
||||||
|
[ 59.224204] [<c095091c>] (dump_stack) from [<c012ab9c>] (__warn+0xe8/0x100)
|
||||||
|
[ 59.231188] [<c012ab9c>] (__warn) from [<c012abfc>] (warn_slowpath_fmt+0x48/0x6c)
|
||||||
|
[ 59.238696] [<c012abfc>] (warn_slowpath_fmt) from [<c017bb64>] (irq_set_irq_wake+0xe4/0x11c)
|
||||||
|
[ 59.247160] [<c017bb64>] (irq_set_irq_wake) from [<c0747594>] (gpio_keys_resume+0xb0/0x11c)
|
||||||
|
[ 59.255537] [<c0747594>] (gpio_keys_resume) from [<c0654b34>] (dpm_run_callback+0x54/0xec)
|
||||||
|
[ 59.263826] [<c0654b34>] (dpm_run_callback) from [<c0655180>] (device_resume+0xcc/0x270)
|
||||||
|
[ 59.271941] [<c0655180>] (device_resume) from [<c0656660>] (dpm_resume+0x100/0x230)
|
||||||
|
[ 59.279621] [<c0656660>] (dpm_resume) from [<c06569e4>] (dpm_resume_end+0xc/0x18)
|
||||||
|
[ 59.287128] [<c06569e4>] (dpm_resume_end) from [<c0175af8>] (suspend_devices_and_enter+0x210/0x5e0)
|
||||||
|
[ 59.296202] [<c0175af8>] (suspend_devices_and_enter) from [<c01761c0>] (pm_suspend+0x2f8/0x380)
|
||||||
|
[ 59.304927] [<c01761c0>] (pm_suspend) from [<c0174a30>] (state_store+0x70/0xcc)
|
||||||
|
[ 59.312260] [<c0174a30>] (state_store) from [<c02c80e4>] (kernfs_fop_write+0xe8/0x1c4)
|
||||||
|
[ 59.320204] [<c02c80e4>] (kernfs_fop_write) from [<c024ce78>] (vfs_write+0xa4/0x1b4)
|
||||||
|
[ 59.327972] [<c024ce78>] (vfs_write) from [<c024d0b4>] (SyS_write+0x4c/0xac)
|
||||||
|
[ 59.335045] [<c024d0b4>] (SyS_write) from [<c0108620>] (ret_fast_syscall+0x0/0x54)
|
||||||
|
[ 59.342633] ---[ end trace c725de247edb5ce9 ]---
|
||||||
|
[ 59.474369] ata2: SATA link down (SStatus 0 SControl 300)
|
||||||
|
[ 59.474443] ata3: SATA link down (SStatus 0 SControl 300)
|
||||||
|
[ 59.638619] ata1: SATA link down (SStatus 0 SControl 300)
|
||||||
|
[ 59.647170] ata4: SATA link up 3.0 Gbps (SStatus 123 SControl 300)
|
||||||
|
[ 60.081905] ata1: SATA link down (SStatus 0 SControl 300)
|
||||||
|
[ 60.087343] ata1: limiting SATA link speed to 1.5 Gbps
|
||||||
|
[ 60.386518] mvneta f1070000.ethernet eth0: Link is Down
|
||||||
|
[ 60.578411] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 310)
|
||||||
|
[ 61.162892] ata4.00: configured for UDMA/100
|
||||||
|
[ 62.431232] mvneta f1070000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
|
||||||
|
[ 63.087435] ata1.00: configured for UDMA/100
|
||||||
|
[ 63.159889] OOM killer enabled.
|
||||||
|
[ 63.164643] Restarting tasks ... done.
|
||||||
|
[ 63.181059] PM: suspend exit
|
||||||
|
```
|
||||||
|
|
||||||
|
- System can wake up from any GPIO interrupt without need to define as wakeup source
|
||||||
|
|
||||||
|
To fix the issue, gpio-mvebu driver needs to be patched to implement [irq_set_wake()](https://www.kernel.org/doc/html/v4.14/core-api/genericirq.html?highlight=irq_set_wake#c.irq_chip)
|
||||||
|
and only enable interrupt on GPIO defined as wakeup source.
|
||||||
|
|
||||||
|
Patch for Linux Kernel 4.14.x can be found [here](/files/wol/lk4.14-mvebu-gpio-add_wake_on_gpio_support.patch)
|
||||||
|
|
||||||
|
|
||||||
|
## Enabling WoL
|
||||||
|
|
||||||
|
Enable the PHY to only raise interrupt when magic packet received then enter suspend mode with these commands:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo ethtool -s eth0 wol g
|
||||||
|
sudo systemctl suspend
|
||||||
|
```
|
||||||
|
|
||||||
|
Both command has to be executed to enter suspend mode otherwise there is a risk that Helios4 will not wake up on magic packet received event.
|
||||||
|
More explaination regarding this issue on next section.
|
||||||
|
|
||||||
|
## Limitation with Current Approach
|
||||||
|
|
||||||
|
PHY INT pin supposed to be handled by the Ethernet controller so when there is an interrupt the driver can respond and acknowledge the interrupt.
|
||||||
|
Without this acknowledgement, the PHY INT pin will stay active and the PHY will not trigger another interrupt.
|
||||||
|
|
||||||
|
On specific case that after user enabled the wol and magic packet received before entering suspend mode, Helios4 will not able to wake up.
|
||||||
|
The reason is PHY interrupt already triggered before entering suspend mode and no other interrupt triggered during suspend mode.
|
||||||
|
The Ethernet controller driver will reset PHY interrupt during resume and when enabling wol.
|
||||||
|
Therefore it is advised to always set wol (**sudo ethtool -s eth0 wol g**) before entering suspend.
|
||||||
|
|
||||||
|
## Power Consumption
|
||||||
|
|
||||||
|
Measured using Sonoff POW R2 on AC side
|
||||||
|
|
||||||
|
| Power state | Power (Watt) | Current (Ampere) | Remarks |
|
||||||
|
|---------------|---------------|------------------|---------|
|
||||||
|
| Idle | 16.18 - 19.87 | 0.14 - 0.17 | |
|
||||||
|
| Standby | 8.24 - 8.63 | 0.09 - 0.10 | |
|
||||||
|
| Suspend | 7.46 - 7.71 | 0.07 - 0.08 | |
|
||||||
|
| Halt/Shutdown | 11.95 | 0.11 | HDDs still active, fans run on full speed |
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
* Nominal Input Voltage: 220V
|
||||||
|
* HDD: 4x WD Red 2TB (WD20EFRX)
|
||||||
|
* [I2C OLED screen](/i2c/) attached to the systems
|
||||||
|
* Variation of power consumption sometimes due to fluctutation of the input voltage
|
||||||
|
|
||||||
|
## Thermal Issue
|
||||||
|
|
||||||
|
Using [Batch 2 fan](/pwm/#new-fan-batch-2)
|
||||||
|
|
||||||
|
| Power state | Temperature (°C) | Remarks |
|
||||||
|
|---------------|------------------|---------|
|
||||||
|
| Standby | 89 - 90 | Fan stopped |
|
||||||
|
| Suspend | 81 - 87 | Fan stopped |
|
||||||
|
|
||||||
|
Using [Batch 1 fan](/pwm/#old-fan-batch-1)
|
||||||
|
|
||||||
|
| Power state | Temperature (°C) | Remarks |
|
||||||
|
|---------------|------------------|---------|
|
||||||
|
| Standby | - | Not yet tested |
|
||||||
|
| Suspend | 74 -76 | Fan run in minimum speed |
|
||||||
|
|
|
@ -75,6 +75,7 @@ pages:
|
||||||
- PWM (Fan) : 'pwm.md'
|
- PWM (Fan) : 'pwm.md'
|
||||||
- SDIO (SD Card) : 'sdcard.md'
|
- SDIO (SD Card) : 'sdcard.md'
|
||||||
- SPI (NOR Flash) : 'spi.md'
|
- SPI (NOR Flash) : 'spi.md'
|
||||||
|
- Wake-On-LAN : 'wol.md'
|
||||||
- Development:
|
- Development:
|
||||||
- Armbian : 'armbian.md'
|
- Armbian : 'armbian.md'
|
||||||
- FreeBSD : 'freebsd.md'
|
- FreeBSD : 'freebsd.md'
|
||||||
|
|
Loading…
Reference in a new issue