summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2014-09-18 18:54:30 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2014-09-18 18:54:30 +0000
commit6ebafeca0dd5c4cd22a6e3867343f9ad90f3523c (patch)
tree6e6f3428ac07ca8ef64ef66ba1115d7179cd48ca /sys
parent231d13d4d0bf14d55fe755ad590ef613f8d1ea78 (diff)
Introduce config_suspend_all(9) a function that invokes config_suspend(9)
on all relevant device hierarchies in the appropriate order. For now this means mpath(4) and mainbus(4), doing mpath(4) before mainbus(4) when suspending or powering down and doing mpath(4) after mainbus(4) when resuming such that mpath(4) can realy on the underlying hardware being in a functional state. Fixes problems with unflushed disk caches on machines where mpath(4) takes control of some of your disks. ok dlg@
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/subr_autoconf.c52
-rw-r--r--sys/sys/device.h4
2 files changed, 54 insertions, 2 deletions
diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c
index 051ef68f1a9..00b988e7c29 100644
--- a/sys/kern/subr_autoconf.c
+++ b/sys/kern/subr_autoconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_autoconf.c,v 1.79 2014/09/14 14:17:25 jsg Exp $ */
+/* $OpenBSD: subr_autoconf.c,v 1.80 2014/09/18 18:54:29 kettenis Exp $ */
/* $NetBSD: subr_autoconf.c,v 1.21 1996/04/04 06:06:18 cgd Exp $ */
/*
@@ -53,6 +53,7 @@
#include <sys/mutex.h>
#include "hotplug.h"
+#include "mpath.h"
/*
* Autoconfiguration subroutines.
@@ -764,6 +765,40 @@ config_suspend(struct device *dev, int act)
return (r);
}
+int
+config_suspend_all(int act)
+{
+ struct device *mainbus = device_mainbus();
+ struct device *mpath = device_mpath();
+ int rv = 0;
+
+ switch (act) {
+ case DVACT_QUIESCE:
+ case DVACT_SUSPEND:
+ case DVACT_POWERDOWN:
+ if (mpath) {
+ rv = config_suspend(mpath, act);
+ if (rv)
+ return rv;
+ }
+ if (mainbus)
+ rv = config_suspend(mainbus, act);
+ break;
+ case DVACT_RESUME:
+ case DVACT_WAKEUP:
+ if (mainbus) {
+ rv = config_suspend(mainbus, act);
+ if (rv)
+ return rv;
+ }
+ if (mpath)
+ rv = config_suspend(mpath, act);
+ break;
+ }
+
+ return (rv);
+}
+
/*
* Call the ca_activate for each of our children, letting each
* decide whether they wish to do the same for their children
@@ -863,6 +898,21 @@ device_mainbus(void)
return (mainbus_cd.cd_devs[0]);
}
+struct device *
+device_mpath(void)
+{
+#if NMPATH > 0
+ extern struct cfdriver mpath_cd;
+
+ if (mpath_cd.cd_ndevs < 1)
+ return (NULL);
+
+ return (mpath_cd.cd_devs[0]);
+#else
+ return (NULL);
+#endif
+}
+
/*
* Increments the ref count on the device structure. The device
* structure is freed when the ref count hits 0.
diff --git a/sys/sys/device.h b/sys/sys/device.h
index 9f1b57b2969..e890b4f31ab 100644
--- a/sys/sys/device.h
+++ b/sys/sys/device.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: device.h,v 1.49 2014/03/29 18:09:31 guenther Exp $ */
+/* $OpenBSD: device.h,v 1.50 2014/09/18 18:54:29 kettenis Exp $ */
/* $NetBSD: device.h,v 1.15 1996/04/09 20:55:24 cgd Exp $ */
/*
@@ -181,6 +181,7 @@ int config_detach(struct device *, int);
int config_detach_children(struct device *, int);
int config_deactivate(struct device *);
int config_suspend(struct device *, int);
+int config_suspend_all(int);
int config_activate_children(struct device *, int);
struct device *config_make_softc(struct device *parent,
struct cfdata *cf);
@@ -189,6 +190,7 @@ void config_pending_incr(void);
void config_pending_decr(void);
struct device *device_mainbus(void);
+struct device *device_mpath(void);
struct device *device_lookup(struct cfdriver *, int unit);
void device_ref(struct device *);
void device_unref(struct device *);