Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1225982 > unrolled thread
| Started by | Jacek Anaszewski <j.anaszewski@samsung.com> |
|---|---|
| First post | 2015-09-16 12:50 +0200 |
| Last post | 2015-09-16 12:50 +0200 |
| Articles | 7 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 0/5] LED core improvements Jacek Anaszewski <j.anaszewski@samsung.com> - 2015-09-16 12:50 +0200
[PATCH 4/5] leds: core: Add an internal led_set_brightness_nosleep function Jacek Anaszewski <j.anaszewski@samsung.com> - 2015-09-16 12:50 +0200
[PATCH 5/5] leds: core: Use set_brightness_work for the blocking op Jacek Anaszewski <j.anaszewski@samsung.com> - 2015-09-16 12:50 +0200
Re: [PATCH 5/5] leds: core: Use set_brightness_work for the blocking op Sakari Ailus <sakari.ailus@linux.intel.com> - 2015-09-22 10:10 +0200
[PATCH 2/5] leds: core: Add LED_BLINK_CHANGE and LED_BLINK_DISABLE flags Jacek Anaszewski <j.anaszewski@samsung.com> - 2015-09-16 12:50 +0200
[PATCH 3/5] leds: Rename brightness_set_sync op to brightness_set_blocking Jacek Anaszewski <j.anaszewski@samsung.com> - 2015-09-16 12:50 +0200
[PATCH 1/5] leds: core: Move LED core callbacks out of led-class.c Jacek Anaszewski <j.anaszewski@samsung.com> - 2015-09-16 12:50 +0200
| From | Jacek Anaszewski <j.anaszewski@samsung.com> |
|---|---|
| Date | 2015-09-16 12:50 +0200 |
| Subject | [PATCH 0/5] LED core improvements |
| Message-ID | <q9irL-226-3@gated-at.bofh.it> |
This patch set prepares the ground for removing work queues from LED class drivers, and is a follow up of the patch set [1]. LED core modifications have been reorganized to make them more clear and easier to review. The patch set is reduced in comparison to it its predecessor, to expose the modifications indispensable for the LED core to gain the capability of handling brightness_set_blocking ops, that is without work queues. Thanks, Jacek Anaszewski [1] https://lkml.org/lkml/2015/8/20/426 Jacek Anaszewski (5): leds: core: Move LED core callbacks out of led-class.c leds: core: Add LED_BLINK_CHANGE and LED_BLINK_DISABLE flags leds: Rename brightness_set_sync op to brightness_set_blocking leds: core: Add an internal led_set_brightness_nosleep function leds: core: Use set_brightness_work for the blocking op drivers/leds/led-class-flash.c | 2 +- drivers/leds/led-class.c | 69 +------------- drivers/leds/led-core.c | 140 +++++++++++++++++++++++++++-- drivers/leds/leds-aat1290.c | 2 +- drivers/leds/leds-ktd2692.c | 2 +- drivers/leds/leds-max77693.c | 2 +- drivers/leds/leds.h | 15 +--- drivers/leds/trigger/ledtrig-backlight.c | 8 +- drivers/leds/trigger/ledtrig-default-on.c | 2 +- drivers/leds/trigger/ledtrig-gpio.c | 6 +- drivers/leds/trigger/ledtrig-heartbeat.c | 4 +- drivers/leds/trigger/ledtrig-oneshot.c | 4 +- drivers/leds/trigger/ledtrig-transient.c | 8 +- include/linux/leds.h | 21 +++-- 14 files changed, 169 insertions(+), 116 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Jacek Anaszewski <j.anaszewski@samsung.com> |
|---|---|
| Date | 2015-09-16 12:50 +0200 |
| Subject | [PATCH 4/5] leds: core: Add an internal led_set_brightness_nosleep function |
| Message-ID | <q9irL-226-1@gated-at.bofh.it> |
| In reply to | #1225982 |
This patch adds led_set_brightness_nosleep function, which guarantees
setting LED brightness in a non-blocking way. It 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: Jacek Anaszewski <j.anaszewski@samsung.com>
---
drivers/leds/led-core.c | 29 ++++++++++++++++++++++++-----
drivers/leds/leds.h | 2 ++
drivers/leds/trigger/ledtrig-backlight.c | 8 ++++----
drivers/leds/trigger/ledtrig-default-on.c | 2 +-
drivers/leds/trigger/ledtrig-gpio.c | 6 +++---
drivers/leds/trigger/ledtrig-heartbeat.c | 4 ++--
drivers/leds/trigger/ledtrig-oneshot.c | 4 ++--
drivers/leds/trigger/ledtrig-transient.c | 8 ++++----
8 files changed, 42 insertions(+), 21 deletions(-)
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 1968e24..fe6c2df 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -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,24 @@ void led_set_brightness(struct led_classdev *led_cdev,
}
EXPORT_SYMBOL(led_set_brightness);
+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;
+
+ /* Use brightness_set op if available, it is guaranteed not to sleep */
+ if (led_cdev->brightness_set)
+ led_cdev->brightness_set(led_cdev, led_cdev->brightness);
+
+ /* If brightness setting can sleep, delegate it to a work queue task */
+ led_cdev->delayed_set_value = led_cdev->brightness;
+ schedule_work(&led_cdev->set_brightness_work);
+}
+EXPORT_SYMBOL(led_set_brightness_nosleep);
+
int led_update_brightness(struct led_classdev *led_cdev)
{
int ret = 0;
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index cf6d448..11520eb 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -46,6 +46,8 @@ 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_nosleep(struct led_classdev *led_cdev,
+ enum led_brightness value);
extern struct rw_semaphore leds_list_lock;
extern struct list_head leds_list;
diff --git a/drivers/leds/trigger/ledtrig-backlight.c b/drivers/leds/trigger/ledtrig-backlight.c
index 59eca17..1ca1f16 100644
--- a/drivers/leds/trigger/ledtrig-backlight.c
+++ b/drivers/leds/trigger/ledtrig-backlight.c
@@ -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;
}
diff --git a/drivers/leds/trigger/ledtrig-default-on.c b/drivers/leds/trigger/ledtrig-default-on.c
index 6f38f88..ff455cb 100644
--- a/drivers/leds/trigger/ledtrig-default-on.c
+++ b/drivers/leds/trigger/ledtrig-default-on.c
@@ -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 = {
diff --git a/drivers/leds/trigger/ledtrig-gpio.c b/drivers/leds/trigger/ledtrig-gpio.c
index 4cc7040..51288a4 100644
--- a/drivers/leds/trigger/ledtrig-gpio.c
+++ b/drivers/leds/trigger/ledtrig-gpio.c
@@ -54,12 +54,12 @@ static void gpio_trig_work(struct work_struct *work)
if (tmp) {
if (gpio_data->desired_brightness)
- led_set_brightness_async(gpio_data->led,
+ led_set_brightness_nosleep(gpio_data->led,
gpio_data->desired_brightness);
else
- led_set_brightness_async(gpio_data->led, LED_FULL);
+ led_set_brightness_nosleep(gpio_data->led, LED_FULL);
} else {
- led_set_brightness_async(gpio_data->led, LED_OFF);
+ led_set_brightness_nosleep(gpio_data->led, LED_OFF);
}
}
diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c
index fea6871..3dc6f0c 100644
--- a/drivers/leds/trigger/ledtrig-heartbeat.c
+++ b/drivers/leds/trigger/ledtrig-heartbeat.c
@@ -37,7 +37,7 @@ static void led_heartbeat_function(unsigned long data)
unsigned long delay = 0;
if (unlikely(panic_heartbeats)) {
- led_set_brightness(led_cdev, LED_OFF);
+ led_set_brightness_nosleep(led_cdev, LED_OFF);
return;
}
@@ -74,7 +74,7 @@ static void led_heartbeat_function(unsigned long data)
break;
}
- led_set_brightness_async(led_cdev, brightness);
+ led_set_brightness_nosleep(led_cdev, brightness);
mod_timer(&heartbeat_data->timer, jiffies + delay);
}
diff --git a/drivers/leds/trigger/ledtrig-oneshot.c b/drivers/leds/trigger/ledtrig-oneshot.c
index fbd02cd..6729317 100644
--- a/drivers/leds/trigger/ledtrig-oneshot.c
+++ b/drivers/leds/trigger/ledtrig-oneshot.c
@@ -63,9 +63,9 @@ static ssize_t led_invert_store(struct device *dev,
oneshot_data->invert = !!state;
if (oneshot_data->invert)
- led_set_brightness_async(led_cdev, LED_FULL);
+ led_set_brightness_nosleep(led_cdev, LED_FULL);
else
- led_set_brightness_async(led_cdev, LED_OFF);
+ led_set_brightness_nosleep(led_cdev, LED_OFF);
return size;
}
diff --git a/drivers/leds/trigger/ledtrig-transient.c b/drivers/leds/trigger/ledtrig-transient.c
index 3c34de4..1dddd8f 100644
--- a/drivers/leds/trigger/ledtrig-transient.c
+++ b/drivers/leds/trigger/ledtrig-transient.c
@@ -41,7 +41,7 @@ static void transient_timer_function(unsigned long data)
struct transient_trig_data *transient_data = led_cdev->trigger_data;
transient_data->activate = 0;
- led_set_brightness_async(led_cdev, transient_data->restore_state);
+ led_set_brightness_nosleep(led_cdev, transient_data->restore_state);
}
static ssize_t transient_activate_show(struct device *dev,
@@ -72,7 +72,7 @@ static ssize_t transient_activate_store(struct device *dev,
if (state == 0 && transient_data->activate == 1) {
del_timer(&transient_data->timer);
transient_data->activate = state;
- led_set_brightness_async(led_cdev,
+ led_set_brightness_nosleep(led_cdev,
transient_data->restore_state);
return size;
}
@@ -81,7 +81,7 @@ static ssize_t transient_activate_store(struct device *dev,
if (state == 1 && transient_data->activate == 0 &&
transient_data->duration != 0) {
transient_data->activate = state;
- led_set_brightness_async(led_cdev, transient_data->state);
+ led_set_brightness_nosleep(led_cdev, transient_data->state);
transient_data->restore_state =
(transient_data->state == LED_FULL) ? LED_OFF : LED_FULL;
mod_timer(&transient_data->timer,
@@ -204,7 +204,7 @@ static void transient_trig_deactivate(struct led_classdev *led_cdev)
if (led_cdev->activated) {
del_timer_sync(&transient_data->timer);
- led_set_brightness_async(led_cdev,
+ led_set_brightness_nosleep(led_cdev,
transient_data->restore_state);
device_remove_file(led_cdev->dev, &dev_attr_activate);
device_remove_file(led_cdev->dev, &dev_attr_duration);
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Jacek Anaszewski <j.anaszewski@samsung.com> |
|---|---|
| Date | 2015-09-16 12:50 +0200 |
| Subject | [PATCH 5/5] leds: core: Use set_brightness_work for the blocking op |
| Message-ID | <q9irL-226-9@gated-at.bofh.it> |
| In reply to | #1225982 |
This patch makes LED core capable of setting brightness for drivers
that implement brightness_set_blocking op. It removes from LED class
drivers responsibility for using work queues on their own.
In order to achieve this set_brightness_delayed callback is being
modified to call newly added __led_set_brightness helper instead of
led_set_brightness_async.
led_set_brightness_async function didn't set brightness in an
asynchronous way in all cases. It was mistakenly assuming that all
LED subsystem drivers used work queue in their brightness_set op,
whereas only half of them did that. Since it has no users now,
it is being removed.
Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
---
drivers/leds/led-core.c | 22 +++++++++++++++++++++-
drivers/leds/leds.h | 10 ----------
include/linux/leds.h | 2 +-
3 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index fe6c2df..d8649f1 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -25,6 +25,22 @@ EXPORT_SYMBOL_GPL(leds_list_lock);
LIST_HEAD(leds_list);
EXPORT_SYMBOL_GPL(leds_list);
+static int __led_set_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ int ret = 0;
+
+ if (led_cdev->brightness_set)
+ led_cdev->brightness_set(led_cdev, led_cdev->brightness);
+ else if (led_cdev->brightness_set_blocking)
+ ret = led_cdev->brightness_set_blocking(led_cdev,
+ led_cdev->brightness);
+ else
+ return -EINVAL;
+
+ return ret;
+}
+
static void led_timer_function(unsigned long data)
{
struct led_classdev *led_cdev = (void *)data;
@@ -83,6 +99,7 @@ static void set_brightness_delayed(struct work_struct *ws)
{
struct led_classdev *led_cdev =
container_of(ws, struct led_classdev, set_brightness_work);
+ int ret;
if (led_cdev->flags & LED_BLINK_DISABLE) {
led_cdev->delayed_set_value = LED_OFF;
@@ -90,7 +107,10 @@ static void set_brightness_delayed(struct work_struct *ws)
led_cdev->flags &= ~LED_BLINK_DISABLE;
}
- led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
+ ret = __led_set_brightness(led_cdev, led_cdev->delayed_set_value);
+ if (ret < 0)
+ dev_err(led_cdev->dev,
+ "Setting an LED's brightness failed (%d)\n", ret);
}
static void led_set_software_blink(struct led_classdev *led_cdev,
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index 11520eb..04b8e41 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -16,16 +16,6 @@
#include <linux/rwsem.h>
#include <linux/leds.h>
-static inline void led_set_brightness_async(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- value = min(value, led_cdev->max_brightness);
- led_cdev->brightness = value;
-
- if (!(led_cdev->flags & LED_SUSPENDED))
- led_cdev->brightness_set(led_cdev, value);
-}
-
static inline int led_set_brightness_sync(struct led_classdev *led_cdev,
enum led_brightness value)
{
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 9f850e6..ae3c178 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -155,7 +155,7 @@ extern void led_blink_set_oneshot(struct led_classdev *led_cdev,
*
* Set an LED's brightness, and, if necessary, cancel the
* software blink timer that implements blinking when the
- * hardware doesn't.
+ * hardware doesn't. This function is guaranteed not to sleep.
*/
extern void led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness);
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Sakari Ailus <sakari.ailus@linux.intel.com> |
|---|---|
| Date | 2015-09-22 10:10 +0200 |
| Subject | Re: [PATCH 5/5] leds: core: Use set_brightness_work for the blocking op |
| Message-ID | <qbqOe-7Y5-7@gated-at.bofh.it> |
| In reply to | #1225985 |
Hi Jacek,
Jacek Anaszewski wrote:
> This patch makes LED core capable of setting brightness for drivers
> that implement brightness_set_blocking op. It removes from LED class
> drivers responsibility for using work queues on their own.
>
> In order to achieve this set_brightness_delayed callback is being
> modified to call newly added __led_set_brightness helper instead of
> led_set_brightness_async.
>
> led_set_brightness_async function didn't set brightness in an
> asynchronous way in all cases. It was mistakenly assuming that all
> LED subsystem drivers used work queue in their brightness_set op,
> whereas only half of them did that. Since it has no users now,
> it is being removed.
>
> Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
> ---
> drivers/leds/led-core.c | 22 +++++++++++++++++++++-
> drivers/leds/leds.h | 10 ----------
> include/linux/leds.h | 2 +-
> 3 files changed, 22 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
> index fe6c2df..d8649f1 100644
> --- a/drivers/leds/led-core.c
> +++ b/drivers/leds/led-core.c
> @@ -25,6 +25,22 @@ EXPORT_SYMBOL_GPL(leds_list_lock);
> LIST_HEAD(leds_list);
> EXPORT_SYMBOL_GPL(leds_list);
>
> +static int __led_set_brightness(struct led_classdev *led_cdev,
> + enum led_brightness brightness)
> +{
> + int ret = 0;
> +
> + if (led_cdev->brightness_set)
> + led_cdev->brightness_set(led_cdev, led_cdev->brightness);
> + else if (led_cdev->brightness_set_blocking)
> + ret = led_cdev->brightness_set_blocking(led_cdev,
You can return here, and drop ret.
> + led_cdev->brightness);
> + else
> + return -EINVAL;
> +
> + return ret;
> +}
> +
> static void led_timer_function(unsigned long data)
> {
> struct led_classdev *led_cdev = (void *)data;
> @@ -83,6 +99,7 @@ static void set_brightness_delayed(struct work_struct *ws)
> {
> struct led_classdev *led_cdev =
> container_of(ws, struct led_classdev, set_brightness_work);
> + int ret;
>
> if (led_cdev->flags & LED_BLINK_DISABLE) {
> led_cdev->delayed_set_value = LED_OFF;
> @@ -90,7 +107,10 @@ static void set_brightness_delayed(struct work_struct *ws)
> led_cdev->flags &= ~LED_BLINK_DISABLE;
> }
>
> - led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
> + ret = __led_set_brightness(led_cdev, led_cdev->delayed_set_value);
As __led_set_brightness() isn't used elsewhere and both are rather
simple functions, I'd just move the contents of that function here.
> + if (ret < 0)
> + dev_err(led_cdev->dev,
> + "Setting an LED's brightness failed (%d)\n", ret);
> }
>
> static void led_set_software_blink(struct led_classdev *led_cdev,
> diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
> index 11520eb..04b8e41 100644
> --- a/drivers/leds/leds.h
> +++ b/drivers/leds/leds.h
> @@ -16,16 +16,6 @@
> #include <linux/rwsem.h>
> #include <linux/leds.h>
>
> -static inline void led_set_brightness_async(struct led_classdev *led_cdev,
> - enum led_brightness value)
> -{
> - value = min(value, led_cdev->max_brightness);
> - led_cdev->brightness = value;
> -
> - if (!(led_cdev->flags & LED_SUSPENDED))
> - led_cdev->brightness_set(led_cdev, value);
> -}
> -
> static inline int led_set_brightness_sync(struct led_classdev *led_cdev,
> enum led_brightness value)
> {
> diff --git a/include/linux/leds.h b/include/linux/leds.h
> index 9f850e6..ae3c178 100644
> --- a/include/linux/leds.h
> +++ b/include/linux/leds.h
> @@ -155,7 +155,7 @@ extern void led_blink_set_oneshot(struct led_classdev *led_cdev,
> *
> * Set an LED's brightness, and, if necessary, cancel the
> * software blink timer that implements blinking when the
> - * hardware doesn't.
> + * hardware doesn't. This function is guaranteed not to sleep.
> */
> extern void led_set_brightness(struct led_classdev *led_cdev,
> enum led_brightness brightness);
>
--
Kind regards,
Sakari Ailus
sakari.ailus@linux.intel.com
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Jacek Anaszewski <j.anaszewski@samsung.com> |
|---|---|
| Date | 2015-09-16 12:50 +0200 |
| Subject | [PATCH 2/5] leds: core: Add LED_BLINK_CHANGE and LED_BLINK_DISABLE flags |
| Message-ID | <q9irM-226-19@gated-at.bofh.it> |
| In reply to | #1225982 |
This patch adds LED_BLINK_CHANGE flag to indicate that blink brightness
has changed, and LED_BLINK_DISABLE flag to indicate that blinking
deactivation has been requested. In order to use the flags
led_timer_function and set_brightness_delayed callbacks as well as
led_set_brightness function are being modified. The main goal of these
modifications is to prepare set_brightness_work for extension of the
scope of its responsibilities.
Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
---
drivers/leds/led-core.c | 36 ++++++++++++++++++++++++++----------
include/linux/leds.h | 10 ++++++----
2 files changed, 32 insertions(+), 14 deletions(-)
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 2cb4e37..1968e24 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -44,18 +44,18 @@ static void led_timer_function(unsigned long data)
brightness = led_get_brightness(led_cdev);
if (!brightness) {
/* Time to switch the LED on. */
- if (led_cdev->delayed_set_value) {
- led_cdev->blink_brightness =
- led_cdev->delayed_set_value;
- led_cdev->delayed_set_value = 0;
- }
brightness = led_cdev->blink_brightness;
delay = led_cdev->blink_delay_on;
} else {
/* Store the current brightness value to be able
* to restore it when the delay_off period is over.
+ * Do it only if there is no pending blink brightness
+ * change, to avoid overwriting the new value.
*/
- led_cdev->blink_brightness = brightness;
+ if (!(led_cdev->flags & LED_BLINK_CHANGE))
+ led_cdev->blink_brightness = brightness;
+ else
+ led_cdev->flags &= ~LED_BLINK_CHANGE;
brightness = LED_OFF;
delay = led_cdev->blink_delay_off;
}
@@ -84,7 +84,11 @@ static void set_brightness_delayed(struct work_struct *ws)
struct led_classdev *led_cdev =
container_of(ws, struct led_classdev, set_brightness_work);
- led_stop_software_blink(led_cdev);
+ if (led_cdev->flags & LED_BLINK_DISABLE) {
+ led_cdev->delayed_set_value = LED_OFF;
+ led_stop_software_blink(led_cdev);
+ led_cdev->flags &= ~LED_BLINK_DISABLE;
+ }
led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
}
@@ -192,11 +196,23 @@ void led_set_brightness(struct led_classdev *led_cdev,
{
int ret = 0;
- /* delay brightness if soft-blink is active */
+ /*
+ * In case blinking is on delay brightness setting
+ * until the next timer tick.
+ */
if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
- led_cdev->delayed_set_value = brightness;
- if (brightness == LED_OFF)
+ /*
+ * If need to disable soft blinking delegate this to the
+ * work queue task to avoid problems in case we are
+ * called from hard irq context.
+ */
+ if (brightness == LED_OFF) {
+ led_cdev->flags |= LED_BLINK_DISABLE;
schedule_work(&led_cdev->set_brightness_work);
+ } else {
+ led_cdev->flags |= LED_BLINK_CHANGE;
+ led_cdev->blink_brightness = brightness;
+ }
return;
}
diff --git a/include/linux/leds.h b/include/linux/leds.h
index b122eea..188352c 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -44,10 +44,12 @@ struct led_classdev {
#define LED_BLINK_ONESHOT (1 << 17)
#define LED_BLINK_ONESHOT_STOP (1 << 18)
#define LED_BLINK_INVERT (1 << 19)
-#define LED_SYSFS_DISABLE (1 << 20)
-#define SET_BRIGHTNESS_ASYNC (1 << 21)
-#define SET_BRIGHTNESS_SYNC (1 << 22)
-#define LED_DEV_CAP_FLASH (1 << 23)
+#define LED_BLINK_CHANGE (1 << 20)
+#define LED_BLINK_DISABLE (1 << 21)
+#define LED_SYSFS_DISABLE (1 << 22)
+#define SET_BRIGHTNESS_ASYNC (1 << 23)
+#define SET_BRIGHTNESS_SYNC (1 << 24)
+#define LED_DEV_CAP_FLASH (1 << 25)
/* Set LED brightness level */
/* Must not sleep, use a workqueue if needed */
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Jacek Anaszewski <j.anaszewski@samsung.com> |
|---|---|
| Date | 2015-09-16 12:50 +0200 |
| Subject | [PATCH 3/5] leds: Rename brightness_set_sync op to brightness_set_blocking |
| Message-ID | <q9irM-226-21@gated-at.bofh.it> |
| In reply to | #1225982 |
The initial purpose of brightness_set_sync op, introduced along with
the LED flash class extension, was to add a means for setting torch LED
brightness as soon as possible, which couldn't have been guaranteed by
brightness_set op. This patch renames the op to brightness_set_blocking,
which describes its purpose in a more generic way, and is beneficial
in view of the prospective changes in the core related to using
LED core's set_brightness_work for setting brightness for LED class
drivers that can sleep or use delays while setting brightness.
Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
---
drivers/leds/led-class-flash.c | 2 +-
drivers/leds/leds-aat1290.c | 2 +-
drivers/leds/leds-ktd2692.c | 2 +-
drivers/leds/leds-max77693.c | 2 +-
drivers/leds/leds.h | 2 +-
include/linux/leds.h | 9 +++------
6 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c
index 3b25734..300a2c9 100644
--- a/drivers/leds/led-class-flash.c
+++ b/drivers/leds/led-class-flash.c
@@ -298,7 +298,7 @@ int led_classdev_flash_register(struct device *parent,
led_cdev = &fled_cdev->led_cdev;
if (led_cdev->flags & LED_DEV_CAP_FLASH) {
- if (!led_cdev->brightness_set_sync)
+ if (!led_cdev->brightness_set_blocking)
return -EINVAL;
ops = fled_cdev->ops;
diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c
index fd7c25f..4bff3b5 100644
--- a/drivers/leds/leds-aat1290.c
+++ b/drivers/leds/leds-aat1290.c
@@ -510,7 +510,7 @@ static int aat1290_led_probe(struct platform_device *pdev)
/* Initialize LED Flash class device */
led_cdev->brightness_set = aat1290_led_brightness_set;
- led_cdev->brightness_set_sync = aat1290_led_brightness_set_sync;
+ led_cdev->brightness_set_blocking = aat1290_led_brightness_set_sync;
led_cdev->max_brightness = led_cfg.max_brightness;
led_cdev->flags |= LED_DEV_CAP_FLASH;
INIT_WORK(&led->work_brightness_set, aat1290_brightness_set_work);
diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/leds-ktd2692.c
index 2ae8c4d..4c14bed 100644
--- a/drivers/leds/leds-ktd2692.c
+++ b/drivers/leds/leds-ktd2692.c
@@ -382,7 +382,7 @@ static int ktd2692_probe(struct platform_device *pdev)
led_cdev->max_brightness = led_cfg.max_brightness;
led_cdev->brightness_set = ktd2692_led_brightness_set;
- led_cdev->brightness_set_sync = ktd2692_led_brightness_set_sync;
+ led_cdev->brightness_set_blocking = ktd2692_led_brightness_set_sync;
led_cdev->flags |= LED_CORE_SUSPENDRESUME | LED_DEV_CAP_FLASH;
mutex_init(&led->lock);
diff --git a/drivers/leds/leds-max77693.c b/drivers/leds/leds-max77693.c
index b8b0eec..f69bcb4 100644
--- a/drivers/leds/leds-max77693.c
+++ b/drivers/leds/leds-max77693.c
@@ -931,7 +931,7 @@ static void max77693_init_fled_cdev(struct max77693_sub_led *sub_led,
led_cdev->name = led_cfg->label[fled_id];
led_cdev->brightness_set = max77693_led_brightness_set;
- led_cdev->brightness_set_sync = max77693_led_brightness_set_sync;
+ led_cdev->brightness_set_blocking = max77693_led_brightness_set_sync;
led_cdev->max_brightness = (led->iout_joint ?
led_cfg->iout_torch_max[FLED1] +
led_cfg->iout_torch_max[FLED2] :
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index 4238fbc..cf6d448 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -34,7 +34,7 @@ static inline int led_set_brightness_sync(struct led_classdev *led_cdev,
led_cdev->brightness = min(value, led_cdev->max_brightness);
if (!(led_cdev->flags & LED_SUSPENDED))
- ret = led_cdev->brightness_set_sync(led_cdev,
+ ret = led_cdev->brightness_set_blocking(led_cdev,
led_cdev->brightness);
return ret;
}
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 188352c..9f850e6 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -55,12 +55,9 @@ struct led_classdev {
/* Must not sleep, use a workqueue if needed */
void (*brightness_set)(struct led_classdev *led_cdev,
enum led_brightness brightness);
- /*
- * Set LED brightness level immediately - it can block the caller for
- * the time required for accessing a LED device register.
- */
- int (*brightness_set_sync)(struct led_classdev *led_cdev,
- enum led_brightness brightness);
+ /* Can sleep or use delays */
+ int (*brightness_set_blocking)(struct led_classdev *led_cdev,
+ enum led_brightness brightness);
/* Get LED brightness level */
enum led_brightness (*brightness_get)(struct led_classdev *led_cdev);
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Jacek Anaszewski <j.anaszewski@samsung.com> |
|---|---|
| Date | 2015-09-16 12:50 +0200 |
| Subject | [PATCH 1/5] leds: core: Move LED core callbacks out of led-class.c |
| Message-ID | <q9irM-226-23@gated-at.bofh.it> |
| In reply to | #1225982 |
Since the API for controlling LED brightness and blinking is defined in
the LED core, move the related timer and work callbacks to the led-core.c,
and initialize them through a new led_core_init API.
Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
---
drivers/leds/led-class.c | 69 +------------------------------------------
drivers/leds/led-core.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/leds/leds.h | 1 +
3 files changed, 75 insertions(+), 68 deletions(-)
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index ca51d58..7385f98 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -102,70 +102,6 @@ static const struct attribute_group *led_groups[] = {
NULL,
};
-static void led_timer_function(unsigned long data)
-{
- struct led_classdev *led_cdev = (void *)data;
- unsigned long brightness;
- unsigned long delay;
-
- if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
- led_set_brightness_async(led_cdev, LED_OFF);
- return;
- }
-
- if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) {
- led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
- return;
- }
-
- brightness = led_get_brightness(led_cdev);
- if (!brightness) {
- /* Time to switch the LED on. */
- if (led_cdev->delayed_set_value) {
- led_cdev->blink_brightness =
- led_cdev->delayed_set_value;
- led_cdev->delayed_set_value = 0;
- }
- brightness = led_cdev->blink_brightness;
- delay = led_cdev->blink_delay_on;
- } else {
- /* Store the current brightness value to be able
- * to restore it when the delay_off period is over.
- */
- led_cdev->blink_brightness = brightness;
- brightness = LED_OFF;
- delay = led_cdev->blink_delay_off;
- }
-
- led_set_brightness_async(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 +
- * delay_off milliseconds in worst case.
- */
- if (led_cdev->flags & LED_BLINK_ONESHOT) {
- if (led_cdev->flags & LED_BLINK_INVERT) {
- if (brightness)
- led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
- } else {
- if (!brightness)
- led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
- }
- }
-
- mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
-}
-
-static void set_brightness_delayed(struct work_struct *ws)
-{
- struct led_classdev *led_cdev =
- container_of(ws, struct led_classdev, set_brightness_work);
-
- led_stop_software_blink(led_cdev);
-
- led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
-}
-
/**
* led_classdev_suspend - suspend an led_classdev.
* @led_cdev: the led_classdev to suspend.
@@ -283,10 +219,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
led_update_brightness(led_cdev);
- INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
-
- setup_timer(&led_cdev->blink_timer, led_timer_function,
- (unsigned long)led_cdev);
+ led_init_core(led_cdev);
#ifdef CONFIG_LEDS_TRIGGERS
led_trigger_set_default(led_cdev);
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 549de7e..2cb4e37 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -25,6 +25,70 @@ EXPORT_SYMBOL_GPL(leds_list_lock);
LIST_HEAD(leds_list);
EXPORT_SYMBOL_GPL(leds_list);
+static void led_timer_function(unsigned long data)
+{
+ struct led_classdev *led_cdev = (void *)data;
+ unsigned long brightness;
+ unsigned long delay;
+
+ if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
+ led_set_brightness_async(led_cdev, LED_OFF);
+ return;
+ }
+
+ if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) {
+ led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
+ return;
+ }
+
+ brightness = led_get_brightness(led_cdev);
+ if (!brightness) {
+ /* Time to switch the LED on. */
+ if (led_cdev->delayed_set_value) {
+ led_cdev->blink_brightness =
+ led_cdev->delayed_set_value;
+ led_cdev->delayed_set_value = 0;
+ }
+ brightness = led_cdev->blink_brightness;
+ delay = led_cdev->blink_delay_on;
+ } else {
+ /* Store the current brightness value to be able
+ * to restore it when the delay_off period is over.
+ */
+ led_cdev->blink_brightness = brightness;
+ brightness = LED_OFF;
+ delay = led_cdev->blink_delay_off;
+ }
+
+ led_set_brightness_async(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 +
+ * delay_off milliseconds in worst case.
+ */
+ if (led_cdev->flags & LED_BLINK_ONESHOT) {
+ if (led_cdev->flags & LED_BLINK_INVERT) {
+ if (brightness)
+ led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
+ } else {
+ if (!brightness)
+ led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
+ }
+ }
+
+ mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
+}
+
+static void set_brightness_delayed(struct work_struct *ws)
+{
+ struct led_classdev *led_cdev =
+ container_of(ws, struct led_classdev, set_brightness_work);
+
+ led_stop_software_blink(led_cdev);
+
+ led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
+}
+
static void led_set_software_blink(struct led_classdev *led_cdev,
unsigned long delay_on,
unsigned long delay_off)
@@ -72,6 +136,15 @@ static void led_blink_setup(struct led_classdev *led_cdev,
led_set_software_blink(led_cdev, *delay_on, *delay_off);
}
+void led_init_core(struct led_classdev *led_cdev)
+{
+ INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
+
+ setup_timer(&led_cdev->blink_timer, led_timer_function,
+ (unsigned long)led_cdev);
+}
+EXPORT_SYMBOL(led_init_core);
+
void led_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index bc89d7a..4238fbc 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -44,6 +44,7 @@ static inline int led_get_brightness(struct led_classdev *led_cdev)
return led_cdev->brightness;
}
+void led_init_core(struct led_classdev *led_cdev);
void led_stop_software_blink(struct led_classdev *led_cdev);
extern struct rw_semaphore leds_list_lock;
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web