Exemplo n.º 1
0
void
ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
                     const struct ath_rc_series *rc, const struct ath_tx_status *ts,
                     int frame_size, int nframes, int nbad)
{
    struct amrr_node *amn = ATH_NODE_AMRR(an);
    int sr = ts->ts_shortretry;
    int lr = ts->ts_longretry;
    int retry_count = sr + lr;

    amn->amn_tx_try0_cnt++;
    if (retry_count == 1) {
        amn->amn_tx_try1_cnt++;
    } else if (retry_count == 2) {
        amn->amn_tx_try1_cnt++;
        amn->amn_tx_try2_cnt++;
    } else if (retry_count == 3) {
        amn->amn_tx_try1_cnt++;
        amn->amn_tx_try2_cnt++;
        amn->amn_tx_try3_cnt++;
    } else if (retry_count > 3) {
        amn->amn_tx_try1_cnt++;
        amn->amn_tx_try2_cnt++;
        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;
    }
}
Exemplo n.º 2
0
void
ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
	const struct ath_desc *ds, const struct ath_desc *ds0)
{
	struct amrr_node *amn = ATH_NODE_AMRR(an);
	int sr = ds->ds_txstat.ts_shortretry;
	int lr = ds->ds_txstat.ts_longretry;
	int retry_count = sr + lr;

	amn->amn_tx_try0_cnt++;
	if (retry_count == 1) {
		amn->amn_tx_try1_cnt++;
	} else if (retry_count == 2) {
		amn->amn_tx_try1_cnt++;
		amn->amn_tx_try2_cnt++;
	} else if (retry_count == 3) {
		amn->amn_tx_try1_cnt++;
		amn->amn_tx_try2_cnt++;
		amn->amn_tx_try3_cnt++;
	} else if (retry_count > 3) {
		amn->amn_tx_try1_cnt++;
		amn->amn_tx_try2_cnt++;
		amn->amn_tx_try3_cnt++;
		amn->amn_tx_failure_cnt++;
	}
}
Exemplo n.º 3
0
void
ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
	const struct ath_buf *bf)
{
	struct amrr_node *amn = ATH_NODE_AMRR(an);
	const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
	int sr = ts->ts_shortretry;
	int lr = ts->ts_longretry;
	int retry_count = sr + lr;

	amn->amn_tx_try0_cnt++;
	if (retry_count == 1) {
		amn->amn_tx_try1_cnt++;
	} else if (retry_count == 2) {
		amn->amn_tx_try1_cnt++;
		amn->amn_tx_try2_cnt++;
	} else if (retry_count == 3) {
		amn->amn_tx_try1_cnt++;
		amn->amn_tx_try2_cnt++;
		amn->amn_tx_try3_cnt++;
	} else if (retry_count > 3) {
		amn->amn_tx_try1_cnt++;
		amn->amn_tx_try2_cnt++;
		amn->amn_tx_try3_cnt++;
		amn->amn_tx_failure_cnt++;
	}
}
Exemplo n.º 4
0
void
ath_rate_node_copy(struct ath_softc *sc,
	struct ath_node *dst, const struct ath_node *src)
{
	struct amrr_node *adst = ATH_NODE_AMRR(dst);
	const struct amrr_node *asrc = (const struct amrr_node *)&src[1];

	memcpy(adst, asrc, sizeof(struct amrr_node));
}
Exemplo n.º 5
0
void
ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
                      struct ath_desc *ds, int shortPreamble, u_int8_t rix)
{
    struct amrr_node *amn = ATH_NODE_AMRR(an);

    ath_hal_setupxtxdesc(sc->sc_ah, ds
                         , amn->amn_tx_rate1sp, amn->amn_tx_try1	/* series 1 */
                         , amn->amn_tx_rate2sp, amn->amn_tx_try2	/* series 2 */
                         , amn->amn_tx_rate3sp, amn->amn_tx_try3	/* series 3 */
                        );
}
Exemplo n.º 6
0
void
ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
                  int shortPreamble, size_t frameLen,
                  u_int8_t *rix, int *try0, u_int8_t *txrate)
{
    struct amrr_node *amn = ATH_NODE_AMRR(an);

    *rix = amn->amn_tx_rix0;
    *try0 = amn->amn_tx_try0;
    if (shortPreamble)
        *txrate = amn->amn_tx_rate0sp;
    else
        *txrate = amn->amn_tx_rate0;
}
Exemplo n.º 7
0
/*
 * Get the TX rates.
 *
 * The short preamble bits aren't set here; the caller should augment
 * the returned rate with the relevant preamble rate flag.
 */
void
ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an,
                     uint8_t rix0, struct ath_rc_series *rc)
{
    struct amrr_node *amn = ATH_NODE_AMRR(an);

    rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0;

    rc[0].rix = amn->amn_tx_rate0;
    rc[1].rix = amn->amn_tx_rate1;
    rc[2].rix = amn->amn_tx_rate2;
    rc[3].rix = amn->amn_tx_rate3;

    rc[0].tries = amn->amn_tx_try0;
    rc[1].tries = amn->amn_tx_try1;
    rc[2].tries = amn->amn_tx_try2;
    rc[3].tries = amn->amn_tx_try3;
}
Exemplo n.º 8
0
/*
 * Examine and potentially adjust the transmit rate.
 */
static void
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 rix;

#define is_success(amn) \
(amn->amn_tx_try1_cnt  < (amn->amn_tx_try0_cnt/10))
#define is_enough(amn) \
(amn->amn_tx_try0_cnt > 10)
#define is_failure(amn) \
(amn->amn_tx_try1_cnt > (amn->amn_tx_try0_cnt/3))

    rix = amn->amn_rix;

    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 &&
                rix + 1 < ni->ni_rates.rs_nrates) {
            amn->amn_recovery = 1;
            amn->amn_success = 0;
            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 (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);
                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;
                IEEE80211_NOTE(ni->ni_vap,
                               IEEE80211_MSG_RATECTL, ni,
                               "decrease rate normal thr: %d",
                               amn->amn_success_threshold);
            }
            amn->amn_recovery = 0;
            rix--;
        } else {
            amn->amn_recovery = 0;
        }

    }
    if (is_enough (amn) || rix != amn->amn_rix) {
        /* reset counters. */
        amn->amn_tx_try0_cnt = 0;
        amn->amn_tx_try1_cnt = 0;
        amn->amn_tx_try2_cnt = 0;
        amn->amn_tx_try3_cnt = 0;
        amn->amn_tx_failure_cnt = 0;
    }
    if (rix != amn->amn_rix) {
        ath_rate_update(sc, ni, rix);
    }
}
Exemplo n.º 9
0
/**
 * The code below assumes that we are dealing with hardware multi rate retry
 * I have no idea what will happen if you try to use this module with another
 * type of hardware. Your machine might catch fire or it might work with
 * horrible performance...
 */
static void
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));

    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);

    amn->amn_rix = rate;
    /*
     * Before associating a node has no rate set setup
     * so we can't calculate any transmit codes to use.
     * This is ok since we should never be sending anything
     * but management frames and those always go at the
     * lowest hardware rate.
     */
    if (ni->ni_rates.rs_nrates > 0) {
        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;
        if (sc->sc_mrretry) {
            amn->amn_tx_try0 = 1;
            amn->amn_tx_try1 = 1;
            amn->amn_tx_try2 = 1;
            amn->amn_tx_try3 = 1;
            if (--rate >= 0) {
                rix = sc->sc_rixmap[
                          ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
                amn->amn_tx_rate1 = rt->info[rix].rateCode;
                amn->amn_tx_rate1sp = amn->amn_tx_rate1 |
                                      rt->info[rix].shortPreamble;
            } else {
                amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0;
            }
            if (--rate >= 0) {
                rix = sc->sc_rixmap[
                          ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
                amn->amn_tx_rate2 = rt->info[rix].rateCode;
                amn->amn_tx_rate2sp = amn->amn_tx_rate2 |
                                      rt->info[rix].shortPreamble;
            } else {
                amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0;
            }
            if (rate > 0) {
                /* NB: only do this if we didn't already do it above */
                amn->amn_tx_rate3 = rt->info[0].rateCode;
                amn->amn_tx_rate3sp =
                    amn->amn_tx_rate3 | rt->info[0].shortPreamble;
            } else {
                amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
            }
        } else {
            amn->amn_tx_try0 = ATH_TXMAXTRY;
            /* theorically, these statements are useless because
             *  the code which uses them tests for an_tx_try0 == ATH_TXMAXTRY
             */
            amn->amn_tx_try1 = 0;
            amn->amn_tx_try2 = 0;
            amn->amn_tx_try3 = 0;
            amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0;
            amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0;
            amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
        }
    }
    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;
}
Exemplo n.º 10
0
/* 
 * Examine and potentially adjust the transmit rate.
 */
static void
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;

#define is_success(amn) \
(amn->amn_tx_try1_cnt  < (amn->amn_tx_try0_cnt/10))
#define is_enough(amn) \
(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;
  
  	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);
  	if (is_success (amn) && is_enough (amn)) {
		amn->amn_success++;
		if (amn->amn_success == amn->amn_success_threshold &&
  		    !is_max_rate (ni)) {
  			amn->amn_recovery = 1;
  			amn->amn_success = 0;
  			ni->ni_txrate++;
			DPRINTF (sc, "increase rate to %d\n", ni->ni_txrate);
  		} else {
			amn->amn_recovery = 0;
		}
  	} else if (is_failure (amn)) {
  		amn->amn_success = 0;
  		if (!is_min_rate (ni)) {
  			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);
  			} else {
  				/* simple failure. */
 				amn->amn_success_threshold = ath_rate_min_success_threshold;
 				DPRINTF (sc, "decrease rate normal thr: %d\n", amn->amn_success_threshold);
  			}
			amn->amn_recovery = 0;
  			ni->ni_txrate--;
   		} else {
			amn->amn_recovery = 0;
		}

   	}
	if (is_enough (amn) || old_rate != ni->ni_txrate) {
		/* reset counters. */
		amn->amn_tx_try0_cnt = 0;
		amn->amn_tx_try1_cnt = 0;
		amn->amn_tx_try2_cnt = 0;
		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);
	}
}
Exemplo n.º 11
0
/**
 * The code below assumes that we are dealing with hardware multi rate retry
 * I have no idea what will happen if you try to use this module with another
 * type of hardware. Your machine might catch fire or it might work with
 * horrible performance...
 */
static void
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);
	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),
	    ni->ni_rates.rs_nrates > 0 ?
		(ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);

	ni->ni_txrate = rate;
	/* XXX management/control frames always go at the lowest speed */
	an->an_tx_mgtrate = rt->info[0].rateCode;
	an->an_tx_mgtratesp = an->an_tx_mgtrate | rt->info[0].shortPreamble;
	/*
	 * Before associating a node has no rate set setup
	 * so we can't calculate any transmit codes to use.
	 * This is ok since we should never be sending anything
	 * but management frames and those always go at the
	 * 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];
		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;
		if (sc->sc_mrretry) {
			amn->amn_tx_try0 = 1;
			amn->amn_tx_try1 = 1;
			amn->amn_tx_try2 = 1;
			amn->amn_tx_try3 = 1;
			if (--rate >= 0) {
				rix = sc->sc_rixmap[
						    ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
				amn->amn_tx_rate1 = rt->info[rix].rateCode;
				amn->amn_tx_rate1sp = amn->amn_tx_rate1 |
					rt->info[rix].shortPreamble;
			} else {
				amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0;
			}
			if (--rate >= 0) {
				rix = sc->sc_rixmap[
						    ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
				amn->amn_tx_rate2 = rt->info[rix].rateCode;
				amn->amn_tx_rate2sp = amn->amn_tx_rate2 |
					rt->info[rix].shortPreamble;
			} else {
				amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0;
			}
			if (rate > 0) {
				/* NB: only do this if we didn't already do it above */
				amn->amn_tx_rate3 = rt->info[0].rateCode;
				amn->amn_tx_rate3sp =
					an->an_tx_mgtrate | rt->info[0].shortPreamble;
			} else {
				amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
			}
		} else {
			amn->amn_tx_try0 = ATH_TXMAXTRY;
			/* theorically, these statements are useless because
			 *  the code which uses them tests for an_tx_try0 == ATH_TXMAXTRY
			 */
			amn->amn_tx_try1 = 0;
			amn->amn_tx_try2 = 0;
			amn->amn_tx_try3 = 0;
			amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0;
			amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0;
			amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0;
		}
	}
	node_reset (amn);
}
Exemplo n.º 12
0
		*txrate = amn->amn_tx_rate0sp;
	else
		*txrate = amn->amn_tx_rate0;
}

/*
 * Get the TX rates.
 *
 * The short preamble bits aren't set here; the caller should augment
 * the returned rate with the relevant preamble rate flag.
 */
void
ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an,
    uint8_t rix0, uint8_t *rix, uint8_t *try)
{
	struct amrr_node *amn = ATH_NODE_AMRR(an);

/*	rix[0] = amn->amn_tx_rate0; */
	rix[1] = amn->amn_tx_rate1;
	rix[2] = amn->amn_tx_rate2;
	rix[3] = amn->amn_tx_rate3;

	try[0] = amn->amn_tx_try0;
	try[1] = amn->amn_tx_try1;
	try[2] = amn->amn_tx_try2;
	try[3] = amn->amn_tx_try3;
}


void
ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,