Ejemplo n.º 1
0
void
ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
	const struct ath_buf *bf)
{
	struct ieee80211com *ic = &sc->sc_ic;
	struct sample_node *sn = ATH_NODE_SAMPLE(an);
	const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
	const struct ath_desc *ds0 = &bf->bf_desc[0];
	int final_rate, short_tries, long_tries, frame_size;
	int mrr;

	final_rate = sc->sc_hwmap[ts->ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
	short_tries = ts->ts_shortretry;
	long_tries = ts->ts_longretry + 1;
	frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
	if (frame_size == 0)		    /* NB: should not happen */
		frame_size = 1500;

	if (sn->num_rates <= 0) {
		DPRINTF(sc, ATH_DEBUG_RATE,
		    "%s: %s size %d %s rate/try %d/%d no rates yet\n", 
		    __func__, ether_sprintf(an->an_node.ni_macaddr),
		    bin_to_size(size_to_bin(frame_size)),
		    ts->ts_status ? "FAIL" : "OK",
		    short_tries, long_tries);
		return;
	}
	mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);
	if (!mrr || !(ts->ts_rate & HAL_TXSTAT_ALTRATE)) {
		int ndx = rate_to_ndx(sn, final_rate);

		/*
		 * Only one rate was used; optimize work.
		 */
		DPRINTF(sc, ATH_DEBUG_RATE,
		    "%s: %s size %d %s rate/try %d/%d/%d\n", 
		     __func__, ether_sprintf(an->an_node.ni_macaddr),
		     bin_to_size(size_to_bin(frame_size)),
		     ts->ts_status ? "FAIL" : "OK",
		     final_rate, short_tries, long_tries);
		update_stats(sc, an, frame_size, 
			     ndx, long_tries,
			     0, 0,
			     0, 0,
			     0, 0,
			     short_tries, long_tries, ts->ts_status);
	} else {
		int hwrate0, rate0, tries0, ndx0;
		int hwrate1, rate1, tries1, ndx1;
		int hwrate2, rate2, tries2, ndx2;
		int hwrate3, rate3, tries3, ndx3;
		int finalTSIdx = ts->ts_finaltsi;

		/*
		 * Process intermediate rates that failed.
		 */
		if (sc->sc_ah->ah_magic != 0x20065416) {
			hwrate0 = MS(ds0->ds_ctl3, AR_XmitRate0);
			hwrate1 = MS(ds0->ds_ctl3, AR_XmitRate1);
			hwrate2 = MS(ds0->ds_ctl3, AR_XmitRate2);
			hwrate3 = MS(ds0->ds_ctl3, AR_XmitRate3);
		} else {
			hwrate0 = MS(ds0->ds_ctl3, AR5416_XmitRate0);
			hwrate1 = MS(ds0->ds_ctl3, AR5416_XmitRate1);
			hwrate2 = MS(ds0->ds_ctl3, AR5416_XmitRate2);
			hwrate3 = MS(ds0->ds_ctl3, AR5416_XmitRate3);
		}

		rate0 = sc->sc_hwmap[hwrate0].ieeerate;
		tries0 = MS(ds0->ds_ctl2, AR_XmitDataTries0);
		ndx0 = rate_to_ndx(sn, rate0);

		rate1 = sc->sc_hwmap[hwrate1].ieeerate;
		tries1 = MS(ds0->ds_ctl2, AR_XmitDataTries1);
		ndx1 = rate_to_ndx(sn, rate1);

		rate2 = sc->sc_hwmap[hwrate2].ieeerate;
		tries2 = MS(ds0->ds_ctl2, AR_XmitDataTries2);
		ndx2 = rate_to_ndx(sn, rate2);

		rate3 = sc->sc_hwmap[hwrate3].ieeerate;
		tries3 = MS(ds0->ds_ctl2, AR_XmitDataTries3);
		ndx3 = rate_to_ndx(sn, rate3);

		DPRINTF(sc, ATH_DEBUG_RATE,
"%s: %s size %d finaltsidx %d tries %d %s rate/try [%d/%d %d/%d %d/%d %d/%d]\n", 
		     __func__, ether_sprintf(an->an_node.ni_macaddr),
		     bin_to_size(size_to_bin(frame_size)),
		     finalTSIdx,
		     long_tries, 
		     ts->ts_status ? "FAIL" : "OK",
		     rate0, tries0,
		     rate1, tries1,
		     rate2, tries2,
		     rate3, tries3);

		/*
		 * NB: series > 0 are not penalized for failure
		 * based on the try counts under the assumption
		 * that losses are often bursty and since we
		 * sample higher rates 1 try at a time doing so
		 * may unfairly penalize them.
		 */
		if (tries0) {
			update_stats(sc, an, frame_size, 
				     ndx0, tries0, 
				     ndx1, tries1, 
				     ndx2, tries2, 
				     ndx3, tries3, 
				     short_tries, long_tries, 
				     long_tries > tries0);
			long_tries -= tries0;
		}
		
		if (tries1 && finalTSIdx > 0) {
			update_stats(sc, an, frame_size, 
				     ndx1, tries1, 
				     ndx2, tries2, 
				     ndx3, tries3, 
				     0, 0, 
				     short_tries, long_tries, 
				     ts->ts_status);
			long_tries -= tries1;
		}

		if (tries2 && finalTSIdx > 1) {
			update_stats(sc, an, frame_size, 
				     ndx2, tries2, 
				     ndx3, tries3, 
				     0, 0,
				     0, 0,
				     short_tries, long_tries, 
				     ts->ts_status);
			long_tries -= tries2;
		}

		if (tries3 && finalTSIdx > 2) {
			update_stats(sc, an, frame_size, 
				     ndx3, tries3, 
				     0, 0,
				     0, 0,
				     0, 0,
				     short_tries, long_tries, 
				     ts->ts_status);
		}
	}
}
Ejemplo 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 ieee80211com *ic = &sc->sc_ic;
	struct sample_node *sn = ATH_NODE_SAMPLE(an);
	const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0;
	int final_rate, short_tries, long_tries, frame_size;
	int ndx = -1;
	int mrr;

	final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
	short_tries = ds->ds_txstat.ts_shortretry + 1;
	long_tries = ds->ds_txstat.ts_longretry + 1;
	frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
	if (frame_size == 0)		    /* NB: should not happen */
		frame_size = 1500;

	if (sn->num_rates <= 0) {
		DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d "
			"no rates yet\n", 
			__func__, ether_sprintf(an->an_node.ni_macaddr),
			bin_to_size(size_to_bin(frame_size)),
			ds->ds_txstat.ts_status,
			short_tries, long_tries);
		return;
	}

	mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);

	if (sc->sc_mrretry && ds->ds_txstat.ts_status) {
		/* this packet failed */
		DPRINTF(sc, "%s: %s size %d rate/try %d/%d %d/%d %d/%d %d/%d status %s retries (%d/%d)\n", 
			__func__,
			ether_sprintf(an->an_node.ni_macaddr),
			bin_to_size(size_to_bin(frame_size)),
			sc->sc_hwmap[ads->xmit_rate0].ieeerate,
				ads->xmit_tries0,
			sc->sc_hwmap[ads->xmit_rate1].ieeerate,
				ads->xmit_tries1,
			sc->sc_hwmap[ads->xmit_rate2].ieeerate,
				ads->xmit_tries2,
			sc->sc_hwmap[ads->xmit_rate3].ieeerate,
				ads->xmit_tries3,
			ds->ds_txstat.ts_status ? "FAIL" : "OK",
			short_tries, 
			long_tries);
	}

	if (!mrr || !(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) {
		/* only one rate was used */
		ndx = rate_to_ndx(sn, final_rate);
		DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d/%d\n", 
			__func__, ether_sprintf(an->an_node.ni_macaddr),
			bin_to_size(size_to_bin(frame_size)),
			ds->ds_txstat.ts_status,
			ndx, short_tries, long_tries);
		if (ndx >= 0 && ndx < sn->num_rates) {
			update_stats(sc, an, frame_size, 
				     ndx, long_tries,
				     0, 0,
				     0, 0,
				     0, 0,
				     short_tries, long_tries, ds->ds_txstat.ts_status);
		}
	} else {
		int rate0, tries0, ndx0;
		int rate1, tries1, ndx1;
		int rate2, tries2, ndx2;
		int rate3, tries3, ndx3;
		int finalTSIdx = ads->final_ts_index;

		/*
		 * Process intermediate rates that failed.
		 */

		rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate;
		tries0 = ads->xmit_tries0;
		ndx0 = rate_to_ndx(sn, rate0);
		
		rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate;
		tries1 = ads->xmit_tries1;
		ndx1 = rate_to_ndx(sn, rate1);
		
		rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate;
		tries2 = ads->xmit_tries2;
		ndx2 = rate_to_ndx(sn, rate2);
		
		rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate;
		tries3 = ads->xmit_tries3;
		ndx3 = rate_to_ndx(sn, rate3);
		
#if 1
		DPRINTF(sc, "%s: %s size %d finaltsidx %d tries %d status %d rate/try %d/%d %d/%d %d/%d %d/%d\n", 
			__func__, ether_sprintf(an->an_node.ni_macaddr),
			bin_to_size(size_to_bin(frame_size)),
			finalTSIdx,
			long_tries, 
			ds->ds_txstat.ts_status,
			rate0, tries0,
			rate1, tries1,
			rate2, tries2,
			rate3, tries3);
#endif

		if (tries0) {
			update_stats(sc, an, frame_size, 
				     ndx0, tries0, 
				     ndx1, tries1, 
				     ndx2, tries2, 
				     ndx3, tries3, 
				     short_tries, ds->ds_txstat.ts_longretry + 1, 
				     long_tries > tries0);
		}
		
		if (tries1 && finalTSIdx > 0) {
			update_stats(sc, an, frame_size, 
				     ndx1, tries1, 
				     ndx2, tries2, 
				     ndx3, tries3, 
				     0, 0, 
				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0, 
				     ds->ds_txstat.ts_status);
		}

		if (tries2 && finalTSIdx > 1) {
			update_stats(sc, an, frame_size, 
				     ndx2, tries2, 
				     ndx3, tries3, 
				     0, 0,
				     0, 0,
				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1, 
				     ds->ds_txstat.ts_status);
		}

		if (tries3 && finalTSIdx > 2) {
			update_stats(sc, an, frame_size, 
				     ndx3, tries3, 
				     0, 0,
				     0, 0,
				     0, 0,
				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1 - tries2, 
				     ds->ds_txstat.ts_status);
		}
	}
}