Extend the pmf suspend/resume hooks by a shutdown method, so drivers

can register a shutdown handler explicitely.
Install a pci bus shutdown handler which disables bus master accesses
for all childs, so the drivers don't need to care.
This will hopefully be sufficient to replace the shutdownhooks
(together with the powerhooks). (It has been suggested to use some
general event notification framework for shutdown handlers, but there
might be cases where shutdown handlers must be run in an order following
the device hierarchy, which wouldn't be easy with event handlers
not tied to drivers.)
approved by David Young
This commit is contained in:
drochner 2008-02-28 14:25:12 +00:00
parent a9e7d15afd
commit 0e748e633e
7 changed files with 81 additions and 26 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cardbus.c,v 1.89 2008/02/23 00:30:56 dyoung Exp $ */
/* $NetBSD: cardbus.c,v 1.90 2008/02/28 14:25:12 drochner Exp $ */
/*
* Copyright (c) 1997, 1998, 1999 and 2000
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.89 2008/02/23 00:30:56 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: cardbus.c,v 1.90 2008/02/28 14:25:12 drochner Exp $");
#include "opt_cardbus.h"
@ -1243,7 +1243,7 @@ cardbus_child_register(device_t child)
}
device_pmf_bus_register(child, priv, cardbus_child_suspend,
cardbus_child_resume, cardbus_child_deregister);
cardbus_child_resume, 0, cardbus_child_deregister);
return true;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: pci.c,v 1.112 2008/02/23 00:27:53 dyoung Exp $ */
/* $NetBSD: pci.c,v 1.113 2008/02/28 14:25:12 drochner Exp $ */
/*
* Copyright (c) 1995, 1996, 1997, 1998
@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.112 2008/02/23 00:27:53 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: pci.c,v 1.113 2008/02/28 14:25:12 drochner Exp $");
#include "opt_pci.h"
@ -895,6 +895,19 @@ pci_child_resume(device_t dv PMF_FN_ARGS)
return true;
}
static bool
pci_child_shutdown(device_t dv, int how)
{
struct pci_child_power *priv = device_pmf_bus_private(dv);
pcireg_t csr;
/* disable busmastering */
csr = pci_conf_read(priv->p_pc, priv->p_tag, PCI_COMMAND_STATUS_REG);
csr &= ~PCI_COMMAND_MASTER_ENABLE;
pci_conf_write(priv->p_pc, priv->p_tag, PCI_COMMAND_STATUS_REG, csr);
return true;
}
static void
pci_child_deregister(device_t dv)
{
@ -933,7 +946,7 @@ pci_child_register(device_t child)
}
device_pmf_bus_register(child, priv, pci_child_suspend,
pci_child_resume, pci_child_deregister);
pci_child_resume, pci_child_shutdown, pci_child_deregister);
return true;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_pmf.c,v 1.12 2008/02/20 22:52:55 drochner Exp $ */
/* $NetBSD: kern_pmf.c,v 1.13 2008/02/28 14:25:12 drochner Exp $ */
/*-
* Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_pmf.c,v 1.12 2008/02/20 22:52:55 drochner Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_pmf.c,v 1.13 2008/02/28 14:25:12 drochner Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -284,7 +284,7 @@ pmf_system_suspend(void)
}
void
pmf_system_shutdown(void)
pmf_system_shutdown(int how)
{
int depth, maxdepth;
device_t curdev;
@ -308,11 +308,17 @@ pmf_system_shutdown(void)
if (!device_pmf_is_registered(curdev))
continue;
if (!device_pmf_class_suspend(curdev)) {
#if 0 /* needed? */
if (!device_pmf_class_shutdown(curdev, how)) {
aprint_debug("(failed)");
continue;
}
if (!device_pmf_driver_suspend(curdev)) {
#endif
if (!device_pmf_driver_shutdown(curdev, how)) {
aprint_debug("(failed)");
continue;
}
if (!device_pmf_bus_shutdown(curdev, how)) {
aprint_debug("(failed)");
continue;
}
@ -348,10 +354,11 @@ pmf_get_platform(const char *key)
}
bool
pmf_device_register(device_t dev,
bool (*suspend)(device_t), bool (*resume)(device_t))
pmf_device_register1(device_t dev,
bool (*suspend)(device_t), bool (*resume)(device_t),
bool (*shutdown)(device_t, int))
{
device_pmf_driver_register(dev, suspend, resume);
device_pmf_driver_register(dev, suspend, resume, shutdown);
if (!device_pmf_driver_child_register(dev)) {
device_pmf_driver_deregister(dev);

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_subr.c,v 1.181 2008/02/20 23:30:13 drochner Exp $ */
/* $NetBSD: kern_subr.c,v 1.182 2008/02/28 14:25:12 drochner Exp $ */
/*-
* Copyright (c) 1997, 1998, 1999, 2002, 2007, 2006 The NetBSD Foundation, Inc.
@ -86,7 +86,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.181 2008/02/20 23:30:13 drochner Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.182 2008/02/28 14:25:12 drochner Exp $");
#include "opt_ddb.h"
#include "opt_md.h"
@ -496,6 +496,8 @@ doshutdownhooks(void)
free(dp, M_DEVBUF);
#endif
}
pmf_system_shutdown(boothowto);
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr_autoconf.c,v 1.132 2008/02/27 19:59:05 matt Exp $ */
/* $NetBSD: subr_autoconf.c,v 1.133 2008/02/28 14:25:12 drochner Exp $ */
/*
* Copyright (c) 1996, 2000 Christopher G. Demetriou
@ -77,7 +77,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.132 2008/02/27 19:59:05 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.133 2008/02/28 14:25:12 drochner Exp $");
#include "opt_multiprocessor.h"
#include "opt_ddb.h"
@ -1882,12 +1882,24 @@ device_pmf_driver_resume(device_t dev)
return true;
}
bool
device_pmf_driver_shutdown(device_t dev, int how)
{
if (*dev->dv_driver_shutdown != NULL &&
!(*dev->dv_driver_shutdown)(dev, how))
return false;
return true;
}
void
device_pmf_driver_register(device_t dev,
bool (*suspend)(device_t), bool (*resume)(device_t))
bool (*suspend)(device_t), bool (*resume)(device_t),
bool (*shutdown)(device_t, int))
{
dev->dv_driver_suspend = suspend;
dev->dv_driver_resume = resume;
dev->dv_driver_shutdown = shutdown;
dev->dv_flags |= DVF_POWER_HANDLERS;
}
@ -1951,14 +1963,25 @@ device_pmf_bus_resume(device_t dev)
return true;
}
bool
device_pmf_bus_shutdown(device_t dev, int how)
{
if (*dev->dv_bus_shutdown != NULL &&
!(*dev->dv_bus_shutdown)(dev, how))
return false;
return true;
}
void
device_pmf_bus_register(device_t dev, void *priv,
bool (*suspend)(device_t), bool (*resume)(device_t),
void (*deregister)(device_t))
bool (*shutdown)(device_t, int), void (*deregister)(device_t))
{
dev->dv_bus_private = priv;
dev->dv_bus_resume = resume;
dev->dv_bus_suspend = suspend;
dev->dv_bus_shutdown = shutdown;
dev->dv_bus_deregister = deregister;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: device.h,v 1.103 2008/02/12 17:30:59 joerg Exp $ */
/* $NetBSD: device.h,v 1.104 2008/02/28 14:25:12 drochner Exp $ */
/*
* Copyright (c) 1996, 2000 Christopher G. Demetriou
@ -142,11 +142,13 @@ struct device {
bool (*dv_driver_suspend)(device_t);
bool (*dv_driver_resume)(device_t);
bool (*dv_driver_shutdown)(device_t, int);
bool (*dv_driver_child_register)(device_t);
void *dv_bus_private;
bool (*dv_bus_suspend)(device_t);
bool (*dv_bus_resume)(device_t);
bool (*dv_bus_shutdown)(device_t, int);
void (*dv_bus_deregister)(device_t);
void *dv_class_private;
@ -450,9 +452,11 @@ bool device_pmf_is_registered(device_t);
bool device_pmf_driver_suspend(device_t);
bool device_pmf_driver_resume(device_t);
bool device_pmf_driver_shutdown(device_t, int);
void device_pmf_driver_register(device_t,
bool (*)(device_t), bool (*)(device_t));
bool (*)(device_t), bool (*)(device_t),
bool (*)(device_t, int));
void device_pmf_driver_deregister(device_t);
bool device_pmf_driver_child_register(device_t);
@ -462,9 +466,11 @@ void device_pmf_driver_set_child_register(device_t,
void *device_pmf_bus_private(device_t);
bool device_pmf_bus_suspend(device_t);
bool device_pmf_bus_resume(device_t);
bool device_pmf_bus_shutdown(device_t, int);
void device_pmf_bus_register(device_t, void *,
bool (*)(device_t), bool (*)(device_t),
bool (*)(device_t, int),
void (*)(device_t));
void device_pmf_bus_deregister(device_t);

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmf.h,v 1.6 2008/02/22 22:33:21 dyoung Exp $ */
/* $NetBSD: pmf.h,v 1.7 2008/02/28 14:25:12 drochner Exp $ */
/*-
* Copyright (c) 2007 Jared D. McNeill <jmcneill@invisible.ca>
@ -72,11 +72,15 @@ const char *pmf_get_platform(const char *);
bool pmf_system_resume(void);
bool pmf_system_bus_resume(void);
bool pmf_system_suspend(void);
void pmf_system_shutdown(void);
void pmf_system_shutdown(int);
bool pmf_device_register(device_t,
bool pmf_device_register1(device_t,
bool (*)(device_t),
bool (*)(device_t));
bool (*)(device_t),
bool (*)(device_t, int));
/* compatibility */
#define pmf_device_register(d, s, r) pmf_device_register1((d), (s), (r), 0)
void pmf_device_deregister(device_t);
bool pmf_device_suspend(device_t);
bool pmf_device_resume(device_t);