Skip to content

Commit

Permalink
leds: trigger: netdev: add support for LED hw control
Browse files Browse the repository at this point in the history
Add support for LED hw control for the netdev trigger.

The trigger on calling set_baseline_state to configure a new mode, will
do various check to verify if hw control can be used for the requested
mode in can_hw_control() function.

It will first check if the LED driver supports hw control for the netdev
trigger, then will use hw_control_is_supported() and finally will call
hw_control_set() to apply the requested mode.

To use such mode, interval MUST be set to the default value and net_dev
MUST be set. If one of these 2 value are not valid, hw control will
never be used and normal software fallback is used.

The default interval value is moved to a define to make sure they are
always synced.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Christian Marangi authored and David S. Miller committed May 31, 2023
1 parent c84c80c commit 7c145a3
Showing 1 changed file with 41 additions and 2 deletions.
43 changes: 41 additions & 2 deletions drivers/leds/trigger/ledtrig-netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <linux/timer.h>
#include "../leds.h"

#define NETDEV_LED_DEFAULT_INTERVAL 50

/*
* Configurable sysfs attributes:
*
Expand Down Expand Up @@ -68,6 +70,13 @@ static void set_baseline_state(struct led_netdev_data *trigger_data)
int current_brightness;
struct led_classdev *led_cdev = trigger_data->led_cdev;

/* 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);

return;
}

current_brightness = led_cdev->brightness;
if (current_brightness)
led_cdev->blink_brightness = current_brightness;
Expand Down Expand Up @@ -103,12 +112,42 @@ static bool supports_hw_control(struct led_classdev *led_cdev)

static bool can_hw_control(struct led_netdev_data *trigger_data)
{
unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL);
unsigned int interval = atomic_read(&trigger_data->interval);
struct led_classdev *led_cdev = trigger_data->led_cdev;
int ret;

if (!supports_hw_control(led_cdev))
return false;

return false;
/*
* Interval must be set to the default
* value. Any different value is rejected if in hw
* control.
*/
if (interval != default_interval)
return false;

/*
* net_dev must be set with hw control, otherwise no
* blinking can be happening and there is nothing to
* offloaded.
*/
if (!trigger_data->net_dev)
return false;

/* Check if the requested mode is supported */
ret = led_cdev->hw_control_is_supported(led_cdev, trigger_data->mode);
/* Fall back to software blinking if not supported */
if (ret == -EOPNOTSUPP)
return false;
if (ret) {
dev_warn(led_cdev->dev,
"Current mode check failed with error %d\n", ret);
return false;
}

return true;
}

static ssize_t device_name_show(struct device *dev,
Expand Down Expand Up @@ -413,7 +452,7 @@ static int netdev_trig_activate(struct led_classdev *led_cdev)
trigger_data->device_name[0] = 0;

trigger_data->mode = 0;
atomic_set(&trigger_data->interval, msecs_to_jiffies(50));
atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL));
trigger_data->last_activity = 0;

led_set_trigger_data(led_cdev, trigger_data);
Expand Down

0 comments on commit 7c145a3

Please sign in to comment.