Hi,

We plan to remove shutdown hooks for good and need to convert
all drivers implementing a watchdog(4) device to the config_*
framework namely implementing the activate method with a
DVACT_POWERDOWN action handler fleshed out.

This is the diff I came up with.  wdog_shutdown will now check
that the registered watchdog is the one we're disabling.

This compiles on amd64, i386 and sparc64, works fine on glxpcib
(the only one we have access to).

Here's a list of drivers that get changed:
 
 armv7/omap/omdog
 armv7/sunxi/sxidog

 i386/esm
 i386/elansc
 i386/geodesc

 sgi/imc

 sparc64/lom
 sparc64/pmc

 ipmi (not enabled)

 fins, it, schsio, viasio

 berkwdt, glxpcib, ichwdt, pwdog, tcpcib, wdt

Tests and OK's are welcome.


diff --git sys/arch/armv7/omap/omdog.c sys/arch/armv7/omap/omdog.c
index a8fb5d4..166bc11 100644
--- sys/arch/armv7/omap/omdog.c
+++ sys/arch/armv7/omap/omdog.c
@@ -55,18 +55,19 @@ struct omdog_softc {
 };
 
 struct omdog_softc *omdog_sc;
 
 void   omdog_attach(struct device *, struct device *, void *);
+int    omdog_activate(struct device *, int);
 void   omdog_start(struct omdog_softc *);
 void   omdog_stop(struct omdog_softc *);
 void   omdog_sync(struct omdog_softc *);
 int    omdog_cb(void *, int);
 void   omdog_reset(void);
 
 struct cfattach        omdog_ca = {
-       sizeof (struct omdog_softc), NULL, omdog_attach
+       sizeof (struct omdog_softc), NULL, omdog_attach, NULL, omdog_activate
 };
 
 struct cfdriver omdog_cd = {
        NULL, "omdog", DV_DULL
 };
@@ -93,10 +94,24 @@ omdog_attach(struct device *parent, struct device *self, 
void *args)
 #ifndef SMALL_KERNEL
        wdog_register(omdog_cb, sc);
 #endif
 }
 
+int
+omdog_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+#ifndef SMALL_KERNEL
+               wdog_shutdown(self);
+#endif
+               break;
+       }
+
+       return (0);
+}
+
 void
 omdog_start(struct omdog_softc *sc)
 {
        /* Write the enable sequence data BBBBh followed by 4444h */
        bus_space_write_4(sc->sc_iot, sc->sc_ioh, WSPR, 0xbbbb);
diff --git sys/arch/armv7/sunxi/sxidog.c sys/arch/armv7/sunxi/sxidog.c
index ab327dd..c59660f 100644
--- sys/arch/armv7/sunxi/sxidog.c
+++ sys/arch/armv7/sunxi/sxidog.c
@@ -64,18 +64,20 @@ struct sxidog_softc {
 };
 
 struct sxidog_softc *sxidog_sc = NULL; /* for sxidog_reset() */
 
 void sxidog_attach(struct device *, struct device *, void *);
+int sxidog_activate(struct device *, int);
 int sxidog_callback(void *, int);
 #if 0
 int sxidog_intr(void *);
 #endif
 void sxidog_reset(void);
 
 struct cfattach        sxidog_ca = {
-       sizeof (struct sxidog_softc), NULL, sxidog_attach
+       sizeof (struct sxidog_softc), NULL, sxidog_attach,
+       NULL, sxidog_activate
 };
 
 struct cfdriver sxidog_cd = {
        NULL, "sxidog", DV_DULL
 };
diff --git sys/arch/i386/i386/esm.c sys/arch/i386/i386/esm.c
index 54f9f6d..40a278b 100644
--- sys/arch/i386/i386/esm.c
+++ sys/arch/i386/i386/esm.c
@@ -43,10 +43,11 @@ int esmdebug = 3;
 #define DPRINTFN(n,x...)       /* n: x */
 #endif
 
 int            esm_match(struct device *, void *, void *);
 void           esm_attach(struct device *, struct device *, void *);
+int            esm_activate(struct device *, int);
 
 enum esm_sensor_type {
        ESM_S_UNKNOWN, /* XXX */
        ESM_S_INTRUSION,
        ESM_S_TEMP,
@@ -122,11 +123,12 @@ struct esm_softc {
        int                     sc_wdog_period;
        volatile int            sc_wdog_tickle;
 };
 
 struct cfattach esm_ca = {
-       sizeof(struct esm_softc), esm_match, esm_attach
+       sizeof(struct esm_softc), esm_match, esm_attach,
+       NULL, esm_activate
 };
 
 struct cfdriver esm_cd = {
        NULL, "esm", DV_DULL
 };
@@ -272,10 +274,22 @@ esm_attach(struct device *parent, struct device *self, 
void *aux)
                timeout_add_sec(&sc->sc_timeout, 1);
        }
 }
 
 int
+esm_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
+int
 esm_watchdog(void *arg, int period)
 {
        struct esm_softc        *sc = arg;
        struct esm_wdog_prop    prop;
        struct esm_wdog_state   state;
diff --git sys/arch/i386/pci/elan520.c sys/arch/i386/pci/elan520.c
index bf077dd..b97476b 100644
--- sys/arch/i386/pci/elan520.c
+++ sys/arch/i386/pci/elan520.c
@@ -68,10 +68,11 @@ struct elansc_softc {
        struct timecounter      sc_tc;
 } *elansc;
 
 int    elansc_match(struct device *, void *, void *);
 void   elansc_attach(struct device *, struct device *, void *);
+int    elansc_activate(struct device *, int);
 void   elansc_update_cpuspeed(void);
 void   elansc_setperf(int);
 int    elansc_cpuspeed(int *);
 
 void   elansc_wdogctl(struct elansc_softc *, int, uint16_t);
@@ -84,11 +85,12 @@ void        elansc_gpio_pin_write(void *, int, int);
 void   elansc_gpio_pin_ctl(void *, int, int);
 
 u_int  elansc_tc_read(struct timecounter *);
 
 struct cfattach elansc_ca = {
-       sizeof(struct elansc_softc), elansc_match, elansc_attach
+       sizeof(struct elansc_softc), elansc_match, elansc_attach,
+       NULL, elansc_activate
 };
 
 struct cfdriver elansc_cd = {
        NULL, "elansc", DV_DULL
 };
@@ -229,10 +231,22 @@ elansc_attach(struct device *parent, struct device *self, 
void *aux)
        tc->tc_quality = 1000;
        tc->tc_priv = sc;
        tc_init(tc);
 }
 
+int
+elansc_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
 u_int
 elansc_tc_read(struct timecounter *tc)
 {
        struct elansc_softc *sc = tc->tc_priv;
        u_int32_t m1, m2, l;
diff --git sys/arch/i386/pci/geodesc.c sys/arch/i386/pci/geodesc.c
index b903ece0..5ee4589 100644
--- sys/arch/i386/pci/geodesc.c
+++ sys/arch/i386/pci/geodesc.c
@@ -39,18 +39,20 @@ struct geodesc_softc {
        bus_space_handle_t      sc_ioh;
 };
 
 int    geodesc_match(struct device *, void *, void *);
 void   geodesc_attach(struct device *, struct device *, void *);
+int    geodesc_activate(struct device *, int);
 void   sc1100_sysreset(void);
 
 #ifndef SMALL_KERNEL
 int    geodesc_wdogctl_cb(void *, int);
 #endif /* SMALL_KERNEL */
 
 struct cfattach geodesc_ca = {
-       sizeof(struct geodesc_softc), geodesc_match, geodesc_attach
+       sizeof(struct geodesc_softc), geodesc_match, geodesc_attach,
+       NULL, geodesc_activate
 };
 
 struct cfdriver geodesc_cd = {
        NULL, "geodesc", DV_DULL
 };
@@ -129,10 +131,24 @@ geodesc_attach(struct device *parent, struct device 
*self, void *aux)
 
        /* We have a special way to reset the CPU on the SC1100 */
        cpuresetfn = sc1100_sysreset;
 }
 
+int
+geodesc_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+#ifndef SMALL_KERNEL
+               wdog_shutdown(self);
+#endif
+               break;
+       }
+
+       return (0);
+}
+
 #ifndef SMALL_KERNEL
 int
 geodesc_wdogctl_cb(void *self, int period)
 {
        struct geodesc_softc *sc = self;
diff --git sys/arch/sgi/localbus/imc.c sys/arch/sgi/localbus/imc.c
index 1382074..35bdcc1 100644
--- sys/arch/sgi/localbus/imc.c
+++ sys/arch/sgi/localbus/imc.c
@@ -73,14 +73,15 @@
 #include <dev/eisa/eisavar.h>
 #endif
 
 int    imc_match(struct device *, void *, void *);
 void   imc_attach(struct device *, struct device *, void *);
+int    imc_activate(struct device *, int);
 int    imc_print(void *, const char *);
 
 const struct cfattach imc_ca = {
-       sizeof(struct device), imc_match, imc_attach
+       sizeof(struct device), imc_match, imc_attach, NULL, imc_activate
 };
 
 struct cfdriver imc_cd = {
        NULL, "imc", DV_DULL
 };
@@ -697,10 +698,27 @@ imc_attach(struct device *parent, struct device *self, 
void *aux)
        wdog_register(imc_watchdog_cb, self);
 #endif
 }
 
 int
+imc_activate(struct device *self, int act)
+{
+       int rv = 0;
+
+       switch (act) {
+       case DVACT_POWERDOWN:
+#ifndef SMALL_KERNEL
+               wdog_shutdown(self);
+#endif
+               rv = config_activate_children(self, act);
+               break;
+       }
+
+       return (rv);
+}
+
+int
 imc_print(void *aux, const char *name)
 {
        struct imc_attach_args *iaa = aux;
 
        if (name != NULL)
diff --git sys/arch/sparc64/dev/lom.c sys/arch/sparc64/dev/lom.c
index 883b90d..38b7a4d 100644
--- sys/arch/sparc64/dev/lom.c
+++ sys/arch/sparc64/dev/lom.c
@@ -366,10 +366,11 @@ lom_activate(struct device *self, int act)
 {
        int ret = 0;
 
        switch (act) {
        case DVACT_POWERDOWN:
+               wdog_shutdown(self);
                lom_shutdown(self);
                break;
        }
 
        return (ret);
diff --git sys/arch/sparc64/dev/pmc.c sys/arch/sparc64/dev/pmc.c
index 77bd9f0..95d6b4d 100644
--- sys/arch/sparc64/dev/pmc.c
+++ sys/arch/sparc64/dev/pmc.c
@@ -48,14 +48,15 @@ struct pmc_softc {
        bus_space_handle_t      sc_ioh;
 };
 
 int    pmc_match(struct device *, void *, void *);
 void   pmc_attach(struct device *, struct device *, void *);
+int    pmc_activate(struct device *, int);
 int    pmc_wdog_cb(void *, int);
 
 struct cfattach pmc_ca = {
-       sizeof(struct pmc_softc), pmc_match, pmc_attach
+       sizeof(struct pmc_softc), pmc_match, pmc_attach, NULL, pmc_activate
 };
 
 struct cfdriver pmc_cd = {
        NULL, "pmc", DV_DULL
 };
@@ -101,10 +102,22 @@ pmc_attach(struct device *parent, struct device *self, 
void *aux)
 
        wdog_register(pmc_wdog_cb, sc);
 }
 
 int
+pmc_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
+int
 pmc_wdog_cb(void *arg, int period)
 {
        struct pmc_softc *sc = arg;
        int mins;
 
diff --git sys/dev/ipmi.c sys/dev/ipmi.c
index 5556db9..fe90d2f 100644
--- sys/dev/ipmi.c
+++ sys/dev/ipmi.c
@@ -156,10 +156,11 @@ void      ipmi_delay(struct ipmi_softc *, int);
 int    ipmi_watchdog(void *, int);
 
 int    ipmi_intr(void *);
 int    ipmi_match(struct device *, void *, void *);
 void   ipmi_attach(struct device *, struct device *, void *);
+int    ipmi_activate(struct device *, int);
 
 long   ipow(long, int);
 long   ipmi_convert(u_int8_t, struct sdrtype1 *, long);
 void   ipmi_sensor_name(char *, int, u_int8_t, u_int8_t *);
 
@@ -833,11 +834,12 @@ struct ipmi_bmc_response {
        u_int8_t        bmc_data_len;
        u_int8_t        bmc_data[1];
 };
 
 struct cfattach ipmi_ca = {
-       sizeof(struct ipmi_softc), ipmi_match, ipmi_attach
+       sizeof(struct ipmi_softc), ipmi_match, ipmi_attach,
+       NULL, ipmi_activate
 };
 
 struct cfdriver ipmi_cd = {
        NULL, "ipmi", DV_DULL
 };
@@ -1759,10 +1761,22 @@ ipmi_attach(struct device *parent, struct device *self, 
void *aux)
        sc->sc_max_retries = 50; /* 50 * 1/100 = 0.5 seconds max */
        timeout_set(&sc->sc_timeout, _bmc_io_wait, sc);
 }
 
 int
+ipmi_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
+int
 ipmi_watchdog(void *arg, int period)
 {
        struct ipmi_softc       *sc = arg;
        struct ipmi_watchdog    wdog;
        int                     s, rc, len;
diff --git sys/dev/isa/fins.c sys/dev/isa/fins.c
index af5087f..b9abd80 100644
--- sys/dev/isa/fins.c
+++ sys/dev/isa/fins.c
@@ -122,10 +122,11 @@ struct fins_softc {
        u_int8_t fins_wdog_cr;
 };
 
 int  fins_match(struct device *, void *, void *);
 void fins_attach(struct device *, struct device *, void *);
+int  fins_activate(struct device *, int);
 
 void fins_unlock(bus_space_tag_t, bus_space_handle_t);
 void fins_lock(bus_space_tag_t, bus_space_handle_t);
 
 u_int8_t fins_read(bus_space_tag_t, bus_space_handle_t, int);
@@ -148,11 +149,13 @@ void fins_get_volt(struct fins_softc *, int);
 int fins_wdog_cb(void *, int);
 
 struct cfattach fins_ca = {
        sizeof(struct fins_softc),
        fins_match,
-       fins_attach
+       fins_attach,
+       NULL,
+       fins_activate
 };
 
 struct cfdriver fins_cd = {
        NULL, "fins", DV_DULL
 };
@@ -303,10 +306,22 @@ fins_attach(struct device *parent, struct device *self, 
void *aux)
        wdog_register(fins_wdog_cb, sc);
 attach_done:
        printf("\n");
 }
 
+int
+fins_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
 u_int8_t
 fins_read(bus_space_tag_t iot, bus_space_handle_t ioh, int reg)
 {
        bus_space_write_1(iot, ioh, FINS_ADDR, reg);
        return (bus_space_read_1(iot, ioh, FINS_DATA));
diff --git sys/dev/isa/it.c sys/dev/isa/it.c
index 90a1801..effa59a 100644
--- sys/dev/isa/it.c
+++ sys/dev/isa/it.c
@@ -46,10 +46,11 @@
 #endif
 
 
 int it_match(struct device *, void *, void *);
 void it_attach(struct device *, struct device *, void *);
+int it_activate(struct device *, int);
 u_int8_t it_readreg(bus_space_tag_t, bus_space_handle_t, int);
 void it_writereg(bus_space_tag_t, bus_space_handle_t, int, u_int8_t);
 void it_enter(bus_space_tag_t, bus_space_handle_t, int);
 void it_exit(bus_space_tag_t, bus_space_handle_t);
 
@@ -287,10 +288,22 @@ it_attach(struct device *parent, struct device *self, 
void *aux)
        for (i = 0; i < IT_EC_NUMSENSORS; i++)
                sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
        sensordev_install(&sc->sc_sensordev);
 }
 
+int
+it_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
 u_int8_t
 it_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int r)
 {
        bus_space_write_1(iot, ioh, IT_IO_ADDR, r);
        return (bus_space_read_1(iot, ioh, IT_IO_DATA));
@@ -523,11 +536,13 @@ it_wdog_cb(void *arg, int period)
 
 
 struct cfattach it_ca = {
        sizeof(struct it_softc),
        it_match,
-       it_attach
+       it_attach,
+       NULL,
+       it_activate
 };
 
 struct cfdriver it_cd = {
        NULL, "it", DV_DULL
 };
diff --git sys/dev/isa/sch311x.c sys/dev/isa/sch311x.c
index 87cd1da..b46bfef 100644
--- sys/dev/isa/sch311x.c
+++ sys/dev/isa/sch311x.c
@@ -158,10 +158,11 @@ struct schsio_softc {
        struct ksensor          sc_sensor[SCHSIO_SENSORS];
 };
 
 int    schsio_probe(struct device *, void *, void *);
 void   schsio_attach(struct device *, struct device *, void *);
+int    schsio_activate(struct device *, int);
 
 static __inline void schsio_config_enable(bus_space_tag_t iot,
     bus_space_handle_t ioh);
 static __inline void schsio_config_disable(bus_space_tag_t iot,
     bus_space_handle_t ioh);
@@ -182,11 +183,13 @@ void schsio_wdt_init(struct schsio_softc *sc);
 int schsio_wdt_cb(void *arg, int period);
 
 struct cfattach schsio_ca = {
        sizeof(struct schsio_softc),
        schsio_probe,
-       schsio_attach
+       schsio_attach,
+       NULL,
+       schsio_activate
 };
 
 struct cfdriver schsio_cd = {
        NULL, "schsio", DV_DULL
 };
@@ -316,10 +319,22 @@ schsio_attach(struct device *parent, struct device *self, 
void *aux)
 
        /* Escape from configuration mode */
        schsio_config_disable(sc->sc_iot, sc->sc_ioh);
 }
 
+int
+schsio_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
 void
 schsio_hwm_init(struct schsio_softc *sc)
 {
        int i;
 
diff --git sys/dev/isa/viasio.c sys/dev/isa/viasio.c
index 3b82c46..59714b2 100644
--- sys/dev/isa/viasio.c
+++ sys/dev/isa/viasio.c
@@ -60,21 +60,24 @@ struct viasio_softc {
        bus_space_handle_t      sc_wdg_ioh;
 };
 
 int    viasio_probe(struct device *, void *, void *);
 void   viasio_attach(struct device *, struct device *, void *);
+int    viasio_activate(struct device *, int);
 
 void   viasio_hm_init(struct viasio_softc *);
 void   viasio_hm_refresh(void *);
 
 void   viasio_wdg_init(struct viasio_softc *);
 int    viasio_wdg_cb(void *, int);
 
 struct cfattach viasio_ca = {
        sizeof(struct viasio_softc),
        viasio_probe,
-       viasio_attach
+       viasio_attach,
+       NULL,
+       viasio_activate
 };
 
 struct cfdriver viasio_cd = {
        NULL, "viasio", DV_DULL
 };
@@ -194,10 +197,22 @@ viasio_attach(struct device *parent, struct device *self, 
void *aux)
 
        /* Escape from configuration mode */
        viasio_conf_disable(sc->sc_iot, sc->sc_ioh);
 }
 
+int
+viasio_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
 void
 viasio_hm_init(struct viasio_softc *sc)
 {
        u_int8_t reg0, reg1;
        u_int16_t iobase;
diff --git sys/dev/pci/berkwdt.c sys/dev/pci/berkwdt.c
index 47eaaa1..c88b788 100644
--- sys/dev/pci/berkwdt.c
+++ sys/dev/pci/berkwdt.c
@@ -44,20 +44,22 @@ struct berkwdt_softc {
        int             sc_period;
 };
 
 int berkwdt_match(struct device *, void *, void *);
 void berkwdt_attach(struct device *, struct device *, void *);
+int berkwdt_activate(struct device *, int);
 
 void berkwdt_start(struct berkwdt_softc *sc);
 void berkwdt_stop(struct berkwdt_softc *sc);
 void berkwdt_reload(struct berkwdt_softc *sc);
 int berkwdt_send_command(struct berkwdt_softc *sc, u_int8_t cmd, int *val);
 
 int berkwdt_set_timeout(void *, int);
 
 struct cfattach berkwdt_ca = {
-       sizeof(struct berkwdt_softc), berkwdt_match, berkwdt_attach
+       sizeof(struct berkwdt_softc), berkwdt_match, berkwdt_attach,
+       NULL, berkwdt_activate
 };
 
 struct cfdriver berkwdt_cd = {
        NULL, "berkwdt", DV_DULL
 };
@@ -212,10 +214,22 @@ berkwdt_attach(struct device *parent, struct device 
*self, void *aux)
        /* register with the watchdog framework */
        wdog_register(berkwdt_set_timeout, sc);
 }
 
 int
+berkwdt_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
+int
 berkwdt_set_timeout(void *self, int timeout)
 {
        struct berkwdt_softc *sc = self;
        int new_timeout = timeout;
 
diff --git sys/dev/pci/glxpcib.c sys/dev/pci/glxpcib.c
index b68efd7..43df7ce 100644
--- sys/dev/pci/glxpcib.c
+++ sys/dev/pci/glxpcib.c
@@ -452,10 +452,17 @@ glxpcib_activate(struct device *self, int act)
                for (i = 0; i < nitems(glxpcib_msrlist); i++)
                        wrmsr(glxpcib_msrlist[i], sc->sc_msrsave[i]);
 #endif
                rv = config_activate_children(self, act);
                break;
+       case DVACT_POWERDOWN:
+#ifndef SMALL_KERNEL
+               if (sc->sc_wdog)
+                       wdog_shutdown(self);
+#endif
+               rv = config_activate_children(self, act);
+               break;
        default:
                rv = config_activate_children(self, act);
                break;
        }
        return (rv);
diff --git sys/dev/pci/ichwdt.c sys/dev/pci/ichwdt.c
index 2d69093..b3338d9 100644
--- sys/dev/pci/ichwdt.c
+++ sys/dev/pci/ichwdt.c
@@ -51,17 +51,20 @@ struct ichwdt_softc {
        int sc_period;
 };
 
 int    ichwdt_match(struct device *, void *, void *);
 void   ichwdt_attach(struct device *, struct device *, void *);
+int    ichwdt_activate(struct device *, int);
 
 int    ichwdt_cb(void *, int);
 
 struct cfattach ichwdt_ca = {
        sizeof(struct ichwdt_softc),
        ichwdt_match,
-       ichwdt_attach
+       ichwdt_attach,
+       NULL,
+       ichwdt_activate
 };
 
 struct cfdriver ichwdt_cd = {
        NULL, "ichwdt", DV_DULL
 };
@@ -138,10 +141,22 @@ ichwdt_attach(struct device *parent, struct device *self, 
void *aux)
        /* Register new watchdog */
        wdog_register(ichwdt_cb, sc);
 }
 
 int
+ichwdt_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
+int
 ichwdt_cb(void *arg, int period)
 {
        struct ichwdt_softc *sc = arg;
        int ticks;
 
diff --git sys/dev/pci/pwdog.c sys/dev/pci/pwdog.c
index c95d9ae..af2a2f0 100644
--- sys/dev/pci/pwdog.c
+++ sys/dev/pci/pwdog.c
@@ -38,14 +38,16 @@ struct pwdog_softc {
 #define PWDOG_ACTIVATE 0
 #define PWDOG_DISABLE  1
 
 int pwdog_probe(struct device *, void *, void *);
 void pwdog_attach(struct device *, struct device *, void *);
+int pwdog_activate(struct device *, int);
 int pwdog_set_timeout(void *, int);
 
 struct cfattach pwdog_ca = {
-       sizeof(struct pwdog_softc), pwdog_probe, pwdog_attach
+       sizeof(struct pwdog_softc), pwdog_probe, pwdog_attach,
+       NULL, pwdog_activate
 };
 
 struct cfdriver pwdog_cd = {
        NULL, "pwdog", DV_DULL
 };
@@ -81,10 +83,22 @@ pwdog_attach(struct device *parent, struct device *self, 
void *aux)
        bus_space_write_1(pwdog->iot, pwdog->ioh, PWDOG_DISABLE, 0);
        wdog_register(pwdog_set_timeout, pwdog);
 }
 
 int
+pwdog_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
+int
 pwdog_set_timeout(void *self, int seconds)
 {
        struct pwdog_softc *pwdog = (struct pwdog_softc *)self;
        int s;
 
diff --git sys/dev/pci/tcpcib.c sys/dev/pci/tcpcib.c
index 97c8f44..e60feac 100644
--- sys/dev/pci/tcpcib.c
+++ sys/dev/pci/tcpcib.c
@@ -293,10 +293,15 @@ tcpcib_activate(struct device *self, int act)
                if (sc->sc_active & E600_HPET_ACTIVE)
                        bus_space_write_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
                            E600_HPET_GC, E600_HPET_GC_ENABLE);
                rv = config_activate_children(self, act);
                break;
+       case DVACT_POWERDOWN:
+               if (sc->sc_active & E600_WDT_ACTIVE)
+                       wdog_shutdown(self);
+               rv = config_activate_children(self, act);
+               break;
        default:
                rv = config_activate_children(self, act);
                break;
        }
        return (rv);
diff --git sys/dev/pci/wdt.c sys/dev/pci/wdt.c
index 2b48fe3..a1140bb 100644
--- sys/dev/pci/wdt.c
+++ sys/dev/pci/wdt.c
@@ -51,10 +51,11 @@ struct wdt_softc {
        bus_space_handle_t      sc_ioh;
 };
 
 int    wdt_probe(struct device *, void *, void *);
 void   wdt_attach(struct device *, struct device *, void *);
+int    wdt_activate(struct device *, int);
 
 int    wdt_is501(struct wdt_softc *);
 void   wdt_8254_count(struct wdt_softc *, int, u_int16_t);
 void   wdt_8254_mode(struct wdt_softc *, int, int);
 int    wdt_set_timeout(void *, int);
@@ -62,11 +63,12 @@ void        wdt_init_timer(struct wdt_softc *);
 void   wdt_buzzer_off(struct wdt_softc *);
 void   wdt_timer_disable(struct wdt_softc *);
 void   wdt_buzzer_enable(struct wdt_softc *);
 
 struct cfattach wdt_ca = {
-       sizeof(struct wdt_softc), wdt_probe, wdt_attach
+       sizeof(struct wdt_softc), wdt_probe, wdt_attach,
+       NULL, wdt_activate
 };
 
 struct cfdriver wdt_cd = {
        NULL, "wdt", DV_DULL
 };
@@ -157,10 +159,22 @@ wdt_attach(struct device *parent, struct device *self, 
void *aux)
         * register with the watchdog framework
         */
        wdog_register(wdt_set_timeout, wdt);
 }
 
+int
+wdt_activate(struct device *self, int act)
+{
+       switch (act) {
+       case DVACT_POWERDOWN:
+               wdog_shutdown(self);
+               break;
+       }
+
+       return (0);
+}
+
 /*
  *     wdt_is501
  *
  *     Returns non-zero if the card is a 501 model.
  */
diff --git sys/kern/kern_watchdog.c sys/kern/kern_watchdog.c
index 0bad9de..f41b646 100644
--- sys/kern/kern_watchdog.c
+++ sys/kern/kern_watchdog.c
@@ -33,11 +33,10 @@
 void   wdog_tickle(void *arg);
 int    (*wdog_ctl_cb)(void *, int) = NULL;
 void   *wdog_ctl_cb_arg = NULL;
 int    wdog_period = 0;
 int    wdog_auto = 1;
-void   *wdog_cookie;
 struct timeout wdog_timeout;
 
 void
 wdog_register(int (*cb)(void *, int), void *cb_arg)
 {
@@ -45,11 +44,10 @@ wdog_register(int (*cb)(void *, int), void *cb_arg)
                return;
 
        wdog_ctl_cb = cb;
        wdog_ctl_cb_arg = cb_arg;
        timeout_set(&wdog_timeout, wdog_tickle, NULL);
-       wdog_cookie = shutdownhook_establish((void (*)(void *))wdog_shutdown, 
NULL);
 }
 
 void
 wdog_tickle(void *arg)
 {
@@ -58,13 +56,13 @@ wdog_tickle(void *arg)
        (void) (*wdog_ctl_cb)(wdog_ctl_cb_arg, wdog_period);
        timeout_add(&wdog_timeout, wdog_period * hz / 2);
 }
 
 void
-wdog_shutdown(int (*cb)(void *, int), void *cb_arg)
+wdog_shutdown(void *arg)
 {
-       if (wdog_ctl_cb == NULL)
+       if (wdog_ctl_cb == NULL || wdog_ctl_cb_arg != arg)
                return;
        timeout_del(&wdog_timeout);
        (void) (*wdog_ctl_cb)(wdog_ctl_cb_arg, 0);
        wdog_ctl_cb = NULL;
        wdog_period = 0;
@@ -93,21 +91,14 @@ sysctl_wdog(int *name, u_int namelen, void *oldp, size_t 
*oldlenp, void *newp,
                break;
        case KERN_WATCHDOG_AUTO:
                error = sysctl_int(oldp, oldlenp, newp, newlen, &wdog_auto);
                if (error)
                        return (error);
-               if (wdog_auto && wdog_cookie == NULL)
-                       wdog_cookie = shutdownhook_establish((void (*)(void 
*))wdog_shutdown,
-                           NULL);
-               else if (!wdog_auto && wdog_cookie) {
-                       shutdownhook_disestablish(wdog_cookie);
-                       wdog_cookie = NULL;
-               }
                break;
        default:
                return (EINVAL);
-       } 
+       }
 
        if (wdog_auto && wdog_period > 0) {
                (void) (*wdog_ctl_cb)(wdog_ctl_cb_arg, wdog_period);
                timeout_add(&wdog_timeout, wdog_period * hz / 2);
        } else
diff --git sys/sys/systm.h sys/sys/systm.h
index f1e7b30..9daa896 100644
--- sys/sys/systm.h
+++ sys/sys/systm.h
@@ -258,11 +258,11 @@ void    wakeup(const volatile void *);
 int    tsleep(const volatile void *, int, const char *, int);
 int    msleep(const volatile void *, struct mutex *, int,  const char*, int);
 void   yield(void);
 
 void   wdog_register(int (*)(void *, int), void *);
-void   wdog_shutdown(int (*)(void *, int), void *);
+void   wdog_shutdown(void *);
 
 /*
  * Startup/shutdown hooks.  Startup hooks are functions running after
  * the scheduler has started but before any threads have been created
  * or root has been mounted. The shutdown hooks are functions to be run

Reply via email to