summaryrefslogtreecommitdiffstats
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
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).
-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