diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6 index 2ea1b79103..86301a2491 100644 --- a/target/linux/generic/config-6.6 +++ b/target/linux/generic/config-6.6 @@ -5180,6 +5180,7 @@ CONFIG_SATA_MOBILE_LPM_POLICY=0 # CONFIG_SATA_MV is not set # CONFIG_SATA_NV is not set # CONFIG_SATA_PMP is not set +# CONFIG_SATA_PMP_LEDS is not set # CONFIG_SATA_PROMISE is not set # CONFIG_SATA_QSTOR is not set # CONFIG_SATA_RCAR is not set diff --git a/target/linux/generic/pending-6.6/835-ledtrig-sata-pmp.patch b/target/linux/generic/pending-6.6/835-ledtrig-sata-pmp.patch new file mode 100644 index 0000000000..5a76fa87dc --- /dev/null +++ b/target/linux/generic/pending-6.6/835-ledtrig-sata-pmp.patch @@ -0,0 +1,247 @@ +From 86884eaf288a8ca29ef5ee049de8c5b9d854ca1f Mon Sep 17 00:00:00 2001 +From: jjm2473 <1129525450@qq.com> +Date: Mon, 30 Oct 2023 13:53:40 +0800 +Subject: [PATCH] drivers/ata: sata pmp supports led trigger + +--- + drivers/ata/Kconfig | 18 ++++++++++++++ + drivers/ata/libata-core.c | 50 +++++++++++++++++++++++++++++++++++++++ + drivers/ata/libata-pmp.c | 42 ++++++++++++++++++++++++++++++++ + drivers/ata/libata.h | 8 +++++++ + include/linux/libata.h | 7 +++++- + 5 files changed, 124 insertions(+), 1 deletion(-) + +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -83,6 +83,14 @@ config ATA_LEDS + + If unsure, say N. + ++config ATA_LINK_SUPPORTS_LEDS ++ bool ++ depends on LEDS_CLASS && LEDS_TRIGGERS ++ default y ++ ++config ATA_LINK_LEDS ++ bool ++ + config ATA_ACPI + bool "ATA ACPI Support" + depends on ACPI +@@ -118,6 +126,16 @@ config SATA_PMP + This option adds support for SATA Port Multipliers + (the SATA version of an ethernet hub, or SAS expander). + ++config SATA_PMP_LEDS ++ bool "support SATA Port Multiplier port LED triggers" ++ depends on SATA_PMP && ATA_LINK_SUPPORTS_LEDS ++ select ATA_LINK_LEDS ++ help ++ This option adds a LED trigger for each registered SATA Port Multiplier port. ++ It is used to drive disk activity leds connected via GPIO. ++ ++ If unsure, say N. ++ + if HAS_DMA + + comment "Controllers with non-SFF native interface" +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -696,6 +696,41 @@ static inline void ata_led_act(struct at + } + #endif + ++#ifdef CONFIG_ATA_LINK_LEDS ++#define ATA_LINK_BLINK_DELAY 40 /* ms */ ++static inline void ata_link_led_act(struct ata_link *link) ++{ ++ unsigned long led_delay = ATA_LINK_BLINK_DELAY; ++ ++ if (likely(!link->ledtrig || link->offline)) ++ return; ++ ++ led_trigger_blink_oneshot(link->ledtrig, &led_delay, &led_delay, !link->offline); ++} ++ ++static inline void ata_link_led_link(struct ata_link *link, int offline) ++{ ++ unsigned long led_delay = ATA_LINK_BLINK_DELAY << 1; ++ link->offline = offline; ++ ++ if (likely(!link->ledtrig)) ++ return; ++ ++ led_trigger_blink_oneshot(link->ledtrig, &led_delay, &led_delay, !offline); ++} ++ ++int ata_link_trig_activate(struct led_classdev *led_cdev) ++{ ++ char (*ledtrig_name)[12] = (char (*)[12])led_cdev->trigger->name; ++ struct ata_link *link = ++ container_of(ledtrig_name, struct ata_link, ledtrig_name); ++ ++ led_set_brightness(led_cdev, link->offline ? LED_OFF : LED_FULL); ++ return 0; ++} ++ ++#endif ++ + /** + * ata_build_rw_tf - Build ATA taskfile for given read/write request + * @qc: Metadata associated with the taskfile to build +@@ -3184,9 +3219,15 @@ static void sata_print_link_status(struc + tmp = (sstatus >> 4) & 0xf; + ata_link_info(link, "SATA link up %s (SStatus %X SControl %X)\n", + sata_spd_string(tmp), sstatus, scontrol); ++#ifdef CONFIG_ATA_LINK_LEDS ++ ata_link_led_link(link, 0); ++#endif + } else { + ata_link_info(link, "SATA link down (SStatus %X SControl %X)\n", + sstatus, scontrol); ++#ifdef CONFIG_ATA_LINK_LEDS ++ ata_link_led_link(link, 1); ++#endif + } + } + +@@ -4786,6 +4827,10 @@ void __ata_qc_complete(struct ata_queued + ata_led_act(ap); + #endif + ++#ifdef CONFIG_ATA_LINK_LEDS ++ ata_link_led_act(link); ++#endif ++ + /* clear exclusive status */ + if (unlikely(qc->flags & ATA_QCFLAG_CLEAR_EXCL && + ap->excl_link == link)) +@@ -5418,6 +5463,11 @@ void ata_link_init(struct ata_port *ap, + link->active_tag = ATA_TAG_POISON; + link->hw_sata_spd_limit = UINT_MAX; + ++#ifdef CONFIG_ATA_LINK_LEDS ++ link->offline = 0; ++ link->ledtrig = NULL; ++#endif ++ + /* can't use iterator, ap isn't initialized yet */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &link->device[i]; +--- a/drivers/ata/libata-pmp.c ++++ b/drivers/ata/libata-pmp.c +@@ -355,6 +355,16 @@ static int sata_pmp_init_links (struct a + goto err_tlink; + } + } ++#ifdef CONFIG_SATA_PMP_LEDS ++ for (i = 0; i < SATA_PMP_MAX_PORTS; i++) { ++ struct ata_link *link = &pmp_link[i]; ++ link->ledtrig = NULL; ++ link->offline = 1; ++ snprintf(link->ledtrig_name, ++ sizeof(link->ledtrig_name), "ata%up%u", ++ ap->print_id, link->pmp); ++ } ++#endif + } + + for (i = 0; i < nr_ports; i++) { +@@ -366,6 +376,23 @@ static int sata_pmp_init_links (struct a + ehc->i.action |= ATA_EH_RESET; + } + ++#ifdef CONFIG_SATA_PMP_LEDS ++ for (i = 0; i < nr_ports; i++) { ++ struct ata_link *link = &pmp_link[i]; ++ link->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); ++ if (unlikely(!link->ledtrig)) ++ continue; ++ ++ link->ledtrig->name = link->ledtrig_name; ++ link->ledtrig->activate = ata_link_trig_activate; ++ ++ if (led_trigger_register(link->ledtrig)) { ++ kfree(link->ledtrig); ++ link->ledtrig = NULL; ++ } ++ } ++#endif ++ + return 0; + err_tlink: + while (--i >= 0) +@@ -562,6 +589,10 @@ static void sata_pmp_detach(struct ata_d + struct ata_port *ap = link->ap; + struct ata_link *tlink; + unsigned long flags; ++#ifdef CONFIG_SATA_PMP_LEDS ++ int i; ++ struct ata_link *pmp_link = ap->pmp_link; ++#endif + + ata_dev_info(dev, "Port Multiplier detaching\n"); + +@@ -578,6 +609,17 @@ static void sata_pmp_detach(struct ata_d + ap->nr_pmp_links = 0; + link->pmp = 0; + spin_unlock_irqrestore(ap->lock, flags); ++ ++#ifdef CONFIG_SATA_PMP_LEDS ++ for (i = 0; i < SATA_PMP_MAX_PORTS; i++) { ++ struct ata_link *link = &pmp_link[i]; ++ if (link->ledtrig) { ++ led_trigger_unregister(link->ledtrig); ++ kfree(link->ledtrig); ++ link->ledtrig = NULL; ++ } ++ } ++#endif + } + + /** +--- a/drivers/ata/libata.h ++++ b/drivers/ata/libata.h +@@ -12,6 +12,10 @@ + #ifndef __LIBATA_H__ + #define __LIBATA_H__ + ++#ifdef CONFIG_ATA_LINK_LEDS ++#include ++#endif ++ + #define DRV_NAME "libata" + #define DRV_VERSION "3.00" /* must be exactly four chars */ + +@@ -236,4 +240,8 @@ static inline void zpodd_disable_run_wak + static inline void zpodd_post_poweron(struct ata_device *dev) {} + #endif /* CONFIG_SATA_ZPODD */ + ++#ifdef CONFIG_ATA_LINK_LEDS ++int ata_link_trig_activate(struct led_classdev *led_cdev); ++#endif ++ + #endif /* __LIBATA_H__ */ +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -23,7 +23,7 @@ + #include + #include + #include +-#ifdef CONFIG_ATA_LEDS ++#if defined(CONFIG_ATA_LEDS) || defined(CONFIG_ATA_LINK_LEDS) + #include + #endif + +@@ -803,6 +803,11 @@ struct ata_link { + struct ata_device device[ATA_MAX_DEVICES]; + + unsigned long last_lpm_change; /* when last LPM change happened */ ++#ifdef CONFIG_ATA_LINK_LEDS ++ unsigned int offline; ++ struct led_trigger *ledtrig; ++ char ledtrig_name[12]; ++#endif + }; + #define ATA_LINK_CLEAR_BEGIN offsetof(struct ata_link, active_tag) + #define ATA_LINK_CLEAR_END offsetof(struct ata_link, device[0])