Index: sys/dev/bwi/if_bwi.c =================================================================== --- sys/dev/bwi/if_bwi.c +++ sys/dev/bwi/if_bwi.c @@ -3321,7 +3321,6 @@ struct bwi_txbuf *tb; int ring_idx, buf_idx; struct ieee80211_node *ni; - struct ieee80211vap *vap; if (tx_id == 0) { device_printf(sc->sc_dev, "%s: zero tx id\n", __func__); @@ -3348,7 +3347,7 @@ if ((ni = tb->tb_ni) != NULL) { const struct bwi_txbuf_hdr *hdr = mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *); - vap = ni->ni_vap; + struct ieee80211_ratectl_tx_status txs; /* NB: update rate control only for unicast frames */ if (hdr->txh_mac_ctrl & htole32(BWI_TXH_MAC_C_ACK)) { @@ -3359,9 +3358,15 @@ * well so to avoid over-aggressive downshifting we * treat any number of retries as "1". */ - ieee80211_ratectl_tx_complete(vap, ni, - (data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS : - IEEE80211_RATECTL_TX_FAILURE, &acked, NULL); + txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY; + txs.long_retries = acked; + if (data_txcnt > 1) + txs.status = IEEE80211_RATECTL_TX_SUCCESS; + else { + txs.status = + IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; + } + ieee80211_ratectl_tx_complete(ni, &txs); } ieee80211_tx_complete(ni, tb->tb_mbuf, !acked); tb->tb_ni = NULL; Index: sys/dev/bwn/if_bwn.c =================================================================== --- sys/dev/bwn/if_bwn.c +++ sys/dev/bwn/if_bwn.c @@ -258,6 +258,8 @@ static void bwn_dma_buf_addr(void *, bus_dma_segment_t *, int, bus_size_t, int); static uint8_t bwn_dma_check_redzone(struct bwn_dma_ring *, struct mbuf *); +static void bwn_ratectl_tx_complete(const struct ieee80211_node *, + const struct bwn_txstatus *); static void bwn_dma_handle_txeof(struct bwn_mac *, const struct bwn_txstatus *); static int bwn_dma_tx_start(struct bwn_mac *, struct ieee80211_node *, @@ -5891,6 +5893,33 @@ } static void +bwn_ratectl_tx_complete(const struct ieee80211_node *ni, + const struct bwn_txstatus *status) +{ + struct ieee80211_ratectl_tx_status txs; + int retrycnt = 0; + + /* + * If we don't get an ACK, then we should log the + * full framecnt. That may be 0 if it's a PHY + * failure, so ensure that gets logged as some + * retry attempt. + */ + txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY; + if (status->ack) { + txs.status = IEEE80211_RATECTL_TX_SUCCESS; + retrycnt = status->framecnt - 1; + } else { + txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; + retrycnt = status->framecnt; + if (retrycnt == 0) + retrycnt = 1; + } + txs.long_retries = retrycnt; + ieee80211_ratectl_tx_complete(ni, &txs); +} + +static void bwn_dma_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status) { @@ -5900,7 +5929,6 @@ struct bwn_dmadesc_meta *meta; struct bwn_softc *sc = mac->mac_sc; int slot; - int retrycnt = 0; BWN_ASSERT_LOCKED(sc); @@ -5925,24 +5953,7 @@ KASSERT(meta->mt_m != NULL, ("%s:%d: fail", __func__, __LINE__)); - /* - * If we don't get an ACK, then we should log the - * full framecnt. That may be 0 if it's a PHY - * failure, so ensure that gets logged as some - * retry attempt. - */ - if (status->ack) { - retrycnt = status->framecnt - 1; - } else { - retrycnt = status->framecnt; - if (retrycnt == 0) - retrycnt = 1; - } - ieee80211_ratectl_tx_complete(meta->mt_ni->ni_vap, meta->mt_ni, - status->ack ? - IEEE80211_RATECTL_TX_SUCCESS : - IEEE80211_RATECTL_TX_FAILURE, - &retrycnt, 0); + bwn_ratectl_tx_complete(meta->mt_ni, status); ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0); meta->mt_ni = NULL; meta->mt_m = NULL; @@ -5970,7 +5981,6 @@ struct bwn_pio_txqueue *tq; struct bwn_pio_txpkt *tp = NULL; struct bwn_softc *sc = mac->mac_sc; - int retrycnt = 0; BWN_ASSERT_LOCKED(sc); @@ -5981,31 +5991,14 @@ tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4); tq->tq_free++; + /* XXX ieee80211_tx_complete()? */ if (tp->tp_ni != NULL) { /* * Do any tx complete callback. Note this must * be done before releasing the node reference. */ - /* - * If we don't get an ACK, then we should log the - * full framecnt. That may be 0 if it's a PHY - * failure, so ensure that gets logged as some - * retry attempt. - */ - if (status->ack) { - retrycnt = status->framecnt - 1; - } else { - retrycnt = status->framecnt; - if (retrycnt == 0) - retrycnt = 1; - } - ieee80211_ratectl_tx_complete(tp->tp_ni->ni_vap, tp->tp_ni, - status->ack ? - IEEE80211_RATECTL_TX_SUCCESS : - IEEE80211_RATECTL_TX_FAILURE, - &retrycnt, 0); - + bwn_ratectl_tx_complete(tp->tp_ni, status); if (tp->tp_m->m_flags & M_TXCB) ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0); ieee80211_free_node(tp->tp_ni); Index: sys/dev/iwm/if_iwm.c =================================================================== --- sys/dev/iwm/if_iwm.c +++ sys/dev/iwm/if_iwm.c @@ -3027,10 +3027,9 @@ struct iwm_node *in) { struct iwm_mvm_tx_resp *tx_resp = (void *)pkt->data; + struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct ieee80211_node *ni = &in->in_ni; - struct ieee80211vap *vap = ni->ni_vap; int status = le16toh(tx_resp->status.status) & IWM_TX_STATUS_MSK; - int failack = tx_resp->failure_frame; KASSERT(tx_resp->frame_count == 1, ("too many frames")); @@ -3046,16 +3045,32 @@ le32toh(tx_resp->initial_rate), (int) le16toh(tx_resp->wireless_media_time)); + txs->flags = IEEE80211_RATECTL_STATUS_SHORT_RETRY | + IEEE80211_RATECTL_STATUS_LONG_RETRY; + txs->short_retries = tx_resp->failure_rts; + txs->long_retries = tx_resp->failure_frame; if (status != IWM_TX_STATUS_SUCCESS && status != IWM_TX_STATUS_DIRECT_DONE) { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, &failack, NULL); - return (1); + switch (status) { + case IWM_TX_STATUS_FAIL_SHORT_LIMIT: + txs->status = IEEE80211_RATECTL_TX_FAIL_SHORT; + break; + case IWM_TX_STATUS_FAIL_LONG_LIMIT: + txs->status = IEEE80211_RATECTL_TX_FAIL_LONG; + break; + case IWM_TX_STATUS_FAIL_LIFE_EXPIRE: + txs->status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; + break; + default: + txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; + break; + } } else { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, &failack, NULL); - return (0); + txs->status = IEEE80211_RATECTL_TX_SUCCESS; } + ieee80211_ratectl_tx_complete(ni, txs); + + return (txs->status != IEEE80211_RATECTL_TX_SUCCESS); } static void Index: sys/dev/iwm/if_iwmvar.h =================================================================== --- sys/dev/iwm/if_iwmvar.h +++ sys/dev/iwm/if_iwmvar.h @@ -392,6 +392,7 @@ struct mtx sc_mtx; struct mbufq sc_snd; struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_status sc_txs; int sc_flags; #define IWM_FLAG_USE_ICT (1 << 0) Index: sys/dev/iwn/if_iwn.c =================================================================== --- sys/dev/iwn/if_iwn.c +++ sys/dev/iwn/if_iwn.c @@ -210,9 +210,10 @@ struct iwn_rx_data *); static void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *, struct iwn_rx_data *); -static void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, int, +static void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, int, int, uint8_t); -static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, int, void *); +static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, int, int, + void *); static void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *); static void iwn_notif_intr(struct iwn_softc *); static void iwn_wakeup_intr(struct iwn_softc *); @@ -3147,6 +3148,7 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc, struct iwn_rx_data *data) { + struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct iwn_ops *ops = &sc->ops; struct iwn_node *wn; struct ieee80211_node *ni; @@ -3158,7 +3160,7 @@ uint64_t bitmap; uint16_t ssn; uint8_t tid; - int ackfailcnt = 0, i, lastidx, qid, *res, shift; + int i, lastidx, qid, *res, shift; int tx_ok = 0, tx_err = 0; DPRINTF(sc, IWN_DEBUG_TRACE | IWN_DEBUG_XMIT, "->%s begin\n", __func__); @@ -3227,15 +3229,15 @@ ni = tap->txa_ni; bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap; for (i = 0; bitmap; i++) { + txs->flags = 0; /* XXX TODO */ if ((bitmap & 1) == 0) { tx_err ++; - ieee80211_ratectl_tx_complete(ni->ni_vap, ni, - IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); + txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; } else { tx_ok ++; - ieee80211_ratectl_tx_complete(ni->ni_vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); + txs->status = IEEE80211_RATECTL_TX_SUCCESS; } + ieee80211_ratectl_tx_complete(ni, txs); bitmap >>= 1; } @@ -3501,9 +3503,9 @@ bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); if (qid >= sc->firstaggqueue) { iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, - stat->ackfailcnt, &stat->status); + stat->rtsfailcnt, stat->ackfailcnt, &stat->status); } else { - iwn_tx_done(sc, desc, stat->ackfailcnt, + iwn_tx_done(sc, desc, stat->rtsfailcnt, stat->ackfailcnt, le32toh(stat->status) & 0xff); } } @@ -3536,9 +3538,9 @@ bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); if (qid >= sc->firstaggqueue) { iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes, - stat->ackfailcnt, &stat->status); + stat->rtsfailcnt, stat->ackfailcnt, &stat->status); } else { - iwn_tx_done(sc, desc, stat->ackfailcnt, + iwn_tx_done(sc, desc, stat->rtsfailcnt, stat->ackfailcnt, le16toh(stat->status) & 0xff); } } @@ -3547,14 +3549,14 @@ * Adapter-independent backend for TX_DONE firmware notifications. */ static void -iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt, - uint8_t status) +iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int rtsfailcnt, + int ackfailcnt, uint8_t status) { + struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf]; struct iwn_tx_data *data = &ring->data[desc->idx]; struct mbuf *m; struct ieee80211_node *ni; - struct ieee80211vap *vap; KASSERT(data->ni != NULL, ("no node")); @@ -3565,17 +3567,33 @@ bus_dmamap_unload(ring->data_dmat, data->map); m = data->m, data->m = NULL; ni = data->ni, data->ni = NULL; - vap = ni->ni_vap; /* * Update rate control statistics for the node. */ - if (status & IWN_TX_FAIL) - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); - else - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); + txs->flags = IEEE80211_RATECTL_STATUS_SHORT_RETRY | + IEEE80211_RATECTL_STATUS_LONG_RETRY; + txs->short_retries = rtsfailcnt; + txs->long_retries = ackfailcnt; + if (!(status & IWN_TX_FAIL)) + txs->status = IEEE80211_RATECTL_TX_SUCCESS; + else { + switch (status) { + case IWN_TX_FAIL_SHORT_LIMIT: + txs->status = IEEE80211_RATECTL_TX_FAIL_SHORT; + break; + case IWN_TX_FAIL_LONG_LIMIT: + txs->status = IEEE80211_RATECTL_TX_FAIL_LONG; + break; + case IWN_TX_STATUS_FAIL_LIFE_EXPIRE: + txs->status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; + break; + default: + txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; + break; + } + } + ieee80211_ratectl_tx_complete(ni, txs); /* * Channels marked for "radar" require traffic to be received @@ -3640,10 +3658,11 @@ static void iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes, - int ackfailcnt, void *stat) + int rtsfailcnt, int ackfailcnt, void *stat) { struct iwn_ops *ops = &sc->ops; struct iwn_tx_ring *ring = &sc->txq[qid]; + struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct iwn_tx_data *data; struct mbuf *m; struct iwn_node *wn; @@ -3682,6 +3701,10 @@ * handled differently. */ if (nframes == 1) { + txs->flags = IEEE80211_RATECTL_STATUS_SHORT_RETRY | + IEEE80211_RATECTL_STATUS_LONG_RETRY; + txs->short_retries = rtsfailcnt; + txs->long_retries = ackfailcnt; if ((*status & 0xff) != 1 && (*status & 0xff) != 2) { #ifdef NOT_YET printf("ieee80211_send_bar()\n"); @@ -3691,11 +3714,8 @@ * notification is pushed up to the rate control * layer. */ - ieee80211_ratectl_tx_complete(ni->ni_vap, - ni, - IEEE80211_RATECTL_TX_FAILURE, - &ackfailcnt, - NULL); + /* XXX */ + txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; } else { /* * If nframes=1, then we won't be getting a BA for @@ -3703,12 +3723,9 @@ * rate control code with how many retries were * needed to send it. */ - ieee80211_ratectl_tx_complete(ni->ni_vap, - ni, - IEEE80211_RATECTL_TX_SUCCESS, - &ackfailcnt, - NULL); + txs->status = IEEE80211_RATECTL_TX_SUCCESS; } + ieee80211_ratectl_tx_complete(ni, txs); } bitmap = 0; Index: sys/dev/iwn/if_iwnvar.h =================================================================== --- sys/dev/iwn/if_iwnvar.h +++ sys/dev/iwn/if_iwnvar.h @@ -238,6 +238,7 @@ struct cdev *sc_cdev; struct mtx sc_mtx; struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_status sc_txs; u_int sc_flags; #define IWN_FLAG_HAS_OTPROM (1 << 1) Index: sys/dev/otus/if_otus.c =================================================================== --- sys/dev/otus/if_otus.c +++ sys/dev/otus/if_otus.c @@ -2148,14 +2148,18 @@ static void otus_tx_update_ratectl(struct otus_softc *sc, struct ieee80211_node *ni) { - int tx, tx_success, tx_retry; + struct ieee80211_ratectl_tx_stats *txs = &sc->sc_txs; + struct otus_node *on = OTUS_NODE(ni); - tx = OTUS_NODE(ni)->tx_done; - tx_success = OTUS_NODE(ni)->tx_done - OTUS_NODE(ni)->tx_err; - tx_retry = OTUS_NODE(ni)->tx_retries; + txs->flags = IEEE80211_RATECTL_TX_STATS_NODE | + IEEE80211_RATECTL_TX_STATS_RETRIES; + txs->ni = ni; + txs->nframes = on->tx_done; + txs->nsuccess = on->tx_done - on->tx_err; + txs->nretries = on->tx_retries; - ieee80211_ratectl_tx_update(ni->ni_vap, ni, &tx, &tx_success, - &tx_retry); + ieee80211_ratectl_tx_update(ni->ni_vap, txs); + on->tx_done = on->tx_err = on->tx_retries = 0; } /* Index: sys/dev/otus/if_otusreg.h =================================================================== --- sys/dev/otus/if_otusreg.h +++ sys/dev/otus/if_otusreg.h @@ -997,6 +997,7 @@ struct otus_softc { struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_stats sc_txs; struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; Index: sys/dev/ral/if_ral_pci.c =================================================================== --- sys/dev/ral/if_ral_pci.c +++ sys/dev/ral/if_ral_pci.c @@ -44,6 +44,7 @@ #include #include +#include #include #include Index: sys/dev/ral/rt2560.c =================================================================== --- sys/dev/ral/rt2560.c +++ sys/dev/ral/rt2560.c @@ -911,17 +911,18 @@ static void rt2560_tx_intr(struct rt2560_softc *sc) { + struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; struct mbuf *m; - struct ieee80211vap *vap; struct ieee80211_node *ni; uint32_t flags; - int retrycnt, status; + int status; bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map, BUS_DMASYNC_POSTREAD); + txs->flags = IEEE80211_RATECTL_STATUS_LONG_RETRY; for (;;) { desc = &sc->txq.desc[sc->txq.next]; data = &sc->txq.data[sc->txq.next]; @@ -934,41 +935,37 @@ m = data->m; ni = data->ni; - vap = ni->ni_vap; switch (flags & RT2560_TX_RESULT_MASK) { case RT2560_TX_SUCCESS: - retrycnt = 0; + txs->status = IEEE80211_RATECTL_TX_SUCCESS; + txs->long_retries = 0; DPRINTFN(sc, 10, "%s\n", "data frame sent successfully"); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, - &retrycnt, NULL); + ieee80211_ratectl_tx_complete(ni, txs); status = 0; break; case RT2560_TX_SUCCESS_RETRY: - retrycnt = RT2560_TX_RETRYCNT(flags); + txs->status = IEEE80211_RATECTL_TX_SUCCESS; + txs->long_retries = RT2560_TX_RETRYCNT(flags); DPRINTFN(sc, 9, "data frame sent after %u retries\n", - retrycnt); + txs->long_retries); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, - &retrycnt, NULL); + ieee80211_ratectl_tx_complete(ni, txs); status = 0; break; case RT2560_TX_FAIL_RETRY: - retrycnt = RT2560_TX_RETRYCNT(flags); + txs->status = IEEE80211_RATECTL_TX_FAIL_LONG; + txs->long_retries = RT2560_TX_RETRYCNT(flags); DPRINTFN(sc, 9, "data frame failed after %d retries\n", - retrycnt); + txs->long_retries); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, - &retrycnt, NULL); + ieee80211_ratectl_tx_complete(ni, txs); status = 1; break; Index: sys/dev/ral/rt2560var.h =================================================================== --- sys/dev/ral/rt2560var.h +++ sys/dev/ral/rt2560var.h @@ -105,6 +105,7 @@ struct rt2560_softc { struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_status sc_txs; struct mtx sc_mtx; struct mbufq sc_snd; device_t sc_dev; Index: sys/dev/ral/rt2661.c =================================================================== --- sys/dev/ral/rt2661.c +++ sys/dev/ral/rt2661.c @@ -851,12 +851,13 @@ static void rt2661_tx_intr(struct rt2661_softc *sc) { + struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct rt2661_tx_ring *txq; struct rt2661_tx_data *data; uint32_t val; - int error, qid, retrycnt; - struct ieee80211vap *vap; + int error, qid; + txs->flags = IEEE80211_RATECTL_TX_FAIL_LONG; for (;;) { struct ieee80211_node *ni; struct mbuf *m; @@ -879,31 +880,27 @@ /* if no frame has been sent, ignore */ if (ni == NULL) continue; - else - vap = ni->ni_vap; switch (RT2661_TX_RESULT(val)) { case RT2661_TX_SUCCESS: - retrycnt = RT2661_TX_RETRYCNT(val); + txs->status = IEEE80211_RATECTL_TX_SUCCESS; + txs->long_retries = RT2661_TX_RETRYCNT(val); DPRINTFN(sc, 10, "data frame sent successfully after " - "%d retries\n", retrycnt); + "%d retries\n", txs->long_retries); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, - &retrycnt, NULL); + ieee80211_ratectl_tx_complete(ni, txs); error = 0; break; case RT2661_TX_RETRY_FAIL: - retrycnt = RT2661_TX_RETRYCNT(val); + txs->status = IEEE80211_RATECTL_TX_FAIL_LONG; + txs->long_retries = RT2661_TX_RETRYCNT(val); DPRINTFN(sc, 9, "%s\n", "sending data frame failed (too much retries)"); if (data->rix != IEEE80211_FIXED_RATE_NONE) - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, - &retrycnt, NULL); + ieee80211_ratectl_tx_complete(ni, txs); error = 1; break; Index: sys/dev/ral/rt2661var.h =================================================================== --- sys/dev/ral/rt2661var.h +++ sys/dev/ral/rt2661var.h @@ -98,6 +98,7 @@ struct rt2661_softc { struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_status sc_txs; struct mtx sc_mtx; struct mbufq sc_snd; device_t sc_dev; Index: sys/dev/ral/rt2860.c =================================================================== --- sys/dev/ral/rt2860.c +++ sys/dev/ral/rt2860.c @@ -1083,12 +1083,13 @@ static void rt2860_drain_stats_fifo(struct rt2860_softc *sc) { + struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct ieee80211_node *ni; uint32_t stat; - int retrycnt; uint8_t wcid, mcs, pid; /* drain Tx status FIFO (maxsize = 16) */ + txs->flags = IEEE80211_RATECTL_STATUS_LONG_RETRY; while ((stat = RAL_READ(sc, RT2860_TX_STAT_FIFO)) & RT2860_TXQ_VLD) { DPRINTFN(4, ("tx stat 0x%08x\n", stat)); @@ -1110,14 +1111,15 @@ mcs = (stat >> RT2860_TXQ_MCS_SHIFT) & 0x7f; pid = (stat >> RT2860_TXQ_PID_SHIFT) & 0xf; if (mcs + 1 != pid) - retrycnt = 1; + txs->long_retries = 1; else - retrycnt = 0; - ieee80211_ratectl_tx_complete(ni->ni_vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL); + txs->long_retries = 0; + txs->status = IEEE80211_RATECTL_TX_SUCCESS; + ieee80211_ratectl_tx_complete(ni, txs); } else { - ieee80211_ratectl_tx_complete(ni->ni_vap, ni, - IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); + txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; + txs->long_retries = 1; /* XXX */ + ieee80211_ratectl_tx_complete(ni, txs); if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); } Index: sys/dev/ral/rt2860var.h =================================================================== --- sys/dev/ral/rt2860var.h +++ sys/dev/ral/rt2860var.h @@ -116,6 +116,7 @@ struct rt2860_softc { struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_status sc_txs; struct mbufq sc_snd; struct mtx sc_mtx; device_t sc_dev; Index: sys/dev/urtwn/if_urtwn.c =================================================================== --- sys/dev/urtwn/if_urtwn.c +++ sys/dev/urtwn/if_urtwn.c @@ -1016,7 +1016,7 @@ urtwn_r88e_ratectl_tx_complete(struct urtwn_softc *sc, void *arg) { struct r88e_tx_rpt_ccx *rpt = arg; - struct ieee80211vap *vap; + struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct ieee80211_node *ni; uint8_t macid; int ntries; @@ -1027,19 +1027,28 @@ URTWN_NT_LOCK(sc); ni = sc->node_list[macid]; if (ni != NULL) { - vap = ni->ni_vap; URTWN_DPRINTF(sc, URTWN_DEBUG_INTR, "%s: frame for macid %d was" "%s sent (%d retries)\n", __func__, macid, (rpt->rptb1 & R88E_RPTB1_PKT_OK) ? "" : " not", ntries); - if (rpt->rptb1 & R88E_RPTB1_PKT_OK) { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL); - } else { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL); - } + txs->flags = IEEE80211_RATECTL_STATUS_LONG_RETRY | + IEEE80211_RATECTL_STATUS_FINAL_RATE; + txs->long_retries = ntries; + if (rpt->final_rate > URTWN_RIDX_OFDM54) { /* MCS */ + txs->final_rate = + (rpt->final_rate - 12) | IEEE80211_RATE_MCS; + } else + txs->final_rate = ridx2rate[rpt->final_rate]; + if (rpt->rptb1 & R88E_RPTB1_PKT_OK) + txs->status = IEEE80211_RATECTL_TX_SUCCESS; + else if (rpt->rptb2 & R88E_RPTB2_RETRY_OVER) + txs->status = IEEE80211_RATECTL_TX_FAIL_LONG; + else if (rpt->rptb2 & R88E_RPTB2_LIFE_EXPIRE) + txs->status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; + else + txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; + ieee80211_ratectl_tx_complete(ni, txs); } else { URTWN_DPRINTF(sc, URTWN_DEBUG_INTR, "%s: macid %d, ni is NULL\n", __func__, macid); Index: sys/dev/urtwn/if_urtwnreg.h =================================================================== --- sys/dev/urtwn/if_urtwnreg.h +++ sys/dev/urtwn/if_urtwnreg.h @@ -1227,9 +1227,8 @@ #define R88E_RPTB2_LIFE_EXPIRE 0x40 #define R88E_RPTB2_RETRY_OVER 0x80 - uint8_t rptb3; - uint8_t rptb4; - uint8_t rptb5; + uint16_t ccx_qtime; + uint8_t final_rate; uint8_t rptb6; #define R88E_RPTB6_QSEL_M 0xf0 #define R88E_RPTB6_QSEL_S 4 Index: sys/dev/urtwn/if_urtwnvar.h =================================================================== --- sys/dev/urtwn/if_urtwnvar.h +++ sys/dev/urtwn/if_urtwnvar.h @@ -136,6 +136,7 @@ struct urtwn_softc { struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_status sc_txs; struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; Index: sys/dev/usb/wlan/if_rum.c =================================================================== --- sys/dev/usb/wlan/if_rum.c +++ sys/dev/usb/wlan/if_rum.c @@ -1668,8 +1668,10 @@ rate = tp->ucastrate; else if (m0->m_flags & M_EAPOL) rate = tp->mgmtrate; - else + else { + (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; + } if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_get_txkey(ni, m0); @@ -3154,9 +3156,8 @@ struct rum_vap *rvp = arg; struct ieee80211vap *vap = &rvp->vap; struct rum_softc *sc = vap->iv_ic->ic_softc; - struct ieee80211_node *ni; + struct ieee80211_ratectl_tx_stats *txs = &sc->sc_txs; int ok[3], fail; - int sum, success, retrycnt; RUM_LOCK(sc); /* read and clear statistic registers (STA_CSR0 to STA_CSR5) */ @@ -3167,17 +3168,14 @@ ok[2] = (le32toh(sc->sta[5]) & 0xffff); /* TX ok w/ multiple retries */ fail = (le32toh(sc->sta[5]) >> 16); /* TX retry-fail count */ - success = ok[0] + ok[1] + ok[2]; - sum = success + fail; + txs->flags = IEEE80211_RATECTL_TX_STATS_RETRIES; + txs->nframes = ok[0] + ok[1] + ok[2] + fail; + txs->nsuccess = txs->nframes - fail; /* XXX at least */ - retrycnt = ok[1] + ok[2] * 2 + fail * (rvp->maxretry + 1); + txs->nretries = ok[1] + ok[2] * 2 + fail * (rvp->maxretry + 1); - if (sum != 0) { - ni = ieee80211_ref_node(vap->iv_bss); - ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt); - (void) ieee80211_ratectl_rate(ni, NULL, 0); - ieee80211_free_node(ni); - } + if (txs->nframes != 0) + ieee80211_ratectl_tx_update(vap, txs); /* count TX retry-fail as Tx errors */ if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, fail); Index: sys/dev/usb/wlan/if_rumvar.h =================================================================== --- sys/dev/usb/wlan/if_rumvar.h +++ sys/dev/usb/wlan/if_rumvar.h @@ -110,6 +110,7 @@ struct rum_softc { struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_stats sc_txs; struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; Index: sys/dev/usb/wlan/if_run.c =================================================================== --- sys/dev/usb/wlan/if_run.c +++ sys/dev/usb/wlan/if_run.c @@ -2552,11 +2552,12 @@ run_iter_func(void *arg, struct ieee80211_node *ni) { struct run_softc *sc = arg; + struct ieee80211_ratectl_tx_stats *txs = &sc->sc_txs; struct ieee80211vap *vap = ni->ni_vap; struct run_node *rn = RUN_NODE(ni); union run_stats sta[2]; uint16_t (*wstat)[3]; - int txcnt, success, retrycnt, error; + int error; RUN_LOCK(sc); @@ -2565,6 +2566,9 @@ ni != vap->iv_bss) goto fail; + txs->flags = IEEE80211_RATECTL_TX_STATS_NODE | + IEEE80211_RATECTL_TX_STATS_RETRIES; + txs->ni = ni; if (sc->rvp_cnt <= 1 && (vap->iv_opmode == IEEE80211_M_IBSS || vap->iv_opmode == IEEE80211_M_STA)) { /* read statistic counters (clear on read) and update AMRR state */ @@ -2577,12 +2581,15 @@ if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, le16toh(sta[0].error.fail)); - retrycnt = le16toh(sta[1].tx.retry); - success = le16toh(sta[1].tx.success); - txcnt = retrycnt + success + le16toh(sta[0].error.fail); + txs->nretries = le16toh(sta[1].tx.retry); + txs->nsuccess = le16toh(sta[1].tx.success); + /* nretries??? */ + txs->nframes = txs->nretries + txs->nsuccess + + le16toh(sta[0].error.fail); DPRINTFN(3, "retrycnt=%d success=%d failcnt=%d\n", - retrycnt, success, le16toh(sta[0].error.fail)); + txs->nretries, txs->nsuccess, + le16toh(sta[0].error.fail)); } else { wstat = &(sc->wcid_stats[RUN_AID2WCID(ni->ni_associd)]); @@ -2590,16 +2597,16 @@ wstat > &(sc->wcid_stats[RT2870_WCID_MAX])) goto fail; - txcnt = (*wstat)[RUN_TXCNT]; - success = (*wstat)[RUN_SUCCESS]; - retrycnt = (*wstat)[RUN_RETRY]; + txs->nretries = (*wstat)[RUN_RETRY]; + txs->nsuccess = (*wstat)[RUN_SUCCESS]; + txs->nframes = (*wstat)[RUN_TXCNT]; DPRINTFN(3, "retrycnt=%d txcnt=%d success=%d\n", - retrycnt, txcnt, success); + txs->nretries, txs->nframes, txs->nsuccess); memset(wstat, 0, sizeof(*wstat)); } - ieee80211_ratectl_tx_update(vap, ni, &txcnt, &success, &retrycnt); + ieee80211_ratectl_tx_update(vap, txs); rn->amrr_ridx = ieee80211_ratectl_rate(ni, NULL, 0); fail: Index: sys/dev/usb/wlan/if_runvar.h =================================================================== --- sys/dev/usb/wlan/if_runvar.h +++ sys/dev/usb/wlan/if_runvar.h @@ -159,6 +159,7 @@ struct run_softc { struct mtx sc_mtx; struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_stats sc_txs; struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; Index: sys/dev/usb/wlan/if_ural.c =================================================================== --- sys/dev/usb/wlan/if_ural.c +++ sys/dev/usb/wlan/if_ural.c @@ -1254,8 +1254,10 @@ rate = tp->mcastrate; else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) rate = tp->ucastrate; - else + else { + (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; + } if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m0); @@ -2208,32 +2210,29 @@ { struct ural_vap *uvp = arg; struct ieee80211vap *vap = &uvp->vap; - struct ieee80211com *ic = vap->iv_ic; - struct ural_softc *sc = ic->ic_softc; - struct ieee80211_node *ni; - int ok, fail; - int sum, retrycnt; + struct ural_softc *sc = vap->iv_ic->ic_softc; + struct ieee80211_ratectl_tx_stats *txs = &sc->sc_txs; + int fail; - ni = ieee80211_ref_node(vap->iv_bss); RAL_LOCK(sc); /* read and clear statistic registers (STA_CSR0 to STA_CSR10) */ ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof(sc->sta)); - ok = sc->sta[7] + /* TX ok w/o retry */ - sc->sta[8]; /* TX ok w/ retry */ + txs->flags = IEEE80211_RATECTL_TX_STATS_RETRIES; + txs->nsuccess = sc->sta[7] + /* TX ok w/o retry */ + sc->sta[8]; /* TX ok w/ retry */ fail = sc->sta[9]; /* TX retry-fail count */ - sum = ok+fail; - retrycnt = sc->sta[8] + fail; + txs->nframes = txs->nsuccess + fail; + /* XXX fail * maxretry */ + txs->nretries = sc->sta[8] + fail; - ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt); - (void) ieee80211_ratectl_rate(ni, NULL, 0); + ieee80211_ratectl_tx_update(vap, txs); /* count TX retry-fail as Tx errors */ - if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail); + if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, fail); usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp); RAL_UNLOCK(sc); - ieee80211_free_node(ni); } static int Index: sys/dev/usb/wlan/if_uralvar.h =================================================================== --- sys/dev/usb/wlan/if_uralvar.h +++ sys/dev/usb/wlan/if_uralvar.h @@ -90,6 +90,7 @@ struct ural_softc { struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_stats sc_txs; struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; Index: sys/dev/usb/wlan/if_zyd.c =================================================================== --- sys/dev/usb/wlan/if_zyd.c +++ sys/dev/usb/wlan/if_zyd.c @@ -662,12 +662,24 @@ */ ni = ieee80211_find_txnode(vap, retry->macaddr); if (ni != NULL) { + struct ieee80211_ratectl_tx_status *txs = + &sc->sc_txs; int retrycnt = (int)(le16toh(retry->count) & 0xff); - - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, - &retrycnt, NULL); + + txs->flags = + IEEE80211_RATECTL_STATUS_LONG_RETRY; + txs->long_retries = retrycnt; + if (le16toh(retry->count) & 0x100) { + txs->status = + IEEE80211_RATECTL_TX_FAIL_LONG; + } else { + txs->status = + IEEE80211_RATECTL_TX_SUCCESS; + } + + + ieee80211_ratectl_tx_complete(ni, txs); ieee80211_free_node(ni); } if (le16toh(retry->count) & 0x100) Index: sys/dev/usb/wlan/if_zydreg.h =================================================================== --- sys/dev/usb/wlan/if_zydreg.h +++ sys/dev/usb/wlan/if_zydreg.h @@ -1254,6 +1254,7 @@ struct zyd_softc { struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_status sc_txs; struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; Index: sys/dev/wpi/if_wpi.c =================================================================== --- sys/dev/wpi/if_wpi.c +++ sys/dev/wpi/if_wpi.c @@ -526,6 +526,10 @@ wpi_radiotap_attach(sc); + /* Setup Tx status flags (constant). */ + sc->sc_txs.flags = IEEE80211_RATECTL_STATUS_SHORT_RETRY | + IEEE80211_RATECTL_STATUS_LONG_RETRY; + callout_init_mtx(&sc->calib_to, &sc->rxon_mtx, 0); callout_init_mtx(&sc->scan_timeout, &sc->rxon_mtx, 0); callout_init_mtx(&sc->tx_timeout, &sc->txq_state_mtx, 0); @@ -2051,14 +2055,13 @@ static void wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc) { + struct ieee80211_ratectl_tx_status *txs = &sc->sc_txs; struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3]; struct wpi_tx_data *data = &ring->data[desc->idx]; struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1); struct mbuf *m; struct ieee80211_node *ni; - struct ieee80211vap *vap; uint32_t status = le32toh(stat->status); - int ackfailcnt = stat->ackfailcnt / WPI_NTRIES_DEFAULT; KASSERT(data->ni != NULL, ("no node")); KASSERT(data->m != NULL, ("no mbuf")); @@ -2075,18 +2078,32 @@ bus_dmamap_unload(ring->data_dmat, data->map); m = data->m, data->m = NULL; ni = data->ni, data->ni = NULL; - vap = ni->ni_vap; /* * Update rate control statistics for the node. */ - if (status & WPI_TX_STATUS_FAIL) { - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); - } else - ieee80211_ratectl_tx_complete(vap, ni, - IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); + txs->short_retries = stat->rtsfailcnt; + txs->long_retries = stat->ackfailcnt / WPI_NTRIES_DEFAULT; + if (!(status & WPI_TX_STATUS_FAIL)) + txs->status = IEEE80211_RATECTL_TX_SUCCESS; + else { + switch (status & 0xff) { + case WPI_TX_STATUS_FAIL_SHORT_LIMIT: + txs->status = IEEE80211_RATECTL_TX_FAIL_SHORT; + break; + case WPI_TX_STATUS_FAIL_LONG_LIMIT: + txs->status = IEEE80211_RATECTL_TX_FAIL_LONG; + break; + case WPI_TX_STATUS_FAIL_LIFE_EXPIRE: + txs->status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; + break; + default: + txs->status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; + break; + } + } + ieee80211_ratectl_tx_complete(ni, txs); ieee80211_tx_complete(ni, m, (status & WPI_TX_STATUS_FAIL) != 0); WPI_TXQ_STATE_LOCK(sc); Index: sys/dev/wpi/if_wpivar.h =================================================================== --- sys/dev/wpi/if_wpivar.h +++ sys/dev/wpi/if_wpivar.h @@ -170,6 +170,7 @@ struct mtx sc_mtx; struct ieee80211com sc_ic; + struct ieee80211_ratectl_tx_status sc_txs; struct mtx tx_mtx; Index: sys/net80211/ieee80211_amrr.c =================================================================== --- sys/net80211/ieee80211_amrr.c +++ sys/net80211/ieee80211_amrr.c @@ -69,11 +69,11 @@ static int amrr_update(struct ieee80211_amrr *, struct ieee80211_amrr_node *, struct ieee80211_node *); static int amrr_rate(struct ieee80211_node *, void *, uint32_t); -static void amrr_tx_complete(const struct ieee80211vap *, - const struct ieee80211_node *, int, - void *, void *); -static void amrr_tx_update(const struct ieee80211vap *vap, - const struct ieee80211_node *, void *, void *, void *); +static void amrr_tx_complete(const struct ieee80211_node *, + const struct ieee80211_ratectl_tx_status *); +static void amrr_tx_update_cb(void *, struct ieee80211_node *); +static void amrr_tx_update(struct ieee80211vap *vap, + struct ieee80211_ratectl_tx_stats *); static void amrr_sysctlattach(struct ieee80211vap *, struct sysctl_ctx_list *, struct sysctl_oid *); static void amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s); @@ -360,34 +360,56 @@ * retransmissions (i.e. xmit attempts - 1). */ static void -amrr_tx_complete(const struct ieee80211vap *vap, - const struct ieee80211_node *ni, int ok, - void *arg1, void *arg2 __unused) +amrr_tx_complete(const struct ieee80211_node *ni, + const struct ieee80211_ratectl_tx_status *status) { struct ieee80211_amrr_node *amn = ni->ni_rctls; - int retries = *(int *)arg1; + int retries; + + retries = 0; + if (status->flags & IEEE80211_RATECTL_STATUS_LONG_RETRY) + retries = status->long_retries; amn->amn_txcnt++; - if (ok) + if (status->status == IEEE80211_RATECTL_TX_SUCCESS) amn->amn_success++; amn->amn_retrycnt += retries; } +static void +amrr_tx_update_cb(void *arg, struct ieee80211_node *ni) +{ + struct ieee80211_ratectl_tx_stats *stats = arg; + struct ieee80211_amrr_node *amn = ni->ni_rctls; + int txcnt, success, retrycnt; + + txcnt = stats->nframes; + success = stats->nsuccess; + retrycnt = 0; + if (stats->flags & IEEE80211_RATECTL_TX_STATS_RETRIES) + retrycnt = stats->nretries; + + amn->amn_txcnt += txcnt; + amn->amn_success += success; + amn->amn_retrycnt += retrycnt; +} + /* * Set tx count/retry statistics explicitly. Intended for * drivers that poll the device for statistics maintained * in the device. */ static void -amrr_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni, - void *arg1, void *arg2, void *arg3) +amrr_tx_update(struct ieee80211vap *vap, + struct ieee80211_ratectl_tx_stats *stats) { - struct ieee80211_amrr_node *amn = ni->ni_rctls; - int txcnt = *(int *)arg1, success = *(int *)arg2, retrycnt = *(int *)arg3; - amn->amn_txcnt = txcnt; - amn->amn_success = success; - amn->amn_retrycnt = retrycnt; + if (stats->flags & IEEE80211_RATECTL_TX_STATS_NODE) + amrr_tx_update_cb(stats, stats->ni); + else { + ieee80211_iterate_nodes_vap(&vap->iv_ic->ic_sta, vap, + amrr_tx_update_cb, stats); + } } static int Index: sys/net80211/ieee80211_ratectl.h =================================================================== --- sys/net80211/ieee80211_ratectl.h +++ sys/net80211/ieee80211_ratectl.h @@ -34,8 +34,49 @@ IEEE80211_RATECTL_MAX }; -#define IEEE80211_RATECTL_TX_SUCCESS 1 -#define IEEE80211_RATECTL_TX_FAILURE 0 +/* used fields for tx_complete() events */ +#define IEEE80211_RATECTL_STATUS_PKTLEN 0x00000001 +#define IEEE80211_RATECTL_STATUS_FINAL_RATE 0x00000002 +#define IEEE80211_RATECTL_STATUS_SHORT_RETRY 0x00000004 +#define IEEE80211_RATECTL_STATUS_LONG_RETRY 0x00000008 +#define IEEE80211_RATECTL_STATUS_RSSI 0x00000010 + +/* failure reason */ +enum ieee80211_ratectl_tx_fail_reason { + IEEE80211_RATECTL_TX_SUCCESS = 0, + IEEE80211_RATECTL_TX_FAIL_SHORT = 1, /* too many RTS retries */ + IEEE80211_RATECTL_TX_FAIL_LONG = 2, /* too many retries */ + IEEE80211_RATECTL_TX_FAIL_EXPIRED = 3, /* lifetime expired */ + IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED = 4, /* another reason */ +}; +#define IEEE80211_RATECTL_TX_FAIL_MAX \ + (IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED + 1) + +struct ieee80211_ratectl_tx_status { + uint32_t flags; /* mark used fields */ + enum ieee80211_ratectl_tx_fail_reason status; /* Tx status */ + + int pktlen; /* frame length */ + int final_rate; /* transmission rate */ + uint_fast8_t short_retries; /* RTS/CTS retries */ + uint_fast8_t long_retries; /* ACK retries */ + int8_t rssi; /* ACK RSSI */ + + uint8_t spare[15]; /* for future use */ +}; + +/* used fields for tx_update() events */ +#define IEEE80211_RATECTL_TX_STATS_NODE 0x00000001 +#define IEEE80211_RATECTL_TX_STATS_RETRIES 0x00000002 + +struct ieee80211_ratectl_tx_stats { + uint32_t flags; /* mark used fields */ + + struct ieee80211_node *ni; /* receiver */ + int nframes; /* transmitted frames */ + int nsuccess; /* ACKed frames */ + int nretries; /* number of retries */ +}; struct ieee80211_ratectl { const char *ir_name; @@ -46,12 +87,10 @@ void (*ir_node_init)(struct ieee80211_node *); void (*ir_node_deinit)(struct ieee80211_node *); int (*ir_rate)(struct ieee80211_node *, void *, uint32_t); - void (*ir_tx_complete)(const struct ieee80211vap *, - const struct ieee80211_node *, int, - void *, void *); - void (*ir_tx_update)(const struct ieee80211vap *, - const struct ieee80211_node *, - void *, void *, void *); + void (*ir_tx_complete)(const struct ieee80211_node *, + const struct ieee80211_ratectl_tx_status *); + void (*ir_tx_update)(struct ieee80211vap *, + struct ieee80211_ratectl_tx_stats *); void (*ir_setinterval)(const struct ieee80211vap *, int); void (*ir_node_stats)(struct ieee80211_node *ni, struct sbuf *s); }; @@ -94,19 +133,21 @@ } static __inline void -ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap, - const struct ieee80211_node *ni, int status, void *arg1, void *arg2) +ieee80211_ratectl_tx_complete(const struct ieee80211_node *ni, + const struct ieee80211_ratectl_tx_status *status) { - vap->iv_rate->ir_tx_complete(vap, ni, status, arg1, arg2); + const struct ieee80211vap *vap = ni->ni_vap; + + vap->iv_rate->ir_tx_complete(ni, status); } static __inline void -ieee80211_ratectl_tx_update(const struct ieee80211vap *vap, - const struct ieee80211_node *ni, void *arg1, void *arg2, void *arg3) +ieee80211_ratectl_tx_update(struct ieee80211vap *vap, + struct ieee80211_ratectl_tx_stats *stats) { if (vap->iv_rate->ir_tx_update == NULL) return; - vap->iv_rate->ir_tx_update(vap, ni, arg1, arg2, arg3); + vap->iv_rate->ir_tx_update(vap, stats); } static __inline void Index: sys/net80211/ieee80211_ratectl_none.c =================================================================== --- sys/net80211/ieee80211_ratectl_none.c +++ sys/net80211/ieee80211_ratectl_none.c @@ -80,15 +80,14 @@ } static void -none_tx_complete(const struct ieee80211vap *vap, - const struct ieee80211_node *ni, int ok, - void *arg1, void *arg2 __unused) +none_tx_complete(const struct ieee80211_node *ni, + const struct ieee80211_ratectl_tx_status *status) { } static void -none_tx_update(const struct ieee80211vap *vap, const struct ieee80211_node *ni, - void *arg1, void *arg2, void *arg3) +none_tx_update(struct ieee80211vap *vap, + struct ieee80211_ratectl_tx_stats *stats) { } Index: sys/net80211/ieee80211_rssadapt.c =================================================================== --- sys/net80211/ieee80211_rssadapt.c +++ sys/net80211/ieee80211_rssadapt.c @@ -87,9 +87,8 @@ static void rssadapt_lower_rate(struct ieee80211_rssadapt_node *, int, int); static void rssadapt_raise_rate(struct ieee80211_rssadapt_node *, int, int); -static void rssadapt_tx_complete(const struct ieee80211vap *, - const struct ieee80211_node *, int, - void *, void *); +static void rssadapt_tx_complete(const struct ieee80211_node *, + const struct ieee80211_ratectl_tx_status *); static void rssadapt_sysctlattach(struct ieee80211vap *, struct sysctl_ctx_list *, struct sysctl_oid *); @@ -310,13 +309,21 @@ } static void -rssadapt_tx_complete(const struct ieee80211vap *vap, - const struct ieee80211_node *ni, int success, void *arg1, void *arg2) +rssadapt_tx_complete(const struct ieee80211_node *ni, + const struct ieee80211_ratectl_tx_status *status) { struct ieee80211_rssadapt_node *ra = ni->ni_rctls; - int pktlen = *(int *)arg1, rssi = *(int *)arg2; + int pktlen, rssi; - if (success) { + if ((status->flags & + (IEEE80211_RATECTL_STATUS_PKTLEN|IEEE80211_RATECTL_STATUS_RSSI)) != + (IEEE80211_RATECTL_STATUS_PKTLEN|IEEE80211_RATECTL_STATUS_RSSI)) + return; + + pktlen = status->pktlen; + rssi = status->rssi; + + if (status->status == IEEE80211_RATECTL_TX_SUCCESS) { ra->ra_nok++; if ((ra->ra_rix + 1) < ra->ra_rates.rs_nrates && (ticks - ra->ra_last_raise) >= ra->ra_raise_interval)