summaryrefslogtreecommitdiff
path: root/sys/dev/ic/rt2661.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic/rt2661.c')
-rw-r--r--sys/dev/ic/rt2661.c138
1 files changed, 60 insertions, 78 deletions
diff --git a/sys/dev/ic/rt2661.c b/sys/dev/ic/rt2661.c
index 480ba3de285..5e686488728 100644
--- a/sys/dev/ic/rt2661.c
+++ b/sys/dev/ic/rt2661.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rt2661.c,v 1.28 2006/10/18 21:11:02 mglocker Exp $ */
+/* $OpenBSD: rt2661.c,v 1.29 2006/10/22 12:14:44 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -56,7 +56,7 @@
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
-#include <net80211/ieee80211_rssadapt.h>
+#include <net80211/ieee80211_amrr.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/ic/rt2661reg.h>
@@ -88,12 +88,12 @@ void rt2661_reset_rx_ring(struct rt2661_softc *,
void rt2661_free_rx_ring(struct rt2661_softc *,
struct rt2661_rx_ring *);
struct ieee80211_node *rt2661_node_alloc(struct ieee80211com *);
-void rt2661_node_copy(struct ieee80211com *ic,
- struct ieee80211_node *, const struct ieee80211_node *);
int rt2661_media_change(struct ifnet *);
void rt2661_next_scan(void *);
void rt2661_iter_func(void *, struct ieee80211_node *);
void rt2661_updatestats(void *);
+void rt2661_newassoc(struct ieee80211com *, struct ieee80211_node *,
+ int);
int rt2661_newstate(struct ieee80211com *, enum ieee80211_state,
int);
uint16_t rt2661_eeprom_read(struct rt2661_softc *, uint8_t);
@@ -204,8 +204,10 @@ rt2661_attach(void *xsc, int id)
sc->sc_id = id;
- timeout_set(&sc->scan_ch, rt2661_next_scan, sc);
- timeout_set(&sc->rssadapt_ch, rt2661_updatestats, sc);
+ sc->amrr.amrr_min_success_threshold = 1;
+ sc->amrr.amrr_max_success_threshold = 15;
+ timeout_set(&sc->amrr_to, rt2661_updatestats, sc);
+ timeout_set(&sc->scan_to, rt2661_next_scan, sc);
/* wait for NIC to initialize */
for (ntries = 0; ntries < 1000; ntries++) {
@@ -314,7 +316,7 @@ rt2661_attach(void *xsc, int id)
if_attach(ifp);
ieee80211_ifattach(ifp);
ic->ic_node_alloc = rt2661_node_alloc;
- ic->ic_node_copy = rt2661_node_copy;
+ ic->ic_newassoc = rt2661_newassoc;
ic->ic_updateslot = rt2661_updateslot;
/* override state transition machine */
@@ -365,8 +367,8 @@ rt2661_detach(void *xsc)
struct ifnet *ifp = &sc->sc_ic.ic_if;
int ac;
- timeout_del(&sc->scan_ch);
- timeout_del(&sc->rssadapt_ch);
+ timeout_del(&sc->scan_to);
+ timeout_del(&sc->amrr_to);
ieee80211_ifdetach(ifp); /* free all nodes */
if_detach(ifp);
@@ -695,19 +697,9 @@ rt2661_node_alloc(struct ieee80211com *ic)
struct rt2661_node *rn;
rn = malloc(sizeof (struct rt2661_node), M_DEVBUF, M_NOWAIT);
- if (rn == NULL)
- return NULL;
-
- memset(rn, 0, sizeof (struct rt2661_node));
-
- return &rn->ni;
-}
-
-void
-rt2661_node_copy(struct ieee80211com *ic, struct ieee80211_node *dst,
- const struct ieee80211_node *src)
-{
- *(struct rt2661_node *)dst = *(const struct rt2661_node *)src;
+ if (rn != NULL)
+ bzero(rn, sizeof (struct rt2661_node));
+ return (struct ieee80211_node *)rn;
}
int
@@ -735,9 +727,12 @@ rt2661_next_scan(void *arg)
struct rt2661_softc *sc = arg;
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = &ic->ic_if;
+ int s;
+ s = splnet();
if (ic->ic_state == IEEE80211_S_SCAN)
ieee80211_next_scan(ifp);
+ splx(s);
}
/*
@@ -746,13 +741,14 @@ rt2661_next_scan(void *arg)
void
rt2661_iter_func(void *arg, struct ieee80211_node *ni)
{
+ struct rt2661_softc *sc = arg;
struct rt2661_node *rn = (struct rt2661_node *)ni;
- ieee80211_rssadapt_updatestats(&rn->rssadapt);
+ ieee80211_amrr_choose(&sc->amrr, ni, &rn->amn);
}
/*
- * This function is called periodically (every 100ms) in RUN state to update
+ * This function is called periodically (every 500ms) in RUN state to update
* various settings like rate control statistics or Rx sensitivity.
*/
void
@@ -760,19 +756,35 @@ rt2661_updatestats(void *arg)
{
struct rt2661_softc *sc = arg;
struct ieee80211com *ic = &sc->sc_ic;
+ int s;
+ s = splnet();
if (ic->ic_opmode == IEEE80211_M_STA)
rt2661_iter_func(sc, ic->ic_bss);
else
ieee80211_iterate_nodes(ic, rt2661_iter_func, arg);
/* update rx sensitivity every 1 sec */
- if (++sc->ncalls == 10) {
+ if (++sc->ncalls & 1)
rt2661_rx_tune(sc);
- sc->ncalls = 0;
- }
+ splx(s);
+
+ timeout_add(&sc->amrr_to, hz / 2);
+}
+
+void
+rt2661_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
+{
+ struct rt2661_softc *sc = ic->ic_softc;
+ int i;
- timeout_add(&sc->rssadapt_ch, hz / 10);
+ ieee80211_amrr_node_init(&sc->amrr, &((struct rt2661_node *)ni)->amn);
+
+ /* set rate to some reasonable initial value */
+ for (i = ni->ni_rates.rs_nrates - 1;
+ i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
+ i--);
+ ni->ni_txrate = i;
}
int
@@ -785,11 +797,11 @@ rt2661_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
int error = 0;
ostate = ic->ic_state;
- timeout_del(&sc->scan_ch);
+ timeout_del(&sc->scan_to);
switch (nstate) {
case IEEE80211_S_INIT:
- timeout_del(&sc->rssadapt_ch);
+ timeout_del(&sc->amrr_to);
if (ostate == IEEE80211_S_RUN) {
/* abort TSF synchronization */
@@ -800,7 +812,7 @@ rt2661_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
case IEEE80211_S_SCAN:
rt2661_set_chan(sc, ic->ic_bss->ni_chan);
- timeout_add(&sc->scan_ch, hz / 5);
+ timeout_add(&sc->scan_to, hz / 5);
break;
case IEEE80211_S_AUTH:
@@ -825,10 +837,15 @@ rt2661_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
ic->ic_opmode == IEEE80211_M_IBSS)
rt2661_prepare_beacon(sc);
+ if (ic->ic_opmode == IEEE80211_M_STA) {
+ /* fake a join to init the tx rate */
+ rt2661_newassoc(ic, ni, 1);
+ }
+
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
sc->ncalls = 0;
sc->avg_rssi = -95; /* reset EMA */
- timeout_add(&sc->rssadapt_ch, hz / 10);
+ timeout_add(&sc->amrr_to, hz / 2);
rt2661_enable_tsf_sync(sc);
}
break;
@@ -929,20 +946,17 @@ rt2661_tx_intr(struct rt2661_softc *sc)
DPRINTFN(10, ("data frame sent successfully after "
"%d retries\n", retrycnt));
- if (retrycnt == 0 && data->id.id_node != NULL) {
- ieee80211_rssadapt_raise_rate(ic,
- &rn->rssadapt, &data->id);
- }
+ rn->amn.amn_txcnt++;
+ if (retrycnt > 0)
+ rn->amn.amn_retrycnt++;
ifp->if_opackets++;
break;
case RT2661_TX_RETRY_FAIL:
DPRINTFN(9, ("sending data frame failed (too much "
"retries)\n"));
- if (data->id.id_node != NULL) {
- ieee80211_rssadapt_lower_rate(ic, data->ni,
- &rn->rssadapt, &data->id);
- }
+ rn->amn.amn_txcnt++;
+ rn->amn.amn_retrycnt++;
ifp->if_oerrors++;
break;
@@ -1014,7 +1028,6 @@ rt2661_rx_intr(struct rt2661_softc *sc)
struct ifnet *ifp = &ic->ic_if;
struct rt2661_rx_desc *desc;
struct rt2661_rx_data *data;
- struct rt2661_node *rn;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *mnew, *m;
@@ -1134,12 +1147,7 @@ rt2661_rx_intr(struct rt2661_softc *sc)
ni = ieee80211_find_rxnode(ic, wh);
/* send the frame to the 802.11 layer */
- ieee80211_input(ifp, m, ni, desc->rssi, 0);
-
- /* give rssi to the rate adatation algorithm */
- rn = (struct rt2661_node *)ni;
- rssi = rt2661_get_rssi(sc, desc->rssi);
- ieee80211_rssadapt_input(ic, ni, &rn->rssadapt, rssi);
+ ieee80211_input(ifp, m, ni, rssi, 0);
/*-
* Keep track of the average RSSI using an Exponential Moving
@@ -1599,8 +1607,6 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
struct rt2661_tx_ring *txq = &sc->txq[ac];
struct rt2661_tx_desc *desc;
struct rt2661_tx_data *data;
- struct rt2661_node *rn;
- struct ieee80211_rateset *rs;
struct ieee80211_frame *wh;
struct mbuf *mnew;
uint16_t dur;
@@ -1609,24 +1615,12 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
wh = mtod(m0, struct ieee80211_frame *);
- /* XXX this should be reworked! */
if (ic->ic_fixed_rate != -1) {
- if (ic->ic_curmode != IEEE80211_MODE_AUTO)
- rs = &ic->ic_sup_rates[ic->ic_curmode];
- else
- rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];
-
- rate = rs->rs_rates[ic->ic_fixed_rate];
- } else {
- rs = &ni->ni_rates;
- rn = (struct rt2661_node *)ni;
- ni->ni_txrate = ieee80211_rssadapt_choose(&rn->rssadapt, rs,
- wh, m0->m_pkthdr.len, -1, NULL, 0);
- rate = rs->rs_rates[ni->ni_txrate];
- }
+ 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;
- if (rate == 0)
- rate = 2; /* fallback to 1Mbps; should not happen */
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
m0 = ieee80211_wep_crypt(ifp, m0, 1);
@@ -1696,9 +1690,6 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
data->m = m;
data->ni = ni;
- /* RTS frames are not taken into account for rssadapt */
- data->id.id_node = NULL;
-
rt2661_setup_tx_desc(sc, desc, RT2661_TX_NEED_ACK |
RT2661_TX_MORE_FRAG, 0, m->m_pkthdr.len, rtsrate,
data->map->dm_segs, data->map->dm_nsegs, ac);
@@ -1785,15 +1776,6 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
data->m = m0;
data->ni = ni;
- /* remember link conditions for rate control algorithm */
- if (ic->ic_fixed_rate == -1) {
- data->id.id_len = m0->m_pkthdr.len;
- data->id.id_rateidx = ni->ni_txrate;
- data->id.id_node = ni;
- data->id.id_rssi = ni->ni_rssi;
- } else
- data->id.id_node = NULL;
-
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
flags |= RT2661_TX_NEED_ACK;
@@ -2889,7 +2871,7 @@ rt2661_prepare_beacon(struct rt2661_softc *sc)
* Store offset of ERP Information Element so that we can update it
* dynamically when the slot time changes.
* XXX: this is ugly since it depends on how net80211 builds beacon
- * frames but ieee80211_beacon_alloc() don't store offsets for us.
+ * frames but ieee80211_beacon_alloc() doesn't store offsets for us.
*/
if (ic->ic_curmode == IEEE80211_MODE_11G) {
sc->erp_csr =