Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Add init/fini for components (modules etc.). These eat ...
details: https://anonhg.NetBSD.org/src/rev/c88a042bfc02
branches: trunk
changeset: 753389:c88a042bfc02
user: pooka <pooka%NetBSD.org@localhost>
date: Thu Mar 25 19:23:18 2010 +0000
description:
Add init/fini for components (modules etc.). These eat the standard
driver/attach/data typically present and once some locking is grown
in here, these routines can be made to fail or succeed a component
attachment/detachment atomically.
diffstat:
sys/kern/subr_autoconf.c | 173 +++++++++++++++++++++++++++++++++++++++++-----
sys/sys/device.h | 6 +-
2 files changed, 157 insertions(+), 22 deletions(-)
diffs (235 lines):
diff -r 9e14169ba3d3 -r c88a042bfc02 sys/kern/subr_autoconf.c
--- a/sys/kern/subr_autoconf.c Thu Mar 25 16:36:00 2010 +0000
+++ b/sys/kern/subr_autoconf.c Thu Mar 25 19:23:18 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_autoconf.c,v 1.203 2010/02/24 22:38:10 dyoung Exp $ */
+/* $NetBSD: subr_autoconf.c,v 1.204 2010/03/25 19:23:18 pooka 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.203 2010/02/24 22:38:10 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.204 2010/03/25 19:23:18 pooka Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -237,6 +237,91 @@
static void sysctl_detach_setup(struct sysctllog **);
+typedef int (*cfdriver_fn)(struct cfdriver *);
+static int
+frob_cfdrivervec(struct cfdriver * const *cfdriverv,
+ cfdriver_fn drv_do, cfdriver_fn drv_undo,
+ const char *style, bool dopanic)
+{
+ void (*pr)(const char *, ...) = dopanic ? panic : printf;
+ int i = 0, error = 0, e2;
+
+ for (i = 0; cfdriverv[i] != NULL; i++) {
+ if ((error = drv_do(cfdriverv[i])) != 0) {
+ pr("configure: `%s' driver %s failed: %d",
+ cfdriverv[i]->cd_name, style, error);
+ goto bad;
+ }
+ }
+
+ KASSERT(error == 0);
+ return 0;
+
+ bad:
+ printf("\n");
+ for (i--; i >= 0; i--) {
+ e2 = drv_undo(cfdriverv[i]);
+ KASSERT(e2 == 0);
+ }
+
+ return error;
+}
+
+typedef int (*cfattach_fn)(const char *, struct cfattach *);
+static int
+frob_cfattachvec(const struct cfattachinit *cfattachv,
+ cfattach_fn att_do, cfattach_fn att_undo,
+ const char *style, bool dopanic)
+{
+ const struct cfattachinit *cfai = NULL;
+ void (*pr)(const char *, ...) = dopanic ? panic : printf;
+ int j = 0, error = 0, e2;
+
+ for (cfai = &cfattachv[0]; cfai->cfai_name != NULL; cfai++) {
+ for (j = 0; cfai->cfai_list[j] != NULL; j++) {
+ if ((error = att_do(cfai->cfai_name,
+ cfai->cfai_list[j]) != 0)) {
+ pr("configure: attachment `%s' "
+ "of `%s' driver %s failed: %d",
+ cfai->cfai_list[j]->ca_name,
+ cfai->cfai_name, style, error);
+ goto bad;
+ }
+ }
+ }
+
+ KASSERT(error == 0);
+ return 0;
+
+ bad:
+ /*
+ * Rollback in reverse order. dunno if super-important, but
+ * do that anyway. Although the code looks a little like
+ * someone did a little integration (in the math sense).
+ */
+ printf("\n");
+ if (cfai) {
+ bool last;
+
+ for (last = false; last == false; ) {
+ if (cfai == &cfattachv[0])
+ last = true;
+ for (j--; j >= 0; j--) {
+ e2 = att_undo(cfai->cfai_name,
+ cfai->cfai_list[j]);
+ KASSERT(e2 == 0);
+ }
+ if (!last) {
+ cfai--;
+ for (j = 0; cfai->cfai_list[j] != NULL; j++)
+ ;
+ }
+ }
+ }
+
+ return error;
+}
+
/*
* Initialize the autoconfiguration data structures. Normally this
* is done by configure(), but some platforms need to do this very
@@ -245,8 +330,6 @@
void
config_init(void)
{
- const struct cfattachinit *cfai;
- int i, j;
KASSERT(config_initialized == false);
@@ -257,23 +340,10 @@
callout_init(&config_twiddle_ch, CALLOUT_MPSAFE);
- /* allcfdrivers is statically initialized. */
- for (i = 0; cfdriver_list_initial[i] != NULL; i++) {
- if (config_cfdriver_attach(cfdriver_list_initial[i]) != 0)
- panic("configure: duplicate `%s' drivers",
- cfdriver_list_initial[i]->cd_name);
- }
-
- for (cfai = &cfattachinit[0]; cfai->cfai_name != NULL; cfai++) {
- for (j = 0; cfai->cfai_list[j] != NULL; j++) {
- if (config_cfattach_attach(cfai->cfai_name,
- cfai->cfai_list[j]) != 0)
- panic("configure: duplicate `%s' attachment "
- "of `%s' driver",
- cfai->cfai_list[j]->ca_name,
- cfai->cfai_name);
- }
- }
+ frob_cfdrivervec(cfdriver_list_initial,
+ config_cfdriver_attach, NULL, "bootstrap", true);
+ frob_cfattachvec(cfattachinit,
+ config_cfattach_attach, NULL, "bootstrap", true);
initcftable.ct_cfdata = cfdata;
TAILQ_INSERT_TAIL(&allcftables, &initcftable, ct_list);
@@ -281,6 +351,67 @@
config_initialized = true;
}
+/*
+ * Init or fini drivers and attachments. Either all or none
+ * are processed (via rollback). It would be nice if this were
+ * atomic to outside consumers, but with the current state of
+ * locking ...
+ */
+int
+config_init_component(struct cfdriver * const *cfdriverv,
+ const struct cfattachinit *cfattachv, struct cfdata *cfdatav)
+{
+ int error;
+
+ if ((error = frob_cfdrivervec(cfdriverv,
+ config_cfdriver_attach, config_cfdriver_detach, "init", false))!= 0)
+ return error;
+ if ((error = frob_cfattachvec(cfattachv,
+ config_cfattach_attach, config_cfattach_detach,
+ "init", false)) != 0) {
+ frob_cfdrivervec(cfdriverv,
+ config_cfdriver_detach, NULL, "init rollback", true);
+ return error;
+ }
+ if ((error = config_cfdata_attach(cfdatav, 1)) != 0) {
+ frob_cfattachvec(cfattachv,
+ config_cfattach_detach, NULL, "init rollback", true);
+ frob_cfdrivervec(cfdriverv,
+ config_cfdriver_detach, NULL, "init rollback", true);
+ return error;
+ }
+
+ return 0;
+}
+
+int
+config_fini_component(struct cfdriver * const *cfdriverv,
+ const struct cfattachinit *cfattachv, struct cfdata *cfdatav)
+{
+ int error;
+
+ if ((error = config_cfdata_detach(cfdatav)) != 0)
+ return error;
+ if ((error = frob_cfattachvec(cfattachv,
+ config_cfattach_detach, config_cfattach_attach,
+ "fini", false)) != 0) {
+ if (config_cfdata_attach(cfdatav, 0) != 0)
+ panic("config_cfdata fini rollback failed");
+ return error;
+ }
+ if ((error = frob_cfdrivervec(cfdriverv,
+ config_cfdriver_detach, config_cfdriver_attach,
+ "fini", false)) != 0) {
+ frob_cfattachvec(cfattachv,
+ config_cfattach_attach, NULL, "fini rollback", true);
+ if (config_cfdata_attach(cfdatav, 0) != 0)
+ panic("config_cfdata fini rollback failed");
+ return error;
+ }
+
+ return 0;
+}
+
void
config_init_mi(void)
{
diff -r 9e14169ba3d3 -r c88a042bfc02 sys/sys/device.h
--- a/sys/sys/device.h Thu Mar 25 16:36:00 2010 +0000
+++ b/sys/sys/device.h Thu Mar 25 19:23:18 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: device.h,v 1.135 2010/02/24 22:38:10 dyoung Exp $ */
+/* $NetBSD: device.h,v 1.136 2010/03/25 19:23:18 pooka Exp $ */
/*
* Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -431,6 +431,10 @@
int config_handle_wedges(struct device *, int);
void config_init(void);
+int config_init_component(struct cfdriver *const*,
+ const struct cfattachinit *, struct cfdata *);
+int config_fini_component(struct cfdriver *const*,
+ const struct cfattachinit *, struct cfdata *);
void config_init_mi(void);
void drvctl_init(void);
Home |
Main Index |
Thread Index |
Old Index