summaryrefslogtreecommitdiffstats
path: root/sys/dev/led
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2013-02-19 19:25:50 +0000
committermav <mav@FreeBSD.org>2013-02-19 19:25:50 +0000
commited091f220714e658fdfe5a1a5cb757becd74e20a (patch)
treeb8f3d75827e7d0c800e3f4ac0a8ae49cd5d3278b /sys/dev/led
parent6e88c5a765360a8c1663ac824ac82dc5641734a8 (diff)
downloadFreeBSD-src-ed091f220714e658fdfe5a1a5cb757becd74e20a.zip
FreeBSD-src-ed091f220714e658fdfe5a1a5cb757becd74e20a.tar.gz
MFcalloutng:
Make led(4) fire callouts at 10Hz only when there is at least one LED that is requested to blink. Do not fire if all LEDs are static (usual case).
Diffstat (limited to 'sys/dev/led')
-rw-r--r--sys/dev/led/led.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/sys/dev/led/led.c b/sys/dev/led/led.c
index e2a4370..fe0b66b 100644
--- a/sys/dev/led/led.c
+++ b/sys/dev/led/led.c
@@ -43,6 +43,7 @@ static struct mtx led_mtx;
static struct sx led_sx;
static LIST_HEAD(, ledsc) led_list = LIST_HEAD_INITIALIZER(led_list);
static struct callout led_ch;
+static int blinkers = 0;
static MALLOC_DEFINE(M_LED, "LED", "LED driver");
@@ -51,7 +52,6 @@ led_timeout(void *p)
{
struct ledsc *sc;
- mtx_lock(&led_mtx);
LIST_FOREACH(sc, &led_list, list) {
if (sc->ptr == NULL)
continue;
@@ -61,6 +61,7 @@ led_timeout(void *p)
}
if (*sc->ptr == '.') {
sc->ptr = NULL;
+ blinkers--;
continue;
} else if (*sc->ptr == 'U' || *sc->ptr == 'u') {
if (sc->last_second == time_second)
@@ -78,9 +79,8 @@ led_timeout(void *p)
if (*sc->ptr == '\0')
sc->ptr = sc->str;
}
- mtx_unlock(&led_mtx);
- callout_reset(&led_ch, hz / 10, led_timeout, p);
- return;
+ if (blinkers > 0)
+ callout_reset(&led_ch, hz / 10, led_timeout, p);
}
static int
@@ -92,9 +92,15 @@ led_state(struct ledsc *sc, struct sbuf **sb, int state)
sc->spec = *sb;
if (*sb != NULL) {
sc->str = sbuf_data(*sb);
+ if (sc->ptr == NULL) {
+ blinkers++;
+ callout_reset(&led_ch, hz / 10, led_timeout, NULL);
+ }
sc->ptr = sc->str;
} else {
sc->str = NULL;
+ if (sc->ptr != NULL)
+ blinkers--;
sc->ptr = NULL;
sc->func(sc->private, state);
}
@@ -286,8 +292,6 @@ led_create_state(led_t *func, void *priv, char const *name, int state)
mtx_lock(&led_mtx);
sc->dev->si_drv1 = sc;
- if (LIST_EMPTY(&led_list))
- callout_reset(&led_ch, hz / 10, led_timeout, NULL);
LIST_INSERT_HEAD(&led_list, sc, list);
sc->func(sc->private, state != 0);
mtx_unlock(&led_mtx);
@@ -303,7 +307,8 @@ led_destroy(struct cdev *dev)
mtx_lock(&led_mtx);
sc = dev->si_drv1;
dev->si_drv1 = NULL;
-
+ if (sc->ptr != NULL)
+ blinkers--;
LIST_REMOVE(sc, list);
if (LIST_EMPTY(&led_list))
callout_stop(&led_ch);
@@ -326,7 +331,7 @@ led_drvinit(void *unused)
led_unit = new_unrhdr(0, INT_MAX, NULL);
mtx_init(&led_mtx, "LED mtx", NULL, MTX_DEF);
sx_init(&led_sx, "LED sx");
- callout_init(&led_ch, CALLOUT_MPSAFE);
+ callout_init_mtx(&led_ch, &led_mtx, 0);
}
SYSINIT(leddev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, led_drvinit, NULL);
OpenPOWER on IntegriCloud