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:
parent
a9e7d15afd
commit
0e748e633e
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user