All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stas Sergeev <stsp@list.ru>
To: linux-leds@vger.kernel.org
Cc: Linux kernel <linux-kernel@vger.kernel.org>,
	Stas Sergeev <stsp@users.sourceforge.net>,
	Bryan Wu <cooloney@gmail.com>, Richard Purdie <rpurdie@rpsys.net>,
	Jacek Anaszewski <j.anaszewski@samsung.com>,
	Kyungmin Park <kyungmin.park@samsung.com>
Subject: [PATCH 01/20] leds: implement LED_BRIGHTNESS_FAST flag
Date: Wed, 20 May 2015 18:19:22 +0300	[thread overview]
Message-ID: <555CA5FA.2080308@list.ru> (raw)
In-Reply-To: <555CA58A.10700@list.ru>


Add LED_BRIGHTNESS_FAST flag. This flag is used to mark the led drivers
that do not use waiting operations when setting led brightness and do not
use work-queue in .brightness_set op.
When this flag is not set, disallow the blink periods smaller than 10mS
(LED_SLOW_MIN_PERIOD define).

CC: Bryan Wu <cooloney@gmail.com>
CC: Richard Purdie <rpurdie@rpsys.net>
CC: Jacek Anaszewski <j.anaszewski@samsung.com>
CC: Kyungmin Park <kyungmin.park@samsung.com>
CC: linux-leds@vger.kernel.org
CC: linux-kernel@vger.kernel.org

Signed-off-by: Stas Sergeev <stsp@users.sourceforge.net>
---
 drivers/leds/led-core.c                |   30 +++++++++++++++++++-----------
 drivers/leds/led-triggers.c            |    8 +++++---
 drivers/leds/trigger/ledtrig-oneshot.c |    5 ++++-
 drivers/leds/trigger/ledtrig-timer.c   |   18 +++++++++++++-----
 include/linux/leds.h                   |   12 ++++++++++--
 5 files changed, 51 insertions(+), 22 deletions(-)

diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 9886dac..89241aa 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -25,12 +25,19 @@ EXPORT_SYMBOL_GPL(leds_list_lock);
 LIST_HEAD(leds_list);
 EXPORT_SYMBOL_GPL(leds_list);

-static void led_set_software_blink(struct led_classdev *led_cdev,
+static int led_set_software_blink(struct led_classdev *led_cdev,
 				   unsigned long delay_on,
 				   unsigned long delay_off)
 {
 	int current_brightness;

+	if (!(led_cdev->flags & LED_BRIGHTNESS_FAST)) {
+		if (delay_on < LED_SLOW_MIN_PERIOD)
+			return -ERANGE;
+		if (delay_off < LED_SLOW_MIN_PERIOD)
+			return -ERANGE;
+	}
+
 	current_brightness = led_get_brightness(led_cdev);
 	if (current_brightness)
 		led_cdev->blink_brightness = current_brightness;
@@ -43,36 +50,37 @@ 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);
-		return;
+		return 0;
 	}

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

 	mod_timer(&led_cdev->blink_timer, jiffies + 1);
+	return 0;
 }


-static void led_blink_setup(struct led_classdev *led_cdev,
+static int led_blink_setup(struct led_classdev *led_cdev,
 		     unsigned long *delay_on,
 		     unsigned long *delay_off)
 {
 	if (!(led_cdev->flags & LED_BLINK_ONESHOT) &&
 	    led_cdev->blink_set &&
 	    !led_cdev->blink_set(led_cdev, delay_on, delay_off))
-		return;
+		return 0;

 	/* blink with 1 Hz as default if nothing specified */
 	if (!*delay_on && !*delay_off)
 		*delay_on = *delay_off = 500;

-	led_set_software_blink(led_cdev, *delay_on, *delay_off);
+	return led_set_software_blink(led_cdev, *delay_on, *delay_off);
 }

-void led_blink_set(struct led_classdev *led_cdev,
+int led_blink_set(struct led_classdev *led_cdev,
 		   unsigned long *delay_on,
 		   unsigned long *delay_off)
 {
@@ -81,18 +89,18 @@ void led_blink_set(struct led_classdev *led_cdev,
 	led_cdev->flags &= ~LED_BLINK_ONESHOT;
 	led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;

-	led_blink_setup(led_cdev, delay_on, delay_off);
+	return led_blink_setup(led_cdev, delay_on, delay_off);
 }
 EXPORT_SYMBOL(led_blink_set);

-void led_blink_set_oneshot(struct led_classdev *led_cdev,
+int led_blink_set_oneshot(struct led_classdev *led_cdev,
 			   unsigned long *delay_on,
 			   unsigned long *delay_off,
 			   int invert)
 {
 	if ((led_cdev->flags & LED_BLINK_ONESHOT) &&
 	     timer_pending(&led_cdev->blink_timer))
-		return;
+		return -EBUSY;

 	led_cdev->flags |= LED_BLINK_ONESHOT;
 	led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
@@ -102,7 +110,7 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev,
 	else
 		led_cdev->flags &= ~LED_BLINK_INVERT;

-	led_blink_setup(led_cdev, delay_on, delay_off);
+	return led_blink_setup(led_cdev, delay_on, delay_off);
 }
 EXPORT_SYMBOL(led_blink_set_oneshot);

diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index e8b1120..63305b1 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -272,6 +272,7 @@ static void led_trigger_blink_setup(struct led_trigger *trig,
 			     int oneshot,
 			     int invert)
 {
+	int ret = 0;
 	struct led_classdev *led_cdev;

 	if (!trig)
@@ -280,12 +281,13 @@ static void led_trigger_blink_setup(struct led_trigger *trig,
 	read_lock(&trig->leddev_list_lock);
 	list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) {
 		if (oneshot)
-			led_blink_set_oneshot(led_cdev, delay_on, delay_off,
-					      invert);
+			ret = led_blink_set_oneshot(led_cdev, delay_on,
+						   delay_off, invert);
 		else
-			led_blink_set(led_cdev, delay_on, delay_off);
+			ret = led_blink_set(led_cdev, delay_on, delay_off);
 	}
 	read_unlock(&trig->leddev_list_lock);
+	WARN_ON(ret);
 }

 void led_trigger_blink(struct led_trigger *trig,
diff --git a/drivers/leds/trigger/ledtrig-oneshot.c b/drivers/leds/trigger/ledtrig-oneshot.c
index fbd02cd..ba91838 100644
--- a/drivers/leds/trigger/ledtrig-oneshot.c
+++ b/drivers/leds/trigger/ledtrig-oneshot.c
@@ -29,12 +29,15 @@ struct oneshot_trig_data {
 static ssize_t led_shot(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t size)
 {
+	ssize_t ret;
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
 	struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;

-	led_blink_set_oneshot(led_cdev,
+	ret = led_blink_set_oneshot(led_cdev,
 			&led_cdev->blink_delay_on, &led_cdev->blink_delay_off,
 			oneshot_data->invert);
+	if (ret)
+		return ret;

 	/* content is ignored */
 	return size;
diff --git a/drivers/leds/trigger/ledtrig-timer.c b/drivers/leds/trigger/ledtrig-timer.c
index 8d09327..edc0c7f 100644
--- a/drivers/leds/trigger/ledtrig-timer.c
+++ b/drivers/leds/trigger/ledtrig-timer.c
@@ -31,13 +31,15 @@ static ssize_t led_delay_on_store(struct device *dev,
 {
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
 	unsigned long state;
-	ssize_t ret = -EINVAL;
+	ssize_t ret;

 	ret = kstrtoul(buf, 10, &state);
 	if (ret)
 		return ret;

-	led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
+	ret = led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
+	if (ret)
+		return ret;
 	led_cdev->blink_delay_on = state;

 	return size;
@@ -56,13 +58,15 @@ static ssize_t led_delay_off_store(struct device *dev,
 {
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
 	unsigned long state;
-	ssize_t ret = -EINVAL;
+	ssize_t ret;

 	ret = kstrtoul(buf, 10, &state);
 	if (ret)
 		return ret;

-	led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
+	ret = led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
+	if (ret)
+		return ret;
 	led_cdev->blink_delay_off = state;

 	return size;
@@ -84,12 +88,16 @@ static void timer_trig_activate(struct led_classdev *led_cdev)
 	if (rc)
 		goto err_out_delayon;

-	led_blink_set(led_cdev, &led_cdev->blink_delay_on,
+	rc = led_blink_set(led_cdev, &led_cdev->blink_delay_on,
 		      &led_cdev->blink_delay_off);
+	if (rc)
+		goto err_out_delayoff;
 	led_cdev->activated = true;

 	return;

+err_out_delayoff:
+	device_remove_file(led_cdev->dev, &dev_attr_delay_off);
 err_out_delayon:
 	device_remove_file(led_cdev->dev, &dev_attr_delay_on);
 }
diff --git a/include/linux/leds.h b/include/linux/leds.h
index b122eea..d3c6c2e 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -48,6 +48,10 @@ struct led_classdev {
 #define SET_BRIGHTNESS_ASYNC	(1 << 21)
 #define SET_BRIGHTNESS_SYNC	(1 << 22)
 #define LED_DEV_CAP_FLASH	(1 << 23)
+#define LED_BRIGHTNESS_FAST	(1 << 24)
+
+/* safe period value for slow leds is 10mS */
+#define LED_SLOW_MIN_PERIOD 10

 	/* Set LED brightness level */
 	/* Must not sleep, use a workqueue if needed */
@@ -127,8 +131,10 @@ extern void led_classdev_resume(struct led_classdev *led_cdev);
  * Note that if software blinking is active, simply calling
  * led_cdev->brightness_set() will not stop the blinking,
  * use led_classdev_brightness_set() instead.
+ *
+ * Returns: 0 on success or negative error value on failure
  */
-extern void led_blink_set(struct led_classdev *led_cdev,
+extern int led_blink_set(struct led_classdev *led_cdev,
 			  unsigned long *delay_on,
 			  unsigned long *delay_off);
 /**
@@ -144,8 +150,10 @@ extern void led_blink_set(struct led_classdev *led_cdev,
  *
  * If invert is set, led blinks for delay_off first, then for
  * delay_on and leave the led on after the on-off cycle.
+ *
+ * Returns: 0 on success or negative error value on failure
  */
-extern void led_blink_set_oneshot(struct led_classdev *led_cdev,
+extern int led_blink_set_oneshot(struct led_classdev *led_cdev,
 				  unsigned long *delay_on,
 				  unsigned long *delay_off,
 				  int invert);
-- 
1.7.9.5

  reply	other threads:[~2015-05-20 15:19 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-20 15:17 [PATCH 0/20] leds: put hard limit on minimum blink period for slow leds Stas Sergeev
2015-05-20 15:19 ` Stas Sergeev [this message]
2015-05-21 13:22   ` [PATCH 01/20] leds: implement LED_BRIGHTNESS_FAST flag Jacek Anaszewski
2015-05-21 13:27     ` Stas Sergeev
2015-05-21 13:37       ` Jacek Anaszewski
2015-05-21 15:26         ` Stas Sergeev
2015-05-29 16:24           ` Stas Sergeev
2015-06-01  8:31   ` Jacek Anaszewski
2015-06-01 11:56     ` Stas Sergeev
2015-06-01 14:19       ` Jacek Anaszewski
2015-06-01 14:37         ` Stas Sergeev
2015-06-02  8:11           ` Jacek Anaszewski
2015-05-20 15:20 ` [PATCH 02/20] leds: mark dell-led driver with " Stas Sergeev
2015-05-20 15:21 ` [PATCH 03/20] leds: mark asic3 " Stas Sergeev
2015-05-20 15:22 ` [PATCH 04/20] leds: mark bcm6328 " Stas Sergeev
2015-05-20 15:23 ` [PATCH 05/20] leds: mark clevo-mail " Stas Sergeev
2015-05-20 15:24 ` [PATCH 06/20] leds: mark cobalt-qube " Stas Sergeev
2015-05-20 15:25 ` [PATCH 07/20] leds: mark cobalt-raq " Stas Sergeev
2015-05-20 15:26 ` [PATCH 08/20] leds: mark fsg " Stas Sergeev
2015-05-20 15:27 ` [PATCH 09/20] leds: mark gpio " Stas Sergeev
2015-05-20 15:28 ` [PATCH 10/20] leds: mark hp6xx " Stas Sergeev
2015-05-20 15:29 ` [PATCH 11/20] leds: mark locomo " Stas Sergeev
2015-05-20 15:30 ` [PATCH 12/20] leds: mark net48xx " Stas Sergeev
2015-05-20 15:31 ` [PATCH 13/20] leds: mark netxbig " Stas Sergeev
2015-05-20 15:32 ` [PATCH 14/20] leds: mark ns2 " Stas Sergeev
2015-05-20 15:33 ` [PATCH 15/20] leds: mark ot200 " Stas Sergeev
2015-05-20 15:34 ` [PATCH 16/20] leds: mark pwm " Stas Sergeev
2015-05-20 15:35 ` [PATCH 17/20] leds: mark s3c24xx " Stas Sergeev
2015-05-20 15:35 ` [PATCH 18/20] leds: mark ss4200 " Stas Sergeev
2015-05-20 15:36 ` [PATCH 19/20] leds: mark versatile " Stas Sergeev
2015-05-20 15:37 ` [PATCH 20/20] leds: mark wrap " Stas Sergeev
2015-05-21 15:11 ` [PATCH 02/20] leds: mark dell-led " Stas Sergeev
2015-05-21 15:12 ` [PATCH 03/20] leds: mark asic3 " Stas Sergeev
2015-05-21 15:13 ` [PATCH 04/20] leds: mark bcm6328 " Stas Sergeev
2015-05-21 15:14 ` [PATCH 05/20] leds: mark clevo-mail " Stas Sergeev
2015-05-21 15:15 ` [PATCH 06/20] leds: mark cobalt-qube " Stas Sergeev
2015-05-21 15:15 ` [PATCH 07/20] leds: mark cobalt-raq " Stas Sergeev
2015-05-21 15:16 ` [PATCH 08/20] leds: mark fsg " Stas Sergeev
2015-05-21 15:16 ` [PATCH 09/20] leds: mark gpio " Stas Sergeev
2015-05-21 15:17 ` [PATCH 10/20] leds: mark hp6xx " Stas Sergeev
2015-05-21 15:18 ` [PATCH 11/20] leds: mark locomo " Stas Sergeev
2015-05-21 15:19 ` [PATCH 13/20] leds: mark netxbig " Stas Sergeev
2015-05-21 15:20 ` [PATCH 14/20] leds: mark ns2 " Stas Sergeev
2015-05-21 15:21 ` [PATCH 15/20] leds: mark ot200 " Stas Sergeev
2015-05-26  9:16   ` Christian Gmeiner
2015-05-21 15:21 ` [PATCH 16/20] leds: mark pwm " Stas Sergeev
2015-05-21 15:22 ` [PATCH 17/20] leds: mark s3c24xx " Stas Sergeev
2015-05-21 15:23 ` [PATCH 18/20] leds: mark ss4200 " Stas Sergeev
2015-05-21 15:23 ` [PATCH 19/20] leds: mark versatile " Stas Sergeev
2015-05-22  7:14   ` Linus Walleij
2015-05-22 10:06     ` Stas Sergeev
2015-05-21 15:24 ` [PATCH 20/20] leds: mark wrap " Stas Sergeev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=555CA5FA.2080308@list.ru \
    --to=stsp@list.ru \
    --cc=cooloney@gmail.com \
    --cc=j.anaszewski@samsung.com \
    --cc=kyungmin.park@samsung.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-leds@vger.kernel.org \
    --cc=rpurdie@rpsys.net \
    --cc=stsp@users.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.