summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath/ath_rate/amrr/amrr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ath/ath_rate/amrr/amrr.c')
-rw-r--r--sys/dev/ath/ath_rate/amrr/amrr.c146
1 files changed, 53 insertions, 93 deletions
diff --git a/sys/dev/ath/ath_rate/amrr/amrr.c b/sys/dev/ath/ath_rate/amrr/amrr.c
index 00ae568..c230bdf 100644
--- a/sys/dev/ath/ath_rate/amrr/amrr.c
+++ b/sys/dev/ath/ath_rate/amrr/amrr.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
* Mathieu Lacage, Hossein Manshaei, Thierry Turletti
*/
#include "opt_inet.h"
+#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -65,7 +66,6 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_arp.h>
-#include <net/ethernet.h> /* XXX for ether_sprintf */
#include <net80211/ieee80211_var.h>
@@ -80,21 +80,10 @@ __FBSDID("$FreeBSD$");
#include <dev/ath/ath_rate/amrr/amrr.h>
#include <contrib/dev/ath/ah_desc.h>
-#define AMRR_DEBUG
-#ifdef AMRR_DEBUG
-#define DPRINTF(sc, _fmt, ...) do { \
- if (sc->sc_debug & 0x10) \
- printf(_fmt, __VA_ARGS__); \
-} while (0)
-#else
-#define DPRINTF(sc, _fmt, ...)
-#endif
-
static int ath_rateinterval = 1000; /* rate ctl interval (ms) */
static int ath_rate_max_success_threshold = 10;
static int ath_rate_min_success_threshold = 1;
-static void ath_ratectl(void *);
static void ath_rate_update(struct ath_softc *, struct ieee80211_node *,
int rate);
static void ath_rate_ctl_start(struct ath_softc *, struct ieee80211_node *);
@@ -104,7 +93,6 @@ void
ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
{
/* NB: assumed to be zero'd by caller */
- ath_rate_update(sc, &an->an_node, 0);
}
void
@@ -166,6 +154,11 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
amn->amn_tx_try3_cnt++;
amn->amn_tx_failure_cnt++;
}
+ if (amn->amn_interval != 0 &&
+ ticks - amn->amn_ticks > amn->amn_interval) {
+ ath_rate_ctl(sc, &an->an_node);
+ amn->amn_ticks = ticks;
+ }
}
void
@@ -176,7 +169,7 @@ ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
}
static void
-node_reset (struct amrr_node *amn)
+node_reset(struct amrr_node *amn)
{
amn->amn_tx_try0_cnt = 0;
amn->amn_tx_try1_cnt = 0;
@@ -200,17 +193,18 @@ ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
{
struct ath_node *an = ATH_NODE(ni);
struct amrr_node *amn = ATH_NODE_AMRR(an);
+ struct ieee80211vap *vap = ni->ni_vap;
const HAL_RATE_TABLE *rt = sc->sc_currates;
u_int8_t rix;
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
- DPRINTF(sc, "%s: set xmit rate for %s to %dM\n",
- __func__, ether_sprintf(ni->ni_macaddr),
+ IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL, ni,
+ "%s: set xmit rate to %dM", __func__,
ni->ni_rates.rs_nrates > 0 ?
(ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);
- ni->ni_txrate = rate;
+ amn->amn_rix = rate;
/*
* Before associating a node has no rate set setup
* so we can't calculate any transmit codes to use.
@@ -219,8 +213,8 @@ ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
* lowest hardware rate.
*/
if (ni->ni_rates.rs_nrates > 0) {
- amn->amn_tx_rix0 = sc->sc_rixmap[
- ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL];
+ ni->ni_txrate = ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL;
+ amn->amn_tx_rix0 = sc->sc_rixmap[ni->ni_txrate];
amn->amn_tx_rate0 = rt->info[amn->amn_tx_rix0].rateCode;
amn->amn_tx_rate0sp = amn->amn_tx_rate0 |
rt->info[amn->amn_tx_rix0].shortPreamble;
@@ -268,7 +262,12 @@ ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
}
}
- node_reset (amn);
+ node_reset(amn);
+
+ amn->amn_interval = ath_rateinterval;
+ if (vap->iv_opmode == IEEE80211_M_STA)
+ amn->amn_interval /= 2;
+ amn->amn_interval = (amn->amn_interval * hz) / 1000;
}
/*
@@ -278,11 +277,12 @@ static void
ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni)
{
#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ath_node *an = ATH_NODE(ni);
+ const struct ieee80211_txparam *tp = an->an_tp;
int srate;
KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates"));
- if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
+ if (tp == NULL || tp->ucastrate == IEEE80211_FIXED_RATE_NONE) {
/*
* No fixed rate is requested. For 11b start with
* the highest negotiated rate; otherwise, for 11g
@@ -308,7 +308,7 @@ ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni)
*/
/* NB: the rate set is assumed sorted */
srate = ni->ni_rates.rs_nrates - 1;
- for (; srate >= 0 && RATE(srate) != ic->ic_fixed_rate; srate--)
+ for (; srate >= 0 && RATE(srate) != tp->ucastrate; srate--)
;
}
/*
@@ -333,22 +333,20 @@ ath_rate_cb(void *arg, struct ieee80211_node *ni)
* Reset the rate control state for each 802.11 state transition.
*/
void
-ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state)
+ath_rate_newstate(struct ieee80211vap *vap, enum ieee80211_state state)
{
- struct amrr_softc *asc = (struct amrr_softc *) sc->sc_rc;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ieee80211_node *ni;
- if (state == IEEE80211_S_INIT) {
- callout_stop(&asc->timer);
+ if (state == IEEE80211_S_INIT)
return;
- }
- if (ic->ic_opmode == IEEE80211_M_STA) {
+ if (vap->iv_opmode == IEEE80211_M_STA) {
/*
* Reset local xmit state; this is really only
* meaningful when operating in station mode.
*/
- ni = ic->ic_bss;
+ ni = vap->iv_bss;
if (state == IEEE80211_S_RUN) {
ath_rate_ctl_start(sc, ni);
} else {
@@ -362,20 +360,7 @@ ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state)
* tx rate state of each node.
*/
ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, sc);
- ath_rate_update(sc, ic->ic_bss, 0);
- }
- if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE &&
- state == IEEE80211_S_RUN) {
- int interval;
- /*
- * Start the background rate control thread if we
- * are not configured to use a fixed xmit rate.
- */
- interval = ath_rateinterval;
- if (ic->ic_opmode == IEEE80211_M_STA)
- interval /= 2;
- callout_reset(&asc->timer, (interval * hz) / 1000,
- ath_ratectl, sc->sc_ifp);
+ ath_rate_update(sc, vap->iv_bss, 0);
}
}
@@ -387,7 +372,7 @@ ath_rate_ctl(void *arg, struct ieee80211_node *ni)
{
struct ath_softc *sc = arg;
struct amrr_node *amn = ATH_NODE_AMRR(ATH_NODE (ni));
- int old_rate;
+ int rix;
#define is_success(amn) \
(amn->amn_tx_try1_cnt < (amn->amn_tx_try0_cnt/10))
@@ -395,52 +380,53 @@ ath_rate_ctl(void *arg, struct ieee80211_node *ni)
(amn->amn_tx_try0_cnt > 10)
#define is_failure(amn) \
(amn->amn_tx_try1_cnt > (amn->amn_tx_try0_cnt/3))
-#define is_max_rate(ni) \
-((ni->ni_txrate + 1) >= ni->ni_rates.rs_nrates)
-#define is_min_rate(ni) \
-(ni->ni_txrate == 0)
- old_rate = ni->ni_txrate;
+ rix = amn->amn_rix;
- DPRINTF (sc, "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d\n",
- amn->amn_tx_try0_cnt,
- amn->amn_tx_try1_cnt,
- amn->amn_tx_try2_cnt,
- amn->amn_tx_try3_cnt,
- amn->amn_success_threshold);
+ IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
+ "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d",
+ amn->amn_tx_try0_cnt, amn->amn_tx_try1_cnt, amn->amn_tx_try2_cnt,
+ amn->amn_tx_try3_cnt, amn->amn_success_threshold);
if (is_success (amn) && is_enough (amn)) {
amn->amn_success++;
if (amn->amn_success == amn->amn_success_threshold &&
- !is_max_rate (ni)) {
+ rix + 1 < ni->ni_rates.rs_nrates) {
amn->amn_recovery = 1;
amn->amn_success = 0;
- ni->ni_txrate++;
- DPRINTF (sc, "increase rate to %d\n", ni->ni_txrate);
+ rix++;
+ IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
+ "increase rate to %d", rix);
} else {
amn->amn_recovery = 0;
}
} else if (is_failure (amn)) {
amn->amn_success = 0;
- if (!is_min_rate (ni)) {
+ if (rix > 0) {
if (amn->amn_recovery) {
/* recovery failure. */
amn->amn_success_threshold *= 2;
amn->amn_success_threshold = min (amn->amn_success_threshold,
(u_int)ath_rate_max_success_threshold);
- DPRINTF (sc, "decrease rate recovery thr: %d\n", amn->amn_success_threshold);
+ IEEE80211_NOTE(ni->ni_vap,
+ IEEE80211_MSG_RATECTL, ni,
+ "decrease rate recovery thr: %d",
+ amn->amn_success_threshold);
} else {
/* simple failure. */
amn->amn_success_threshold = ath_rate_min_success_threshold;
- DPRINTF (sc, "decrease rate normal thr: %d\n", amn->amn_success_threshold);
+ IEEE80211_NOTE(ni->ni_vap,
+ IEEE80211_MSG_RATECTL, ni,
+ "decrease rate normal thr: %d",
+ amn->amn_success_threshold);
}
amn->amn_recovery = 0;
- ni->ni_txrate--;
+ rix--;
} else {
amn->amn_recovery = 0;
}
}
- if (is_enough (amn) || old_rate != ni->ni_txrate) {
+ if (is_enough (amn) || rix != amn->amn_rix) {
/* reset counters. */
amn->amn_tx_try0_cnt = 0;
amn->amn_tx_try1_cnt = 0;
@@ -448,33 +434,9 @@ ath_rate_ctl(void *arg, struct ieee80211_node *ni)
amn->amn_tx_try3_cnt = 0;
amn->amn_tx_failure_cnt = 0;
}
- if (old_rate != ni->ni_txrate) {
- ath_rate_update(sc, ni, ni->ni_txrate);
- }
-}
-
-static void
-ath_ratectl(void *arg)
-{
- struct ifnet *ifp = arg;
- struct ath_softc *sc = ifp->if_softc;
- struct amrr_softc *asc = (struct amrr_softc *) sc->sc_rc;
- struct ieee80211com *ic = &sc->sc_ic;
- int interval;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- sc->sc_stats.ast_rate_calls++;
-
- if (ic->ic_opmode == IEEE80211_M_STA)
- ath_rate_ctl(sc, ic->ic_bss); /* NB: no reference */
- else
- ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_ctl, sc);
+ if (rix != amn->amn_rix) {
+ ath_rate_update(sc, ni, rix);
}
- interval = ath_rateinterval;
- if (ic->ic_opmode == IEEE80211_M_STA)
- interval /= 2;
- callout_reset(&asc->timer, (interval * hz) / 1000,
- ath_ratectl, sc->sc_ifp);
}
static void
@@ -504,7 +466,6 @@ ath_rate_attach(struct ath_softc *sc)
if (asc == NULL)
return NULL;
asc->arc.arc_space = sizeof(struct amrr_node);
- callout_init(&asc->timer, CALLOUT_MPSAFE);
ath_rate_sysctlattach(sc);
return &asc->arc;
@@ -515,7 +476,6 @@ ath_rate_detach(struct ath_ratectrl *arc)
{
struct amrr_softc *asc = (struct amrr_softc *) arc;
- callout_drain(&asc->timer);
free(asc, M_DEVBUF);
}
OpenPOWER on IntegriCloud