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