Module Name:    src
Committed By:   dyoung
Date:           Thu Apr  2 00:09:34 UTC 2009

Modified Files:
        src/sys/arch/i386/isa: npx_isa.c
        src/sys/arch/i386/pci: elan520.c
        src/sys/arch/x86/include: pic.h
        src/sys/arch/x86/pci: pcib.c
        src/sys/dev/ata: ata.c wd.c
        src/sys/dev/cardbus: cardbus.c cardslot.c if_atw_cardbus.c
        src/sys/dev/gpio: gpio.c
        src/sys/dev/isa: com_isa.c wdc_isa.c
        src/sys/dev/mii: nsphyter.c
        src/sys/dev/pci: if_sip.c pccbb.c pci.c ppb.c
        src/sys/dev/pcmcia: pcmcia.c
        src/sys/kern: kern_pmf.c subr_autoconf.c
        src/sys/sys: device.h pmf.h

Log Message:
During shutdown, detach devices in an orderly fashion.

Call the detach routine for every device in the device tree, starting
with the leaves and moving toward the root, expecting that each
(pseudo-)device driver will use the opportunity to gracefully commit
outstandings transactions to the underlying (pseudo-)device and to
relinquish control of the hardware to the system BIOS.

Detaching devices is not suitable for every shutdown: in an emergency,
or if the system state is inconsistent, we should resort to a fast,
simple shutdown that uses only the pmf(9) shutdown hooks and the
(deprecated) shutdownhooks.  For now, if the flag RB_NOSYNC is set in
boothowto, opt for the fast, simple shutdown.

Add a device flag, DVF_DETACH_SHUTDOWN, that indicates by its presence
that it is safe to detach a device during shutdown.  Introduce macros
CFATTACH_DECL3() and CFATTACH_DECL3_NEW() for creating autoconf
attachments with default device flags.  Add DVF_DETACH_SHUTDOWN
to configuration attachments for atabus(4), atw(4) at cardbus(4),
cardbus(4), cardslot(4), com(4) at isa(4), elanpar(4), elanpex(4),
elansc(4), gpio(4), npx(4) at isa(4), nsphyter(4), pci(4), pcib(4),
pcmcia(4), ppb(4), sip(4), wd(4), and wdc(4) at isa(4).

Add a device-detachment "reason" flag, DETACH_SHUTDOWN, that tells the
autoconf code and a device driver that the reason for detachment is
system shutdown.

Add a sysctl, kern.detachall, that tells the system to try to detach
every device at shutdown, regardless of any device's DVF_DETACH_SHUTDOWN
flag.  The default for kern.detachall is 0.  SET IT TO 1, PLEASE, TO
HELP TEST AND DEBUG DEVICE DETACHMENT AT SHUTDOWN.

This is a work in progress.  In future work, I aim to treat
pseudo-devices more thoroughly, and to gracefully tear down a stack of
(pseudo-)disk drivers and filesystems, including cgd(4), vnd(4), and
raid(4) instances at shutdown.

Also commit some changes that are not easily untangled from the rest:

(1) begin to simplify device_t locking: rename struct pmf_private to
device_lock, and incorporate device_lock into struct device.

(2) #include <sys/device.h> in sys/pmf.h in order to get some
definitions that it needs.  Stop unnecessarily #including <sys/device.h>
in sys/arch/x86/include/pic.h to keep the amd64, xen, and i386 releases
building.


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/i386/isa/npx_isa.c
cvs rdiff -u -r1.38 -r1.39 src/sys/arch/i386/pci/elan520.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/x86/include/pic.h
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/x86/pci/pcib.c
cvs rdiff -u -r1.102 -r1.103 src/sys/dev/ata/ata.c
cvs rdiff -u -r1.370 -r1.371 src/sys/dev/ata/wd.c
cvs rdiff -u -r1.95 -r1.96 src/sys/dev/cardbus/cardbus.c
cvs rdiff -u -r1.46 -r1.47 src/sys/dev/cardbus/cardslot.c
cvs rdiff -u -r1.25 -r1.26 src/sys/dev/cardbus/if_atw_cardbus.c
cvs rdiff -u -r1.17 -r1.18 src/sys/dev/gpio/gpio.c
cvs rdiff -u -r1.34 -r1.35 src/sys/dev/isa/com_isa.c
cvs rdiff -u -r1.55 -r1.56 src/sys/dev/isa/wdc_isa.c
cvs rdiff -u -r1.33 -r1.34 src/sys/dev/mii/nsphyter.c
cvs rdiff -u -r1.137 -r1.138 src/sys/dev/pci/if_sip.c
cvs rdiff -u -r1.184 -r1.185 src/sys/dev/pci/pccbb.c
cvs rdiff -u -r1.121 -r1.122 src/sys/dev/pci/pci.c
cvs rdiff -u -r1.39 -r1.40 src/sys/dev/pci/ppb.c
cvs rdiff -u -r1.90 -r1.91 src/sys/dev/pcmcia/pcmcia.c
cvs rdiff -u -r1.21 -r1.22 src/sys/kern/kern_pmf.c
cvs rdiff -u -r1.173 -r1.174 src/sys/kern/subr_autoconf.c
cvs rdiff -u -r1.116 -r1.117 src/sys/sys/device.h
cvs rdiff -u -r1.14 -r1.15 src/sys/sys/pmf.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/arch/i386/isa/npx_isa.c
diff -u src/sys/arch/i386/isa/npx_isa.c:1.19 src/sys/arch/i386/isa/npx_isa.c:1.20
--- src/sys/arch/i386/isa/npx_isa.c:1.19	Fri Apr 11 20:42:34 2008
+++ src/sys/arch/i386/isa/npx_isa.c	Thu Apr  2 00:09:32 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: npx_isa.c,v 1.19 2008/04/11 20:42:34 cegger Exp $	*/
+/*	$NetBSD: npx_isa.c,v 1.20 2009/04/02 00:09:32 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 1991 The Regents of the University of California.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npx_isa.c,v 1.19 2008/04/11 20:42:34 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npx_isa.c,v 1.20 2009/04/02 00:09:32 dyoung Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -86,8 +86,9 @@
 int npx_isa_probe(device_t, struct cfdata *, void *);
 void npx_isa_attach(device_t, device_t, void *);
 
-CFATTACH_DECL_NEW(npx_isa, sizeof(struct npx_softc),
-    npx_isa_probe, npx_isa_attach, npxdetach, NULL);
+CFATTACH_DECL3_NEW(npx_isa, sizeof(struct npx_softc),
+    npx_isa_probe, npx_isa_attach, npxdetach, NULL, NULL, NULL,
+    DVF_DETACH_SHUTDOWN);
 
 int
 npx_isa_probe(device_t parent, struct cfdata *match, void *aux)

Index: src/sys/arch/i386/pci/elan520.c
diff -u src/sys/arch/i386/pci/elan520.c:1.38 src/sys/arch/i386/pci/elan520.c:1.39
--- src/sys/arch/i386/pci/elan520.c:1.38	Tue Feb 24 06:03:54 2009
+++ src/sys/arch/i386/pci/elan520.c	Thu Apr  2 00:09:32 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: elan520.c,v 1.38 2009/02/24 06:03:54 yamt Exp $	*/
+/*	$NetBSD: elan520.c,v 1.39 2009/04/02 00:09:32 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: elan520.c,v 1.38 2009/02/24 06:03:54 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: elan520.c,v 1.39 2009/04/02 00:09:32 dyoung Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1464,15 +1464,17 @@
 	return 0;
 }
 
-CFATTACH_DECL_NEW(elanpar, 0,
-    elanpar_match, elanpar_attach, elanpar_detach, NULL);
+CFATTACH_DECL3_NEW(elanpar, 0,
+    elanpar_match, elanpar_attach, elanpar_detach, NULL, NULL, NULL,
+    DVF_DETACH_SHUTDOWN);
+
+CFATTACH_DECL3_NEW(elanpex, 0,
+    elanpex_match, elanpex_attach, elanpex_detach, NULL, NULL, NULL,
+    DVF_DETACH_SHUTDOWN);
 
-CFATTACH_DECL_NEW(elanpex, 0,
-    elanpex_match, elanpex_attach, elanpex_detach, NULL);
-
-CFATTACH_DECL2_NEW(elansc, sizeof(struct elansc_softc),
+CFATTACH_DECL3_NEW(elansc, sizeof(struct elansc_softc),
     elansc_match, elansc_attach, elansc_detach, NULL, elansc_rescan,
-    elansc_childdetached);
+    elansc_childdetached, DVF_DETACH_SHUTDOWN);
 
 #if NGPIO > 0
 static int

Index: src/sys/arch/x86/include/pic.h
diff -u src/sys/arch/x86/include/pic.h:1.5 src/sys/arch/x86/include/pic.h:1.6
--- src/sys/arch/x86/include/pic.h:1.5	Thu Jul  3 14:02:25 2008
+++ src/sys/arch/x86/include/pic.h	Thu Apr  2 00:09:32 2009
@@ -1,10 +1,8 @@
-/*	$NetBSD: pic.h,v 1.5 2008/07/03 14:02:25 drochner Exp $	*/
+/*	$NetBSD: pic.h,v 1.6 2009/04/02 00:09:32 dyoung Exp $	*/
 
 #ifndef _X86_PIC_H
 #define _X86_PIC_H
 
-#include <sys/device.h>
-
 struct cpu_info;
 
 /* 

Index: src/sys/arch/x86/pci/pcib.c
diff -u src/sys/arch/x86/pci/pcib.c:1.7 src/sys/arch/x86/pci/pcib.c:1.8
--- src/sys/arch/x86/pci/pcib.c:1.7	Mon Aug  4 06:01:18 2008
+++ src/sys/arch/x86/pci/pcib.c	Thu Apr  2 00:09:32 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcib.c,v 1.7 2008/08/04 06:01:18 cegger Exp $	*/
+/*	$NetBSD: pcib.c,v 1.8 2009/04/02 00:09:32 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1998 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.7 2008/08/04 06:01:18 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.8 2009/04/02 00:09:32 dyoung Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -54,8 +54,9 @@
 int	pcibdetach(device_t, int);
 void	pcibchilddet(device_t, device_t);
 
-CFATTACH_DECL2_NEW(pcib, sizeof(struct pcib_softc),
-    pcibmatch, pcibattach, pcibdetach, NULL, NULL, pcibchilddet);
+CFATTACH_DECL3_NEW(pcib, sizeof(struct pcib_softc),
+    pcibmatch, pcibattach, pcibdetach, NULL, NULL, pcibchilddet,
+    DVF_DETACH_SHUTDOWN);
 
 void	pcib_callback(device_t);
 

Index: src/sys/dev/ata/ata.c
diff -u src/sys/dev/ata/ata.c:1.102 src/sys/dev/ata/ata.c:1.103
--- src/sys/dev/ata/ata.c:1.102	Sun Nov 16 19:31:21 2008
+++ src/sys/dev/ata/ata.c	Thu Apr  2 00:09:32 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ata.c,v 1.102 2008/11/16 19:31:21 bouyer Exp $	*/
+/*	$NetBSD: ata.c,v 1.103 2009/04/02 00:09:32 dyoung Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.102 2008/11/16 19:31:21 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.103 2009/04/02 00:09:32 dyoung Exp $");
 
 #include "opt_ata.h"
 
@@ -617,9 +617,9 @@
 	aprint_error_dev(self, "unknown child %p", (const void *)child);
 }
 
-CFATTACH_DECL2_NEW(atabus, sizeof(struct atabus_softc),
+CFATTACH_DECL3_NEW(atabus, sizeof(struct atabus_softc),
     atabus_match, atabus_attach, atabus_detach, atabus_activate, NULL,
-    atabus_childdetached);
+    atabus_childdetached, DVF_DETACH_SHUTDOWN);
 
 /*****************************************************************************
  * Common ATA bus operations.

Index: src/sys/dev/ata/wd.c
diff -u src/sys/dev/ata/wd.c:1.370 src/sys/dev/ata/wd.c:1.371
--- src/sys/dev/ata/wd.c:1.370	Tue Feb 10 19:45:22 2009
+++ src/sys/dev/ata/wd.c	Thu Apr  2 00:09:32 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: wd.c,v 1.370 2009/02/10 19:45:22 tron Exp $ */
+/*	$NetBSD: wd.c,v 1.371 2009/04/02 00:09:32 dyoung Exp $ */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -59,7 +59,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.370 2009/02/10 19:45:22 tron Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.371 2009/04/02 00:09:32 dyoung Exp $");
 
 #include "opt_ata.h"
 
@@ -136,8 +136,8 @@
 static bool	wd_suspend(device_t PMF_FN_PROTO);
 static int	wd_standby(struct wd_softc *, int);
 
-CFATTACH_DECL_NEW(wd, sizeof(struct wd_softc),
-    wdprobe, wdattach, wddetach, wdactivate);
+CFATTACH_DECL3_NEW(wd, sizeof(struct wd_softc),
+    wdprobe, wdattach, wddetach, wdactivate, NULL, NULL, DVF_DETACH_SHUTDOWN);
 
 extern struct cfdriver wd_cd;
 

Index: src/sys/dev/cardbus/cardbus.c
diff -u src/sys/dev/cardbus/cardbus.c:1.95 src/sys/dev/cardbus/cardbus.c:1.96
--- src/sys/dev/cardbus/cardbus.c:1.95	Wed Jun 25 11:42:32 2008
+++ src/sys/dev/cardbus/cardbus.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: cardbus.c,v 1.95 2008/06/25 11:42:32 drochner Exp $	*/
+/*	$NetBSD: cardbus.c,v 1.96 2009/04/02 00:09:33 dyoung Exp $	*/
 
 /*
  * Copyright (c) 1997, 1998, 1999 and 2000
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.95 2008/06/25 11:42:32 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.96 2009/04/02 00:09:33 dyoung Exp $");
 
 #include "opt_cardbus.h"
 
@@ -91,9 +91,9 @@
 
 static bool cardbus_child_register(device_t);
 
-CFATTACH_DECL2_NEW(cardbus, sizeof(struct cardbus_softc),
+CFATTACH_DECL3_NEW(cardbus, sizeof(struct cardbus_softc),
     cardbusmatch, cardbusattach, cardbusdetach, NULL,
-    cardbus_rescan, cardbus_childdetached);
+    cardbus_rescan, cardbus_childdetached, DVF_DETACH_SHUTDOWN);
 
 #ifndef __NetBSD_Version__
 struct cfdriver cardbus_cd = {

Index: src/sys/dev/cardbus/cardslot.c
diff -u src/sys/dev/cardbus/cardslot.c:1.46 src/sys/dev/cardbus/cardslot.c:1.47
--- src/sys/dev/cardbus/cardslot.c:1.46	Sat Mar 14 15:36:16 2009
+++ src/sys/dev/cardbus/cardslot.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: cardslot.c,v 1.46 2009/03/14 15:36:16 dsl Exp $	*/
+/*	$NetBSD: cardslot.c,v 1.47 2009/04/02 00:09:33 dyoung Exp $	*/
 
 /*
  * Copyright (c) 1999 and 2000
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cardslot.c,v 1.46 2009/03/14 15:36:16 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cardslot.c,v 1.47 2009/04/02 00:09:33 dyoung Exp $");
 
 #include "opt_cardslot.h"
 
@@ -75,8 +75,9 @@
 static int cardslot_16_submatch(struct device *, struct cfdata *,
 				     const int *, void *);
 
-CFATTACH_DECL_NEW(cardslot, sizeof(struct cardslot_softc),
-    cardslotmatch, cardslotattach, cardslotdetach, NULL);
+CFATTACH_DECL3_NEW(cardslot, sizeof(struct cardslot_softc),
+    cardslotmatch, cardslotattach, cardslotdetach, NULL, NULL, NULL,
+    DVF_DETACH_SHUTDOWN);
 
 STATIC int
 cardslotmatch(struct device *parent, struct cfdata *cf,

Index: src/sys/dev/cardbus/if_atw_cardbus.c
diff -u src/sys/dev/cardbus/if_atw_cardbus.c:1.25 src/sys/dev/cardbus/if_atw_cardbus.c:1.26
--- src/sys/dev/cardbus/if_atw_cardbus.c:1.25	Fri Feb  6 02:00:50 2009
+++ src/sys/dev/cardbus/if_atw_cardbus.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: if_atw_cardbus.c,v 1.25 2009/02/06 02:00:50 dyoung Exp $ */
+/* $NetBSD: if_atw_cardbus.c,v 1.26 2009/04/02 00:09:33 dyoung Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2003 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_atw_cardbus.c,v 1.25 2009/02/06 02:00:50 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_atw_cardbus.c,v 1.26 2009/04/02 00:09:33 dyoung Exp $");
 
 #include "opt_inet.h"
 #include "bpfilter.h"
@@ -116,8 +116,9 @@
 static void	atw_cardbus_attach(device_t, device_t, void *);
 static int	atw_cardbus_detach(device_t, int);
 
-CFATTACH_DECL_NEW(atw_cardbus, sizeof(struct atw_cardbus_softc),
-    atw_cardbus_match, atw_cardbus_attach, atw_cardbus_detach, atw_activate);
+CFATTACH_DECL3_NEW(atw_cardbus, sizeof(struct atw_cardbus_softc),
+    atw_cardbus_match, atw_cardbus_attach, atw_cardbus_detach, atw_activate,
+    NULL, NULL, DVF_DETACH_SHUTDOWN);
 
 static void	atw_cardbus_setup(struct atw_cardbus_softc *);
 

Index: src/sys/dev/gpio/gpio.c
diff -u src/sys/dev/gpio/gpio.c:1.17 src/sys/dev/gpio/gpio.c:1.18
--- src/sys/dev/gpio/gpio.c:1.17	Thu May  1 22:00:44 2008
+++ src/sys/dev/gpio/gpio.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: gpio.c,v 1.17 2008/05/01 22:00:44 cegger Exp $ */
+/* $NetBSD: gpio.c,v 1.18 2009/04/02 00:09:33 dyoung Exp $ */
 /*	$OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $	*/
 
 /*
@@ -18,7 +18,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.17 2008/05/01 22:00:44 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.18 2009/04/02 00:09:33 dyoung Exp $");
 
 /*
  * General Purpose Input/Output framework.
@@ -55,8 +55,9 @@
 int	gpio_search(device_t, cfdata_t, const int *, void *);
 int	gpio_print(void *, const char *);
 
-CFATTACH_DECL_NEW(gpio, sizeof(struct gpio_softc),
-    gpio_match, gpio_attach, gpio_detach, gpio_activate);
+CFATTACH_DECL3_NEW(gpio, sizeof(struct gpio_softc),
+    gpio_match, gpio_attach, gpio_detach, gpio_activate, NULL, NULL,
+    DVF_DETACH_SHUTDOWN);
 
 dev_type_open(gpioopen);
 dev_type_close(gpioclose);

Index: src/sys/dev/isa/com_isa.c
diff -u src/sys/dev/isa/com_isa.c:1.34 src/sys/dev/isa/com_isa.c:1.35
--- src/sys/dev/isa/com_isa.c:1.34	Mon Apr 28 20:23:52 2008
+++ src/sys/dev/isa/com_isa.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: com_isa.c,v 1.34 2008/04/28 20:23:52 martin Exp $	*/
+/*	$NetBSD: com_isa.c,v 1.35 2009/04/02 00:09:33 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: com_isa.c,v 1.34 2008/04/28 20:23:52 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: com_isa.c,v 1.35 2009/04/02 00:09:33 dyoung Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -107,8 +107,9 @@
 #endif
 
 
-CFATTACH_DECL_NEW(com_isa, sizeof(struct com_isa_softc),
-    com_isa_probe, com_isa_attach, com_isa_detach, com_activate);
+CFATTACH_DECL3_NEW(com_isa, sizeof(struct com_isa_softc),
+    com_isa_probe, com_isa_attach, com_isa_detach, com_activate,
+    NULL, NULL, DVF_DETACH_SHUTDOWN);
 
 int
 com_isa_probe(device_t parent, cfdata_t match, void *aux)

Index: src/sys/dev/isa/wdc_isa.c
diff -u src/sys/dev/isa/wdc_isa.c:1.55 src/sys/dev/isa/wdc_isa.c:1.56
--- src/sys/dev/isa/wdc_isa.c:1.55	Mon Apr 28 20:23:52 2008
+++ src/sys/dev/isa/wdc_isa.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: wdc_isa.c,v 1.55 2008/04/28 20:23:52 martin Exp $ */
+/*	$NetBSD: wdc_isa.c,v 1.56 2009/04/02 00:09:33 dyoung Exp $ */
 
 /*-
  * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wdc_isa.c,v 1.55 2008/04/28 20:23:52 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wdc_isa.c,v 1.56 2009/04/02 00:09:33 dyoung Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -71,9 +71,9 @@
 static void	wdc_isa_attach(device_t, device_t, void *);
 static int	wdc_isa_detach(device_t, int);
 
-CFATTACH_DECL2_NEW(wdc_isa, sizeof(struct wdc_isa_softc),
+CFATTACH_DECL3_NEW(wdc_isa, sizeof(struct wdc_isa_softc),
     wdc_isa_probe, wdc_isa_attach, wdc_isa_detach, NULL, NULL,
-    wdc_childdetached);
+    wdc_childdetached, DVF_DETACH_SHUTDOWN);
 
 #if 0
 static void	wdc_isa_dma_setup(struct wdc_isa_softc *);

Index: src/sys/dev/mii/nsphyter.c
diff -u src/sys/dev/mii/nsphyter.c:1.33 src/sys/dev/mii/nsphyter.c:1.34
--- src/sys/dev/mii/nsphyter.c:1.33	Mon Nov 17 03:04:27 2008
+++ src/sys/dev/mii/nsphyter.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: nsphyter.c,v 1.33 2008/11/17 03:04:27 dyoung Exp $	*/
+/*	$NetBSD: nsphyter.c,v 1.34 2009/04/02 00:09:33 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nsphyter.c,v 1.33 2008/11/17 03:04:27 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nsphyter.c,v 1.34 2009/04/02 00:09:33 dyoung Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -89,8 +89,9 @@
 static int	nsphytermatch(device_t, cfdata_t, void *);
 static void	nsphyterattach(device_t, device_t, void *);
 
-CFATTACH_DECL_NEW(nsphyter, sizeof(struct mii_softc),
-    nsphytermatch, nsphyterattach, mii_phy_detach, mii_phy_activate);
+CFATTACH_DECL3_NEW(nsphyter, sizeof(struct mii_softc),
+    nsphytermatch, nsphyterattach, mii_phy_detach, mii_phy_activate, NULL,
+    NULL, DVF_DETACH_SHUTDOWN);
 
 static int	nsphyter_service(struct mii_softc *, struct mii_data *, int);
 static void	nsphyter_status(struct mii_softc *);

Index: src/sys/dev/pci/if_sip.c
diff -u src/sys/dev/pci/if_sip.c:1.137 src/sys/dev/pci/if_sip.c:1.138
--- src/sys/dev/pci/if_sip.c:1.137	Fri Mar 27 16:45:53 2009
+++ src/sys/dev/pci/if_sip.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_sip.c,v 1.137 2009/03/27 16:45:53 dyoung Exp $	*/
+/*	$NetBSD: if_sip.c,v 1.138 2009/04/02 00:09:33 dyoung Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
@@ -73,7 +73,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_sip.c,v 1.137 2009/03/27 16:45:53 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_sip.c,v 1.138 2009/04/02 00:09:33 dyoung Exp $");
 
 #include "bpfilter.h"
 #include "rnd.h"
@@ -613,10 +613,12 @@
 int	gsip_copy_small = 0;
 int	sip_copy_small = 0;
 
-CFATTACH_DECL(gsip, sizeof(struct sip_softc),
-    sipcom_match, sipcom_attach, sipcom_detach, NULL);
-CFATTACH_DECL(sip, sizeof(struct sip_softc),
-    sipcom_match, sipcom_attach, sipcom_detach, NULL);
+CFATTACH_DECL3(gsip, sizeof(struct sip_softc),
+    sipcom_match, sipcom_attach, sipcom_detach, NULL, NULL, NULL,
+    DVF_DETACH_SHUTDOWN);
+CFATTACH_DECL3(sip, sizeof(struct sip_softc),
+    sipcom_match, sipcom_attach, sipcom_detach, NULL, NULL, NULL,
+    DVF_DETACH_SHUTDOWN);
 
 /*
  * Descriptions of the variants of the SiS900.

Index: src/sys/dev/pci/pccbb.c
diff -u src/sys/dev/pci/pccbb.c:1.184 src/sys/dev/pci/pccbb.c:1.185
--- src/sys/dev/pci/pccbb.c:1.184	Thu Mar  5 01:38:12 2009
+++ src/sys/dev/pci/pccbb.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: pccbb.c,v 1.184 2009/03/05 01:38:12 msaitoh Exp $	*/
+/*	$NetBSD: pccbb.c,v 1.185 2009/04/02 00:09:33 dyoung Exp $	*/
 
 /*
  * Copyright (c) 1998, 1999 and 2000
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pccbb.c,v 1.184 2009/03/05 01:38:12 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pccbb.c,v 1.185 2009/04/02 00:09:33 dyoung Exp $");
 
 /*
 #define CBB_DEBUG
@@ -211,8 +211,9 @@
     bus_space_tag_t memt, bus_space_handle_t memh);
 #endif
 
-CFATTACH_DECL_NEW(cbb_pci, sizeof(struct pccbb_softc),
-    pcicbbmatch, pccbbattach, pccbbdetach, NULL);
+CFATTACH_DECL3_NEW(cbb_pci, sizeof(struct pccbb_softc),
+    pcicbbmatch, pccbbattach, pccbbdetach, NULL, NULL, NULL,
+    DVF_DETACH_SHUTDOWN);
 
 static const struct pcmcia_chip_functions pccbb_pcmcia_funcs = {
 	pccbb_pcmcia_mem_alloc,

Index: src/sys/dev/pci/pci.c
diff -u src/sys/dev/pci/pci.c:1.121 src/sys/dev/pci/pci.c:1.122
--- src/sys/dev/pci/pci.c:1.121	Tue Dec 16 22:35:33 2008
+++ src/sys/dev/pci/pci.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: pci.c,v 1.121 2008/12/16 22:35:33 christos Exp $	*/
+/*	$NetBSD: pci.c,v 1.122 2009/04/02 00:09:33 dyoung Exp $	*/
 
 /*
  * Copyright (c) 1995, 1996, 1997, 1998
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.121 2008/12/16 22:35:33 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.122 2009/04/02 00:09:33 dyoung Exp $");
 
 #include "opt_pci.h"
 
@@ -401,8 +401,9 @@
 	c->c_dev = NULL;
 }
 
-CFATTACH_DECL2_NEW(pci, sizeof(struct pci_softc),
-    pcimatch, pciattach, pcidetach, NULL, pcirescan, pcidevdetached);
+CFATTACH_DECL3_NEW(pci, sizeof(struct pci_softc),
+    pcimatch, pciattach, pcidetach, NULL, pcirescan, pcidevdetached,
+    DVF_DETACH_SHUTDOWN);
 
 int
 pci_get_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid,

Index: src/sys/dev/pci/ppb.c
diff -u src/sys/dev/pci/ppb.c:1.39 src/sys/dev/pci/ppb.c:1.40
--- src/sys/dev/pci/ppb.c:1.39	Sat May  3 05:44:06 2008
+++ src/sys/dev/pci/ppb.c	Thu Apr  2 00:09:33 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ppb.c,v 1.39 2008/05/03 05:44:06 cegger Exp $	*/
+/*	$NetBSD: ppb.c,v 1.40 2009/04/02 00:09:33 dyoung Exp $	*/
 
 /*
  * Copyright (c) 1996, 1998 Christopher G. Demetriou.  All rights reserved.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.39 2008/05/03 05:44:06 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.40 2009/04/02 00:09:33 dyoung Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -206,5 +206,6 @@
 	/* we keep no references to child devices, so do nothing */
 }
 
-CFATTACH_DECL2_NEW(ppb, sizeof(struct ppb_softc),
-    ppbmatch, ppbattach, ppbdetach, NULL, NULL, ppbchilddet);
+CFATTACH_DECL3_NEW(ppb, sizeof(struct ppb_softc),
+    ppbmatch, ppbattach, ppbdetach, NULL, NULL, ppbchilddet,
+    DVF_DETACH_SHUTDOWN);

Index: src/sys/dev/pcmcia/pcmcia.c
diff -u src/sys/dev/pcmcia/pcmcia.c:1.90 src/sys/dev/pcmcia/pcmcia.c:1.91
--- src/sys/dev/pcmcia/pcmcia.c:1.90	Sun Mar 15 20:30:57 2009
+++ src/sys/dev/pcmcia/pcmcia.c	Thu Apr  2 00:09:34 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcmcia.c,v 1.90 2009/03/15 20:30:57 cegger Exp $	*/
+/*	$NetBSD: pcmcia.c,v 1.91 2009/04/02 00:09:34 dyoung Exp $	*/
 
 /*
  * Copyright (c) 2004 Charles M. Hannum.  All rights reserved.
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pcmcia.c,v 1.90 2009/03/15 20:30:57 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pcmcia.c,v 1.91 2009/04/02 00:09:34 dyoung Exp $");
 
 #include "opt_pcmciaverbose.h"
 
@@ -87,9 +87,9 @@
 void	pcmcia_childdetached(struct device *, struct device *);
 int	pcmcia_print(void *, const char *);
 
-CFATTACH_DECL2_NEW(pcmcia, sizeof(struct pcmcia_softc),
+CFATTACH_DECL3_NEW(pcmcia, sizeof(struct pcmcia_softc),
     pcmcia_match, pcmcia_attach, pcmcia_detach, NULL,
-    pcmcia_rescan, pcmcia_childdetached);
+    pcmcia_rescan, pcmcia_childdetached, DVF_DETACH_SHUTDOWN);
 
 int
 pcmcia_ccr_read(struct pcmcia_function *pf, int ccr)

Index: src/sys/kern/kern_pmf.c
diff -u src/sys/kern/kern_pmf.c:1.21 src/sys/kern/kern_pmf.c:1.22
--- src/sys/kern/kern_pmf.c:1.21	Fri Feb  6 01:19:33 2009
+++ src/sys/kern/kern_pmf.c	Thu Apr  2 00:09:34 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_pmf.c,v 1.21 2009/02/06 01:19:33 dyoung Exp $ */
+/* $NetBSD: kern_pmf.c,v 1.22 2009/04/02 00:09:34 dyoung Exp $ */
 
 /*-
  * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_pmf.c,v 1.21 2009/02/06 01:19:33 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_pmf.c,v 1.22 2009/04/02 00:09:34 dyoung Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -297,13 +297,19 @@
 	static struct shutdown_state s;
 	device_t curdev;
 
+	(void)pmf_check_system_drivers();
+
 	aprint_debug("Shutting down devices:");
+	suspendsched();
 
 	for (curdev = shutdown_first(&s); curdev != NULL;
 	     curdev = shutdown_next(&s)) {
 		aprint_debug(" attempting %s shutdown",
 		    device_xname(curdev));
-		if (!device_pmf_is_registered(curdev))
+		if ((boothowto & RB_NOSYNC) == 0 &&
+		    config_detach(curdev, DETACH_SHUTDOWN) == 0)
+			aprint_debug("(detached)");
+		else if (!device_pmf_is_registered(curdev))
 			aprint_debug("(skipped)");
 #if 0 /* needed? */
 		else if (!device_pmf_class_shutdown(curdev, how))

Index: src/sys/kern/subr_autoconf.c
diff -u src/sys/kern/subr_autoconf.c:1.173 src/sys/kern/subr_autoconf.c:1.174
--- src/sys/kern/subr_autoconf.c:1.173	Sat Mar 28 18:43:20 2009
+++ src/sys/kern/subr_autoconf.c	Thu Apr  2 00:09:34 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_autoconf.c,v 1.173 2009/03/28 18:43:20 christos Exp $ */
+/* $NetBSD: subr_autoconf.c,v 1.174 2009/04/02 00:09:34 dyoung 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.173 2009/03/28 18:43:20 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.174 2009/04/02 00:09:34 dyoung Exp $");
 
 #include "opt_ddb.h"
 #include "drvctl.h"
@@ -104,10 +104,9 @@
 #include <sys/fcntl.h>
 #include <sys/lockf.h>
 #include <sys/callout.h>
-#include <sys/mutex.h>
-#include <sys/condvar.h>
 #include <sys/devmon.h>
 #include <sys/cpu.h>
+#include <sys/sysctl.h>
 
 #include <sys/disk.h>
 
@@ -130,14 +129,6 @@
  * Autoconfiguration subroutines.
  */
 
-typedef struct pmf_private {
-	int		pp_nwait;
-	int		pp_nlock;
-	lwp_t		*pp_holder;
-	kmutex_t	pp_mtx;
-	kcondvar_t	pp_cv;
-} pmf_private_t;
-
 /*
  * ioconf.c exports exactly two names: cfdata and cfroots.  All system
  * devices and drivers are found via these tables.
@@ -227,6 +218,8 @@
 static kmutex_t config_misc_lock;
 static kcondvar_t config_misc_cv;
 
+static int detachall = 0;
+
 #define	STREQ(s1, s2)			\
 	(*(s1) == *(s2) && strcmp((s1), (s2)) == 0)
 
@@ -1185,6 +1178,7 @@
 	device_t dev;
 	void *dev_private;
 	const struct cfiattrdata *ia;
+	device_lock_t dvl;
 
 	cd = config_cfdriver_lookup(cf->cf_name);
 	if (cd == NULL)
@@ -1242,6 +1236,11 @@
 	if (dev == NULL)
 		panic("config_devalloc: memory allocation for device_t failed");
 
+	dvl = device_getlock(dev);
+
+	mutex_init(&dvl->dvl_mtx, MUTEX_DEFAULT, IPL_NONE);
+	cv_init(&dvl->dvl_cv, "pmfsusp");
+
 	dev->dv_class = cd->cd_class;
 	dev->dv_cfdata = cf;
 	dev->dv_cfdriver = cd;
@@ -1282,8 +1281,12 @@
 static void
 config_devdealloc(device_t dev)
 {
+	device_lock_t dvl = device_getlock(dev);
 	int priv = (dev->dv_flags & DVF_PRIV_ALLOC);
 
+	cv_destroy(&dvl->dvl_cv);
+	mutex_destroy(&dvl->dvl_mtx);
+
 	KASSERT(dev->dv_properties != NULL);
 	prop_object_release(dev->dv_properties);
 
@@ -1493,7 +1496,11 @@
 	 * remain set.  Otherwise, if DVF_ACTIVE is still set, the
 	 * device is busy, and the detach fails.
 	 */
-	if (ca->ca_activate != NULL)
+	if (!detachall &&
+	    (flags & (DETACH_SHUTDOWN|DETACH_FORCE)) == DETACH_SHUTDOWN &&
+	    (dev->dv_flags & DVF_DETACH_SHUTDOWN) == 0) {
+		rv = EBUSY;	/* XXX EOPNOTSUPP? */
+	} else if (ca->ca_activate != NULL)
 		rv = config_deactivate(dev);
 
 	/*
@@ -2093,14 +2100,6 @@
     bool (*resume)(device_t PMF_FN_PROTO),
     bool (*shutdown)(device_t, int))
 {
-	pmf_private_t *pp;
-
-	if ((pp = kmem_zalloc(sizeof(*pp), KM_SLEEP)) == NULL)
-		return false;
-	mutex_init(&pp->pp_mtx, MUTEX_DEFAULT, IPL_NONE);
-	cv_init(&pp->pp_cv, "pmfsusp");
-	dev->dv_pmf_private = pp;
-
 	dev->dv_driver_suspend = suspend;
 	dev->dv_driver_resume = resume;
 	dev->dv_driver_shutdown = shutdown;
@@ -2120,34 +2119,25 @@
 void
 device_pmf_driver_deregister(device_t dev)
 {
-	pmf_private_t *pp = dev->dv_pmf_private;
-
-	/* XXX avoid crash in case we are not initialized */
-	if (!pp)
-		return;
+	device_lock_t dvl = device_getlock(dev);
 
 	dev->dv_driver_suspend = NULL;
 	dev->dv_driver_resume = NULL;
 
-	mutex_enter(&pp->pp_mtx);
+	mutex_enter(&dvl->dvl_mtx);
 	dev->dv_flags &= ~DVF_POWER_HANDLERS;
-	while (pp->pp_nlock > 0 || pp->pp_nwait > 0) {
+	while (dvl->dvl_nlock > 0 || dvl->dvl_nwait > 0) {
 		/* Wake a thread that waits for the lock.  That
 		 * thread will fail to acquire the lock, and then
 		 * it will wake the next thread that waits for the
 		 * lock, or else it will wake us.
 		 */
-		cv_signal(&pp->pp_cv);
+		cv_signal(&dvl->dvl_cv);
 		pmflock_debug(dev, __func__, __LINE__);
-		cv_wait(&pp->pp_cv, &pp->pp_mtx);
+		cv_wait(&dvl->dvl_cv, &dvl->dvl_mtx);
 		pmflock_debug(dev, __func__, __LINE__);
 	}
-	dev->dv_pmf_private = NULL;
-	mutex_exit(&pp->pp_mtx);
-
-	cv_destroy(&pp->pp_cv);
-	mutex_destroy(&pp->pp_mtx);
-	kmem_free(pp, sizeof(*pp));
+	mutex_exit(&dvl->dvl_mtx);
 }
 
 bool
@@ -2200,46 +2190,46 @@
 static void
 pmflock_debug(device_t dev, const char *func, int line)
 {
-	pmf_private_t *pp = device_pmf_private(dev);
+	device_lock_t dvl = device_getlock(dev);
 
-	aprint_debug_dev(dev, "%s.%d, %s pp_nlock %d pp_nwait %d dv_flags %x\n",
-	    func, line, curlwp_name(), pp->pp_nlock, pp->pp_nwait,
+	aprint_debug_dev(dev, "%s.%d, %s dvl_nlock %d dvl_nwait %d dv_flags %x\n",
+	    func, line, curlwp_name(), dvl->dvl_nlock, dvl->dvl_nwait,
 	    dev->dv_flags);
 }
 
 static void
 pmflock_debug_with_flags(device_t dev, const char *func, int line PMF_FN_ARGS)
 {
-	pmf_private_t *pp = device_pmf_private(dev);
+	device_lock_t dvl = device_getlock(dev);
 
-	aprint_debug_dev(dev, "%s.%d, %s pp_nlock %d pp_nwait %d dv_flags %x "
+	aprint_debug_dev(dev, "%s.%d, %s dvl_nlock %d dvl_nwait %d dv_flags %x "
 	    "flags " PMF_FLAGS_FMT "\n", func, line, curlwp_name(),
-	    pp->pp_nlock, pp->pp_nwait, dev->dv_flags PMF_FN_CALL);
+	    dvl->dvl_nlock, dvl->dvl_nwait, dev->dv_flags PMF_FN_CALL);
 }
 
 static bool
 device_pmf_lock1(device_t dev PMF_FN_ARGS)
 {
-	pmf_private_t *pp = device_pmf_private(dev);
+	device_lock_t dvl = device_getlock(dev);
 
 	while (device_pmf_is_registered(dev) &&
-	    pp->pp_nlock > 0 && pp->pp_holder != curlwp) {
-		pp->pp_nwait++;
+	    dvl->dvl_nlock > 0 && dvl->dvl_holder != curlwp) {
+		dvl->dvl_nwait++;
 		pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
-		cv_wait(&pp->pp_cv, &pp->pp_mtx);
+		cv_wait(&dvl->dvl_cv, &dvl->dvl_mtx);
 		pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
-		pp->pp_nwait--;
+		dvl->dvl_nwait--;
 	}
 	if (!device_pmf_is_registered(dev)) {
 		pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 		/* We could not acquire the lock, but some other thread may
 		 * wait for it, also.  Wake that thread.
 		 */
-		cv_signal(&pp->pp_cv);
+		cv_signal(&dvl->dvl_cv);
 		return false;
 	}
-	pp->pp_nlock++;
-	pp->pp_holder = curlwp;
+	dvl->dvl_nlock++;
+	dvl->dvl_holder = curlwp;
 	pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
 	return true;
 }
@@ -2248,11 +2238,11 @@
 device_pmf_lock(device_t dev PMF_FN_ARGS)
 {
 	bool rc;
-	pmf_private_t *pp = device_pmf_private(dev);
+	device_lock_t dvl = device_getlock(dev);
 
-	mutex_enter(&pp->pp_mtx);
+	mutex_enter(&dvl->dvl_mtx);
 	rc = device_pmf_lock1(dev PMF_FN_CALL);
-	mutex_exit(&pp->pp_mtx);
+	mutex_exit(&dvl->dvl_mtx);
 
 	return rc;
 }
@@ -2260,21 +2250,21 @@
 void
 device_pmf_unlock(device_t dev PMF_FN_ARGS)
 {
-	pmf_private_t *pp = device_pmf_private(dev);
+	device_lock_t dvl = device_getlock(dev);
 
-	KASSERT(pp->pp_nlock > 0);
-	mutex_enter(&pp->pp_mtx);
-	if (--pp->pp_nlock == 0)
-		pp->pp_holder = NULL;
-	cv_signal(&pp->pp_cv);
+	KASSERT(dvl->dvl_nlock > 0);
+	mutex_enter(&dvl->dvl_mtx);
+	if (--dvl->dvl_nlock == 0)
+		dvl->dvl_holder = NULL;
+	cv_signal(&dvl->dvl_cv);
 	pmflock_debug_with_flags(dev, __func__, __LINE__ PMF_FN_CALL);
-	mutex_exit(&pp->pp_mtx);
+	mutex_exit(&dvl->dvl_mtx);
 }
 
-void *
-device_pmf_private(device_t dev)
+device_lock_t
+device_getlock(device_t dev)
 {
-	return dev->dv_pmf_private;
+	return &dev->dv_lock;
 }
 
 void *
@@ -2688,3 +2678,24 @@
 	}
 	mutex_exit(&alldevs_mtx);
 }
+
+SYSCTL_SETUP(sysctl_detach_setup, "sysctl detach setup")
+{
+	const struct sysctlnode *node = NULL;
+
+	sysctl_createv(clog, 0, NULL, &node,
+		CTLFLAG_PERMANENT,
+		CTLTYPE_NODE, "kern", NULL,
+		NULL, 0, NULL, 0,
+		CTL_KERN, CTL_EOL);
+
+	if (node == NULL)
+		return;
+
+	sysctl_createv(clog, 0, &node, NULL,
+		CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+		CTLTYPE_INT, "detachall",
+		SYSCTL_DESCR("Detach all devices at shutdown"),
+		NULL, 0, &detachall, 0,
+		CTL_CREATE, CTL_EOL);
+}

Index: src/sys/sys/device.h
diff -u src/sys/sys/device.h:1.116 src/sys/sys/device.h:1.117
--- src/sys/sys/device.h:1.116	Thu Feb 12 18:24:18 2009
+++ src/sys/sys/device.h	Thu Apr  2 00:09:34 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: device.h,v 1.116 2009/02/12 18:24:18 christos Exp $ */
+/* $NetBSD: device.h,v 1.117 2009/04/02 00:09:34 dyoung Exp $ */
 
 /*
  * Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -82,6 +82,8 @@
 
 typedef struct device *device_t;
 #ifdef _KERNEL
+#include <sys/mutex.h>
+#include <sys/condvar.h>
 #include <sys/pmf.h>
 #endif
 
@@ -121,6 +123,16 @@
 typedef struct cfattach *cfattach_t;
 
 #ifdef _KERNEL
+struct device_lock {
+	int		dvl_nwait;
+	int		dvl_nlock;
+	lwp_t		*dvl_holder;
+	kmutex_t	dvl_mtx;
+	kcondvar_t	dvl_cv;
+};
+
+typedef struct device_lock *device_lock_t;
+
 struct device {
 	devclass_t	dv_class;	/* this device's classification */
 	TAILQ_ENTRY(device) dv_list;	/* entry on list of all devices */
@@ -157,7 +169,7 @@
 	bool		(*dv_class_resume)(device_t PMF_FN_PROTO);
 	void		(*dv_class_deregister)(device_t);
 
-	void		*dv_pmf_private;
+	struct device_lock	dv_lock;
 };
 
 /* dv_flags */
@@ -168,6 +180,7 @@
 #define	DVF_DRIVER_SUSPENDED	0x0010	/* device driver suspend was called */
 #define	DVF_BUS_SUSPENDED	0x0020	/* device bus suspend was called */
 #define	DVF_SELF_SUSPENDED	0x0040	/* device suspended itself */
+#define	DVF_DETACH_SHUTDOWN	0x0080	/* device detaches safely at shutdown */
 
 TAILQ_HEAD(devicelist, device);
 
@@ -287,11 +300,12 @@
 };
 LIST_HEAD(cfattachlist, cfattach);
 
-#define	CFATTACH_DECL2(name, ddsize, matfn, attfn, detfn, actfn, \
-	rescanfn, chdetfn) \
+#define	CFATTACH_DECL3(name, ddsize, matfn, attfn, detfn, actfn, \
+	rescanfn, chdetfn, __flags) \
 struct cfattach __CONCAT(name,_ca) = {					\
 	.ca_name		= ___STRING(name),			\
 	.ca_devsize		= ddsize,				\
+	.ca_flags		= (__flags),				\
 	.ca_match 		= matfn,				\
 	.ca_attach		= attfn,				\
 	.ca_detach		= detfn,				\
@@ -300,15 +314,20 @@
 	.ca_childdetached	= chdetfn,				\
 }
 
+#define	CFATTACH_DECL2(name, ddsize, matfn, attfn, detfn, actfn,	\
+	rescanfn, chdetfn)						\
+	CFATTACH_DECL3(name, ddsize, matfn, attfn, detfn, actfn,	\
+	    rescanfn, chdetfn, 0)
+
 #define	CFATTACH_DECL(name, ddsize, matfn, attfn, detfn, actfn)		\
 	CFATTACH_DECL2(name, ddsize, matfn, attfn, detfn, actfn, NULL, NULL)
 
-#define	CFATTACH_DECL2_NEW(name, ddsize, matfn, attfn, detfn, actfn, \
-	rescanfn, chdetfn) \
+#define	CFATTACH_DECL3_NEW(name, ddsize, matfn, attfn, detfn, actfn, \
+	rescanfn, chdetfn, __flags) \
 struct cfattach __CONCAT(name,_ca) = {					\
 	.ca_name		= ___STRING(name),			\
 	.ca_devsize		= ddsize,				\
-	.ca_flags		= DVF_PRIV_ALLOC,			\
+	.ca_flags		= (__flags) | DVF_PRIV_ALLOC,		\
 	.ca_match 		= matfn,				\
 	.ca_attach		= attfn,				\
 	.ca_detach		= detfn,				\
@@ -317,12 +336,18 @@
 	.ca_childdetached	= chdetfn,				\
 }
 
-#define	CFATTACH_DECL_NEW(name, ddsize, matfn, attfn, detfn, actfn)		\
+#define	CFATTACH_DECL2_NEW(name, ddsize, matfn, attfn, detfn, actfn,	\
+	rescanfn, chdetfn)						\
+	CFATTACH_DECL3_NEW(name, ddsize, matfn, attfn, detfn, actfn,	\
+	    rescanfn, chdetfn, 0)
+
+#define	CFATTACH_DECL_NEW(name, ddsize, matfn, attfn, detfn, actfn)	\
 	CFATTACH_DECL2_NEW(name, ddsize, matfn, attfn, detfn, actfn, NULL, NULL)
 
 /* Flags given to config_detach(), and the ca_detach function. */
 #define	DETACH_FORCE	0x01		/* force detachment; hardware gone */
 #define	DETACH_QUIET	0x02		/* don't print a notice */
+#define	DETACH_SHUTDOWN	0x04		/* detach because of system shutdown */
 
 struct cfdriver {
 	LIST_ENTRY(cfdriver) cd_list;	/* link on allcfdrivers */
@@ -498,7 +523,7 @@
 bool		device_pmf_bus_resume(device_t PMF_FN_PROTO);
 bool		device_pmf_bus_shutdown(device_t, int);
 
-void		*device_pmf_private(device_t);
+device_lock_t	device_getlock(device_t);
 void		device_pmf_unlock(device_t PMF_FN_PROTO);
 bool		device_pmf_lock(device_t PMF_FN_PROTO);
 

Index: src/sys/sys/pmf.h
diff -u src/sys/sys/pmf.h:1.14 src/sys/sys/pmf.h:1.15
--- src/sys/sys/pmf.h:1.14	Fri Feb  6 01:19:33 2009
+++ src/sys/sys/pmf.h	Thu Apr  2 00:09:34 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: pmf.h,v 1.14 2009/02/06 01:19:33 dyoung Exp $ */
+/* $NetBSD: pmf.h,v 1.15 2009/04/02 00:09:34 dyoung Exp $ */
 
 /*-
  * Copyright (c) 2007 Jared D. McNeill <jmcne...@invisible.ca>
@@ -32,6 +32,7 @@
 #ifdef _KERNEL
 
 #include <sys/types.h>
+#include <sys/device.h>
 
 typedef enum {
 	PMFE_DISPLAY_ON,

Reply via email to