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/rt2661.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/rt2661.c')
-rw-r--r-- | sys/dev/ic/rt2661.c | 141 |
1 files changed, 80 insertions, 61 deletions
diff --git a/sys/dev/ic/rt2661.c b/sys/dev/ic/rt2661.c index b9ce6f07b20..ca351be844b 100644 --- a/sys/dev/ic/rt2661.c +++ b/sys/dev/ic/rt2661.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2661.c,v 1.54 2010/05/19 15:27:35 oga Exp $ */ +/* $OpenBSD: rt2661.c,v 1.55 2010/08/04 19:48:33 damien Exp $ */ /*- * Copyright (c) 2006 @@ -74,6 +74,7 @@ int rt2661_debug = 1; #define DPRINTFN(n, x) #endif +void rt2661_attachhook(void *); int rt2661_alloc_tx_ring(struct rt2661_softc *, struct rt2661_tx_ring *, int); void rt2661_reset_tx_ring(struct rt2661_softc *, @@ -144,8 +145,7 @@ void rt2661_read_eeprom(struct rt2661_softc *); int rt2661_bbp_init(struct rt2661_softc *); int rt2661_init(struct ifnet *); void rt2661_stop(struct ifnet *, int); -int rt2661_load_microcode(struct rt2661_softc *, const uint8_t *, - int); +int rt2661_load_microcode(struct rt2661_softc *); void rt2661_rx_tune(struct rt2661_softc *); #ifdef notyet void rt2661_radar_start(struct rt2661_softc *); @@ -186,9 +186,8 @@ rt2661_attach(void *xsc, int id) { struct rt2661_softc *sc = xsc; struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = &ic->ic_if; uint32_t val; - int error, ac, i, ntries; + int error, ac, ntries; sc->sc_id = id; @@ -243,6 +242,51 @@ rt2661_attach(void *xsc, int id) goto fail2; } + if (rootvp == NULL) + mountroothook_establish(rt2661_attachhook, sc); + else + rt2661_attachhook(sc); + + sc->sc_powerhook = powerhook_establish(rt2661_power, sc); + if (sc->sc_powerhook == NULL) { + printf("%s: WARNING: unable to establish power hook\n", + sc->sc_dev.dv_xname); + } + + return 0; + +fail2: rt2661_free_tx_ring(sc, &sc->mgtq); +fail1: while (--ac >= 0) + rt2661_free_tx_ring(sc, &sc->txq[ac]); + return ENXIO; +} + +void +rt2661_attachhook(void *xsc) +{ + struct rt2661_softc *sc = xsc; + struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = &ic->ic_if; + const char *name = NULL; /* make lint happy */ + int i, error; + + switch (sc->sc_id) { + case PCI_PRODUCT_RALINK_RT2561: + name = "ral-rt2561"; + break; + case PCI_PRODUCT_RALINK_RT2561S: + name = "ral-rt2561s"; + break; + case PCI_PRODUCT_RALINK_RT2661: + name = "ral-rt2661"; + break; + } + if ((error = loadfirmware(name, &sc->ucode, &sc->ucsize)) != 0) { + printf("%s: error %d, could not read firmware %s\n", + sc->sc_dev.dv_xname, error, name); + 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; @@ -328,19 +372,6 @@ rt2661_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(RT2661_TX_RADIOTAP_PRESENT); #endif - - sc->sc_powerhook = powerhook_establish(rt2661_power, sc); - if (sc->sc_powerhook == NULL) { - printf("%s: WARNING: unable to establish power hook\n", - sc->sc_dev.dv_xname); - } - - return 0; - -fail2: rt2661_free_tx_ring(sc, &sc->mgtq); -fail1: while (--ac >= 0) - rt2661_free_tx_ring(sc, &sc->txq[ac]); - return ENXIO; } int @@ -364,9 +395,30 @@ rt2661_detach(void *xsc) rt2661_free_tx_ring(sc, &sc->mgtq); rt2661_free_rx_ring(sc, &sc->rxq); + if (sc->ucode != NULL) + free(sc->ucode, M_DEVBUF); + return 0; } +void +rt2661_suspend(void *xsc) +{ + struct rt2661_softc *sc = xsc; + struct ifnet *ifp = &sc->sc_ic.ic_if; + + if (ifp->if_flags & IFF_RUNNING) + rt2661_stop(ifp, 0); +} + +void +rt2661_resume(void *xsc) +{ + struct rt2661_softc *sc = xsc; + + rt2661_power(PWR_RESUME, sc); +} + int rt2661_alloc_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring, int count) @@ -2404,11 +2456,8 @@ rt2661_init(struct ifnet *ifp) { struct rt2661_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; - const char *name = NULL; /* make lint happy */ - uint8_t *ucode; - size_t size; uint32_t tmp, sta[3]; - int i, ntries, error; + int i, ntries; /* for CardBus, power on the socket */ if (!(sc->sc_flags & RT2661_ENABLED)) { @@ -2422,36 +2471,11 @@ rt2661_init(struct ifnet *ifp) rt2661_stop(ifp, 0); - if (!(sc->sc_flags & RT2661_FWLOADED)) { - switch (sc->sc_id) { - case PCI_PRODUCT_RALINK_RT2561: - name = "ral-rt2561"; - break; - case PCI_PRODUCT_RALINK_RT2561S: - name = "ral-rt2561s"; - break; - case PCI_PRODUCT_RALINK_RT2661: - name = "ral-rt2661"; - break; - } - - if ((error = loadfirmware(name, &ucode, &size)) != 0) { - printf("%s: error %d, could not read firmware %s\n", - sc->sc_dev.dv_xname, error, name); - rt2661_stop(ifp, 1); - return EIO; - } - - if (rt2661_load_microcode(sc, ucode, size) != 0) { - printf("%s: could not load 8051 microcode\n", - sc->sc_dev.dv_xname); - free(ucode, M_DEVBUF); - rt2661_stop(ifp, 1); - return EIO; - } - - free(ucode, M_DEVBUF); - sc->sc_flags |= RT2661_FWLOADED; + if (rt2661_load_microcode(sc) != 0) { + printf("%s: could not load 8051 microcode\n", + sc->sc_dev.dv_xname); + rt2661_stop(ifp, 1); + return EIO; } /* initialize Tx rings */ @@ -2614,13 +2638,13 @@ rt2661_stop(struct ifnet *ifp, int disable) if (disable && sc->sc_disable != NULL) { if (sc->sc_flags & RT2661_ENABLED) { (*sc->sc_disable)(sc); - sc->sc_flags &= ~(RT2661_ENABLED | RT2661_FWLOADED); + sc->sc_flags &= ~RT2661_ENABLED; } } } int -rt2661_load_microcode(struct rt2661_softc *sc, const uint8_t *ucode, int size) +rt2661_load_microcode(struct rt2661_softc *sc) { int ntries; @@ -2634,7 +2658,7 @@ rt2661_load_microcode(struct rt2661_softc *sc, const uint8_t *ucode, int size) /* write 8051's microcode */ RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET | RT2661_MCU_SEL); - RAL_WRITE_REGION_1(sc, RT2661_MCU_CODE_BASE, ucode, size); + RAL_WRITE_REGION_1(sc, RT2661_MCU_CODE_BASE, sc->ucode, sc->ucsize); RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET); /* kick 8051's ass */ @@ -2906,14 +2930,11 @@ rt2661_power(int why, void *arg) struct ifnet *ifp = &sc->sc_ic.ic_if; int s; - DPRINTF(("%s: rt2661_power(%d)\n", sc->sc_dev.dv_xname, why)); - s = splnet(); switch (why) { case PWR_SUSPEND: case PWR_STANDBY: - rt2661_stop(ifp, 1); - sc->sc_flags &= ~RT2661_FWLOADED; + rt2661_stop(ifp, 0); if (sc->sc_power != NULL) (*sc->sc_power)(sc, why); break; @@ -2922,8 +2943,6 @@ rt2661_power(int why, void *arg) rt2661_init(ifp); if (sc->sc_power != NULL) (*sc->sc_power)(sc, why); - if (ifp->if_flags & IFF_RUNNING) - rt2661_start(ifp); } break; } |