834-ledtrig-libata.patch 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. From: Daniel Golle <[email protected]>
  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 <[email protected]>
  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. @@ -67,6 +67,22 @@ config ATA_FORCE
  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. @@ -663,6 +663,19 @@ u64 ata_tf_read_block(const struct ata_t
  43. qc->flags |= ATA_QCFLAG_HAS_CDL | ATA_QCFLAG_RESULT_TF;
  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. * @qc: Metadata associated with the taskfile to build
  61. @@ -4716,6 +4729,9 @@ void __ata_qc_complete(struct ata_queued
  62. link->active_tag = ATA_TAG_POISON;
  63. ap->nr_active_links--;
  64. }
  65. +#ifdef CONFIG_ATA_LEDS
  66. + ata_led_act(ap);
  67. +#endif
  68. /* clear exclusive status */
  69. if (unlikely(qc->flags & ATA_QCFLAG_CLEAR_EXCL &&
  70. @@ -5438,6 +5454,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. @@ -5469,6 +5488,12 @@ static void ata_host_release(struct kref
  80. kfree(ap->pmp_link);
  81. kfree(ap->slave_link);
  82. kfree(ap->ncq_sense_buf);
  83. +#ifdef CONFIG_ATA_LEDS
  84. + if (ap->ledtrig) {
  85. + led_trigger_unregister(ap->ledtrig);
  86. + kfree(ap->ledtrig);
  87. + };
  88. +#endif
  89. kfree(ap);
  90. host->ports[i] = NULL;
  91. }
  92. @@ -5875,7 +5900,23 @@ int ata_host_register(struct ata_host *h
  93. host->ports[i]->print_id = atomic_inc_return(&ata_print_id);
  94. host->ports[i]->local_port_no = i + 1;
  95. }
  96. +#ifdef CONFIG_ATA_LEDS
  97. + for (i = 0; i < host->n_ports; i++) {
  98. + if (unlikely(!host->ports[i]->ledtrig))
  99. + continue;
  100. + snprintf(host->ports[i]->ledtrig_name,
  101. + sizeof(host->ports[i]->ledtrig_name), "ata%u",
  102. + host->ports[i]->print_id);
  103. +
  104. + host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name;
  105. +
  106. + if (led_trigger_register(host->ports[i]->ledtrig)) {
  107. + kfree(host->ports[i]->ledtrig);
  108. + host->ports[i]->ledtrig = NULL;
  109. + }
  110. + }
  111. +#endif
  112. /* Create associated sysfs transport objects */
  113. for (i = 0; i < host->n_ports; i++) {
  114. rc = ata_tport_add(host->dev,host->ports[i]);
  115. --- a/include/linux/libata.h
  116. +++ b/include/linux/libata.h
  117. @@ -23,6 +23,9 @@
  118. #include <linux/cdrom.h>
  119. #include <linux/sched.h>
  120. #include <linux/async.h>
  121. +#ifdef CONFIG_ATA_LEDS
  122. +#include <linux/leds.h>
  123. +#endif
  124. /*
  125. * Define if arch has non-standard setup. This is a _PCI_ standard
  126. @@ -864,6 +867,12 @@ struct ata_port {
  127. #ifdef CONFIG_ATA_ACPI
  128. struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */
  129. #endif
  130. +
  131. +#ifdef CONFIG_ATA_LEDS
  132. + struct led_trigger *ledtrig;
  133. + char ledtrig_name[8];
  134. +#endif
  135. +
  136. /* owned by EH */
  137. u8 *ncq_sense_buf;
  138. u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned;