Second part of the AMRR commit.

Enable automatic rate adaptation in BSS operating mode.
Works great here.  Will need a lot of testing though.
This commit is contained in:
Damien Bergamini 2005-11-18 21:37:02 +00:00
parent ef39adf007
commit 8403bb96a2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=152593
2 changed files with 112 additions and 13 deletions

View file

@ -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) {

View file

@ -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];