summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2006-10-09 20:45:28 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2006-10-09 20:45:28 +0000
commit61baa35a9736a996edde76ac89462a4fccad29d5 (patch)
tree509470340e6ea73c7664237b59952931f1bd2e5f
parent4d12400f85ba5fc1e76f23b4fb8735e540bde0a2 (diff)
Add powerhooks. Tested with a Netgear WG511v1 on my X40.
ok claudio@
-rw-r--r--sys/dev/cardbus/if_pgt_cardbus.c14
-rw-r--r--sys/dev/ic/pgt.c83
-rw-r--r--sys/dev/ic/pgtvar.h7
3 files changed, 88 insertions, 16 deletions
diff --git a/sys/dev/cardbus/if_pgt_cardbus.c b/sys/dev/cardbus/if_pgt_cardbus.c
index de27604745c..d181916cd6e 100644
--- a/sys/dev/cardbus/if_pgt_cardbus.c
+++ b/sys/dev/cardbus/if_pgt_cardbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_pgt_cardbus.c,v 1.3 2006/10/06 21:55:33 mglocker Exp $ */
+/* $OpenBSD: if_pgt_cardbus.c,v 1.4 2006/10/09 20:45:27 mglocker Exp $ */
/*
* Copyright (c) 2006 Marcus Glocker <mglocker@openbsd.org>
@@ -216,12 +216,12 @@ pgt_cardbus_disable(struct pgt_softc *sc)
void
pgt_cardbus_power(struct pgt_softc *sc, int why)
{
- struct pgt_cardbus_softc *csc = (struct pgt_cardbus_softc *)sc;
-
- if (why == PWR_RESUME) {
- /* kick the PCI configuration registers */
- pgt_cardbus_setup(csc);
- }
+ if (why == PWR_RESUME)
+ if (sc->sc_enable != NULL)
+ (*sc->sc_enable)(sc);
+ if (why == PWR_SUSPEND)
+ if (sc->sc_disable != NULL)
+ (*sc->sc_disable)(sc);
}
void
diff --git a/sys/dev/ic/pgt.c b/sys/dev/ic/pgt.c
index 11d1d5207a5..5d4413b13df 100644
--- a/sys/dev/ic/pgt.c
+++ b/sys/dev/ic/pgt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pgt.c,v 1.30 2006/10/06 21:55:33 mglocker Exp $ */
+/* $OpenBSD: pgt.c,v 1.31 2006/10/09 20:45:27 mglocker Exp $ */
/*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@@ -133,7 +133,8 @@ int pgt_load_firmware(struct pgt_softc *);
void pgt_cleanup_queue(struct pgt_softc *, enum pgt_queue,
struct pgt_frag []);
int pgt_reset(struct pgt_softc *);
-void pgt_disable(struct pgt_softc *, unsigned int);
+void pgt_stop(struct pgt_softc *, unsigned int);
+void pgt_reboot(struct pgt_softc *);
void pgt_init_intr(struct pgt_softc *);
void pgt_update_intr(struct pgt_softc *, int);
struct mbuf
@@ -191,6 +192,8 @@ int pgt_dma_alloc(struct pgt_softc *);
int pgt_dma_alloc_queue(struct pgt_softc *sc, enum pgt_queue pq);
void pgt_dma_free(struct pgt_softc *);
void pgt_dma_free_queue(struct pgt_softc *sc, enum pgt_queue pq);
+void pgt_shutdown(void *);
+void pgt_power(int, void *);
void
pgt_write_memory_barrier(struct pgt_softc *sc)
@@ -470,7 +473,7 @@ pgt_reset(struct pgt_softc *sc)
* we'll spend a minute seeing if we can't do the reset.
*/
void
-pgt_disable(struct pgt_softc *sc, unsigned int flag)
+pgt_stop(struct pgt_softc *sc, unsigned int flag)
{
struct ieee80211com *ic;
unsigned int wokeup;
@@ -624,13 +627,21 @@ int
pgt_detach(struct pgt_softc *sc)
{
/* stop card */
- pgt_disable(sc, SC_DYING);
+ pgt_stop(sc, SC_DYING);
pgt_reboot(sc);
/* disable card if possible */
if (sc->sc_disable != NULL)
(*sc->sc_disable)(sc);
+ /*
+ * Disable shutdown and power hooks
+ */
+ if (sc->sc_shutdown_hook != NULL)
+ shutdownhook_disestablish(sc->sc_shutdown_hook);
+ if (sc->sc_power_hook != NULL)
+ powerhook_disestablish(sc->sc_power_hook);
+
ieee80211_ifdetach(&sc->sc_ic.ic_if);
if_detach(&sc->sc_ic.ic_if);
@@ -1136,7 +1147,7 @@ pgt_per_device_kthread(void *argp)
sck->sck_update = 0;
pgt_empty_traps(sck);
s = splnet();
- pgt_disable(sc, SC_NEEDS_RESET);
+ pgt_stop(sc, SC_NEEDS_RESET);
splx(s);
} else if (!TAILQ_EMPTY(&sck->sck_traps)) {
DPRINTF(("%s: [thread] got a trap\n",
@@ -2012,6 +2023,18 @@ pgt_net_attach(struct pgt_softc *sc)
sc->sc_txtap.wt_ihdr.it_present = htole32(PGT_TX_RADIOTAP_PRESENT);
#endif
+ /*
+ * Enable shutdown and power hooks
+ */
+ sc->sc_shutdown_hook = shutdownhook_establish(pgt_shutdown, sc);
+ if (sc->sc_shutdown_hook == NULL)
+ printf("%s: WARNING: unable to establish shutdown hook\n",
+ sc->sc_dev.dv_xname);
+ sc->sc_power_hook = powerhook_establish(pgt_power, sc);
+ if (sc->sc_power_hook == NULL)
+ printf("%s: WARNING: unable to establish power hook\n",
+ sc->sc_dev.dv_xname);
+
return (0);
}
@@ -2362,7 +2385,7 @@ pgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t req)
}
} else {
if (ifp->if_flags & IFF_RUNNING) {
- pgt_disable(sc, SC_NEEDS_RESET);
+ pgt_stop(sc, SC_NEEDS_RESET);
error = ENETRESET;
}
}
@@ -3271,3 +3294,51 @@ pgt_dma_free_queue(struct pgt_softc *sc, enum pgt_queue pq)
free(pd, M_DEVBUF);
}
}
+
+void
+pgt_shutdown(void *arg)
+{
+ struct pgt_softc *sc = arg;
+
+ DPRINTF(("%s: %s\n", sc->sc_dev.dv_xname, __func__));
+
+ pgt_stop(sc, SC_DYING);
+}
+
+void
+pgt_power(int why, void *arg)
+{
+ struct pgt_softc *sc = arg;
+ struct ifnet *ifp = &sc->sc_ic.ic_if;
+ int s;
+
+ DPRINTF(("%s: %s(%d)\n", sc->sc_dev.dv_xname, __func__, why));
+
+ s = splnet();
+
+ switch (why) {
+ case PWR_STANDBY:
+ case PWR_SUSPEND:
+ pgt_stop(sc, SC_NEEDS_RESET);
+ pgt_update_hw_from_sw(sc, 0, 0);
+
+ if (sc->sc_power != NULL)
+ (*sc->sc_power)(sc, why);
+ break;
+ case PWR_RESUME:
+ if (sc->sc_power != NULL)
+ (*sc->sc_power)(sc, why);
+
+ pgt_stop(sc, SC_NEEDS_RESET);
+ pgt_update_hw_from_sw(sc, 0, 0);
+
+ if ((ifp->if_flags & IFF_UP) &&
+ !(ifp->if_flags & IFF_RUNNING)) {
+ pgt_init(ifp);
+ pgt_update_hw_from_sw(sc, 0, 0);
+ }
+ break;
+ }
+
+ splx(s);
+}
diff --git a/sys/dev/ic/pgtvar.h b/sys/dev/ic/pgtvar.h
index d4c6f9ba860..0407201a561 100644
--- a/sys/dev/ic/pgtvar.h
+++ b/sys/dev/ic/pgtvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pgtvar.h,v 1.9 2006/10/06 21:55:33 mglocker Exp $ */
+/* $OpenBSD: pgtvar.h,v 1.10 2006/10/09 20:45:27 mglocker Exp $ */
/*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@@ -178,6 +178,8 @@ struct pgt_softc {
int (*sc_enable)(struct pgt_softc *);
void (*sc_disable)(struct pgt_softc *);
void (*sc_power)(struct pgt_softc *, int);
+ void *sc_shutdown_hook; /* shutdown hook */
+ void *sc_power_hook; /* power mgmt hook */
struct pgt_mgmt_descq sc_mgmtinprog;
struct pgt_descq sc_freeq[PGT_QUEUE_COUNT];
@@ -213,8 +215,7 @@ struct pgt_softc {
int pgt_intr(void *);
void pgt_attach(void *);
-int pgt_detach(struct pgt_softc *sc);
-void pgt_reboot(struct pgt_softc *);
+int pgt_detach(struct pgt_softc *);
static __inline int
pgt_queue_is_rx(enum pgt_queue pq)