From 5c2c29acd3c4953c40bc593fe3dd2c9e07464720 Mon Sep 17 00:00:00 2001 From: deraadt Date: Wed, 28 Jul 2010 21:21:38 +0000 Subject: [PATCH] Make legacy xxpower() functions call xxstop() on suspend, and simplify their resume paths. For new-style suspend/resume, add a ca_activate function where it is missing, and use a workq to resume because these drivers like to sleep. ok damien --- sys/dev/pci/if_ipw.c | 47 +++++++++++++++++++++++++++++++--------- sys/dev/pci/if_ipwvar.h | 3 ++- sys/dev/pci/if_iwi.c | 48 ++++++++++++++++++++++++++++++++--------- sys/dev/pci/if_iwivar.h | 3 ++- sys/dev/pci/if_iwn.c | 18 +++++++--------- sys/dev/pci/if_wpi.c | 11 +++++----- 6 files changed, 93 insertions(+), 37 deletions(-) diff --git a/sys/dev/pci/if_ipw.c b/sys/dev/pci/if_ipw.c index fa131e7d59a..d7f90e163bc 100644 --- a/sys/dev/pci/if_ipw.c +++ b/sys/dev/pci/if_ipw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ipw.c,v 1.86 2010/04/20 22:05:43 tedu Exp $ */ +/* $OpenBSD: if_ipw.c,v 1.87 2010/07/28 21:21:38 deraadt Exp $ */ /*- * Copyright (c) 2004-2008 @@ -64,6 +64,8 @@ int ipw_match(struct device *, void *, void *); void ipw_attach(struct device *, struct device *, void *); +int ipw_activate(struct device *, int); +void ipw_resume(void *, void *); void ipw_power(int, void *); int ipw_dma_alloc(struct ipw_softc *); void ipw_release(struct ipw_softc *); @@ -132,7 +134,8 @@ int ipw_debug = 0; #endif struct cfattach ipw_ca = { - sizeof (struct ipw_softc), ipw_match, ipw_attach + sizeof (struct ipw_softc), ipw_match, ipw_attach, NULL, + ipw_activate }; int @@ -291,27 +294,51 @@ ipw_attach(struct device *parent, struct device *self, void *aux) #endif } +int +ipw_activate(struct device *self, int act) +{ + struct ipw_softc *sc = (struct ipw_softc *)self; + struct ifnet *ifp = &sc->sc_ic.ic_if; + + switch (act) { + case DVACT_SUSPEND: + if (ifp->if_flags & IFF_RUNNING) + ipw_stop(ifp, 0); + break; + case DVACT_RESUME: + workq_queue_task(NULL, &sc->sc_resume_wqt, 0, + ipw_resume, sc, NULL); + break; + } + + return (0); +} + +void +ipw_resume(void *arg1, void *arg2) +{ + ipw_power(PWR_RESUME, arg1); +} + void ipw_power(int why, void *arg) { struct ipw_softc *sc = arg; - struct ifnet *ifp; + struct ifnet *ifp = &sc->sc_ic.ic_if; pcireg_t data; - if (why != PWR_RESUME) + if (why != PWR_RESUME) { + ipw_stop(ifp, 0); return; + } /* clear device specific PCI configuration register 0x41 */ data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); data &= ~0x0000ff00; pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data); - ifp = &sc->sc_ic.ic_if; - if (ifp->if_flags & IFF_UP) { - ifp->if_init(ifp); - if (ifp->if_flags & IFF_RUNNING) - ifp->if_start(ifp); - } + if (ifp->if_flags & IFF_UP) + ipw_init(ifp); } int diff --git a/sys/dev/pci/if_ipwvar.h b/sys/dev/pci/if_ipwvar.h index 7d46e38dddc..77029a5c904 100644 --- a/sys/dev/pci/if_ipwvar.h +++ b/sys/dev/pci/if_ipwvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ipwvar.h,v 1.18 2008/08/28 15:08:38 damien Exp $ */ +/* $OpenBSD: if_ipwvar.h,v 1.19 2010/07/28 21:21:38 deraadt Exp $ */ /*- * Copyright (c) 2004-2006 @@ -128,6 +128,7 @@ struct ipw_softc { int txfree; void *powerhook; + struct workq_task sc_resume_wqt; #if NBPFILTER > 0 caddr_t sc_drvbpf; diff --git a/sys/dev/pci/if_iwi.c b/sys/dev/pci/if_iwi.c index 50abb89e7d5..8c307a6dff4 100644 --- a/sys/dev/pci/if_iwi.c +++ b/sys/dev/pci/if_iwi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwi.c,v 1.103 2010/05/19 15:27:35 oga Exp $ */ +/* $OpenBSD: if_iwi.c,v 1.104 2010/07/28 21:21:38 deraadt Exp $ */ /*- * Copyright (c) 2004-2008 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -73,6 +74,8 @@ const struct pci_matchid iwi_devices[] = { int iwi_match(struct device *, void *, void *); void iwi_attach(struct device *, struct device *, void *); +int iwi_activate(struct device *, int); +void iwi_resume(void *, void *); void iwi_power(int, void *); int iwi_alloc_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *); void iwi_reset_cmd_ring(struct iwi_softc *, struct iwi_cmd_ring *); @@ -141,7 +144,8 @@ int iwi_debug = 0; #endif struct cfattach iwi_ca = { - sizeof (struct iwi_softc), iwi_match, iwi_attach + sizeof (struct iwi_softc), iwi_match, iwi_attach, NULL, + iwi_activate }; int @@ -332,16 +336,44 @@ fail: while (--ac >= 0) iwi_free_cmd_ring(sc, &sc->cmdq); } +int +iwi_activate(struct device *self, int act) +{ + struct iwi_softc *sc = (struct iwi_softc *)self; + struct ifnet *ifp = &sc->sc_ic.ic_if; + + switch (act) { + case DVACT_SUSPEND: + if (ifp->if_flags & IFF_RUNNING) + iwi_stop(ifp, 0); + break; + case DVACT_RESUME: + workq_queue_task(NULL, &sc->sc_resume_wqt, 0, + iwi_resume, sc, NULL); + break; + } + + return (0); +} + +void +iwi_resume(void *arg1, void *arg2) +{ + iwi_power(PWR_RESUME, arg1); +} + void iwi_power(int why, void *arg) { struct iwi_softc *sc = arg; - struct ifnet *ifp; + struct ifnet *ifp = &sc->sc_ic.ic_if; pcireg_t data; int s; - if (why != PWR_RESUME) + if (why != PWR_RESUME) { + iwi_stop(ifp, 0); return; + } /* clear device specific PCI configuration register 0x41 */ data = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); @@ -349,12 +381,8 @@ iwi_power(int why, void *arg) pci_conf_write(sc->sc_pct, sc->sc_pcitag, 0x40, data); s = splnet(); - ifp = &sc->sc_ic.ic_if; - if (ifp->if_flags & IFF_UP) { - ifp->if_init(ifp); - if (ifp->if_flags & IFF_RUNNING) - ifp->if_start(ifp); - } + if (ifp->if_flags & IFF_UP) + iwi_init(ifp); splx(s); } diff --git a/sys/dev/pci/if_iwivar.h b/sys/dev/pci/if_iwivar.h index c98d3ebc0ab..b0c51fae01d 100644 --- a/sys/dev/pci/if_iwivar.h +++ b/sys/dev/pci/if_iwivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwivar.h,v 1.20 2009/06/05 22:40:31 deraadt Exp $ */ +/* $OpenBSD: if_iwivar.h,v 1.21 2010/07/28 21:21:38 deraadt Exp $ */ /*- * Copyright (c) 2004-2006 @@ -114,6 +114,7 @@ struct iwi_softc { int sc_tx_timer; void *powerhook; + struct workq_task sc_resume_wqt; #if NBPFILTER > 0 caddr_t sc_drvbpf; diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index 958b7c5deb6..b1374e0abab 100644 --- a/sys/dev/pci/if_iwn.c +++ b/sys/dev/pci/if_iwn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwn.c,v 1.99 2010/07/23 06:43:00 phessler Exp $ */ +/* $OpenBSD: if_iwn.c,v 1.100 2010/07/28 21:21:38 deraadt Exp $ */ /*- * Copyright (c) 2007-2010 Damien Bergamini @@ -750,7 +750,7 @@ iwn_activate(struct device *self, int act) switch (act) { case DVACT_SUSPEND: if (ifp->if_flags & IFF_RUNNING) - iwn_stop(ifp, 1); + iwn_stop(ifp, 0); break; case DVACT_RESUME: workq_queue_task(NULL, &sc->sc_resume_wqt, 0, @@ -771,12 +771,14 @@ void iwn_power(int why, void *arg) { struct iwn_softc *sc = arg; - struct ifnet *ifp; + struct ifnet *ifp = &sc->sc_ic.ic_if; pcireg_t reg; int s; - if (why != PWR_RESUME) + if (why != PWR_RESUME) { + iwn_stop(ifp, 0); return; + } /* Clear device-specific "PCI retry timeout" register (41h). */ reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); @@ -786,12 +788,8 @@ iwn_power(int why, void *arg) s = splnet(); sc->sc_flags |= IWN_FLAG_BUSY; - ifp = &sc->sc_ic.ic_if; - if (ifp->if_flags & IFF_UP) { - ifp->if_init(ifp); - if (ifp->if_flags & IFF_RUNNING) - ifp->if_start(ifp); - } + if (ifp->if_flags & IFF_UP) + iwn_init(ifp); sc->sc_flags &= ~IWN_FLAG_BUSY; splx(s); diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c index d3df5abe025..46cb8514d1c 100644 --- a/sys/dev/pci/if_wpi.c +++ b/sys/dev/pci/if_wpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wpi.c,v 1.102 2010/07/22 14:42:43 kettenis Exp $ */ +/* $OpenBSD: if_wpi.c,v 1.103 2010/07/28 21:21:38 deraadt Exp $ */ /*- * Copyright (c) 2006-2008 @@ -400,7 +400,7 @@ wpi_activate(struct device *self, int act) switch (act) { case DVACT_SUSPEND: if (ifp->if_flags & IFF_RUNNING) - wpi_stop(ifp, 1); + wpi_stop(ifp, 0); break; case DVACT_RESUME: workq_queue_task(NULL, &sc->sc_resume_wqt, 0, @@ -421,12 +421,14 @@ void wpi_power(int why, void *arg) { struct wpi_softc *sc = arg; - struct ifnet *ifp; + struct ifnet *ifp = &sc->sc_ic.ic_if; pcireg_t reg; int s; - if (why != PWR_RESUME) + if (why != PWR_RESUME) { + wpi_stop(ifp, 0); return; + } /* Clear device-specific "PCI retry timeout" register (41h). */ reg = pci_conf_read(sc->sc_pct, sc->sc_pcitag, 0x40); @@ -436,7 +438,6 @@ wpi_power(int why, void *arg) s = splnet(); sc->sc_flags |= WPI_FLAG_BUSY; - ifp = &sc->sc_ic.ic_if; if (ifp->if_flags & IFF_UP) { ifp->if_init(ifp); if (ifp->if_flags & IFF_RUNNING) -- 2.20.1