diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2010-08-04 19:48:34 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2010-08-04 19:48:34 +0000 |
commit | 0126dd6fb799c4d32dff3b0e343b89e8ee793fbf (patch) | |
tree | fef8ca36c2a9a2e02f3e13be96afa8bfc45b73a5 /sys/dev/ic/rt2860.c | |
parent | e1efbf1bbe92de81860c2803bda817a394fa24c3 (diff) |
add suspend/resume support for PCI ral(4) devices.
ok deraadt@, sthen@
tested by matthew@ (RT2560), dcoppa@ (RT2790), okan@ (RT2860), todd@ (RT2560)
Diffstat (limited to 'sys/dev/ic/rt2860.c')
-rw-r--r-- | sys/dev/ic/rt2860.c | 108 |
1 files changed, 67 insertions, 41 deletions
diff --git a/sys/dev/ic/rt2860.c b/sys/dev/ic/rt2860.c index 88ecaa7cd4d..25b6a782968 100644 --- a/sys/dev/ic/rt2860.c +++ b/sys/dev/ic/rt2860.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2860.c,v 1.56 2010/07/19 19:47:52 damien Exp $ */ +/* $OpenBSD: rt2860.c,v 1.57 2010/08/04 19:48:33 damien Exp $ */ /*- * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> @@ -78,6 +78,7 @@ int rt2860_debug = 0; #define DPRINTFN(n, x) #endif +void rt2860_attachhook(void *); int rt2860_alloc_tx_ring(struct rt2860_softc *, struct rt2860_tx_ring *); void rt2860_reset_tx_ring(struct rt2860_softc *, @@ -206,8 +207,7 @@ rt2860_attach(void *xsc, int id) { struct rt2860_softc *sc = xsc; struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; - int i, qid, ntries, error; + int qid, ntries, error; uint32_t tmp; sc->amrr.amrr_min_success_threshold = 1; @@ -272,6 +272,40 @@ rt2860_attach(void *xsc, int id) sc->mgtqid = (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) ? EDCA_AC_VO : 5; + if (rootvp == NULL) + mountroothook_establish(rt2860_attachhook, sc); + else + rt2860_attachhook(sc); + + sc->sc_powerhook = powerhook_establish(rt2860_power, sc); + if (sc->sc_powerhook == NULL) { + printf("%s: WARNING: unable to establish power hook\n", + sc->sc_dev.dv_xname); + } + + return 0; + +fail2: rt2860_free_rx_ring(sc, &sc->rxq); +fail1: while (--qid >= 0) + rt2860_free_tx_ring(sc, &sc->txq[qid]); + return error; +} + +void +rt2860_attachhook(void *xsc) +{ + struct rt2860_softc *sc = xsc; + struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; + int i, error; + + error = loadfirmware("ral-rt2860", &sc->ucode, &sc->ucsize); + if (error != 0) { + printf("%s: error %d, could not read firmware file %s\n", + sc->sc_dev.dv_xname, error, "ral-rt2860"); + return; + } + ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ ic->ic_state = IEEE80211_S_INIT; @@ -362,19 +396,6 @@ rt2860_attach(void *xsc, int id) sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); sc->sc_txtap.wt_ihdr.it_present = htole32(RT2860_TX_RADIOTAP_PRESENT); #endif - - sc->sc_powerhook = powerhook_establish(rt2860_power, sc); - if (sc->sc_powerhook == NULL) { - printf("%s: WARNING: unable to establish power hook\n", - sc->sc_dev.dv_xname); - } - - return 0; - -fail2: rt2860_free_rx_ring(sc, &sc->rxq); -fail1: while (--qid >= 0) - rt2860_free_tx_ring(sc, &sc->txq[qid]); - return error; } int @@ -395,9 +416,30 @@ rt2860_detach(void *xsc) rt2860_free_rx_ring(sc, &sc->rxq); rt2860_free_tx_pool(sc); + if (sc->ucode != NULL) + free(sc->ucode, M_DEVBUF); + return 0; } +void +rt2860_suspend(void *xsc) +{ + struct rt2860_softc *sc = xsc; + struct ifnet *ifp = &sc->sc_ic.ic_if; + + if (ifp->if_flags & IFF_RUNNING) + rt2860_stop(ifp, 0); +} + +void +rt2860_resume(void *xsc) +{ + struct rt2860_softc *sc = xsc; + + rt2860_power(PWR_RESUME, sc); +} + int rt2860_alloc_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) { @@ -3340,14 +3382,11 @@ rt2860_init(struct ifnet *ifp) RAL_BARRIER_WRITE(sc); RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe00); - if (!(sc->sc_flags & RT2860_FWLOADED)) { - if ((error = rt2860_load_microcode(sc)) != 0) { - printf("%s: could not load 8051 microcode\n", - sc->sc_dev.dv_xname); - rt2860_stop(ifp, 1); - return error; - } - sc->sc_flags |= RT2860_FWLOADED; + if ((error = rt2860_load_microcode(sc)) != 0) { + printf("%s: could not load 8051 microcode\n", + sc->sc_dev.dv_xname); + rt2860_stop(ifp, 1); + return error; } IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl)); @@ -3620,7 +3659,7 @@ rt2860_stop(struct ifnet *ifp, int disable) if (disable && sc->sc_disable != NULL) { if (sc->sc_flags & RT2860_ENABLED) { (*sc->sc_disable)(sc); - sc->sc_flags &= ~(RT2860_ENABLED | RT2860_FWLOADED); + sc->sc_flags &= ~RT2860_ENABLED; } } } @@ -3628,20 +3667,12 @@ rt2860_stop(struct ifnet *ifp, int disable) int rt2860_load_microcode(struct rt2860_softc *sc) { - u_char *ucode; - size_t size; - int error, ntries; - - if ((error = loadfirmware("ral-rt2860", &ucode, &size)) != 0) { - printf("%s: error %d, could not read firmware file %s\n", - sc->sc_dev.dv_xname, error, "ral-rt2860"); - return error; - } + int ntries; /* set "host program ram write selection" bit */ RAL_WRITE(sc, RT2860_SYS_CTRL, RT2860_HST_PM_SEL); /* write microcode image */ - RAL_WRITE_REGION_1(sc, RT2860_FW_BASE, ucode, size); + RAL_WRITE_REGION_1(sc, RT2860_FW_BASE, sc->ucode, sc->ucsize); /* kick microcontroller unit */ RAL_WRITE(sc, RT2860_SYS_CTRL, 0); RAL_BARRIER_WRITE(sc); @@ -3650,8 +3681,6 @@ rt2860_load_microcode(struct rt2860_softc *sc) RAL_WRITE(sc, RT2860_H2M_BBPAGENT, 0); RAL_WRITE(sc, RT2860_H2M_MAILBOX, 0); - free(ucode, M_DEVBUF); - /* wait until microcontroller is ready */ RAL_BARRIER_READ_WRITE(sc); for (ntries = 0; ntries < 1000; ntries++) { @@ -3845,8 +3874,7 @@ rt2860_power(int why, void *arg) switch (why) { case PWR_SUSPEND: case PWR_STANDBY: - rt2860_stop(ifp, 1); - sc->sc_flags &= ~RT2860_FWLOADED; + rt2860_stop(ifp, 0); if (sc->sc_power != NULL) (*sc->sc_power)(sc, why); break; @@ -3855,8 +3883,6 @@ rt2860_power(int why, void *arg) rt2860_init(ifp); if (sc->sc_power != NULL) (*sc->sc_power)(sc, why); - if (ifp->if_flags & IFF_RUNNING) - rt2860_start(ifp); } break; } |