Fri Aug 26 13:29:57 2011 UTC ()
Add a pmf resume function to put the hardware in a defined state after
resume.  Problem found by jmcneill@.


(mbalmer)
diff -r1.3 -r1.4 src/sys/dev/pci/pwdog.c

cvs diff -r1.3 -r1.4 src/sys/dev/pci/pwdog.c (expand / switch to unified diff)

--- src/sys/dev/pci/pwdog.c 2011/08/26 10:30:47 1.3
+++ src/sys/dev/pci/pwdog.c 2011/08/26 13:29:56 1.4
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $$NetBSD: pwdog.c,v 1.3 2011/08/26 10:30:47 mbalmer Exp $ */ 1/* $$NetBSD: pwdog.c,v 1.4 2011/08/26 13:29:56 mbalmer Exp $ */
2/* $OpenBSD: pwdog.c,v 1.7 2010/04/08 00:23:53 tedu Exp $ */ 2/* $OpenBSD: pwdog.c,v 1.7 2010/04/08 00:23:53 tedu Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2006, 2011 Marc Balmer <mbalmer@NetBSD.org> 5 * Copyright (c) 2006, 2011 Marc Balmer <mbalmer@NetBSD.org>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
@@ -44,26 +44,27 @@ struct pwdog_softc { @@ -44,26 +44,27 @@ struct pwdog_softc {
44}; 44};
45 45
46/* registers */ 46/* registers */
47#define PWDOG_ACTIVATE 0 47#define PWDOG_ACTIVATE 0
48#define PWDOG_DISABLE 1 48#define PWDOG_DISABLE 1
49 49
50/* maximum timeout period in seconds */ 50/* maximum timeout period in seconds */
51#define PWDOG_MAX_PERIOD (12*60) /* 12 minutes */ 51#define PWDOG_MAX_PERIOD (12*60) /* 12 minutes */
52 52
53static int pwdog_match(device_t, cfdata_t, void *); 53static int pwdog_match(device_t, cfdata_t, void *);
54static void pwdog_attach(device_t, device_t, void *); 54static void pwdog_attach(device_t, device_t, void *);
55static int pwdog_detach(device_t, int); 55static int pwdog_detach(device_t, int);
56static bool pwdog_suspend(device_t, const pmf_qual_t *); 56static bool pwdog_suspend(device_t, const pmf_qual_t *);
 57static bool pwdog_resume(device_t, const pmf_qual_t *);
57static int pwdog_setmode(struct sysmon_wdog *); 58static int pwdog_setmode(struct sysmon_wdog *);
58static int pwdog_tickle(struct sysmon_wdog *); 59static int pwdog_tickle(struct sysmon_wdog *);
59 60
60CFATTACH_DECL_NEW( 61CFATTACH_DECL_NEW(
61 pwdog, 62 pwdog,
62 sizeof(struct pwdog_softc), 63 sizeof(struct pwdog_softc),
63 pwdog_match, 64 pwdog_match,
64 pwdog_attach, 65 pwdog_attach,
65 pwdog_detach, 66 pwdog_detach,
66 NULL 67 NULL
67); 68);
68 69
69static int 70static int
@@ -86,63 +87,81 @@ pwdog_attach(device_t parent, device_t s @@ -86,63 +87,81 @@ pwdog_attach(device_t parent, device_t s
86 87
87 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START); 88 memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);
88 if (pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, &sc->sc_iot, 89 if (pci_mapreg_map(pa, PCI_MAPREG_START, memtype, 0, &sc->sc_iot,
89 &sc->sc_ioh, NULL, &sc->sc_iosize)) { 90 &sc->sc_ioh, NULL, &sc->sc_iosize)) {
90 aprint_error("\n"); 91 aprint_error("\n");
91 aprint_error_dev(self, "PCI %s region not found\n", 92 aprint_error_dev(self, "PCI %s region not found\n",
92 memtype == PCI_MAPREG_TYPE_IO ? "I/O" : "memory"); 93 memtype == PCI_MAPREG_TYPE_IO ? "I/O" : "memory");
93 return; 94 return;
94 } 95 }
95 printf("\n"); 96 printf("\n");
96 97
97 sc->sc_dev = self; 98 sc->sc_dev = self;
98 99
99 pmf_device_register(self, pwdog_suspend, NULL); 100 pmf_device_register(self, pwdog_suspend, pwdog_resume);
100 bus_space_write_1(sc->sc_iot, sc->sc_ioh, PWDOG_DISABLE, 0); 101 bus_space_write_1(sc->sc_iot, sc->sc_ioh, PWDOG_DISABLE, 0);
101 102
102 sc->sc_smw.smw_name = device_xname(self); 103 sc->sc_smw.smw_name = device_xname(self);
103 sc->sc_smw.smw_cookie = sc; 104 sc->sc_smw.smw_cookie = sc;
104 sc->sc_smw.smw_setmode = pwdog_setmode; 105 sc->sc_smw.smw_setmode = pwdog_setmode;
105 sc->sc_smw.smw_tickle = pwdog_tickle; 106 sc->sc_smw.smw_tickle = pwdog_tickle;
106 sc->sc_smw.smw_period = PWDOG_MAX_PERIOD; 107 sc->sc_smw.smw_period = PWDOG_MAX_PERIOD;
107 108
108 if (sysmon_wdog_register(&sc->sc_smw)) 109 if (sysmon_wdog_register(&sc->sc_smw))
109 aprint_error_dev(self, "couldn't register with sysmon\n"); 110 aprint_error_dev(self, "couldn't register with sysmon\n");
110 else 111 else
111 sc->sc_smw_valid = true; 112 sc->sc_smw_valid = true;
112} 113}
113 114
114static int 115static int
115pwdog_detach(device_t self, int flags) 116pwdog_detach(device_t self, int flags)
116{ 117{
117 struct pwdog_softc *sc = device_private(self); 118 struct pwdog_softc *sc = device_private(self);
118 119
 120 /* XXX check flags & DETACH_FORCE (or DETACH_SHUTDOWN)? */
119 if (sc->sc_smw_valid) { 121 if (sc->sc_smw_valid) {
120 if ((sc->sc_smw.smw_mode & WDOG_MODE_MASK) 122 if ((sc->sc_smw.smw_mode & WDOG_MODE_MASK)
121 != WDOG_MODE_DISARMED) 123 != WDOG_MODE_DISARMED)
122 return EBUSY; 124 return EBUSY;
123 125
124 sysmon_wdog_unregister(&sc->sc_smw); 126 sysmon_wdog_unregister(&sc->sc_smw);
125 sc->sc_smw_valid = false; 127 sc->sc_smw_valid = false;
126 } 128 }
127 129
128 pmf_device_deregister(self); 130 pmf_device_deregister(self);
129 131
130 if (sc->sc_iosize) 132 if (sc->sc_iosize)
131 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize); 133 bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize);
132 return 0; 134 return 0;
133} 135}
134 136
135static bool 137static bool
 138pwdog_resume(device_t self, const pmf_qual_t *qual)
 139{
 140 struct pwdog_softc *sc = device_private(self);
 141
 142 if (sc->sc_smw_valid == false)
 143 return true;
 144
 145 /*
 146 * suspend is inhibited when the watchdog timer was armed,
 147 * so when we end up here, the watchdog is disabled; program the
 148 * hardware accordingly.
 149 */
 150 bus_space_write_1(sc->sc_iot, sc->sc_ioh, PWDOG_DISABLE, 0);
 151 return true;
 152}
 153
 154static bool
136pwdog_suspend(device_t self, const pmf_qual_t *qual) 155pwdog_suspend(device_t self, const pmf_qual_t *qual)
137{ 156{
138 struct pwdog_softc *sc = device_private(self); 157 struct pwdog_softc *sc = device_private(self);
139 158
140 if (sc->sc_smw_valid == false) 159 if (sc->sc_smw_valid == false)
141 return true; 160 return true;
142 161
143 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)
144 return false; 163 return false;
145 164
146 return true; 165 return true;
147} 166}
148 167