summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorkevlo <kevlo@FreeBSD.org>2007-05-09 09:32:41 +0000
committerkevlo <kevlo@FreeBSD.org>2007-05-09 09:32:41 +0000
commit845a83180fe66da77c8ddce13b7cef4d80092a3d (patch)
treeb78931c3920427e322e7192231742912c6f421fb /sys/dev
parent987f7301857b90bc6a41f2aeadb401898aa7d040 (diff)
downloadFreeBSD-src-845a83180fe66da77c8ddce13b7cef4d80092a3d.zip
FreeBSD-src-845a83180fe66da77c8ddce13b7cef4d80092a3d.tar.gz
- Remove dependency on deprecated if_watchdog ABI.
- Move amrr code into net80211 itself. - Handle ->INIT state transition in ural_newstate() to eliminate the race. Tested with a ASUS WL-167g.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/if_ural.c139
-rw-r--r--sys/dev/usb/if_uralvar.h13
2 files changed, 34 insertions, 118 deletions
diff --git a/sys/dev/usb/if_ural.c b/sys/dev/usb/if_ural.c
index e6876ca..1cc40ac 100644
--- a/sys/dev/usb/if_ural.c
+++ b/sys/dev/usb/if_ural.c
@@ -50,14 +50,9 @@ __FBSDID("$FreeBSD$");
#include <net/if_types.h>
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
#include <net80211/ieee80211_radiotap.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/if_ether.h>
-
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
@@ -105,6 +100,7 @@ static const struct usb_devno ural_devs[] = {
};
MODULE_DEPEND(ural, wlan, 1, 1, 1);
+MODULE_DEPEND(ural, wlan_amrr, 1, 1, 1);
static int ural_alloc_tx_list(struct ural_softc *);
static void ural_free_tx_list(struct ural_softc *);
@@ -132,7 +128,7 @@ static int ural_tx_mgt(struct ural_softc *, struct mbuf *,
static int ural_tx_data(struct ural_softc *, struct mbuf *,
struct ieee80211_node *);
static void ural_start(struct ifnet *);
-static void ural_watchdog(struct ifnet *);
+static void ural_watchdog(void *);
static int ural_reset(struct ifnet *);
static int ural_ioctl(struct ifnet *, u_long, caddr_t);
static void ural_set_testmode(struct ural_softc *);
@@ -171,8 +167,6 @@ static void ural_amrr_start(struct ural_softc *,
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 *);
/*
* Default values for MAC registers; values taken from the reference driver.
@@ -410,6 +404,7 @@ USB_ATTACH(ural)
MTX_DEF | MTX_RECURSE);
usb_init_task(&sc->sc_task, ural_task, sc);
+ callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
callout_init(&sc->scan_ch, debug_mpsafenet ? CALLOUT_MPSAFE : 0);
callout_init(&sc->amrr_ch, 0);
@@ -435,7 +430,6 @@ USB_ATTACH(ural)
ifp->if_init = ural_init;
ifp->if_ioctl = ural_ioctl;
ifp->if_start = ural_start;
- ifp->if_watchdog = ural_watchdog;
IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
IFQ_SET_READY(&ifp->if_snd);
@@ -494,6 +488,8 @@ USB_ATTACH(ural)
ic->ic_raw_xmit = ural_raw_xmit;
ieee80211_media_init(ic, ural_media_change, ieee80211_media_status);
+ ieee80211_amrr_init(&sc->amrr, ic, 1, 15);
+
bpfattach2(ifp, DLT_IEEE802_11_RADIO,
sizeof (struct ieee80211_frame) + 64, &sc->sc_drvbpf);
@@ -519,6 +515,7 @@ USB_DETACH(ural)
ural_stop(sc);
usb_rem_task(sc->sc_udev, &sc->sc_task);
+ callout_stop(&sc->watchdog_ch);
callout_stop(&sc->scan_ch);
callout_stop(&sc->amrr_ch);
@@ -719,6 +716,8 @@ ural_task(void *arg)
ostate = ic->ic_state;
+ RAL_LOCK(sc);
+
switch (sc->sc_state) {
case IEEE80211_S_INIT:
if (ostate == IEEE80211_S_RUN) {
@@ -785,7 +784,8 @@ ural_task(void *arg)
break;
}
- sc->sc_newstate(ic, sc->sc_state, -1);
+ RAL_UNLOCK(sc);
+ sc->sc_newstate(ic, sc->sc_state, sc->sc_arg);
}
static int
@@ -793,14 +793,18 @@ ural_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
{
struct ural_softc *sc = ic->ic_ifp->if_softc;
- 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;
- usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
+ sc->sc_arg = arg;
+ usb_rem_task(sc->sc_udev, &sc->sc_task);
+ if (nstate == IEEE80211_S_INIT)
+ sc->sc_newstate(ic, nstate, arg);
+ else
+ usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
return 0;
}
@@ -1466,34 +1470,27 @@ ural_start(struct ifnet *ifp)
}
sc->sc_tx_timer = 5;
- ifp->if_timer = 1;
+ callout_reset(&sc->watchdog_ch, hz, ural_watchdog, sc);
}
}
static void
-ural_watchdog(struct ifnet *ifp)
+ural_watchdog(void *arg)
{
- struct ural_softc *sc = ifp->if_softc;
+ struct ural_softc *sc = (struct ural_softc *)arg;
struct ieee80211com *ic = &sc->sc_ic;
- RAL_LOCK(sc);
-
- ifp->if_timer = 0;
-
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
/*ural_init(sc); XXX needs a process context! */
- ifp->if_oerrors++;
- RAL_UNLOCK(sc);
+ sc->sc_ifp->if_oerrors++;
return;
}
- ifp->if_timer = 1;
+ callout_reset(&sc->watchdog_ch, hz, ural_watchdog, sc);
}
ieee80211_watchdog(ic);
-
- RAL_UNLOCK(sc);
}
/*
@@ -2268,12 +2265,11 @@ ural_stop(void *priv)
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = ic->ic_ifp;
- ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
-
sc->sc_tx_timer = 0;
- ifp->if_timer = 0;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+
/* disable Rx */
ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX);
@@ -2344,7 +2340,7 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
goto bad;
}
sc->sc_tx_timer = 5;
- ifp->if_timer = 1;
+ callout_reset(&sc->watchdog_ch, hz, ural_watchdog, sc);
return 0;
bad:
@@ -2353,22 +2349,15 @@ bad:
return EIO; /* XXX */
}
-#define URAL_AMRR_MIN_SUCCESS_THRESHOLD 1
-#define URAL_AMRR_MAX_SUCCESS_THRESHOLD 10
-
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->txcnt = amrr->retrycnt = 0;
- amrr->success_threshold = URAL_AMRR_MIN_SUCCESS_THRESHOLD;
+ ieee80211_amrr_node_init(&sc->amrr, &sc->amn);
/* set rate to some reasonable initial value */
for (i = ni->ni_rates.rs_nrates - 1;
@@ -2406,7 +2395,6 @@ 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;
struct ifnet *ifp = sc->sc_ic.ic_ifp;
if (status != USBD_NORMAL_COMPLETION) {
@@ -2418,85 +2406,18 @@ ural_amrr_update(usbd_xfer_handle xfer, usbd_private_handle priv,
/* count TX retry-fail as Tx errors */
ifp->if_oerrors += sc->sta[9];
- amrr->retrycnt =
+ sc->amn.amn_retrycnt =
sc->sta[7] + /* TX one-retry ok count */
sc->sta[8] + /* TX more-retry ok count */
sc->sta[9]; /* TX retry-fail count */
- amrr->txcnt =
- amrr->retrycnt +
+ sc->amn.amn_txcnt =
+ sc->amn.amn_retrycnt +
sc->sta[6]; /* TX no-retry ok count */
- ural_ratectl(amrr, sc->sc_ic.ic_bss);
+ ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn);
callout_reset(&sc->amrr_ch, hz, ural_amrr_timeout, sc);
}
-/*-
- * Naive implementation of the Adaptive Multi Rate Retry algorithm:
- * "IEEE 802.11 Rate Adaptation: A Practical Approach"
- * Mathieu Lacage, Hossein Manshaei, Thierry Turletti
- * INRIA Sophia - Projet Planete
- * 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 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 is_success(amrr) \
- ((amrr)->retrycnt < (amrr)->txcnt / 10)
-#define is_failure(amrr) \
- ((amrr)->retrycnt > (amrr)->txcnt / 3)
-#define is_enough(amrr) \
- ((amrr)->txcnt > 10)
-#define is_min_rate(ni) \
- ((ni)->ni_txrate == 0)
-#define is_max_rate(ni) \
- ((ni)->ni_txrate == (ni)->ni_rates.rs_nrates - 1)
-#define increase_rate(ni) \
- ((ni)->ni_txrate++)
-#define decrease_rate(ni) \
- ((ni)->ni_txrate--)
-#define reset_cnt(amrr) \
- do { (amrr)->txcnt = (amrr)->retrycnt = 0; } while (0)
-static void
-ural_ratectl(struct ural_amrr *amrr, struct ieee80211_node *ni)
-{
- int need_change = 0;
-
- if (is_success(amrr) && is_enough(amrr)) {
- amrr->success++;
- if (amrr->success >= amrr->success_threshold &&
- !is_max_rate(ni)) {
- amrr->recovery = 1;
- amrr->success = 0;
- increase_rate(ni);
- need_change = 1;
- } else {
- amrr->recovery = 0;
- }
- } else if (is_failure(amrr)) {
- amrr->success = 0;
- if (!is_min_rate(ni)) {
- if (amrr->recovery) {
- amrr->success_threshold *= 2;
- if (amrr->success_threshold >
- URAL_AMRR_MAX_SUCCESS_THRESHOLD)
- amrr->success_threshold =
- URAL_AMRR_MAX_SUCCESS_THRESHOLD;
- } else {
- amrr->success_threshold =
- URAL_AMRR_MIN_SUCCESS_THRESHOLD;
- }
- decrease_rate(ni);
- need_change = 1;
- }
- amrr->recovery = 0; /* original paper was incorrect */
- }
-
- if (is_enough(amrr) || need_change)
- reset_cnt(amrr);
-}
-
DRIVER_MODULE(ural, uhub, ural_driver, ural_devclass, usbd_driver_load, 0);
diff --git a/sys/dev/usb/if_uralvar.h b/sys/dev/usb/if_uralvar.h
index 6c6a44e..18b5cdf 100644
--- a/sys/dev/usb/if_uralvar.h
+++ b/sys/dev/usb/if_uralvar.h
@@ -69,14 +69,6 @@ struct ural_rx_data {
struct mbuf *m;
};
-struct ural_amrr {
- int txcnt;
- int retrycnt;
- int success;
- int success_threshold;
- int recovery;
-};
-
struct ural_softc {
struct ifnet *sc_ifp;
struct ieee80211com sc_ic;
@@ -98,9 +90,11 @@ struct ural_softc {
usbd_pipe_handle sc_tx_pipeh;
enum ieee80211_state sc_state;
+ int sc_arg;
struct usb_task sc_task;
- struct ural_amrr amrr;
+ struct ieee80211_amrr amrr;
+ struct ieee80211_amrr_node amn;
struct ural_rx_data rx_data[RAL_RX_LIST_COUNT];
struct ural_tx_data tx_data[RAL_TX_LIST_COUNT];
@@ -110,6 +104,7 @@ struct ural_softc {
struct mtx sc_mtx;
+ struct callout watchdog_ch;
struct callout scan_ch;
struct callout amrr_ch;
OpenPOWER on IntegriCloud