1
0

834-ledtrig-libata.patch 3.9 KB

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