Module Name: src Committed By: tsutsui Date: Fri Jun 25 15:10:43 UTC 2010
Modified Files: src/sys/kern: init_main.c subr_autoconf.c src/sys/sys: device.h Log Message: 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. To generate a diff of this commit: cvs rdiff -u -r1.420 -r1.421 src/sys/kern/init_main.c cvs rdiff -u -r1.206 -r1.207 src/sys/kern/subr_autoconf.c cvs rdiff -u -r1.136 -r1.137 src/sys/sys/device.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/init_main.c diff -u src/sys/kern/init_main.c:1.420 src/sys/kern/init_main.c:1.421 --- src/sys/kern/init_main.c:1.420 Thu Jun 10 20:54:53 2010 +++ src/sys/kern/init_main.c Fri Jun 25 15:10:42 2010 @@ -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; Index: src/sys/kern/subr_autoconf.c diff -u src/sys/kern/subr_autoconf.c:1.206 src/sys/kern/subr_autoconf.c:1.207 --- src/sys/kern/subr_autoconf.c:1.206 Fri Apr 30 21:17:22 2010 +++ src/sys/kern/subr_autoconf.c Fri Jun 25 15:10:42 2010 @@ -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 Index: src/sys/sys/device.h diff -u src/sys/sys/device.h:1.136 src/sys/sys/device.h:1.137 --- src/sys/sys/device.h:1.136 Thu Mar 25 19:23:18 2010 +++ src/sys/sys/device.h Fri Jun 25 15:10:42 2010 @@ -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);