834-ledtrig-libata.patch 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. @@ -685,6 +685,17 @@ static inline void ata_set_tf_cdl(struct
  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. + if (unlikely(!ap->ledtrig))
  50. + return;
  51. +
  52. + led_trigger_blink_oneshot(ap->ledtrig, LIBATA_BLINK_DELAY, LIBATA_BLINK_DELAY, 0);
  53. +}
  54. +#endif
  55. +
  56. /**
  57. * ata_build_rw_tf - Build ATA taskfile for given read/write request
  58. * @qc: Metadata associated with the taskfile to build
  59. @@ -4771,6 +4782,9 @@ void __ata_qc_complete(struct ata_queued
  60. link->active_tag = ATA_TAG_POISON;
  61. ap->nr_active_links--;
  62. }
  63. +#ifdef CONFIG_ATA_LEDS
  64. + ata_led_act(ap);
  65. +#endif
  66. /* clear exclusive status */
  67. if (unlikely(qc->flags & ATA_QCFLAG_CLEAR_EXCL &&
  68. @@ -5494,6 +5508,9 @@ struct ata_port *ata_port_alloc(struct a
  69. ap->stats.unhandled_irq = 1;
  70. ap->stats.idle_irq = 1;
  71. #endif
  72. +#ifdef CONFIG_ATA_LEDS
  73. + ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
  74. +#endif
  75. ata_sff_port_init(ap);
  76. return ap;
  77. @@ -5530,6 +5547,12 @@ static void ata_host_release(struct kref
  78. kfree(ap->pmp_link);
  79. kfree(ap->slave_link);
  80. kfree(ap->ncq_sense_buf);
  81. +#ifdef CONFIG_ATA_LEDS
  82. + if (ap->ledtrig) {
  83. + led_trigger_unregister(ap->ledtrig);
  84. + kfree(ap->ledtrig);
  85. + };
  86. +#endif
  87. kfree(ap);
  88. host->ports[i] = NULL;
  89. }
  90. @@ -5920,7 +5943,23 @@ int ata_host_register(struct ata_host *h
  91. host->ports[i]->print_id = atomic_inc_return(&ata_print_id);
  92. host->ports[i]->local_port_no = i + 1;
  93. }
  94. +#ifdef CONFIG_ATA_LEDS
  95. + for (i = 0; i < host->n_ports; i++) {
  96. + if (unlikely(!host->ports[i]->ledtrig))
  97. + continue;
  98. + snprintf(host->ports[i]->ledtrig_name,
  99. + sizeof(host->ports[i]->ledtrig_name), "ata%u",
  100. + host->ports[i]->print_id);
  101. +
  102. + host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name;
  103. +
  104. + if (led_trigger_register(host->ports[i]->ledtrig)) {
  105. + kfree(host->ports[i]->ledtrig);
  106. + host->ports[i]->ledtrig = NULL;
  107. + }
  108. + }
  109. +#endif
  110. /* Create associated sysfs transport objects */
  111. for (i = 0; i < host->n_ports; i++) {
  112. rc = ata_tport_add(host->dev,host->ports[i]);
  113. --- a/include/linux/libata.h
  114. +++ b/include/linux/libata.h
  115. @@ -23,6 +23,9 @@
  116. #include <linux/cdrom.h>
  117. #include <linux/sched.h>
  118. #include <linux/async.h>
  119. +#ifdef CONFIG_ATA_LEDS
  120. +#include <linux/leds.h>
  121. +#endif
  122. /*
  123. * Define if arch has non-standard setup. This is a _PCI_ standard
  124. @@ -875,6 +878,12 @@ struct ata_port {
  125. #ifdef CONFIG_ATA_ACPI
  126. struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */
  127. #endif
  128. +
  129. +#ifdef CONFIG_ATA_LEDS
  130. + struct led_trigger *ledtrig;
  131. + char ledtrig_name[8];
  132. +#endif
  133. +
  134. /* owned by EH */
  135. u8 *ncq_sense_buf;
  136. u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned;