summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2025-01-20 12:36:53 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-05-29 11:02:58 +0200
commit39255ab2edfb01707cade37b05a20328c9873e01 (patch)
tree79f2d3bc997936ccf5075f2b64dc641fbd038fb1
parent16ddd67bb5579a14cb91c9692a11b1fd0349be45 (diff)
leds: trigger: netdev: Configure LED blink interval for HW offload
[ Upstream commit c629c972b310af41e9e072febb6dae9a299edde6 ] In case a PHY LED implements .blink_set callback to set LED blink interval, call it even if .hw_control is already set, as that LED blink interval likely controls the blink rate of that HW offloaded LED. For PHY LEDs, that can be their activity blinking interval. The software blinking is not affected by this change. With this change, the LED interval setting looks something like this: $ echo netdev > /sys/class/leds/led:green:lan/trigger $ echo 1 > /sys/class/leds/led:green:lan/brightness $ echo 250 > /sys/class/leds/led:green:lan/interval Signed-off-by: Marek Vasut <marex@denx.de> Link: https://lore.kernel.org/r/20250120113740.91807-1-marex@denx.de Signed-off-by: Lee Jones <lee@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/leds/trigger/ledtrig-netdev.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
index 4b0863db901a..356a55ced2c2 100644
--- a/drivers/leds/trigger/ledtrig-netdev.c
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -68,6 +68,7 @@ struct led_netdev_data {
unsigned int last_activity;
unsigned long mode;
+ unsigned long blink_delay;
int link_speed;
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported_link_modes);
u8 duplex;
@@ -86,6 +87,10 @@ static void set_baseline_state(struct led_netdev_data *trigger_data)
/* Already validated, hw control is possible with the requested mode */
if (trigger_data->hw_control) {
led_cdev->hw_control_set(led_cdev, trigger_data->mode);
+ if (led_cdev->blink_set) {
+ led_cdev->blink_set(led_cdev, &trigger_data->blink_delay,
+ &trigger_data->blink_delay);
+ }
return;
}
@@ -454,10 +459,11 @@ static ssize_t interval_store(struct device *dev,
size_t size)
{
struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev);
+ struct led_classdev *led_cdev = trigger_data->led_cdev;
unsigned long value;
int ret;
- if (trigger_data->hw_control)
+ if (trigger_data->hw_control && !led_cdev->blink_set)
return -EINVAL;
ret = kstrtoul(buf, 0, &value);
@@ -466,9 +472,13 @@ static ssize_t interval_store(struct device *dev,
/* impose some basic bounds on the timer interval */
if (value >= 5 && value <= 10000) {
- cancel_delayed_work_sync(&trigger_data->work);
+ if (trigger_data->hw_control) {
+ trigger_data->blink_delay = value;
+ } else {
+ cancel_delayed_work_sync(&trigger_data->work);
- atomic_set(&trigger_data->interval, msecs_to_jiffies(value));
+ atomic_set(&trigger_data->interval, msecs_to_jiffies(value));
+ }
set_baseline_state(trigger_data); /* resets timer */
}