net80211: ieee80211_ratectl*: switch to reusable KPI
Replace various void * / int argument combinations with common structures: - ieee80211_ratectl_tx_status for *_tx_complete(); - ieee80211_ratectl_tx_stats for *_tx_update(); While here, improve amrr_tx_update() for a bit: 1. In case, if receiver is not known (typical for Ralink USB drivers), refresh Tx rate for all nodes on the interface. 2. There was a misuse: - otus(4) sends non-decreasing counters (as originally intended); - but ural(4), rum(4) and run(4) are using 'read & clear' registers to obtain statistics for some period of time (and those 'last period' values are used as arguments for tx_update()). If arguments are not big enough, they are just discarded after the next call. Fix: move counting into *_tx_update() (now otus(4) will zero out all node counters after every tx_update() call) Tested with: - Intel 3945BG (wpi(4)), STA mode. - WUSB54GC (rum(4)), STA / HOSTAP mode. - RTL8188EU (urtwn(4)), STA mode. Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D8037
This commit is contained in:
parent
43f9a6a577
commit
a6044b10a0
@ -3321,7 +3321,6 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
|
||||
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 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
|
||||
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 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
|
||||
* 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;
|
||||
|
@ -258,6 +258,8 @@ static int bwn_dma_newbuf(struct bwn_dma_ring *,
|
||||
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 *,
|
||||
@ -5890,6 +5892,33 @@ bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
|
||||
device_printf(sc->sc_dev, "%s: dropped\n", __func__);
|
||||
}
|
||||
|
||||
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 @@ bwn_dma_handle_txeof(struct bwn_mac *mac,
|
||||
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 @@ bwn_dma_handle_txeof(struct bwn_mac *mac,
|
||||
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 @@ bwn_pio_handle_txeof(struct bwn_mac *mac,
|
||||
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 @@ bwn_pio_handle_txeof(struct bwn_mac *mac,
|
||||
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);
|
||||
|
@ -3027,10 +3027,9 @@ iwm_mvm_rx_tx_cmd_single(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
|
||||
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 @@ iwm_mvm_rx_tx_cmd_single(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
|
||||
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
|
||||
|
@ -392,6 +392,7 @@ struct iwm_softc {
|
||||
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)
|
||||
|
@ -210,9 +210,10 @@ static void iwn4965_tx_done(struct iwn_softc *, struct iwn_rx_desc *,
|
||||
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 @@ static void
|
||||
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 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
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 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
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 @@ iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
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 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
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 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
* 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 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
|
||||
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 @@ iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc)
|
||||
|
||||
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 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
|
||||
* 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 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
|
||||
* 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 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
|
||||
* 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;
|
||||
|
@ -238,6 +238,7 @@ struct iwn_softc {
|
||||
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)
|
||||
|
@ -2148,14 +2148,18 @@ otus_hw_rate_is_ofdm(struct otus_softc *sc, uint8_t hw_rate)
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -997,6 +997,7 @@ struct otus_vap {
|
||||
|
||||
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;
|
||||
|
@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <net80211/ieee80211_var.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
#include <net80211/ieee80211_ratectl.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
@ -911,17 +911,18 @@ rt2560_encryption_intr(struct rt2560_softc *sc)
|
||||
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 @@ rt2560_tx_intr(struct rt2560_softc *sc)
|
||||
|
||||
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;
|
||||
|
||||
|
@ -105,6 +105,7 @@ struct rt2560_vap {
|
||||
|
||||
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;
|
||||
|
@ -851,12 +851,13 @@ rt2661_eeprom_read(struct rt2661_softc *sc, uint8_t addr)
|
||||
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 @@ rt2661_tx_intr(struct rt2661_softc *sc)
|
||||
/* 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;
|
||||
|
||||
|
@ -98,6 +98,7 @@ struct rt2661_vap {
|
||||
|
||||
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;
|
||||
|
@ -1083,12 +1083,13 @@ rt2860_intr_coherent(struct rt2860_softc *sc)
|
||||
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 @@ rt2860_drain_stats_fifo(struct rt2860_softc *sc)
|
||||
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);
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ struct rt2860_vap {
|
||||
|
||||
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;
|
||||
|
@ -1016,7 +1016,7 @@ static void
|
||||
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_r88e_ratectl_tx_complete(struct urtwn_softc *sc, void *arg)
|
||||
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);
|
||||
|
@ -1227,9 +1227,8 @@ struct r88e_tx_rpt_ccx {
|
||||
#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
|
||||
|
@ -136,6 +136,7 @@ union urtwn_rom {
|
||||
|
||||
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;
|
||||
|
@ -1668,8 +1668,10 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
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 @@ rum_ratectl_task(void *arg, int pending)
|
||||
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 @@ rum_ratectl_task(void *arg, int pending)
|
||||
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);
|
||||
|
@ -110,6 +110,7 @@ enum {
|
||||
|
||||
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;
|
||||
|
@ -2552,11 +2552,12 @@ static void
|
||||
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 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
|
||||
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 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
|
||||
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 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
|
||||
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:
|
||||
|
@ -159,6 +159,7 @@ struct run_endpoint_queue {
|
||||
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;
|
||||
|
@ -1254,8 +1254,10 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
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 @@ ural_ratectl_task(void *arg, int pending)
|
||||
{
|
||||
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
|
||||
|
@ -90,6 +90,7 @@ enum {
|
||||
|
||||
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;
|
||||
|
@ -662,12 +662,24 @@ zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
*/
|
||||
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)
|
||||
|
@ -1254,6 +1254,7 @@ enum {
|
||||
|
||||
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;
|
||||
|
@ -526,6 +526,10 @@ wpi_attach(device_t dev)
|
||||
|
||||
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 @@ wpi_rx_statistics(struct wpi_softc *sc, struct wpi_rx_desc *desc,
|
||||
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 @@ wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc)
|
||||
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);
|
||||
|
@ -170,6 +170,7 @@ struct wpi_softc {
|
||||
|
||||
struct mtx sc_mtx;
|
||||
struct ieee80211com sc_ic;
|
||||
struct ieee80211_ratectl_tx_status sc_txs;
|
||||
|
||||
struct mtx tx_mtx;
|
||||
|
||||
|
@ -69,11 +69,11 @@ static void amrr_node_deinit(struct ieee80211_node *);
|
||||
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 @@ amrr_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused)
|
||||
* 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
|
||||
|
@ -34,8 +34,49 @@ enum ieee80211_ratealgs {
|
||||
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 @@ struct ieee80211_ratectl {
|
||||
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 @@ ieee80211_ratectl_rate(struct ieee80211_node *ni, void *arg, uint32_t iarg)
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -80,15 +80,14 @@ none_rate(struct ieee80211_node *ni, void *arg __unused, uint32_t iarg __unused)
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -87,9 +87,8 @@ static int rssadapt_rate(struct ieee80211_node *, void *, uint32_t);
|
||||
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 @@ rssadapt_raise_rate(struct ieee80211_rssadapt_node *ra, int pktlen, int rssi)
|
||||
}
|
||||
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user