RE: Bug when using both "set" and "blink" functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jacek Anaszewski wrote:
> On 11/22/2017 01:55 AM, Craig McQueen wrote:
> > I'd like to control a LED to possibly be any of:
> >
> > * Off
> > * On
> > * Blinking
> >
> > I've had this working fine in 3.14.x kernel.
> >
> > But when upgrading to 4.4.x, I found that the transition from "blinking" to
> "on" didn't work. Namely, if it's blinking and then I call
> led_set_brightness(led_cdev, LED_FULL), then it wouldn't work (I can't
> remember if it turned off, or remained blinking; it wasn't on anyway). I
> worked around it by calling led_set_brightness(led_cdev, LED_OFF) just
> before led_set_brightness(led_cdev, LED_FULL).
> 
> Could you please check it with 4.14?

It isn't easy for me to try 4.14 in my current setup (Yocto build with meta-ti).

> The expected behavior in 4.14 is:
> 
> use case 1: led_set_brightness(led_cdev, LED_OFF) while timer trigger
>             is active.
> expected result: LED is off, trigger is deactivated.
> 
> use case 2: led_set_brightness(led_cdev, LED_FULL) while timer trigger
>             is active.
> expected result: LED blink brightness is LED_FULL, trigger remains active.

Yes, I understand that API design.

> > Now I have upgraded to 4.9.x, and found that the transition from "blinking"
> to "on" again isn't working. The LED ends up being off instead of on.
> 
> Could you provide the exact steps to reproduce this case?
> LED shouldn't be in any way off after setting brightness to non-zero value
> when blinking.

I'm using a custom kernel driver that tries to go from blinking to steady-on using these function calls:

		led_trigger_event(trigger, LED_OFF);
		led_trigger_event(trigger, LED_FULL);

> There were indeed changes in 4.9 in this area, that modified semantics of
> setting brightness to non-zero value when blinking. See the
> reasoning:
> 
> commit 7cfe749fad5158247282f2fee30773fd454029ab
> Author: Tony Makkiel <tony.makkiel@xxxxxxxxx>
> Date:   Wed May 18 17:22:45 2016 +0100
> 
>     leds: core: Fix brightness setting upon hardware blinking enabled
> 
>     Commit 76931edd54f8 ("leds: fix brightness changing when software
> blinking
>     is active") changed the semantics of led_set_brightness() which according
>     to the documentation should disable blinking upon any brightness setting.
>     Moreover it made it different for soft blink case, where it was possible
>     to change blink brightness, and for hardware blink case, where setting
>     any brightness greater than 0 was ignored.
> 
>     While the change itself is against the documentation claims, it was driven
>     also by the fact that timer trigger remained active after turning blinking
>     off. Fixing that would have required major refactoring in the led-core,
>     led-class, and led-triggers because of cyclic dependencies.
> 
>     Finally, it has been decided that allowing for brightness change during
>     blinking is beneficial as it can be accomplished without disturbing
>     blink rhythm.
> 
>     The change in brightness setting semantics will not affect existing
>     LED class drivers that implement blink_set op thanks to the LED_BLINK_SW
>     flag introduced by this patch. The flag state will be from now on checked
>     in led_set_brightness() which will allow to distinguish between software
>     and hardware blink mode. In the latter case the control will be passed
>     directly to the drivers which apply their semantics on brightness set,
>     which is disable the blinking in case of most such drivers. New drivers
>     will apply new semantics and just change the brightness while hardware
>     blinking is on, if possible.
> 
>     The issue was smuggled by subsequent LED core improvements, which
> modified
>     the code that originally introduced the problem.
> 
> 
> 
> > Examining the code of led_set_brightness():
> >
> > * Behaviour is different depending on whether the brightness is LED_OFF
> (it schedules the blink to be turned off "soon") or other (it alters the
> brightness of subsequent blinks).
> > * It looks as though there are race conditions in the transition from blinking
> to steady off -- it schedules the blink to be turned off "soon", so it's difficult
> to guarantee a reliable transition from blinking to on/off.
> >
> > The combination of the above two points makes it seem difficult to
> robustly go from blinking to off/on.
> >
> > So, my questions are:
> >
> > * What is the correct way to use the API to reliably control an LED for a
> combination of off/on/blinking?
> > * Is my above analysis of the code correct, so that there are indeed race
> conditions going from blinking to off, leading to undefined behaviour? Can
> that be fixed?
> 
> I checked earlier discussed case i.e. disabling trigger and immediately setting
> brightness to non-zero value and it seems to work fine. Checked with uleds
> driver:
> 
> # echo "timer" > trigger
> # echo 0 > brightness; echo 100 > brightness
> 
> Brightness always is 100 after that, even when setting delay_on/off to 1.

I still think there's a race condition, but you don't discover it when using userspace, because there's sufficient time between setting the brightness to 0 and later 100, for LED_BLINK_DISABLE to be processed in-between.

But I'm using a custom kernel driver that tries to go from blinking to steady-on using these function calls:

		led_trigger_event(trigger, LED_OFF);   /* which calls led_set_brightness(led_cdev, LED_OFF) */
		led_trigger_event(trigger, LED_FULL);  /* which calls led_set_brightness(led_cdev, LED_FULL) */

In this case, LED_BLINK_DISABLE is not yet processed before the second function call, so the second function call becomes ineffective, because the pending LED_BLINK_DISABLE is later processed, turning off the LED and leaving it off.

-- 
Craig McQueen




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux