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