123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- From: Daniel Golle <daniel@makrotopia.org>
- Subject: 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.
- Signed-off-by: Daniel Golle <daniel@makrotopia.org>
- ---
- drivers/ata/Kconfig | 16 ++++++++++++++++
- drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++++
- include/linux/libata.h | 9 +++++++++
- 3 files changed, 66 insertions(+)
- --- 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
- --- a/drivers/ata/libata-core.c
- +++ b/drivers/ata/libata-core.c
- @@ -731,6 +731,19 @@ u64 ata_tf_read_block(const struct ata_t
- return block;
- }
-
- +#ifdef CONFIG_ATA_LEDS
- +#define LIBATA_BLINK_DELAY 20 /* ms */
- +static inline void ata_led_act(struct ata_port *ap)
- +{
- + unsigned long led_delay = LIBATA_BLINK_DELAY;
- +
- + if (unlikely(!ap->ledtrig))
- + return;
- +
- + led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0);
- +}
- +#endif
- +
- /**
- * ata_build_rw_tf - Build ATA taskfile for given read/write request
- * @tf: Target ATA taskfile
- @@ -4994,6 +5007,9 @@ struct ata_queued_cmd *ata_qc_new_init(s
- if (tag < 0)
- return NULL;
- }
- +#ifdef CONFIG_ATA_LEDS
- + ata_led_act(ap);
- +#endif
-
- qc = __ata_qc_from_tag(ap, tag);
- qc->tag = tag;
- @@ -5895,6 +5911,9 @@ struct ata_port *ata_port_alloc(struct a
- 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;
- @@ -5916,6 +5935,12 @@ static void ata_host_release(struct devi
-
- 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;
- }
- @@ -6362,7 +6387,23 @@ int ata_host_register(struct ata_host *h
- host->ports[i]->print_id = atomic_inc_return(&ata_print_id);
- host->ports[i]->local_port_no = i + 1;
- }
- +#ifdef CONFIG_ATA_LEDS
- + 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]);
- --- a/include/linux/libata.h
- +++ b/include/linux/libata.h
- @@ -38,6 +38,9 @@
- #include <linux/acpi.h>
- #include <linux/cdrom.h>
- #include <linux/sched.h>
- +#ifdef CONFIG_ATA_LEDS
- +#include <linux/leds.h>
- +#endif
-
- /*
- * Define if arch has non-standard setup. This is a _PCI_ standard
- @@ -884,6 +887,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;
- };
|