From 97da3b129c8619afb533f82b074b78fb416e86d6 Mon Sep 17 00:00:00 2001 From: perry Date: Tue, 20 Jun 2006 14:38:34 +0000 Subject: [PATCH] Power hook for ath pci front end. Written and tested by George Michaelson [ggm at apnic.net] --- sys/dev/pci/if_ath_pci.c | 47 +++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/sys/dev/pci/if_ath_pci.c b/sys/dev/pci/if_ath_pci.c index f4201551688e..2fa7fcee5508 100644 --- a/sys/dev/pci/if_ath_pci.c +++ b/sys/dev/pci/if_ath_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ath_pci.c,v 1.13 2006/06/05 05:15:31 gdamore Exp $ */ +/* $NetBSD: if_ath_pci.c,v 1.14 2006/06/20 14:38:34 perry Exp $ */ /*- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting @@ -41,7 +41,7 @@ __FBSDID("$FreeBSD: src/sys/dev/ath/if_ath_pci.c,v 1.11 2005/01/18 18:08:16 sam Exp $"); #endif #ifdef __NetBSD__ -__KERNEL_RCSID(0, "$NetBSD: if_ath_pci.c,v 1.13 2006/06/05 05:15:31 gdamore Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ath_pci.c,v 1.14 2006/06/20 14:38:34 perry Exp $"); #endif /* @@ -91,6 +91,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_ath_pci.c,v 1.13 2006/06/05 05:15:31 gdamore Exp struct ath_pci_softc { struct ath_softc sc_sc; pci_chipset_tag_t sc_pc; + pcitag_t sc_pcitag; + struct pci_conf_state sc_pciconf; void *sc_ih; /* interrupt handler */ bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; @@ -103,6 +105,7 @@ struct ath_pci_softc { static int ath_pci_match(struct device *, struct cfdata *, void *); static void ath_pci_attach(struct device *, struct device *, void *); static void ath_pci_shutdown(void *); +static void ath_pci_powerhook(int, void *); static int ath_pci_detach(struct device *, int); CFATTACH_DECL(ath_pci, @@ -165,11 +168,14 @@ ath_pci_attach(struct device *parent, struct device *self, void *aux) struct pci_attach_args *pa = aux; pci_chipset_tag_t pc = pa->pa_pc; pci_intr_handle_t ih; - void *hook; + void *shook; + void *phook; const char *intrstr = NULL; psc->sc_pc = pc; + psc->sc_pcitag = pa->pa_tag; + if (!ath_pci_setup(pa)) goto bad; @@ -207,16 +213,23 @@ ath_pci_attach(struct device *parent, struct device *self, void *aux) sc->sc_dmat = pa->pa_dmat; - hook = shutdownhook_establish(ath_pci_shutdown, psc); - if (hook == NULL) { + shook = shutdownhook_establish(ath_pci_shutdown, psc); + if (shook == NULL) { aprint_error("couldn't make shutdown hook\n"); goto bad3; } + phook = powerhook_establish(ath_pci_powerhook, psc); + if (phook == NULL) { + aprint_error("couldn't make power hook\n"); + goto bad3; + } + if (ath_attach(PCI_PRODUCT(pa->pa_id), sc) == 0) return; - shutdownhook_disestablish(hook); + shutdownhook_disestablish(shook); + powerhook_disestablish(phook); bad3: pci_intr_disestablish(pc, psc->sc_ih); bad2: /* XXX */ @@ -243,3 +256,25 @@ ath_pci_shutdown(void *self) ath_shutdown(&psc->sc_sc); } + +static void +ath_pci_powerhook(int why, void *arg) +{ + struct ath_pci_softc *sc = arg; + pci_chipset_tag_t pc = sc->sc_pc; + pcitag_t tag = sc->sc_pcitag; + + switch (why) { + case PWR_SOFTSUSPEND: + ath_pci_shutdown(sc); + break; + case PWR_SUSPEND: + pci_conf_capture(pc, tag, &sc->sc_pciconf); + break; + case PWR_RESUME: + pci_conf_restore(pc, tag, &sc->sc_pciconf); + break; + } + + return; +}