svn commit: r247008 - head/sys/dev/led

Alexander Motin mav at FreeBSD.org
Tue Feb 19 19:25:51 UTC 2013


Author: mav
Date: Tue Feb 19 19:25:50 2013
New Revision: 247008
URL: http://svnweb.freebsd.org/changeset/base/247008

Log:
  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).

Modified:
  head/sys/dev/led/led.c

Modified: head/sys/dev/led/led.c
==============================================================================
--- head/sys/dev/led/led.c	Tue Feb 19 19:14:22 2013	(r247007)
+++ head/sys/dev/led/led.c	Tue Feb 19 19:25:50 2013	(r247008)
@@ -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 
 	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
 
 	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);


More information about the svn-src-head mailing list