diff mbox series

[v2,net-next,1/3] led: trig: netdev: Fix requesting offload device

Message ID 20230624205629.4158216-2-andrew@lunn.ch (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series Support offload LED blinking to PHY. | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 8 this patch: 8
netdev/cc_maintainers warning 4 maintainers not CCed: lee@kernel.org davem@davemloft.net pavel@ucw.cz linux-leds@vger.kernel.org
netdev/build_clang success Errors and warnings before: 8 this patch: 8
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 8 this patch: 8
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 20 lines checked
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Andrew Lunn June 24, 2023, 8:56 p.m. UTC
When the netdev trigger is activates, it tries to determine what
device the LED blinks for, and what the current blink mode is.

The documentation for hw_control_get() says:

	 * Return 0 on success, a negative error number on failing parsing the
	 * initial mode. Error from this function is NOT FATAL as the device
	 * may be in a not supported initial state by the attached LED trigger.
	 */

For the Marvell PHY and the Armada 370-rd board, the initial LED blink
mode is not supported by the trigger, so it returns an error. This
resulted in not getting the device the LED is blinking for. As a
result, the device is unknown and offloaded is never performed.

Change to condition to always get the device if offloading is
supported, and reduce the scope of testing for an error from
hw_control_get() to skip setting trigger internal state if there is an
error.

Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/leds/trigger/ledtrig-netdev.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Comments

Daniel Golle July 18, 2023, 7:34 p.m. UTC | #1
On Sat, Jun 24, 2023 at 10:56:27PM +0200, Andrew Lunn wrote:
> When the netdev trigger is activates, it tries to determine what
> device the LED blinks for, and what the current blink mode is.
> 
> The documentation for hw_control_get() says:
> 
> 	 * Return 0 on success, a negative error number on failing parsing the
> 	 * initial mode. Error from this function is NOT FATAL as the device
> 	 * may be in a not supported initial state by the attached LED trigger.
> 	 */
> 
> For the Marvell PHY and the Armada 370-rd board, the initial LED blink
> mode is not supported by the trigger, so it returns an error. This
> resulted in not getting the device the LED is blinking for. As a
> result, the device is unknown and offloaded is never performed.
> 
> Change to condition to always get the device if offloading is
> supported, and reduce the scope of testing for an error from
> hw_control_get() to skip setting trigger internal state if there is an
> error.
> 
> Reviewed-by: Simon Horman <simon.horman@corigine.com>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> ---
>  drivers/leds/trigger/ledtrig-netdev.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
> index 32b66703068a..247b100ee1d3 100644
> --- a/drivers/leds/trigger/ledtrig-netdev.c
> +++ b/drivers/leds/trigger/ledtrig-netdev.c
> @@ -565,15 +565,17 @@ static int netdev_trig_activate(struct led_classdev *led_cdev)
>  	/* Check if hw control is active by default on the LED.
>  	 * Init already enabled mode in hw control.
>  	 */
> -	if (supports_hw_control(led_cdev) &&
> -	    !led_cdev->hw_control_get(led_cdev, &mode)) {
> +	if (supports_hw_control(led_cdev)) {
>  		dev = led_cdev->hw_control_get_device(led_cdev);
>  		if (dev) {
>  			const char *name = dev_name(dev);
>  
>  			set_device_name(trigger_data, name, strlen(name));
>  			trigger_data->hw_control = true;
> -			trigger_data->mode = mode;
> +
> +			rc = led_cdev->hw_control_get(led_cdev, &mode);

Shouldn't there also be something like
led_cdev->hw_control_get(led_cdev, 0);
in netdev_trig_deactivate then?
Because somehow we need to tell the hardware to no longer perform an
offloading operation.

> +			if (!rc)
> +				trigger_data->mode = mode;
>  		}
>  	}
>  
> -- 
> 2.40.1
> 
>
Andrew Lunn Aug. 7, 2023, 10:27 p.m. UTC | #2
> > +	if (supports_hw_control(led_cdev)) {
> >  		dev = led_cdev->hw_control_get_device(led_cdev);
> >  		if (dev) {
> >  			const char *name = dev_name(dev);
> >  
> >  			set_device_name(trigger_data, name, strlen(name));
> >  			trigger_data->hw_control = true;
> > -			trigger_data->mode = mode;
> > +
> > +			rc = led_cdev->hw_control_get(led_cdev, &mode);
> 
> Shouldn't there also be something like
> led_cdev->hw_control_get(led_cdev, 0);
> in netdev_trig_deactivate then?
> Because somehow we need to tell the hardware to no longer perform an
> offloading operation.

Hi Daniel

Back from vacation, so getting around to this now.

Interesting question. I would actually expect the trigger that takes
its place will set the brightness to what it wants it to default
it. It is documented that setting the brightness disables any offload.

Have you seen a real problem with changing triggers?

     Andrew
Daniel Golle Aug. 7, 2023, 10:49 p.m. UTC | #3
Hi Andrew,

On Tue, Aug 08, 2023 at 12:27:10AM +0200, Andrew Lunn wrote:
> > > +	if (supports_hw_control(led_cdev)) {
> > >  		dev = led_cdev->hw_control_get_device(led_cdev);
> > >  		if (dev) {
> > >  			const char *name = dev_name(dev);
> > >  
> > >  			set_device_name(trigger_data, name, strlen(name));
> > >  			trigger_data->hw_control = true;
> > > -			trigger_data->mode = mode;
> > > +
> > > +			rc = led_cdev->hw_control_get(led_cdev, &mode);
> > 
> > Shouldn't there also be something like
> > led_cdev->hw_control_get(led_cdev, 0);
> > in netdev_trig_deactivate then?
> > Because somehow we need to tell the hardware to no longer perform an
> > offloading operation.
> 
> Hi Daniel
> 
> Back from vacation, so getting around to this now.
> 
> Interesting question. I would actually expect the trigger that takes
> its place will set the brightness to what it wants it to default
> it. It is documented that setting the brightness disables any offload.

So setting the brigthness should result in the trigger to be cleared
back to 'none' then, and that would result in calling
netdev_trig_deactivate if it was previously active.

Because otherwise, even if I take care of truning off all hardware
triggers in the led_set_brightness call, the netdev trigger would
still be selected.

> 
> Have you seen a real problem with changing triggers?

Yes, when manually switching from the netdev trigger to none (or
any other trigger), hardware offloading would remain active with
my implementation of the PHY LED driver[1] (which doesn't clear any
offloading related things but only sets/clears a FORCE_ON bit in its
led_set_brightness function).

[1]: https://github.com/dangowrt/linux/commit/439d52d7b80c97ff0c682ec68a70812030c3d79e


Cheers


Daniel
Andrew Lunn Aug. 7, 2023, 11:48 p.m. UTC | #4
> So setting the brigthness should result in the trigger to be cleared
> back to 'none' then, and that would result in calling
> netdev_trig_deactivate if it was previously active.
> 
> Because otherwise, even if I take care of truning off all hardware
> triggers in the led_set_brightness call, the netdev trigger would
> still be selected.

I looked at edtrig-timer.c, which can offload the blinking to hardware
if it supports the needed op. Its deactivate function is:

static void timer_trig_deactivate(struct led_classdev *led_cdev)
{
        /* Stop blinking */
        led_set_brightness(led_cdev, LED_OFF);
}

So this does suggest the trigger should disable offload. v3 will do
similar.

	Andrew
diff mbox series

Patch

diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
index 32b66703068a..247b100ee1d3 100644
--- a/drivers/leds/trigger/ledtrig-netdev.c
+++ b/drivers/leds/trigger/ledtrig-netdev.c
@@ -565,15 +565,17 @@  static int netdev_trig_activate(struct led_classdev *led_cdev)
 	/* Check if hw control is active by default on the LED.
 	 * Init already enabled mode in hw control.
 	 */
-	if (supports_hw_control(led_cdev) &&
-	    !led_cdev->hw_control_get(led_cdev, &mode)) {
+	if (supports_hw_control(led_cdev)) {
 		dev = led_cdev->hw_control_get_device(led_cdev);
 		if (dev) {
 			const char *name = dev_name(dev);
 
 			set_device_name(trigger_data, name, strlen(name));
 			trigger_data->hw_control = true;
-			trigger_data->mode = mode;
+
+			rc = led_cdev->hw_control_get(led_cdev, &mode);
+			if (!rc)
+				trigger_data->mode = mode;
 		}
 	}