summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/cardbus/if_ath_cardbus.c3
-rw-r--r--sys/dev/ic/ath.c194
-rw-r--r--sys/dev/ic/athvar.h39
-rw-r--r--sys/dev/pci/if_ath_pci.c3
4 files changed, 73 insertions, 166 deletions
diff --git a/sys/dev/cardbus/if_ath_cardbus.c b/sys/dev/cardbus/if_ath_cardbus.c
index e7713e38956..3d714512e0e 100644
--- a/sys/dev/cardbus/if_ath_cardbus.c
+++ b/sys/dev/cardbus/if_ath_cardbus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ath_cardbus.c,v 1.6 2005/09/08 12:44:56 jsg Exp $ */
+/* $OpenBSD: if_ath_cardbus.c,v 1.7 2005/09/22 10:17:04 reyk Exp $ */
/* $NetBSD: if_ath_cardbus.c,v 1.4 2004/08/02 19:14:28 mycroft Exp $ */
/*
@@ -63,6 +63,7 @@
#endif
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_rssadapt.h>
#if NBPFILTER > 0
#include <net/bpf.h>
diff --git a/sys/dev/ic/ath.c b/sys/dev/ic/ath.c
index 879c5de285b..d953cd3f036 100644
--- a/sys/dev/ic/ath.c
+++ b/sys/dev/ic/ath.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ath.c,v 1.40 2005/09/19 10:27:08 reyk Exp $ */
+/* $OpenBSD: ath.c,v 1.41 2005/09/22 10:17:04 reyk Exp $ */
/* $NetBSD: ath.c,v 1.37 2004/08/18 21:59:39 dyoung Exp $ */
/*-
@@ -78,6 +78,7 @@
#endif
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_rssadapt.h>
#include <dev/pci/pcidevs.h>
#include <dev/gpio/gpiovar.h>
@@ -134,9 +135,8 @@ int ath_getchannels(struct ath_softc *, u_int cc, HAL_BOOL outdoor,
HAL_BOOL xchanmode);
int ath_rate_setup(struct ath_softc *sc, u_int mode);
void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
-void ath_rate_ctl_reset(struct ath_softc *, enum ieee80211_state);
-void ath_rate_ctl_tx_reset(void *, struct ieee80211_node *);
-void ath_rate_ctl(void *, struct ieee80211_node *);
+void ath_rssadapt_updatenode(void *, struct ieee80211_node *);
+void ath_rssadapt_updatestats(void *);
void ath_recv_mgmt(struct ieee80211com *, struct mbuf *,
struct ieee80211_node *, int, int, u_int32_t);
void ath_disable(struct ath_softc *);
@@ -294,6 +294,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
}
timeout_set(&sc->sc_scan_to, ath_next_scan, sc);
timeout_set(&sc->sc_cal_to, ath_calibrate, sc);
+ timeout_set(&sc->sc_rssadapt_to, ath_rssadapt_updatestats, sc);
#ifdef __FreeBSD__
ATH_TXBUF_LOCK_INIT(sc);
@@ -442,6 +443,10 @@ ath_detach(struct ath_softc *sc, int flags)
DPRINTF(ATH_DEBUG_ANY, ("%s: if_flags %x\n", __func__, ifp->if_flags));
+ timeout_del(&sc->sc_scan_to);
+ timeout_del(&sc->sc_cal_to);
+ timeout_del(&sc->sc_rssadapt_to);
+
s = splnet();
ath_stop(ifp);
#if NBPFILTER > 0
@@ -1012,7 +1017,6 @@ void
ath_watchdog(struct ifnet *ifp)
{
struct ath_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = &sc->sc_ic;
ifp->if_timer = 0;
if ((ifp->if_flags & IFF_RUNNING) == 0 || sc->sc_invalid)
@@ -1027,17 +1031,7 @@ ath_watchdog(struct ifnet *ifp)
}
ifp->if_timer = 1;
}
- if (ic->ic_fixed_rate == -1) {
- /*
- * Run the rate control algorithm if we're not
- * locked at a fixed rate.
- */
- if (ic->ic_opmode == IEEE80211_M_STA) {
- ath_rate_ctl(sc, ic->ic_bss);
- } else {
- ieee80211_iterate_nodes(ic, ath_rate_ctl, sc);
- }
- }
+
ieee80211_watchdog(ifp);
}
@@ -2063,7 +2057,11 @@ ath_rx_proc(void *arg, int npending)
* Send frame up for processing.
*/
ieee80211_input(ifp, m, ni,
- ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp);
+ ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp);
+
+ /* Handle the rate adaption */
+ ieee80211_rssadapt_input(ic, ni, &an->an_rssadapt,
+ ds->ds_rxstat.rs_rssi);
/*
* The frame may have caused the node to be marked for
@@ -2236,6 +2234,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
bf->bf_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
bf->bf_m = m0;
bf->bf_node = ni; /* NB: held reference */
+ an = ATH_NODE(ni);
/* setup descriptors */
ds = bf->bf_desc;
@@ -2246,6 +2245,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
* Calculate Atheros packet type from IEEE80211 packet header
* and setup for rate calculations.
*/
+ bf->bf_id.id_node = NULL;
atype = HAL_PKT_TYPE_NORMAL; /* default */
switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
case IEEE80211_FC0_TYPE_MGT:
@@ -2266,8 +2266,18 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
rix = 0; /* XXX lowest rate */
break;
default:
+ /* remember link conditions for rate adaptation algorithm */
+ if (ic->ic_fixed_rate == -1) {
+ bf->bf_id.id_len = m0->m_pkthdr.len;
+ bf->bf_id.id_rateidx = ni->ni_txrate;
+ bf->bf_id.id_node = ni;
+ bf->bf_id.id_rssi = ath_node_getrssi(ic, ni);
+ }
+ ni->ni_txrate = ieee80211_rssadapt_choose(&an->an_rssadapt,
+ &ni->ni_rates, wh, m0->m_pkthdr.len, ic->ic_fixed_rate,
+ ifp->if_xname, 0);
rix = sc->sc_rixmap[ni->ni_rates.rs_rates[ni->ni_txrate] &
- IEEE80211_RATE_VAL];
+ IEEE80211_RATE_VAL];
if (rix == 0xff) {
printf("%s: bogus xmit rate 0x%x\n", ifp->if_xname,
ni->ni_rates.rs_rates[ni->ni_txrate]);
@@ -2277,6 +2287,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
}
break;
}
+
/*
* NB: the 802.11 layer marks whether or not we should
* use short preamble based on the current mode and
@@ -2359,7 +2370,6 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
* initialized to 0 which gives us ``auto'' or the
* ``default'' antenna.
*/
- an = (struct ath_node *) ni;
if (an->an_tx_antenna) {
antenna = an->an_tx_antenna;
} else {
@@ -2500,10 +2510,14 @@ ath_tx_proc(void *arg, int npending)
if (ni != NULL) {
an = (struct ath_node *) ni;
if (ds->ds_txstat.ts_status == 0) {
- an->an_tx_ok++;
+ if (bf->bf_id.id_node != NULL)
+ ieee80211_rssadapt_raise_rate(ic,
+ &an->an_rssadapt, &bf->bf_id);
an->an_tx_antenna = ds->ds_txstat.ts_antenna;
} else {
- an->an_tx_err++;
+ if (bf->bf_id.id_node != NULL)
+ ieee80211_rssadapt_lower_rate(ic, ni,
+ &an->an_rssadapt, &bf->bf_id);
ifp->if_oerrors++;
if (ds->ds_txstat.ts_status & HAL_TXERR_XRETRY)
sc->sc_stats.ast_tx_xretries++;
@@ -2517,8 +2531,6 @@ ath_tx_proc(void *arg, int npending)
lr = ds->ds_txstat.ts_longretry;
sc->sc_stats.ast_tx_shortretry += sr;
sc->sc_stats.ast_tx_longretry += lr;
- if (sr + lr)
- an->an_tx_retr++;
/*
* Reclaim reference to node.
*
@@ -2874,6 +2886,7 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
ath_ledstate(sc, nstate);
if (nstate == IEEE80211_S_INIT) {
+ timeout_del(&sc->sc_rssadapt_to);
sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
ath_hal_set_intr(ah, sc->sc_imask);
return (*sc->sc_newstate)(ic, nstate, arg);
@@ -2939,10 +2952,6 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
}
/*
- * Reset the rate control state.
- */
- ath_rate_ctl_reset(sc, nstate);
- /*
* Invoke the parent method to complete the work.
*/
error = (*sc->sc_newstate)(ic, nstate, arg);
@@ -2950,6 +2959,9 @@ ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
if (nstate == IEEE80211_S_RUN) {
/* start periodic recalibration timer */
timeout_add(&sc->sc_cal_to, hz * ath_calinterval);
+
+ if (ic->ic_opmode != IEEE80211_M_MONITOR)
+ timeout_add(&sc->sc_rssadapt_to, hz / 10);
} else if (nstate == IEEE80211_S_SCAN) {
/* start ap/neighbor scan timer */
timeout_add(&sc->sc_scan_to, (hz * ath_dwelltime) / 1000);
@@ -2993,21 +3005,6 @@ ath_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
{
if (ic->ic_opmode == IEEE80211_M_MONITOR)
return;
-
- if (isnew) {
- struct ath_node *an = (struct ath_node *) ni;
-
- an->an_tx_ok = an->an_tx_err =
- an->an_tx_retr = an->an_tx_upper = 0;
- /* start with highest negotiated rate */
- /*
- * XXX should do otherwise but only when
- * the rate control algorithm is better.
- */
- KASSERT(ni->ni_rates.rs_nrates > 0,
- ("new association w/ no rates!"));
- ni->ni_txrate = ni->ni_rates.rs_nrates - 1;
- }
}
int
@@ -3140,118 +3137,27 @@ ath_setcurmode(struct ath_softc *sc, enum ieee80211_phymode mode)
sc->sc_curmode = mode;
}
-/*
- * Reset the rate control state for each 802.11 state transition.
- */
void
-ath_rate_ctl_reset(struct ath_softc *sc, enum ieee80211_state state)
+ath_rssadapt_updatenode(void *arg, struct ieee80211_node *ni)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211_node *ni;
- struct ath_node *an;
-
- /*
- * When operating as a station the node table holds
- * the AP's that were discovered during scanning.
- * For any other operating mode we want to reset the
- * tx rate state of each node.
- */
- if (ic->ic_opmode != IEEE80211_M_STA)
- ieee80211_iterate_nodes(ic, ath_rate_ctl_tx_reset, NULL);
+ struct ath_node *an = ATH_NODE(ni);
- /*
- * Reset local xmit state; this is really only meaningful
- * when operating in station or adhoc mode.
- */
- ni = ic->ic_bss;
- an = (struct ath_node *) ni;
- an->an_tx_ok = an->an_tx_err = an->an_tx_retr = an->an_tx_upper = 0;
- if (state == IEEE80211_S_RUN &&
- ic->ic_opmode != IEEE80211_M_MONITOR) {
- /* start with highest negotiated rate */
- KASSERT(ni->ni_rates.rs_nrates > 0,
- ("transition to RUN state w/ no rates!"));
- ni->ni_txrate = ni->ni_rates.rs_nrates - 1;
- } else {
- /* use lowest rate */
- ni->ni_txrate = 0;
- }
+ ieee80211_rssadapt_updatestats(&an->an_rssadapt);
}
void
-ath_rate_ctl_tx_reset(void *arg, struct ieee80211_node *ni)
+ath_rssadapt_updatestats(void *arg)
{
- struct ath_node *an = (struct ath_node *) ni;
- ni->ni_txrate = 0; /* use lowest rate */
- an->an_tx_ok = an->an_tx_err = an->an_tx_retr =
- an->an_tx_upper = 0;
-}
-
-/*
- * Examine and potentially adjust the transmit rate.
- */
-void
-ath_rate_ctl(void *arg, struct ieee80211_node *ni)
-{
- struct ath_softc *sc = arg;
- struct ath_node *an = (struct ath_node *) ni;
- struct ieee80211_rateset *rs = &ni->ni_rates;
- int mod = 0, orate, enough;
-
- /*
- * Rate control
- * XXX: very primitive version.
- */
- sc->sc_stats.ast_rate_calls++;
-
- enough = (an->an_tx_ok + an->an_tx_err >= 10);
-
- /* no packet reached -> down */
- if (an->an_tx_err > 0 && an->an_tx_ok == 0)
- mod = -1;
-
- /* all packets needs retry in average -> down */
- if (enough && an->an_tx_ok < an->an_tx_retr)
- mod = -1;
-
- /* no error and less than 10% of packets needs retry -> up */
- if (enough && an->an_tx_err == 0 && an->an_tx_ok > an->an_tx_retr * 10)
- mod = 1;
+ struct ath_softc *sc = (struct ath_softc *)arg;
+ struct ieee80211com *ic = &sc->sc_ic;
- orate = ni->ni_txrate;
- switch (mod) {
- case 0:
- if (enough && an->an_tx_upper > 0)
- an->an_tx_upper--;
- break;
- case -1:
- if (ni->ni_txrate > 0) {
- ni->ni_txrate--;
- sc->sc_stats.ast_rate_drop++;
- }
- an->an_tx_upper = 0;
- break;
- case 1:
- if (++an->an_tx_upper < 2)
- break;
- an->an_tx_upper = 0;
- if (ni->ni_txrate + 1 < rs->rs_nrates) {
- ni->ni_txrate++;
- sc->sc_stats.ast_rate_raise++;
- }
- break;
+ if (ic->ic_opmode == IEEE80211_M_STA) {
+ ath_rssadapt_updatenode(arg, ic->ic_bss);
+ } else {
+ ieee80211_iterate_nodes(ic, ath_rssadapt_updatenode, arg);
}
- if (ni->ni_txrate != orate) {
- DPRINTF(ATH_DEBUG_RATE,
- ("%s: %dM -> %dM (%d ok, %d err, %d retr)\n",
- __func__,
- (rs->rs_rates[orate] & IEEE80211_RATE_VAL) / 2,
- (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL) / 2,
- an->an_tx_ok, an->an_tx_err, an->an_tx_retr));
- }
- if (ni->ni_txrate != orate || enough)
- an->an_tx_ok = an->an_tx_err = an->an_tx_retr = 0;
+ timeout_add(&sc->sc_rssadapt_to, hz / 10);
}
#ifdef AR_DEBUG
diff --git a/sys/dev/ic/athvar.h b/sys/dev/ic/athvar.h
index 9e047bddca5..6596ddc29fa 100644
--- a/sys/dev/ic/athvar.h
+++ b/sys/dev/ic/athvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: athvar.h,v 1.14 2005/08/17 13:14:17 reyk Exp $ */
+/* $OpenBSD: athvar.h,v 1.15 2005/09/22 10:17:04 reyk Exp $ */
/* $NetBSD: athvar.h,v 1.10 2004/08/10 01:03:53 dyoung Exp $ */
/*-
@@ -168,29 +168,27 @@ struct ath_tx_radiotap_header {
* driver-specific node
*/
struct ath_node {
- struct ieee80211_node an_node; /* base class */
- u_int an_tx_ok; /* tx ok pkt */
- u_int an_tx_err; /* tx !ok pkt */
- u_int an_tx_retr; /* tx retry count */
- int an_tx_upper; /* tx upper rate req cnt */
- u_int an_tx_antenna; /* antenna for last good frame */
- u_int an_rx_antenna; /* antenna for last rcvd frame */
- struct ath_recv_hist an_rx_hist[ATH_RHIST_SIZE];
- u_int an_rx_hist_next;/* index of next ``free entry'' */
+ struct ieee80211_node an_node; /* base class */
+ struct ieee80211_rssadapt an_rssadapt; /* rate adaption */
+ u_int an_tx_antenna; /* antenna for last good frame */
+ u_int an_rx_antenna; /* antenna for last rcvd frame */
+ struct ath_recv_hist an_rx_hist[ATH_RHIST_SIZE];
+ u_int an_rx_hist_next;/* index of next ``free entry'' */
};
#define ATH_NODE(_n) ((struct ath_node *)(_n))
struct ath_buf {
- TAILQ_ENTRY(ath_buf) bf_list;
- bus_dmamap_t bf_dmamap; /* DMA map of the buffer */
-#define bf_nseg bf_dmamap->dm_nsegs
-#define bf_mapsize bf_dmamap->dm_mapsize
-#define bf_segs bf_dmamap->dm_segs
- struct ath_desc *bf_desc; /* virtual addr of desc */
- bus_addr_t bf_daddr; /* physical addr of desc */
- struct mbuf *bf_m; /* mbuf for buf */
- struct ieee80211_node *bf_node; /* pointer to the node */
-#define ATH_MAX_SCATTER 64
+ TAILQ_ENTRY(ath_buf) bf_list;
+ bus_dmamap_t bf_dmamap; /* DMA map of the buffer */
+#define bf_nseg bf_dmamap->dm_nsegs
+#define bf_mapsize bf_dmamap->dm_mapsize
+#define bf_segs bf_dmamap->dm_segs
+ struct ath_desc *bf_desc; /* virtual addr of desc */
+ bus_addr_t bf_daddr; /* physical addr of desc */
+ struct mbuf *bf_m; /* mbuf for buf */
+ struct ieee80211_node *bf_node; /* pointer to the node */
+ struct ieee80211_rssdesc bf_id;
+#define ATH_MAX_SCATTER 64
};
typedef struct ath_task {
@@ -299,6 +297,7 @@ struct ath_softc {
struct timeout sc_cal_to;
struct timeval sc_last_beacon;
struct timeout sc_scan_to;
+ struct timeout sc_rssadapt_to;
#else
struct callout sc_cal_ch; /* callout handle for cals */
struct callout sc_scan_ch; /* callout handle for scan */
diff --git a/sys/dev/pci/if_ath_pci.c b/sys/dev/pci/if_ath_pci.c
index 46671cbcac5..31c59429f38 100644
--- a/sys/dev/pci/if_ath_pci.c
+++ b/sys/dev/pci/if_ath_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ath_pci.c,v 1.10 2005/09/08 18:45:28 reyk Exp $ */
+/* $OpenBSD: if_ath_pci.c,v 1.11 2005/09/22 10:17:04 reyk Exp $ */
/* $NetBSD: if_ath_pci.c,v 1.7 2004/06/30 05:58:17 mycroft Exp $ */
/*-
@@ -66,6 +66,7 @@
#endif
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_rssadapt.h>
#include <dev/gpio/gpiovar.h>