Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81fe8e5b authored by Jacek Anaszewski's avatar Jacek Anaszewski
Browse files

leds: core: Add led_set_brightness_nosleep{nopm} functions



This patch adds led_set_brightness_nosleep() and led_set_brightness_nopm()
functions, that guarantee setting LED brightness in a non-blocking way.
The latter is used from pm_ops context and doesn't modify the brightness
cached in the struct led_classdev. Its execution always ends up with
a call to brightness setting op - either directly or through
a set_brightness_work, regardless of LED_SUSPENDED flag state.

The patch also replaces led_set_brightness_async() with
led_set_brightness_nosleep() in all places where the most vital was setting
brightness in a non sleeping way but not necessarily asynchronously, which
is not needed for non-blocking drivers.

Signed-off-by: default avatarJacek Anaszewski <j.anaszewski@samsung.com>
Acked-by: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
parent 437a4240
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@ static const struct attribute_group *led_groups[] = {
void led_classdev_suspend(struct led_classdev *led_cdev)
{
	led_cdev->flags |= LED_SUSPENDED;
	led_cdev->brightness_set(led_cdev, 0);
	led_set_brightness_nopm(led_cdev, 0);
}
EXPORT_SYMBOL_GPL(led_classdev_suspend);

@@ -119,7 +119,7 @@ EXPORT_SYMBOL_GPL(led_classdev_suspend);
 */
void led_classdev_resume(struct led_classdev *led_cdev)
{
	led_cdev->brightness_set(led_cdev, led_cdev->brightness);
	led_set_brightness_nopm(led_cdev, led_cdev->brightness);

	if (led_cdev->flash_resume)
		led_cdev->flash_resume(led_cdev);
+33 −5
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ static void led_timer_function(unsigned long data)
	unsigned long delay;

	if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
		led_set_brightness_async(led_cdev, LED_OFF);
		led_set_brightness_nosleep(led_cdev, LED_OFF);
		return;
	}

@@ -60,7 +60,7 @@ static void led_timer_function(unsigned long data)
		delay = led_cdev->blink_delay_off;
	}

	led_set_brightness_async(led_cdev, brightness);
	led_set_brightness_nosleep(led_cdev, brightness);

	/* Return in next iteration if led is in one-shot mode and we are in
	 * the final blink state so that the led is toggled each delay_on +
@@ -110,13 +110,14 @@ static void led_set_software_blink(struct led_classdev *led_cdev,

	/* never on - just set to off */
	if (!delay_on) {
		led_set_brightness_async(led_cdev, LED_OFF);
		led_set_brightness_nosleep(led_cdev, LED_OFF);
		return;
	}

	/* never off - just set to brightness */
	if (!delay_off) {
		led_set_brightness_async(led_cdev, led_cdev->blink_brightness);
		led_set_brightness_nosleep(led_cdev,
					   led_cdev->blink_brightness);
		return;
	}

@@ -217,7 +218,7 @@ void led_set_brightness(struct led_classdev *led_cdev,
	}

	if (led_cdev->flags & SET_BRIGHTNESS_ASYNC) {
		led_set_brightness_async(led_cdev, brightness);
		led_set_brightness_nosleep(led_cdev, brightness);
		return;
	} else if (led_cdev->flags & SET_BRIGHTNESS_SYNC)
		ret = led_set_brightness_sync(led_cdev, brightness);
@@ -230,6 +231,33 @@ void led_set_brightness(struct led_classdev *led_cdev,
}
EXPORT_SYMBOL_GPL(led_set_brightness);

void led_set_brightness_nopm(struct led_classdev *led_cdev,
			      enum led_brightness value)
{
	/* Use brightness_set op if available, it is guaranteed not to sleep */
	if (led_cdev->brightness_set) {
		led_cdev->brightness_set(led_cdev, value);
		return;
	}

	/* If brightness setting can sleep, delegate it to a work queue task */
	led_cdev->delayed_set_value = value;
	schedule_work(&led_cdev->set_brightness_work);
}
EXPORT_SYMBOL_GPL(led_set_brightness_nopm);

void led_set_brightness_nosleep(struct led_classdev *led_cdev,
				enum led_brightness value)
{
	led_cdev->brightness = min(value, led_cdev->max_brightness);

	if (led_cdev->flags & LED_SUSPENDED)
		return;

	led_set_brightness_nopm(led_cdev, led_cdev->brightness);
}
EXPORT_SYMBOL_GPL(led_set_brightness_nosleep);

int led_update_brightness(struct led_classdev *led_cdev)
{
	int ret = 0;
+4 −0
Original line number Diff line number Diff line
@@ -46,6 +46,10 @@ static inline int led_get_brightness(struct led_classdev *led_cdev)

void led_init_core(struct led_classdev *led_cdev);
void led_stop_software_blink(struct led_classdev *led_cdev);
void led_set_brightness_nopm(struct led_classdev *led_cdev,
				enum led_brightness value);
void led_set_brightness_nosleep(struct led_classdev *led_cdev,
				enum led_brightness value);

extern struct rw_semaphore leds_list_lock;
extern struct list_head leds_list;
+4 −4
Original line number Diff line number Diff line
@@ -51,9 +51,9 @@ static int fb_notifier_callback(struct notifier_block *p,

	if ((n->old_status == UNBLANK) ^ n->invert) {
		n->brightness = led->brightness;
		led_set_brightness_async(led, LED_OFF);
		led_set_brightness_nosleep(led, LED_OFF);
	} else {
		led_set_brightness_async(led, n->brightness);
		led_set_brightness_nosleep(led, n->brightness);
	}

	n->old_status = new_status;
@@ -89,9 +89,9 @@ static ssize_t bl_trig_invert_store(struct device *dev,

	/* After inverting, we need to update the LED. */
	if ((n->old_status == BLANK) ^ n->invert)
		led_set_brightness_async(led, LED_OFF);
		led_set_brightness_nosleep(led, LED_OFF);
	else
		led_set_brightness_async(led, n->brightness);
		led_set_brightness_nosleep(led, n->brightness);

	return num;
}
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@

static void defon_trig_activate(struct led_classdev *led_cdev)
{
	led_set_brightness_async(led_cdev, led_cdev->max_brightness);
	led_set_brightness_nosleep(led_cdev, led_cdev->max_brightness);
}

static struct led_trigger defon_led_trigger = {
Loading