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