summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2012-10-27 16:13:29 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2012-10-27 16:13:29 +0000
commit6546dce36c67affafc99e96af041db55e667b063 (patch)
tree24d803a8f605a4593eaefb3212e1b1ea0422e5d4 /sys/dev/ic
parent03f796e15851d0a9577e7464eb38078cf840ab2b (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.c75
-rw-r--r--sys/dev/ic/acx100.c5
-rw-r--r--sys/dev/ic/acx111.c5
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;