summaryrefslogtreecommitdiff
path: root/sys/dev/ic/rt2860.c
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2010-08-04 19:48:34 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2010-08-04 19:48:34 +0000
commit0126dd6fb799c4d32dff3b0e343b89e8ee793fbf (patch)
treefef8ca36c2a9a2e02f3e13be96afa8bfc45b73a5 /sys/dev/ic/rt2860.c
parente1efbf1bbe92de81860c2803bda817a394fa24c3 (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.c108
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;
}