diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2014-09-18 18:54:30 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2014-09-18 18:54:30 +0000 |
commit | 6ebafeca0dd5c4cd22a6e3867343f9ad90f3523c (patch) | |
tree | 6e6f3428ac07ca8ef64ef66ba1115d7179cd48ca /sys | |
parent | 231d13d4d0bf14d55fe755ad590ef613f8d1ea78 (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.c | 52 | ||||
-rw-r--r-- | sys/sys/device.h | 4 |
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 *); |