Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add config_mountroot(9), which defers device configuration



details:   https://anonhg.NetBSD.org/src/rev/3456448b1390
branches:  trunk
changeset: 755855:3456448b1390
user:      tsutsui <tsutsui%NetBSD.org@localhost>
date:      Fri Jun 25 15:10:42 2010 +0000

description:
Add config_mountroot(9), which defers device configuration
after mountroot(), like config_interrupt(9) that defers
configuration after interrupts are enabled.
This will be used for devices that require firmware loaded
from the root file system by firmload(9) to complete device
initialization (getting MAC address etc).

No objection on tech-kern@:
http://mail-index.NetBSD.org/tech-kern/2010/06/18/msg008370.html
and will also fix PR kern/43125.

diffstat:

 sys/kern/init_main.c     |  21 ++++++++++++++-
 sys/kern/subr_autoconf.c |  65 ++++++++++++++++++++++++++++++++++++++++++++++-
 sys/sys/device.h         |   4 ++-
 3 files changed, 85 insertions(+), 5 deletions(-)

diffs (184 lines):

diff -r 84062df16eb2 -r 3456448b1390 sys/kern/init_main.c
--- a/sys/kern/init_main.c      Fri Jun 25 10:21:50 2010 +0000
+++ b/sys/kern/init_main.c      Fri Jun 25 15:10:42 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: init_main.c,v 1.420 2010/06/10 20:54:53 pooka Exp $    */
+/*     $NetBSD: init_main.c,v 1.421 2010/06/25 15:10:42 tsutsui Exp $  */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.420 2010/06/10 20:54:53 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.421 2010/06/25 15:10:42 tsutsui Exp $");
 
 #include "opt_ddb.h"
 #include "opt_ipsec.h"
@@ -266,6 +266,7 @@
 static void start_init(void *);
 static void configure(void);
 static void configure2(void);
+static void configure3(void);
 void main(void);
 
 /*
@@ -626,6 +627,8 @@
        } while (error != 0);
        mountroothook_destroy();
 
+       configure3();
+
        /*
         * Initialise the time-of-day clock, passing the time recorded
         * in the root filesystem (if any) for use by systems that
@@ -783,6 +786,20 @@
 }
 
 static void
+configure3(void)
+{
+
+       /*
+        * Create threads to call back and finish configuration for
+        * devices that want the mounted root file system.
+        */
+       config_create_mountrootthreads();
+
+       /* Get the threads going and into any sleeps before continuing. */
+       yield();
+}
+
+static void
 check_console(struct lwp *l)
 {
        struct vnode *vp;
diff -r 84062df16eb2 -r 3456448b1390 sys/kern/subr_autoconf.c
--- a/sys/kern/subr_autoconf.c  Fri Jun 25 10:21:50 2010 +0000
+++ b/sys/kern/subr_autoconf.c  Fri Jun 25 15:10:42 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_autoconf.c,v 1.206 2010/04/30 21:17:22 dyoung Exp $ */
+/* $NetBSD: subr_autoconf.c,v 1.207 2010/06/25 15:10:42 tsutsui Exp $ */
 
 /*
  * Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -77,7 +77,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.206 2010/04/30 21:17:22 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.207 2010/06/25 15:10:42 tsutsui Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -200,6 +200,9 @@
 struct deferred_config_head interrupt_config_queue =
        TAILQ_HEAD_INITIALIZER(interrupt_config_queue);
 int interrupt_config_threads = 8;
+struct deferred_config_head mountroot_config_queue =
+       TAILQ_HEAD_INITIALIZER(mountroot_config_queue);
+int mountroot_config_threads = 2;
 
 static void config_process_deferred(struct deferred_config_head *, device_t);
 
@@ -427,6 +430,7 @@
 {
        config_process_deferred(&deferred_config_queue, dev);
        config_process_deferred(&interrupt_config_queue, dev);
+       config_process_deferred(&mountroot_config_queue, dev);
 }
 
 static void
@@ -454,6 +458,30 @@
        }
 }
 
+static void
+config_mountroot_thread(void *cookie)
+{
+       struct deferred_config *dc;
+
+       while ((dc = TAILQ_FIRST(&mountroot_config_queue)) != NULL) {
+               TAILQ_REMOVE(&mountroot_config_queue, dc, dc_queue);
+               (*dc->dc_func)(dc->dc_dev);
+               kmem_free(dc, sizeof(*dc));
+       }
+       kthread_exit(0);
+}
+
+void
+config_create_mountrootthreads()
+{
+       int i;
+
+       for (i = 0; i < mountroot_config_threads; i++) {
+               (void)kthread_create(PRI_NONE, 0, NULL,
+                   config_mountroot_thread, NULL, NULL, "config");
+       }
+}
+
 /*
  * Announce device attach/detach to userland listeners.
  */
@@ -1848,6 +1876,39 @@
 }
 
 /*
+ * Defer some autoconfiguration for a device until after root file system
+ * is mounted (to load firmware etc).
+ */
+void
+config_mountroot(device_t dev, void (*func)(device_t))
+{
+       struct deferred_config *dc;
+
+       /*
+        * If root file system is mounted, callback now.
+        */
+       if (rootvnode != NULL) {
+               (*func)(dev);
+               return;
+       }
+
+#ifdef DIAGNOSTIC
+       TAILQ_FOREACH(dc, &mountroot_config_queue, dc_queue) {
+               if (dc->dc_dev == dev)
+                       panic("%s: deferred twice", __func__);
+       }
+#endif
+
+       dc = kmem_alloc(sizeof(*dc), KM_SLEEP);
+       if (dc == NULL)
+               panic("%s: unable to allocate callback", __func__);
+
+       dc->dc_dev = dev;
+       dc->dc_func = func;
+       TAILQ_INSERT_TAIL(&mountroot_config_queue, dc, dc_queue);
+}
+
+/*
  * Process a deferred configuration queue.
  */
 static void
diff -r 84062df16eb2 -r 3456448b1390 sys/sys/device.h
--- a/sys/sys/device.h  Fri Jun 25 10:21:50 2010 +0000
+++ b/sys/sys/device.h  Fri Jun 25 15:10:42 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: device.h,v 1.136 2010/03/25 19:23:18 pooka Exp $ */
+/* $NetBSD: device.h,v 1.137 2010/06/25 15:10:42 tsutsui Exp $ */
 
 /*
  * Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -479,9 +479,11 @@
 void   config_defer(device_t, void (*)(device_t));
 void   config_deferred(device_t);
 void   config_interrupts(device_t, void (*)(device_t));
+void   config_mountroot(device_t, void (*)(device_t));
 void   config_pending_incr(void);
 void   config_pending_decr(void);
 void   config_create_interruptthreads(void);
+void   config_create_mountrootthreads(void);
 
 int    config_finalize_register(device_t, int (*)(device_t));
 void   config_finalize(void);



Home | Main Index | Thread Index | Old Index