update LED page

This commit is contained in:
Aditya Prayoga 2018-12-07 11:17:40 +08:00
parent c34e9b2a4e
commit 4e5d9d16a1
4 changed files with 385 additions and 12 deletions

View File

@ -0,0 +1,222 @@
From 7c0053bae4a4e7dbab69402c47eb84e33143a176 Mon Sep 17 00:00:00 2001
Message-Id: <7c0053bae4a4e7dbab69402c47eb84e33143a176.1544101943.git.aditya@kobol.io>
From: Daniel Golle <daniel@makrotopia.org>
Date: Sat, 13 Dec 2014 01:07:20 +0100
Subject: [PATCH] libata: add ledtrig support
This adds a LED trigger for each ATA port indicating disk activity.
As this is needed only on specific platforms (NAS SoCs and such),
these platforms should define ARCH_WANTS_LIBATA_LEDS if there
are boards with LED(s) intended to indicate ATA disk activity and
need the OS to take care of that.
In that way, if not selected, LED trigger support not will be
included in libata-core and both, codepaths and structures remain
untouched.
I'm currently deploying this for the oxnas target in OpenWrt
https://dev.openwrt.org/changeset/43675/
v2: rebased to kernel/git/tj/libata.git
plus small corrections and comments added
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
URL: https://patchwork.ozlabs.org/patch/420733/
[Aditya Prayoga:
* Port forward
* Change ATA_LEDS default to no
* Reduce performance impact by moving ata_led_act() call from
ata_qc_new() to ata_qc_complete()]
Signed-off-by: Aditya Prayoga <aditya@kobol.io>
ARM: mvebu: Enable ARCH_WANT_LIBATA_LEDS in Armada 38x
Enable hidden symbol ARCH_WANT_LIBATA_LEDS so CONFIG_ATA_LEDS can be
used in kernel configuration.
URL: https://lists.openwrt.org/pipermail/openwrt-
devel/2017-March/006582.html
Signed-off-by: Aditya Prayoga <aditya@kobol.io>
---
arch/arm/configs/mvebu_v7_defconfig | 1 +
arch/arm/mach-mvebu/Kconfig | 1 +
drivers/ata/Kconfig | 16 +++++++++++
drivers/ata/libata-core.c | 56 +++++++++++++++++++++++++++++++++++++
include/linux/libata.h | 7 +++++
5 files changed, 81 insertions(+)
diff --git a/arch/arm/configs/mvebu_v7_defconfig b/arch/arm/configs/mvebu_v7_defconfig
index 5514021..3d39ab2 100644
--- a/arch/arm/configs/mvebu_v7_defconfig
+++ b/arch/arm/configs/mvebu_v7_defconfig
@@ -59,6 +59,7 @@ CONFIG_MTD_UBI=y
CONFIG_EEPROM_AT24=y
CONFIG_BLK_DEV_SD=y
CONFIG_ATA=y
+CONFIG_ATA_LEDS=y
CONFIG_SATA_AHCI=y
CONFIG_AHCI_MVEBU=y
CONFIG_SATA_MV=y
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 2c20599..51f3256 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -68,6 +68,7 @@ config MACH_ARMADA_38X
select HAVE_SMP
select MACH_MVEBU_V7
select PINCTRL_ARMADA_38X
+ select ARCH_WANT_LIBATA_LEDS
help
Say 'Y' here if you want your kernel to support boards based
on the Marvell Armada 380/385 SoC with device tree.
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 39b181d..143bbd5 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -46,6 +46,22 @@ config ATA_VERBOSE_ERROR
If unsure, say Y.
+config ARCH_WANT_LIBATA_LEDS
+ bool
+
+config ATA_LEDS
+ bool "support ATA port LED triggers"
+ depends on ARCH_WANT_LIBATA_LEDS
+ select NEW_LEDS
+ select LEDS_CLASS
+ select LEDS_TRIGGERS
+ default y
+ help
+ This option adds a LED trigger for each registered ATA port.
+ It is used to drive disk activity leds connected via GPIO.
+
+ If unsure, say N.
+
config ATA_ACPI
bool "ATA ACPI Support"
depends on ACPI
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 599e01b..65228f5 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5105,6 +5105,30 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
}
/**
+ * ata_led_act - Trigger port activity LED
+ * @ap: indicating port
+ *
+ * Blinks any LEDs registered to the trigger.
+ * Commonly used with leds-gpio on NAS systems with disk activity
+ * indicator LEDs.
+ *
+ * LOCKING:
+ * None.
+ */
+static inline void ata_led_act(struct ata_port *ap)
+{
+#ifdef CONFIG_ATA_LEDS
+#define LIBATA_BLINK_DELAY 20 /* ms */
+ unsigned long led_delay = LIBATA_BLINK_DELAY;
+
+ if (unlikely(!ap->ledtrig))
+ return;
+
+ led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0);
+#endif /* CONFIG_ATA_LEDS */
+}
+
+/**
* ata_qc_new_init - Request an available ATA command, and initialize it
* @dev: Device from whom we request an available command structure
* @tag: tag
@@ -5249,6 +5273,10 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
/* Trigger the LED (if available) */
ledtrig_disk_activity(!!(qc->tf.flags & ATA_TFLAG_WRITE));
+#ifdef CONFIG_ATA_LEDS
+ ata_led_act(ap);
+#endif
+
/* XXX: New EH and old EH use different mechanisms to
* synchronize EH with regular execution path.
*
@@ -6028,6 +6056,9 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
ap->stats.unhandled_irq = 1;
ap->stats.idle_irq = 1;
#endif
+#ifdef CONFIG_ATA_LEDS
+ ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
+#endif
ata_sff_port_init(ap);
return ap;
@@ -6063,6 +6094,12 @@ static void ata_host_release(struct kref *kref)
kfree(ap->pmp_link);
kfree(ap->slave_link);
+#ifdef CONFIG_ATA_LEDS
+ if (ap->ledtrig) {
+ led_trigger_unregister(ap->ledtrig);
+ kfree(ap->ledtrig);
+ };
+#endif
kfree(ap);
host->ports[i] = NULL;
}
@@ -6527,6 +6564,25 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
host->ports[i]->local_port_no = i + 1;
}
+#ifdef CONFIG_ATA_LEDS
+ /* register LED triggers for all ports */
+ for (i = 0; i < host->n_ports; i++) {
+ if (unlikely(!host->ports[i]->ledtrig))
+ continue;
+
+ snprintf(host->ports[i]->ledtrig_name,
+ sizeof(host->ports[i]->ledtrig_name), "ata%u",
+ host->ports[i]->print_id);
+
+ host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name;
+
+ if (led_trigger_register(host->ports[i]->ledtrig)) {
+ kfree(host->ports[i]->ledtrig);
+ host->ports[i]->ledtrig = NULL;
+ }
+ }
+#endif
+
/* Create associated sysfs transport objects */
for (i = 0; i < host->n_ports; i++) {
rc = ata_tport_add(host->dev,host->ports[i]);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 38c95d6..3cc5f63 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -38,6 +38,7 @@
#include <linux/acpi.h>
#include <linux/cdrom.h>
#include <linux/sched.h>
+#include <linux/leds.h>
/*
* Define if arch has non-standard setup. This is a _PCI_ standard
@@ -893,6 +894,12 @@ struct ata_port {
#ifdef CONFIG_ATA_ACPI
struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */
#endif
+
+#ifdef CONFIG_ATA_LEDS
+ struct led_trigger *ledtrig;
+ char ledtrig_name[8];
+#endif
+
/* owned by EH */
u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned;
};
--
2.7.4

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -1,6 +1,25 @@
![LED location](/img/led/led_location.png)
## On-Board LEDs
| LED number | Color | Software control | Remarks |
|------------|-------|------------------|---------|
| LED1 | Green | Yes | Active-low |
| LED2 | Red | Yes | Active-low |
| LED3 | Green | Yes | Active-low |
| LED4 | Green | Yes | Active-low |
| LED5 | Green | Yes | Active-low |
| LED6 | Green | Yes | Active-low |
| LED7 | Green | Yes | Active-low |
| LED8 | Green | No | Power indicator |
!!! info
LED1 - LED7 is preconfigured for certain indicator under Linux, see [LED under Linux](#led-under-linux)
## Expansion Panel (J18)
Helios4 board was designed to either use the on-board LEDs or use a custom expansion panel (not-available). If you wish to use the header insure to switch to OFF the DIP switch SW2.
Helios4 board was designed to either use the on-board LEDs or use a custom expansion panel (not-available).
If you wish to use the header insure to switch to OFF the DIP switch SW2.
![Dipswitch LED](/img/led/dipswitch_led_off.png)
@ -9,14 +28,146 @@ Helios4 board was designed to either use the on-board LEDs or use a custom expan
![J18 Pinout](/img/led/gpio_pinout_j18.png)
| Pin | LED number | Remarks |
|------------|----------|---------|
| 1 | - | 3.3V supply |
| 2 | - | Not connected |
| 3 | LED1 | Heartbeat LED |
| 4 | LED2 | System Fault LED |
| 5 | LED3 | SATA port 1 LED |
| 6 | LED4 | SATA port 2 LED |
| 7 | LED5 | SATA port 3 LED |
| 8 | LED6 | SATA port 4 LED |
| 9 | LED7 | USB activity LED |
| 10 | - | GND |
|-----|------------|---------|
| 1 | - | 3.3V supply |
| 2 | - | Not connected |
| 3 | LED1 | Active-low |
| 4 | LED2 | Active-low |
| 5 | LED3 | Active-low |
| 6 | LED4 | Active-low |
| 7 | LED5 | Active-low |
| 8 | LED6 | Active-low |
| 9 | LED7 | Active-low |
| 10 | - | GND |
!!! info
LED1 - LED7 is preconfigured for certain indicator under Linux, see [LED under Linux](#led-under-linux)
### Wiring Diagram
Since the signals to control the LEDs are active low, connect the pin to LED's cathode.
Below is example of the wiring diagram.
![Wiring Example](/img/led/led_expansion_wiring_diagram.png)
## LED under Linux
| LED | Name | Default Trigger | Remarks |
|------|----------------------|-----------------|---------|
| LED1 | helios4:green:status | heartbeat | Blinking periodically |
| LED2 | helios4:red:fault | none | See [Configuring Fault LED](#configuring-fault-led) |
| LED3 | helios4:green:ata1 | ata1 | Blinking on SATA1 activity |
| LED4 | helios4:green:ata2 | ata2 | Blinking on SATA2 activity |
| LED5 | helios4:green:ata3 | ata3 | Blinking on SATA3 activity |
| LED6 | helios4:green:ata4 | ata4 | Blinking on SATA4 activity |
| LED7 | helios4:green:usb | usb-host | Blinking on USB activity, any port |
!!! note
**ata* ** trigger requires additional patch to mainline kernel. The patch can be found from
[here](/files/led/libata_leds_trigger_mvebu.patch) and is not needed for Armbian.
The LEDs can be accessed under leds class in sysfs.
```
root@helios4:~/# ls -l /sys/class/leds/
lrwxrwxrwx 1 root root 0 Dec 4 06:57 helios4:green:ata1 -> ../../devices/platform/io-leds/leds/helios4:green:ata1
lrwxrwxrwx 1 root root 0 Dec 4 06:57 helios4:green:ata2 -> ../../devices/platform/io-leds/leds/helios4:green:ata2
lrwxrwxrwx 1 root root 0 Dec 4 06:57 helios4:green:ata3 -> ../../devices/platform/io-leds/leds/helios4:green:ata3
lrwxrwxrwx 1 root root 0 Dec 4 06:57 helios4:green:ata4 -> ../../devices/platform/io-leds/leds/helios4:green:ata4
lrwxrwxrwx 1 root root 0 Dec 4 06:57 helios4:green:status -> ../../devices/platform/system-leds/leds/helios4:green:status
lrwxrwxrwx 1 root root 0 Dec 4 06:57 helios4:green:usb -> ../../devices/platform/io-leds/leds/helios4:green:usb
lrwxrwxrwx 1 root root 0 Dec 4 06:57 helios4:red:fault -> ../../devices/platform/system-leds/leds/helios4:red:fault
```
### LEDs Trigger
- none
No automatic trigger. Manually control the LED by manipulating "brightness".
More info see [Configuring LED trigger](#configuring-led-trigger).
- heartbeat
LED "double" flashes at a load average based rate. The interval might changed during high load.
If the LED no longer blink, that is mean the system lock-up or hung and has to be reset'd.
- ataN
LED blink on any read/write activity at specific SATA port.
- usb-host
LED blink on USB activity at any port.
- panic
This trigger allows LEDs to be configured to blink on a kernel panic.
- timer
This allows LEDs to be controlled by a programmable timer via sysfs. delay_on to set how long
the led turned on and delay_off to set how long the led turned off.
### Configuring LED trigger
To configure, simply set the trigger type. For example to set status led triggered by timer
```
echo timer | sudo tee -a /sys/class/leds/helios4\:green\:status/trigger
```
and done.
Some of the trigger may exposed additional parameter than can be configured further.
On **none** trigger, to turn on the LED set the brightness bigger than 0.
```
echo 1 | sudo tee -a /sys/class/leds/helios4\:green\:status/brightness
```
and to turn off the LED set the brightness to 0.
```
echo 0 | sudo tee -a /sys/class/leds/helios4\:green\:status/brightness
```
On **timer** trigger, it will exposed *delay_on* and *delay_off* with default value both 0.5 seconds.
To change the delay, set the respective parameter (value in milliseconds)
```
echo 1000 | sudo tee -a /sys/class/leds/helios4\:green\:status/delay_on
echo 200 | sudo tee -a /sys/class/leds/helios4\:green\:status/delay_off
```
!!! note
The changes is not retained across reboot. Use startup script or udev rules to make it permanent.
### Configuring Fault LED
While other LEDs are preconfigured, the fault LED remains unconfigured (trigger:**none**).
#### 1. As Kernel Panic Indicator
To configure the LED as Kernel panic indicator, set the trigger to **panic**.
However, this functionality might be redundant with status LED. If the status LED no longer blinking,
that mean the system is hung which can be translated into kernel panic occurred.
To trigger kernel panic to test the LED, run
```
echo c > /proc/sysrq-trigger
```
!!! warning
Triggering kernel panic can lead to data loss. Use with caution!
#### 2. As MDADM Fault Indicator
To configure the LED as MDADM fault indicator, please refer to [MDADM: Configure Fault LED](/mdadm/#configure-fault-led)
!!! info
On Armbian, this is the default setting for fault LED.