b2c0b4898076470aafc839e10f471bba56faefc4
[openwrt/openwrt.git] / target / linux / generic / pending-4.9 / 834-ledtrig-libata.patch
1 From: Daniel Golle <daniel@makrotopia.org>
2 Subject: libata: add ledtrig support
3
4 This adds a LED trigger for each ATA port indicating disk activity.
5
6 As this is needed only on specific platforms (NAS SoCs and such),
7 these platforms should define ARCH_WANTS_LIBATA_LEDS if there
8 are boards with LED(s) intended to indicate ATA disk activity and
9 need the OS to take care of that.
10 In that way, if not selected, LED trigger support not will be
11 included in libata-core and both, codepaths and structures remain
12 untouched.
13
14 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
15 ---
16 drivers/ata/Kconfig | 16 ++++++++++++++++
17 drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++++
18 include/linux/libata.h | 9 +++++++++
19 3 files changed, 66 insertions(+)
20
21 --- a/drivers/ata/Kconfig
22 +++ b/drivers/ata/Kconfig
23 @@ -46,6 +46,22 @@ config ATA_VERBOSE_ERROR
24
25 If unsure, say Y.
26
27 +config ARCH_WANT_LIBATA_LEDS
28 + bool
29 +
30 +config ATA_LEDS
31 + bool "support ATA port LED triggers"
32 + depends on ARCH_WANT_LIBATA_LEDS
33 + select NEW_LEDS
34 + select LEDS_CLASS
35 + select LEDS_TRIGGERS
36 + default y
37 + help
38 + This option adds a LED trigger for each registered ATA port.
39 + It is used to drive disk activity leds connected via GPIO.
40 +
41 + If unsure, say N.
42 +
43 config ATA_ACPI
44 bool "ATA ACPI Support"
45 depends on ACPI
46 --- a/drivers/ata/libata-core.c
47 +++ b/drivers/ata/libata-core.c
48 @@ -731,6 +731,19 @@ u64 ata_tf_read_block(const struct ata_t
49 return block;
50 }
51
52 +#ifdef CONFIG_ATA_LEDS
53 +#define LIBATA_BLINK_DELAY 20 /* ms */
54 +static inline void ata_led_act(struct ata_port *ap)
55 +{
56 + unsigned long led_delay = LIBATA_BLINK_DELAY;
57 +
58 + if (unlikely(!ap->ledtrig))
59 + return;
60 +
61 + led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0);
62 +}
63 +#endif
64 +
65 /**
66 * ata_build_rw_tf - Build ATA taskfile for given read/write request
67 * @tf: Target ATA taskfile
68 @@ -4994,6 +5007,9 @@ struct ata_queued_cmd *ata_qc_new_init(s
69 if (tag < 0)
70 return NULL;
71 }
72 +#ifdef CONFIG_ATA_LEDS
73 + ata_led_act(ap);
74 +#endif
75
76 qc = __ata_qc_from_tag(ap, tag);
77 qc->tag = tag;
78 @@ -5895,6 +5911,9 @@ struct ata_port *ata_port_alloc(struct a
79 ap->stats.unhandled_irq = 1;
80 ap->stats.idle_irq = 1;
81 #endif
82 +#ifdef CONFIG_ATA_LEDS
83 + ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
84 +#endif
85 ata_sff_port_init(ap);
86
87 return ap;
88 @@ -5916,6 +5935,12 @@ static void ata_host_release(struct devi
89
90 kfree(ap->pmp_link);
91 kfree(ap->slave_link);
92 +#ifdef CONFIG_ATA_LEDS
93 + if (ap->ledtrig) {
94 + led_trigger_unregister(ap->ledtrig);
95 + kfree(ap->ledtrig);
96 + };
97 +#endif
98 kfree(ap);
99 host->ports[i] = NULL;
100 }
101 @@ -6362,7 +6387,23 @@ int ata_host_register(struct ata_host *h
102 host->ports[i]->print_id = atomic_inc_return(&ata_print_id);
103 host->ports[i]->local_port_no = i + 1;
104 }
105 +#ifdef CONFIG_ATA_LEDS
106 + for (i = 0; i < host->n_ports; i++) {
107 + if (unlikely(!host->ports[i]->ledtrig))
108 + continue;
109
110 + snprintf(host->ports[i]->ledtrig_name,
111 + sizeof(host->ports[i]->ledtrig_name), "ata%u",
112 + host->ports[i]->print_id);
113 +
114 + host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name;
115 +
116 + if (led_trigger_register(host->ports[i]->ledtrig)) {
117 + kfree(host->ports[i]->ledtrig);
118 + host->ports[i]->ledtrig = NULL;
119 + }
120 + }
121 +#endif
122 /* Create associated sysfs transport objects */
123 for (i = 0; i < host->n_ports; i++) {
124 rc = ata_tport_add(host->dev,host->ports[i]);
125 --- a/include/linux/libata.h
126 +++ b/include/linux/libata.h
127 @@ -38,6 +38,9 @@
128 #include <linux/acpi.h>
129 #include <linux/cdrom.h>
130 #include <linux/sched.h>
131 +#ifdef CONFIG_ATA_LEDS
132 +#include <linux/leds.h>
133 +#endif
134
135 /*
136 * Define if arch has non-standard setup. This is a _PCI_ standard
137 @@ -884,6 +887,12 @@ struct ata_port {
138 #ifdef CONFIG_ATA_ACPI
139 struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */
140 #endif
141 +
142 +#ifdef CONFIG_ATA_LEDS
143 + struct led_trigger *ledtrig;
144 + char ledtrig_name[8];
145 +#endif
146 +
147 /* owned by EH */
148 u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned;
149 };