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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to