From 8403bb96a26fb7e0df4c7ad65dc93278f0ef3bf5 Mon Sep 17 00:00:00 2001 From: Damien Bergamini Date: Fri, 18 Nov 2005 21:37:02 +0000 Subject: [PATCH] Second part of the AMRR commit. Enable automatic rate adaptation in BSS operating mode. Works great here. Will need a lot of testing though. --- sys/dev/usb/if_ural.c | 121 ++++++++++++++++++++++++++++++++++----- sys/dev/usb/if_uralvar.h | 4 ++ 2 files changed, 112 insertions(+), 13 deletions(-) diff --git a/sys/dev/usb/if_ural.c b/sys/dev/usb/if_ural.c index 85d3ed5fdb4..bb25af35131 100644 --- a/sys/dev/usb/if_ural.c +++ b/sys/dev/usb/if_ural.c @@ -159,6 +159,13 @@ Static void ural_set_txantenna(struct ural_softc *, int); Static void ural_set_rxantenna(struct ural_softc *, int); Static void ural_init(void *); Static void ural_stop(void *); +Static void ural_amrr_start(struct ural_softc *, + struct ieee80211_node *); +Static void ural_amrr_timeout(void *); +Static void ural_amrr_update(usbd_xfer_handle, usbd_private_handle, + usbd_status status); +Static void ural_ratectl(struct ural_amrr *, + struct ieee80211_node *); /* * Supported rates for 802.11a/b/g modes (in 500Kbps unit). @@ -411,6 +418,7 @@ USB_ATTACH(ural) usb_init_task(&sc->sc_task, ural_task, sc); callout_init(&sc->scan_ch, debug_mpsafenet ? CALLOUT_MPSAFE : 0); + callout_init(&sc->amrr_ch, 0); /* retrieve RT2570 rev. no */ sc->asic_rev = ural_read(sc, RAL_MAC_CSR0); @@ -517,6 +525,7 @@ USB_DETACH(ural) usb_rem_task(sc->sc_udev, &sc->sc_task); callout_stop(&sc->scan_ch); + callout_stop(&sc->amrr_ch); if (sc->sc_rx_pipeh != NULL) { usbd_abort_pipe(sc->sc_rx_pipeh); @@ -772,6 +781,12 @@ ural_task(void *arg) if (ic->ic_opmode != IEEE80211_M_MONITOR) ural_enable_tsf_sync(sc); + + /* enable automatic rate adaptation in STA mode */ + if (ic->ic_opmode == IEEE80211_M_STA && + ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) + ural_amrr_start(sc, ic->ic_bss); + break; } @@ -785,6 +800,7 @@ ural_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) usb_rem_task(sc->sc_udev, &sc->sc_task); callout_stop(&sc->scan_ch); + callout_stop(&sc->amrr_ch); /* do it in a process context */ sc->sc_state = nstate; @@ -1918,7 +1934,7 @@ ural_init(void *priv) struct ifnet *ifp = ic->ic_ifp; struct ieee80211_key *wk; struct ural_rx_data *data; - uint16_t sta[11], tmp; + uint16_t tmp; usbd_status error; int i, ntries; @@ -1957,7 +1973,7 @@ ural_init(void *priv) ural_set_chan(sc, ic->ic_curchan); /* clear statistic registers (STA_CSR0 to STA_CSR10) */ - ural_read_multi(sc, RAL_STA_CSR0, sta, sizeof sta); + ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta); ural_set_txantenna(sc, sc->tx_ant); ural_set_rxantenna(sc, sc->rx_ant); @@ -1974,6 +1990,16 @@ ural_init(void *priv) RAL_SEC_CSR0, wk->wk_key, IEEE80211_KEYBUF_SIZE); } + /* + * Allocate xfer for AMRR statistics requests. + */ + sc->amrr_xfer = usbd_alloc_xfer(sc->sc_udev); + if (sc->amrr_xfer == NULL) { + printf("%s: could not allocate AMRR xfer\n", + USBDEVNAME(sc->sc_dev)); + goto fail; + } + /* * Open Tx and Rx USB bulk pipes. */ @@ -2081,6 +2107,81 @@ ural_stop(void *priv) ural_free_rx_list(sc); ural_free_tx_list(sc); + + if (sc->amrr_xfer != NULL) + usbd_free_xfer(sc->amrr_xfer); +} + +Static void +ural_amrr_start(struct ural_softc *sc, struct ieee80211_node *ni) +{ + struct ural_amrr *amrr = &sc->amrr; + int i; + + /* clear statistic registers (STA_CSR0 to STA_CSR10) */ + ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta); + + amrr->success = 0; + amrr->recovery = 0; + amrr->success_threshold = 0; + amrr->txcnt = amrr->retrycnt = 0; + + /* set rate to some reasonable initial value */ + for (i = ni->ni_rates.rs_nrates - 1; + i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72; + i--); + + ni->ni_txrate = i; + + callout_reset(&sc->amrr_ch, hz, ural_amrr_timeout, sc); +} + +Static void +ural_amrr_timeout(void *arg) +{ + struct ural_softc *sc = (struct ural_softc *)arg; + usb_device_request_t req; + int s; + + s = splusb(); + + /* asynchronously read STA registers (cleared by read) */ + + req.bmRequestType = UT_READ_VENDOR_DEVICE; + req.bRequest = RAL_READ_MULTI_MAC; + USETW(req.wValue, 0); + USETW(req.wIndex, RAL_STA_CSR0); + USETW(req.wLength, 22); + + usbd_setup_default_xfer(sc->amrr_xfer, sc->sc_udev, sc, + USBD_DEFAULT_TIMEOUT, &req, sc->sta, 22, 0, ural_amrr_update); + (void)usbd_transfer(sc->amrr_xfer); + + splx(s); +} + +Static void +ural_amrr_update(usbd_xfer_handle xfer, usbd_private_handle priv, + usbd_status status) +{ + struct ural_softc *sc = (struct ural_softc *)priv; + struct ural_amrr *amrr = &sc->amrr; + + if (status != USBD_NORMAL_COMPLETION) + return; + + amrr->retrycnt = + sc->sta[7] + /* TX one-retry ok count */ + sc->sta[8] + /* TX more-retry ok count */ + sc->sta[8]; /* TX retry-fail count */ + + amrr->txcnt = + amrr->retrycnt + + sc->sta[6]; /* TX no-retry ok count */ + + ural_ratectl(amrr, sc->sc_ic.ic_bss); + + callout_reset(&sc->amrr_ch, hz, ural_amrr_timeout, sc); } /*- @@ -2091,8 +2192,9 @@ ural_stop(void *priv) * http://www-sop.inria.fr/rapports/sophia/RR-5208.html * * This algorithm is particularly well suited for ural since it does not - * require per-frame retry statistics. Note however that since we do not - * have per-frame statistics, we cannot do per-node rate adaptation. + * require per-frame retry statistics. Note however that since h/w does + * not provide per-frame stats, we can't do per-node rate adaptation and + * thus automatic rate adaptation is only enabled in STA operating mode. */ #define URAL_AMRR_MIN_SUCCESS_THRESHOLD 1 @@ -2114,16 +2216,9 @@ ural_stop(void *priv) ((ni)->ni_txrate--) #define reset_cnt(amrr) \ do { (amrr)->txcnt = (amrr)->retrycnt = 0; } while (0) - -Static void ural_ratectl(void *) __unused; - Static void -ural_ratectl(void *priv) +ural_ratectl(struct ural_amrr *amrr, struct ieee80211_node *ni) { - struct ural_softc *sc = (struct ural_softc *)priv; - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_node *ni = ic->ic_bss; - struct ural_amrr *amrr = &sc->amrr; int need_change = 0; if (is_success(amrr) && is_enough(amrr)) { @@ -2137,7 +2232,7 @@ ural_ratectl(void *priv) } else { amrr->recovery = 0; } - } else if (is_failure(amrr)) { + } else if (is_failure(amrr)) { amrr->success = 0; if (!is_min_rate(ni)) { if (amrr->recovery) { diff --git a/sys/dev/usb/if_uralvar.h b/sys/dev/usb/if_uralvar.h index e39c387cdda..782ec22ef7f 100644 --- a/sys/dev/usb/if_uralvar.h +++ b/sys/dev/usb/if_uralvar.h @@ -90,6 +90,8 @@ struct ural_softc { uint32_t asic_rev; uint8_t rf_rev; + usbd_xfer_handle amrr_xfer; + usbd_pipe_handle sc_rx_pipeh; usbd_pipe_handle sc_tx_pipeh; @@ -107,9 +109,11 @@ struct ural_softc { struct mtx sc_mtx; struct callout scan_ch; + struct callout amrr_ch; int sc_tx_timer; + uint16_t sta[11]; uint32_t rf_regs[4]; uint8_t txpow[14];