Fri Aug 6 16:02:56 2010 UTC ()
* fix logic inversion in swwdog_reboot (and the sysctl).
* attach sysctl in constructor instead of as a link set to give it
  a chance to work in a module
* teardown sysctl when driver is detached to avoid dangling pointer


(pooka)
diff -r1.10 -r1.11 src/sys/dev/sysmon/swwdog.c

cvs diff -r1.10 -r1.11 src/sys/dev/sysmon/swwdog.c (expand / switch to unified diff)

--- src/sys/dev/sysmon/swwdog.c 2010/07/22 14:10:15 1.10
+++ src/sys/dev/sysmon/swwdog.c 2010/08/06 16:02:56 1.11
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: swwdog.c,v 1.10 2010/07/22 14:10:15 pgoyette Exp $ */ 1/* $NetBSD: swwdog.c,v 1.11 2010/08/06 16:02:56 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2004, 2005 Steven M. Bellovin 4 * Copyright (c) 2004, 2005 Steven M. Bellovin
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -23,27 +23,27 @@ @@ -23,27 +23,27 @@
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE. 32 * POSSIBILITY OF SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36__KERNEL_RCSID(0, "$NetBSD: swwdog.c,v 1.10 2010/07/22 14:10:15 pgoyette Exp $"); 36__KERNEL_RCSID(0, "$NetBSD: swwdog.c,v 1.11 2010/08/06 16:02:56 pooka Exp $");
37 37
38/* 38/*
39 * 39 *
40 * Software watchdog timer 40 * Software watchdog timer
41 * 41 *
42 */ 42 */
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/callout.h> 44#include <sys/callout.h>
45#include <sys/device.h> 45#include <sys/device.h>
46#include <sys/kernel.h> 46#include <sys/kernel.h>
47#include <sys/kmem.h> 47#include <sys/kmem.h>
48#include <sys/reboot.h> 48#include <sys/reboot.h>
49#include <sys/systm.h> 49#include <sys/systm.h>
@@ -72,26 +72,29 @@ static int swwdog_tickle(struct sysmon_w @@ -72,26 +72,29 @@ static int swwdog_tickle(struct sysmon_w
72 72
73static int swwdog_arm(struct swwdog_softc *); 73static int swwdog_arm(struct swwdog_softc *);
74static int swwdog_disarm(struct swwdog_softc *); 74static int swwdog_disarm(struct swwdog_softc *);
75 75
76static void swwdog_panic(void *); 76static void swwdog_panic(void *);
77 77
78bool swwdog_reboot = false; /* set for panic instead of reboot */ 78bool swwdog_reboot = false; /* set for panic instead of reboot */
79 79
80#define SWDOG_DEFAULT 60 /* 60-second default period */ 80#define SWDOG_DEFAULT 60 /* 60-second default period */
81 81
82CFATTACH_DECL_NEW(swwdog, sizeof(struct swwdog_softc), 82CFATTACH_DECL_NEW(swwdog, sizeof(struct swwdog_softc),
83 swwdog_match, swwdog_attach, swwdog_detach, NULL); 83 swwdog_match, swwdog_attach, swwdog_detach, NULL);
84 84
 85static void swwdog_sysctl_setup(void);
 86static struct sysctllog *swwdog_sysctllog;
 87
85void 88void
86swwdogattach(int n __unused) 89swwdogattach(int n __unused)
87{ 90{
88 int err; 91 int err;
89 static struct cfdata cf; 92 static struct cfdata cf;
90 93
91 err = config_cfattach_attach(swwdog_cd.cd_name, &swwdog_ca); 94 err = config_cfattach_attach(swwdog_cd.cd_name, &swwdog_ca);
92 if (err) { 95 if (err) {
93 aprint_error("%s: couldn't register cfattach: %d\n", 96 aprint_error("%s: couldn't register cfattach: %d\n",
94 swwdog_cd.cd_name, err); 97 swwdog_cd.cd_name, err);
95 config_cfdriver_detach(&swwdog_cd); 98 config_cfdriver_detach(&swwdog_cd);
96 return; 99 return;
97 } 100 }
@@ -124,35 +127,38 @@ swwdog_attach(device_t parent, device_t  @@ -124,35 +127,38 @@ swwdog_attach(device_t parent, device_t
124 sc->sc_smw.smw_tickle = swwdog_tickle; 127 sc->sc_smw.smw_tickle = swwdog_tickle;
125 sc->sc_smw.smw_period = SWDOG_DEFAULT; 128 sc->sc_smw.smw_period = SWDOG_DEFAULT;
126 callout_init(&sc->sc_c, 0); 129 callout_init(&sc->sc_c, 0);
127 callout_setfunc(&sc->sc_c, swwdog_panic, sc); 130 callout_setfunc(&sc->sc_c, swwdog_panic, sc);
128 131
129 if (sysmon_wdog_register(&sc->sc_smw) == 0) 132 if (sysmon_wdog_register(&sc->sc_smw) == 0)
130 aprint_normal_dev(self, "software watchdog initialized\n"); 133 aprint_normal_dev(self, "software watchdog initialized\n");
131 else 134 else
132 aprint_error_dev(self, "unable to register software " 135 aprint_error_dev(self, "unable to register software "
133 "watchdog with sysmon\n"); 136 "watchdog with sysmon\n");
134 137
135 if (!pmf_device_register(self, swwdog_suspend, NULL)) 138 if (!pmf_device_register(self, swwdog_suspend, NULL))
136 aprint_error_dev(self, "couldn't establish power handler\n"); 139 aprint_error_dev(self, "couldn't establish power handler\n");
 140
 141 swwdog_sysctl_setup();
137} 142}
138 143
139static int 144static int
140swwdog_detach(device_t self, int flags) 145swwdog_detach(device_t self, int flags)
141{ 146{
142 struct swwdog_softc *sc = device_private(self); 147 struct swwdog_softc *sc = device_private(self);
143 148
144 swwdog_disarm(sc); 149 swwdog_disarm(sc);
145 callout_destroy(&sc->sc_c); 150 callout_destroy(&sc->sc_c);
 151 sysctl_teardown(&swwdog_sysctllog);
146 152
147 return 1; 153 return 1;
148} 154}
149 155
150static bool 156static bool
151swwdog_suspend(device_t dev, const pmf_qual_t *qual) 157swwdog_suspend(device_t dev, const pmf_qual_t *qual)
152{ 158{
153 struct swwdog_softc *sc = device_private(dev); 159 struct swwdog_softc *sc = device_private(dev);
154 160
155 /* Don't allow suspend if watchdog is armed */ 161 /* Don't allow suspend if watchdog is armed */
156 if ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) != WDOG_MODE_DISARMED) 162 if ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) != WDOG_MODE_DISARMED)
157 return false; 163 return false;
158 return true; 164 return true;
@@ -197,48 +203,42 @@ static int @@ -197,48 +203,42 @@ static int
197swwdog_disarm(struct swwdog_softc *sc) 203swwdog_disarm(struct swwdog_softc *sc)
198{ 204{
199 205
200 callout_stop(&sc->sc_c); 206 callout_stop(&sc->sc_c);
201 return 0; 207 return 0;
202} 208}
203 209
204static void 210static void
205swwdog_panic(void *vsc) 211swwdog_panic(void *vsc)
206{ 212{
207 struct swwdog_softc *sc = vsc; 213 struct swwdog_softc *sc = vsc;
208 bool do_panic; 214 bool do_panic;
209 215
210 do_panic = swwdog_reboot; 216 do_panic = !swwdog_reboot;
211 swwdog_reboot = 1; 217 swwdog_reboot = false;
212 callout_schedule(&sc->sc_c, 60 * hz); /* deliberate double-panic */ 218 callout_schedule(&sc->sc_c, 60 * hz); /* deliberate double-panic */
213 219
214 printf("%s: %d second timer expired\n", device_xname(sc->sc_dev), 220 printf("%s: %d second timer expired\n", device_xname(sc->sc_dev),
215 sc->sc_smw.smw_period); 221 sc->sc_smw.smw_period);
216 222
217 if (do_panic) 223 if (do_panic)
218 panic("watchdog timer expired"); 224 panic("watchdog timer expired");
219 else 225 else
220 cpu_reboot(0, NULL); 226 cpu_reboot(0, NULL);
221} 227}
222 228
223SYSCTL_SETUP(sysctl_swwdog, "swwdog subtree setup") 229static void
 230swwdog_sysctl_setup(void)
224{ 231{
225 int err; 
226 const struct sysctlnode *me; 232 const struct sysctlnode *me;
227 233
228 err = sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_PERMANENT, 234 KASSERT(swwdog_sysctllog == NULL);
229 CTLTYPE_NODE, "machdep", NULL, 
230 NULL, 0, NULL, 0, 
231 CTL_HW, CTL_EOL); 
232 235
233 if (err == 0) 236 sysctl_createv(&swwdog_sysctllog, 0, NULL, &me, CTLFLAG_READWRITE,
234 err = sysctl_createv(NULL, 0, NULL, &me, CTLFLAG_READWRITE, 237 CTLTYPE_NODE, "swwdog", NULL,
235 CTLTYPE_NODE, "swwdog", NULL, 238 NULL, 0, NULL, 0,
236 NULL, 0, NULL, 0, 239 CTL_HW, CTL_CREATE, CTL_EOL);
237 CTL_HW, CTL_CREATE, CTL_EOL); 240 sysctl_createv(&swwdog_sysctllog, 0, NULL, NULL, CTLFLAG_READWRITE,
238 241 CTLTYPE_BOOL, "reboot", "reboot if timer expires",
239 if (err == 0) 242 NULL, 0, &swwdog_reboot, sizeof(bool),
240 err = sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READWRITE, 243 CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL);
241 CTLTYPE_BOOL, "reboot", "reboot if timer expires", 
242 NULL, 0, &swwdog_reboot, sizeof(bool), 
243 CTL_HW, me->sysctl_num, CTL_CREATE, CTL_EOL); 
244} 244}