tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: power management and pseudo-devices
(Resent, this time with attachment!)
On Sun, 18 Jul 2010, Quentin Garnier wrote:
On Sun, Jul 18, 2010 at 07:14:57AM -0700, Paul Goyette wrote:
Currently, pseudo-devices are silently attached to the device tree
without giving the driver any access to the associated device_t
structure. As a result, the pseudo-device driver is unable to
access much of the pmf framework. In particular, the pseudo-device
cannot register a suspend/resume/shutdown handler, nor can it
register to receive pmf event notifications.
It seems to me that it would be reasonably useful for pseudo-devices
to be capabile of participating in pmf. One particular example I've
run into recently is the swwdog pseudo-device. Other watchdog
drivers can prevent a suspend if their timer is armed, but since
swwdog is only a pseudo-device it cannot register a pmf handler.
Convert it to a defpseudodev then.
I've done this, and it works! Diffs attached. Any objections to
committing them?
-------------------------------------------------------------------------
| Paul Goyette | PGP Key fingerprint: | E-mail addresses: |
| Customer Service | FA29 0E3B 35AF E8AE 6651 | paul at whooppee.com |
| Network Engineer | 0786 F758 55DE 53BA 7731 | pgoyette at juniper.net |
| Kernel Developer | | pgoyette at netbsd.org |
-------------------------------------------------------------------------
Index: files.sysmon
===================================================================
RCS file: /cvsroot/src/sys/dev/sysmon/files.sysmon,v
retrieving revision 1.11
diff -u -p -r1.11 files.sysmon
--- files.sysmon 30 Jan 2010 21:55:28 -0000 1.11
+++ files.sysmon 18 Jul 2010 19:30:23 -0000
@@ -18,5 +18,5 @@ file dev/sysmon/sysmon_wdog.c sysmon_wdo
file dev/sysmon/sysmon.c sysmon_envsys | sysmon_wdog |
sysmon_power
-defpseudo swwdog: sysmon_wdog
+defpseudodev swwdog: sysmon_wdog
file dev/sysmon/swwdog.c swwdog
Index: swwdog.c
===================================================================
RCS file: /cvsroot/src/sys/dev/sysmon/swwdog.c,v
retrieving revision 1.9
diff -u -p -r1.9 swwdog.c
--- swwdog.c 31 Jan 2010 02:54:56 -0000 1.9
+++ swwdog.c 18 Jul 2010 19:30:23 -0000
@@ -44,20 +44,28 @@ __KERNEL_RCSID(0, "$NetBSD: swwdog.c,v 1
#include <sys/callout.h>
#include <sys/device.h>
#include <sys/kernel.h>
+#include <sys/kmem.h>
#include <sys/reboot.h>
#include <sys/systm.h>
#include <sys/wdog.h>
#include <dev/sysmon/sysmonvar.h>
-#define NSWWDOG 1
struct swwdog_softc {
+ device_t sc_dev;
struct sysmon_wdog sc_smw;
struct callout sc_c;
- char sc_name[20];
int sc_wdog_armed;
-} sc_wdog[NSWWDOG];
+};
-void swwdogattach(int);
+struct swwdog_softc *sc_swwdog = NULL;
+
+extern struct cfdriver swwdog_cd;
+
+void swwdogattach(int);
+
+static int swwdog_match(device_t, cfdata_t, void *);
+static void swwdog_attach(device_t, device_t, void *);
+static int swwdog_detach(device_t, int);
static int swwdog_setmode(struct sysmon_wdog *);
static int swwdog_tickle(struct sysmon_wdog *);
@@ -71,17 +79,63 @@ int swwdog_reboot = 0; /* set for panic
#define SWDOG_DEFAULT 60 /* 60-second default period */
+CFATTACH_DECL_NEW(swwdog, sizeof(struct swwdog_softc),
+ swwdog_match, swwdog_attach, swwdog_detach, NULL);
+
void
-swwdogattach(int count __unused)
+swwdogattach(int n)
{
- int i;
+ int err;
+ cfdata_t cf;
+
+ if (n > 1)
+ aprint_verbose("%s: ignoring count of %d\n",
+ swwdog_cd.cd_name, n);
+
+ err = config_cfattach_attach(swwdog_cd.cd_name, &swwdog_ca);
+ if (err) {
+ aprint_error("%s: couldn't register cfattach: %d\n",
+ swwdog_cd.cd_name, err);
+ config_cfdriver_detach(&swwdog_cd);
+ return;
+ }
+
+ cf = kmem_alloc(sizeof(struct cfdata), KM_NOSLEEP);
+ if (cf == NULL)
+ aprint_error("%s: couldn't allocate cfdata\n",
+ swwdog_cd.cd_name);
+ else {
+ cf->cf_name = swwdog_cd.cd_name;
+ cf->cf_atname = swwdog_cd.cd_name;
+ cf->cf_unit = 0;
+ cf->cf_fstate = FSTATE_STAR;
- for (i = 0; i < NSWWDOG; i++) {
- struct swwdog_softc *sc = &sc_wdog[i];
+ (void)config_attach_pseudo(cf);
+ }
+
+ return;
+}
- snprintf(sc->sc_name, sizeof sc->sc_name, "swwdog%d", i);
- printf("%s: ", sc->sc_name);
- sc->sc_smw.smw_name = sc->sc_name;
+static int
+swwdog_match(device_t parent, cfdata_t data, void *aux)
+{
+ /* Match unless we already have a swwdog */
+ if (sc_swwdog == NULL)
+ return 1;
+
+ return 0;
+}
+
+static void
+swwdog_attach(device_t parent, device_t self, void *aux)
+{
+ struct swwdog_softc *sc = device_private(self);
+
+ if (sc_swwdog == NULL) {
+ sc_swwdog = sc;
+
+ sc->sc_dev = self;
+ sc->sc_smw.smw_name = device_xname(self);
sc->sc_smw.smw_cookie = sc;
sc->sc_smw.smw_setmode = swwdog_setmode;
sc->sc_smw.smw_tickle = swwdog_tickle;
@@ -90,14 +144,30 @@ swwdogattach(int count __unused)
callout_setfunc(&sc->sc_c, swwdog_panic, sc);
if (sysmon_wdog_register(&sc->sc_smw) == 0)
- printf("software watchdog initialized\n");
+ aprint_normal_dev(self,
+ "software watchdog initialized\n");
else
- printf("unable to register software watchdog "
- "with sysmon\n");
+ aprint_error_dev(self, "unable to register "
+ "software watchdog with sysmon\n");
+
+ if (!pmf_device_register(self, NULL, NULL))
+ aprint_error_dev(self, "couldn't establish power "
+ "handler\n");
}
}
static int
+swwdog_detach(device_t self, int flags)
+{
+ struct swwdog_softc *sc = device_private(self);
+
+ swwdog_disarm(sc);
+ callout_destroy(&sc->sc_c);
+
+ return 1;
+}
+
+static int
swwdog_setmode(struct sysmon_wdog *smw)
{
struct swwdog_softc *sc = smw->smw_cookie;
@@ -150,7 +220,7 @@ swwdog_panic(void *vsc)
swwdog_reboot = 1;
callout_schedule(&sc->sc_c, 60 * hz); /* deliberate double-panic */
- printf("%s: %d second timer expired\n", sc->sc_name,
+ printf("%s: %d second timer expired\n", device_xname(sc->sc_dev),
sc->sc_smw.smw_period);
if (do_panic)
Home |
Main Index |
Thread Index |
Old Index