leds: call led_pwm_set() in leds-pwm to enforce default LED_OFF
Subsystems (2)
PATCH 1/3 leds: call led_pwm_set() in leds-pwm to enforce default LED_OFF
From: Markus Hofstaetter <[email protected]>
commit f16703360da7731a057df2ffa902306819c22398 upstream.
Some PWMs are disabled by default or the default pin setting does not match the LED_OFF state (e.g., active-low leds). Hence, the driver may end up reporting 0 brightness, but the leds are actually on using full brightness, because it never enforces its default configuration.
So enforce it by calling led_pwm_set() after successfully registering the device.
Tested on a Phytec phyFLEX i.MX6Q board based on kernel v3.19.5.
--- drivers/leds/leds-pwm.c | 1 + 1 file changed, 1 insertion(+)
drivers/leds/leds-pwm.c +1 -0
@@ -132,6 +132,7 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, ret =led_classdev_register (dev, &led_data->cdev);if (ret ==0 ) { priv->num_leds++; +led_pwm_set (&led_data->cdev, led_data->cdev.brightness); }else {dev_err (dev,"failed to register PWM led for %s: %d\n" , led->name, ret);
Signature · 1 line
2.7.4
PATCH 2/3 leds: turn off the LED and wait for completion on unregistering LED class device
From: Milo Kim <[email protected]>
commit d1aa577f5e191d77d3ad62da93729b5af9532bb4 upstream.
Workqueue, 'set_brightness_work' is used for scheduling brightness control. This workqueue is canceled when the LED class device is unregistered. Currently, LED subsystem handles like below.
cancel_work_sync(&led_cdev->set_brightness_work) led_set_brightness(led_cdev, LED_OFF)
However, this could be a problem.
Workqueue is going to be canceled but LED device needs to be off. The worst case is null pointer access due to scheduling a workqueue.
LED module is loaded.
LED driver private data is allocated by using devm_zalloc().
LED module is unloaded.
led_classdev_unregister() is called.
cancel_work_sync()
led_set_brightness(led_cdev, LED_OFF)
schedule_work() if LED driver uses brightness_set_blocking() In the meantime, driver private data will be freed.
..scheduling..
brightness_set_blocking() callback is invoked.
For the brightness control, LED driver tries to access private data but resource is removed!
To avoid this problem, LED subsystem should turn off the brightness first and wait for completion.
led_set_brightness(led_cdev, LED_OFF)
flush_work(&led_cdev->set_brightness_work)
It guarantees that LED driver turns off the brightness prior to resource management.
--- drivers/leds/led-class.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/leds/led-class.c +3 -2
@@ -247,12 +247,13 @@ void led_classdev_unregister(struct led_classdev *led_cdev)up_write (&led_cdev->trigger_lock);#endif -cancel_work_sync (&led_cdev->set_brightness_work); -/* Stop blinking */ led_stop_software_blink (led_cdev); +led_set_brightness (led_cdev,LED_OFF ); +flush_work (&led_cdev->set_brightness_work); +device_unregister (led_cdev->dev);down_write (&leds_list_lock);
Signature · 1 line
2.7.4
PATCH 3/3 leds: leds-gpio: Fix return value check in create_gpio_led()
In reply to Krzysztof KozlowskiFrom: Wei Yongjun <[email protected]>
commit 2d88a331e48095cf60ad9bdf3177bd401bf99727 upstream.
In case of error, the function gpio_to_desc() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test.
--- drivers/leds/leds-gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/leds/leds-gpio.c +2 -2
@@ -118,8 +118,8 @@ static int create_gpio_led(const struct gpio_led *template,return ret; led_dat->gpiod =gpio_to_desc (template->gpio); -if (IS_ERR (led_dat->gpiod)) -return PTR_ERR (led_dat->gpiod); +if (!led_dat->gpiod) +return -EINVAL ; } led_dat->cdev.name = template->name;
Signature · 1 line
2.7.4
Re: [PATCH stable v4.4+ 3/3] leds: leds-gpio: Fix return value check in create_gpio_led()
Quoted 8 lines · Krzysztof Kozlowski
From: Wei Yongjun <[email protected]>
commit
2d88a331e48095cf60ad9bdf3177bd401bf99727upstream.In case of error, the function
gpio_to_desc()returns NULL pointer notERR_PTR(). TheIS_ERR()test in the return value check should be replaced with NULL test.
Quoted 7 lines
Signed-off-by Wei Yongjun <[email protected]>Signed-off-by Jacek Anaszewski <[email protected]>Signed-off-by Krzysztof Kozlowski <[email protected]>--- drivers/leds/leds-gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
All 3 now queued up, thanks.
greg k-h
Quoted 18 lines
drivers/leds/leds-gpio.c +2
-2@@ -118,8 +118,8 @@ static int create_gpio_led(const struct gpio_led *template,return ret; led_dat->gpiod =gpio_to_desc (template->gpio); -if (IS_ERR (led_dat->gpiod)) -return PTR_ERR (led_dat->gpiod); +if (!led_dat->gpiod) +return -EINVAL ; } led_dat->cdev.name = template->name;Signature · 1 line
2.7.4