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 ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; struct sample_node *sn = ATH_NODE_SAMPLE(an); int final_rix, short_tries, long_tries; const HAL_RATE_TABLE *rt = sc->sc_currates; int status = ts->ts_status; int mrr; final_rix = rt->rateCodeToIndex[ts->ts_rate]; short_tries = ts->ts_shortretry; long_tries = ts->ts_longretry + 1; if (frame_size == 0) /* NB: should not happen */ frame_size = 1500; if (sn->ratemask == 0) { IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: size %d %s rate/try %d/%d no rates yet", __func__, bin_to_size(size_to_bin(frame_size)), status ? "FAIL" : "OK", short_tries, long_tries); return; } mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT); if (!mrr || ts->ts_finaltsi == 0) { if (!IS_RATE_DEFINED(sn, final_rix)) { badrate(ifp, 0, ts->ts_rate, long_tries, status); return; } /* * Only one rate was used; optimize work. */ IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: size %d (%d bytes) %s rate/try %d %s/%d/%d nframes/nbad [%d/%d]", __func__, bin_to_size(size_to_bin(frame_size)), frame_size, status ? "FAIL" : "OK", dot11rate(rt, final_rix), dot11rate_label(rt, final_rix), short_tries, long_tries, nframes, nbad); update_stats(sc, an, frame_size, final_rix, long_tries, 0, 0, 0, 0, 0, 0, short_tries, long_tries, status, nframes, nbad); update_ewma_stats(sc, an, frame_size, final_rix, long_tries, 0, 0, 0, 0, 0, 0, short_tries, long_tries, status, nframes, nbad); } else { int finalTSIdx = ts->ts_finaltsi; int i; /* * Process intermediate rates that failed. */ IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: size %d (%d bytes) finaltsidx %d tries %d %s rate/try [%d %s/%d %d %s/%d %d %s/%d %d %s/%d] nframes/nbad [%d/%d]", __func__, bin_to_size(size_to_bin(frame_size)), frame_size, finalTSIdx, long_tries, status ? "FAIL" : "OK", dot11rate(rt, rc[0].rix), dot11rate_label(rt, rc[0].rix), rc[0].tries, dot11rate(rt, rc[1].rix), dot11rate_label(rt, rc[1].rix), rc[1].tries, dot11rate(rt, rc[2].rix), dot11rate_label(rt, rc[2].rix), rc[2].tries, dot11rate(rt, rc[3].rix), dot11rate_label(rt, rc[3].rix), rc[3].tries, nframes, nbad); for (i = 0; i < 4; i++) { if (rc[i].tries && !IS_RATE_DEFINED(sn, rc[i].rix)) badrate(ifp, 0, rc[i].ratecode, rc[i].tries, status); } /* * 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 (rc[0].tries) { update_stats(sc, an, frame_size, rc[0].rix, rc[0].tries, rc[1].rix, rc[1].tries, rc[2].rix, rc[2].tries, rc[3].rix, rc[3].tries, short_tries, long_tries, long_tries > rc[0].tries, nframes, nbad); long_tries -= rc[0].tries; } if (rc[1].tries && finalTSIdx > 0) { update_stats(sc, an, frame_size, rc[1].rix, rc[1].tries, rc[2].rix, rc[2].tries, rc[3].rix, rc[3].tries, 0, 0, short_tries, long_tries, status, nframes, nbad); long_tries -= rc[1].tries; } if (rc[2].tries && finalTSIdx > 1) { update_stats(sc, an, frame_size, rc[2].rix, rc[2].tries, rc[3].rix, rc[3].tries, 0, 0, 0, 0, short_tries, long_tries, status, nframes, nbad); long_tries -= rc[2].tries; } if (rc[3].tries && finalTSIdx > 2) { update_stats(sc, an, frame_size, rc[3].rix, rc[3].tries, 0, 0, 0, 0, 0, 0, short_tries, long_tries, status, nframes, nbad); } update_ewma_stats(sc, an, frame_size, rc[0].rix, rc[0].tries, rc[1].rix, rc[1].tries, rc[2].rix, rc[2].tries, rc[3].rix, rc[3].tries, short_tries, long_tries, long_tries > rc[0].tries, nframes, nbad); } }
void ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, const struct ath_buf *bf) { struct ifnet *ifp = sc->sc_ifp; struct ieee80211com *ic = ifp->if_l2com; 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_rix, short_tries, long_tries, frame_size; const HAL_RATE_TABLE *rt = sc->sc_currates; int mrr; final_rix = rt->rateCodeToIndex[ts->ts_rate]; 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->ratemask == 0) { IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: size %d %s rate/try %d/%d no rates yet", __func__, 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_finaltsi == 0) { if (!IS_RATE_DEFINED(sn, final_rix)) { badrate(ifp, 0, ts->ts_rate, long_tries, ts->ts_status); return; } /* * Only one rate was used; optimize work. */ IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: size %d %s rate/try %d/%d/%d", __func__, bin_to_size(size_to_bin(frame_size)), ts->ts_status ? "FAIL" : "OK", final_rix, short_tries, long_tries); update_stats(sc, an, frame_size, final_rix, long_tries, 0, 0, 0, 0, 0, 0, short_tries, long_tries, ts->ts_status); } else { int hwrate0, rix0, tries0; int hwrate1, rix1, tries1; int hwrate2, rix2, tries2; int hwrate3, rix3, tries3; 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); } rix0 = rt->rateCodeToIndex[hwrate0]; tries0 = MS(ds0->ds_ctl2, AR_XmitDataTries0); rix1 = rt->rateCodeToIndex[hwrate1]; tries1 = MS(ds0->ds_ctl2, AR_XmitDataTries1); rix2 = rt->rateCodeToIndex[hwrate2]; tries2 = MS(ds0->ds_ctl2, AR_XmitDataTries2); rix3 = rt->rateCodeToIndex[hwrate3]; tries3 = MS(ds0->ds_ctl2, AR_XmitDataTries3); IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, &an->an_node, "%s: size %d finaltsidx %d tries %d %s rate/try [%d/%d %d/%d %d/%d %d/%d]", __func__, bin_to_size(size_to_bin(frame_size)), finalTSIdx, long_tries, ts->ts_status ? "FAIL" : "OK", rix0, tries0, rix1, tries1, rix2, tries2, rix3, tries3); if (tries0 && !IS_RATE_DEFINED(sn, rix0)) badrate(ifp, 0, hwrate0, tries0, ts->ts_status); if (tries1 && !IS_RATE_DEFINED(sn, rix1)) badrate(ifp, 1, hwrate1, tries1, ts->ts_status); if (tries2 && !IS_RATE_DEFINED(sn, rix2)) badrate(ifp, 2, hwrate2, tries2, ts->ts_status); if (tries3 && !IS_RATE_DEFINED(sn, rix3)) badrate(ifp, 3, hwrate3, tries3, ts->ts_status); /* * 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, rix0, tries0, rix1, tries1, rix2, tries2, rix3, tries3, short_tries, long_tries, long_tries > tries0); long_tries -= tries0; } if (tries1 && finalTSIdx > 0) { update_stats(sc, an, frame_size, rix1, tries1, rix2, tries2, rix3, tries3, 0, 0, short_tries, long_tries, ts->ts_status); long_tries -= tries1; } if (tries2 && finalTSIdx > 1) { update_stats(sc, an, frame_size, rix2, tries2, rix3, 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, rix3, tries3, 0, 0, 0, 0, 0, 0, short_tries, long_tries, ts->ts_status); } } }