diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2012-10-27 16:13:29 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2012-10-27 16:13:29 +0000 |
commit | 6546dce36c67affafc99e96af041db55e667b063 (patch) | |
tree | 24d803a8f605a4593eaefb3212e1b1ea0422e5d4 /sys/dev/ic | |
parent | 03f796e15851d0a9577e7464eb38078cf840ab2b (diff) |
Implememnt AP side power saving for acx(4). Tested on acx11.
With some input and OK from kettenis@ and OK sthen@
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/acx.c | 75 | ||||
-rw-r--r-- | sys/dev/ic/acx100.c | 5 | ||||
-rw-r--r-- | sys/dev/ic/acx111.c | 5 |
3 files changed, 66 insertions, 19 deletions
diff --git a/sys/dev/ic/acx.c b/sys/dev/ic/acx.c index ae199d815ac..900e44696bd 100644 --- a/sys/dev/ic/acx.c +++ b/sys/dev/ic/acx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acx.c,v 1.97 2010/08/27 17:08:00 jsg Exp $ */ +/* $OpenBSD: acx.c,v 1.98 2012/10/27 16:13:28 claudio Exp $ */ /* * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> @@ -202,6 +202,9 @@ int acx_init_radio(struct acx_softc *, uint32_t, uint32_t); void acx_iter_func(void *, struct ieee80211_node *); void acx_amrr_timeout(void *); void acx_newassoc(struct ieee80211com *, struct ieee80211_node *, int); +#ifndef IEEE80211_STA_ONLY +void acx_set_tim(struct ieee80211com *, int, int); +#endif int acx_beacon_intvl = 100; /* 100 TU */ @@ -316,6 +319,7 @@ acx_attach(struct acx_softc *sc) #ifndef IEEE80211_STA_ONLY IEEE80211_C_IBSS | /* IBSS mode */ IEEE80211_C_HOSTAP | /* Access Point */ + IEEE80211_C_APPMGT | /* AP Power Mgmt */ #endif IEEE80211_C_SHPREAMBLE; /* Short preamble */ @@ -343,6 +347,11 @@ acx_attach(struct acx_softc *sc) ic->ic_node_alloc = acx_node_alloc; ic->ic_newassoc = acx_newassoc; +#ifndef IEEE80211_STA_ONLY + /* Override set TIM */ + ic->ic_set_tim = acx_set_tim; +#endif + /* Override newstate */ sc->sc_newstate = ic->ic_newstate; ic->ic_newstate = acx_newstate; @@ -939,6 +948,7 @@ acx_start(struct ifnet *ifp) int rate; IF_DEQUEUE(&ic->ic_mgtq, m); + /* first dequeue management frames */ if (m != NULL) { ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; m->m_pkthdr.rcvif = NULL; @@ -962,13 +972,20 @@ acx_start(struct ifnet *ifp) */ rate = ni->ni_rates.rs_rates[0]; rate &= IEEE80211_RATE_VAL; - } else if (!IFQ_IS_EMPTY(&ifp->if_snd)) { + } else { struct ether_header *eh; - IFQ_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - + /* then dequeue packets on the powersave queue */ + IF_DEQUEUE(&ic->ic_pwrsaveq, m); + if (m != NULL) { + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + m->m_pkthdr.rcvif = NULL; + goto encapped; + } else { + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) + break; + } if (ic->ic_state != IEEE80211_S_RUN) { DPRINTF(("%s: data packet dropped due to " "not RUN. Current state %d\n", @@ -997,20 +1014,19 @@ acx_start(struct ifnet *ifp) ifp->if_oerrors++; continue; } - -#if NBPFILTER > 0 - if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT); -#endif - +encapped: if (ic->ic_fixed_rate != -1) { rate = ic->ic_sup_rates[ic->ic_curmode]. rs_rates[ic->ic_fixed_rate]; } else rate = ni->ni_rates.rs_rates[ni->ni_txrate]; rate &= IEEE80211_RATE_VAL; - } else - break; + } + +#if NBPFILTER > 0 + if (ic->ic_rawbpf != NULL) + bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT); +#endif wh = mtod(m, struct ieee80211_frame *); if ((wh->i_fc[1] & IEEE80211_FC1_WEP) && !sc->chip_hw_crypt) { @@ -1064,7 +1080,7 @@ acx_start(struct ifnet *ifp) * acx_txeof(), so it is not freed here. acx_txeof() * will free it for us */ - trans = 1; + trans++; bd->tx_used_count++; idx = (idx + 1) % ACX_TX_DESC_CNT; } @@ -1116,14 +1132,19 @@ acx_intr(void *arg) return (0); } + /* Acknowledge all interrupts */ + CSR_WRITE_2(sc, ACXREG_INTR_ACK, intr_status); + intr_status &= sc->chip_intr_enable; if (intr_status == 0) { /* not interrupts we care about */ return (1); } - /* Acknowledge all interrupts */ - CSR_WRITE_2(sc, ACXREG_INTR_ACK, ACXRV_INTR_ALL); +#ifndef IEEE80211_STA_ONLY + if (intr_status & ACXRV_INTR_DTIM) + ieee80211_notify_dtim(&sc->sc_ic); +#endif if (intr_status & ACXRV_INTR_TX_FINI) acx_txeof(sc); @@ -2733,3 +2754,23 @@ acx_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew) i--); ni->ni_txrate = i; } + +#ifndef IEEE80211_STA_ONLY +void +acx_set_tim(struct ieee80211com *ic, int aid, int set) +{ + struct acx_softc *sc = ic->ic_if.if_softc; + struct acx_tmplt_tim tim; + u_int8_t *ep; + + if (set) + setbit(ic->ic_tim_bitmap, aid & ~0xc000); + else + clrbit(ic->ic_tim_bitmap, aid & ~0xc000); + + bzero(&tim, sizeof(tim)); + ep = ieee80211_add_tim(tim.data.u_mem, ic); + + acx_set_tmplt(sc, ACXCMD_TMPLT_TIM, &tim, ep - (u_int8_t *)&tim); +} +#endif diff --git a/sys/dev/ic/acx100.c b/sys/dev/ic/acx100.c index 97c0e96749d..ebf156781ab 100644 --- a/sys/dev/ic/acx100.c +++ b/sys/dev/ic/acx100.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acx100.c,v 1.21 2010/04/20 22:05:41 tedu Exp $ */ +/* $OpenBSD: acx100.c,v 1.22 2012/10/27 16:13:28 claudio Exp $ */ /* * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> @@ -264,6 +264,9 @@ acx100_set_param(struct acx_softc *sc) sc->chip_ioreg = acx100_reg; sc->chip_hw_crypt = 1; sc->chip_intr_enable = ACX100_INTR_ENABLE; +#ifndef IEEE80211_STA_ONLY + sc->chip_intr_enable |= ACXRV_INTR_DTIM; +#endif sc->chip_intr_disable = ACX100_INTR_DISABLE; sc->chip_gpio_pled = ACX100_GPIO_POWER_LED; sc->chip_ee_eaddr_ofs = ACX100_EE_EADDR_OFS; diff --git a/sys/dev/ic/acx111.c b/sys/dev/ic/acx111.c index 4990a627d7f..d1266040672 100644 --- a/sys/dev/ic/acx111.c +++ b/sys/dev/ic/acx111.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acx111.c,v 1.18 2010/04/20 22:05:41 tedu Exp $ */ +/* $OpenBSD: acx111.c,v 1.19 2012/10/27 16:13:28 claudio Exp $ */ /* * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> @@ -276,6 +276,9 @@ acx111_set_param(struct acx_softc *sc) sc->chip_mem2_rid = PCIR_BAR(1); sc->chip_ioreg = acx111_reg; sc->chip_intr_enable = ACX111_INTR_ENABLE; +#ifndef IEEE80211_STA_ONLY + sc->chip_intr_enable |= ACXRV_INTR_DTIM; +#endif sc->chip_intr_disable = ACX111_INTR_DISABLE; sc->chip_gpio_pled = ACX111_GPIO_POWER_LED; sc->chip_ee_eaddr_ofs = ACX111_EE_EADDR_OFS; |