summaryrefslogtreecommitdiff
path: root/sys/dev/pci/if_wpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/if_wpi.c')
-rw-r--r--sys/dev/pci/if_wpi.c175
1 files changed, 48 insertions, 127 deletions
diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c
index 998ecf8553d..7772e78f522 100644
--- a/sys/dev/pci/if_wpi.c
+++ b/sys/dev/pci/if_wpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpi.c,v 1.20 2006/06/17 18:35:46 damien Exp $ */
+/* $OpenBSD: if_wpi.c,v 1.21 2006/06/17 19:07:19 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -58,6 +58,7 @@
#include <netinet/ip.h>
#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
#include <net80211/ieee80211_radiotap.h>
#include <dev/pci/if_wpireg.h>
@@ -103,8 +104,6 @@ int wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *,
void wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
void wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
struct ieee80211_node *wpi_node_alloc(struct ieee80211com *);
-void wpi_node_copy(struct ieee80211com *, struct ieee80211_node *,
- const struct ieee80211_node *);
int wpi_media_change(struct ifnet *);
int wpi_newstate(struct ieee80211com *, enum ieee80211_state, int);
void wpi_mem_lock(struct wpi_softc *);
@@ -121,8 +120,7 @@ int wpi_load_firmware(struct wpi_softc *, uint32_t, const char *,
int);
void wpi_rx_intr(struct wpi_softc *, struct wpi_rx_desc *,
struct wpi_rx_data *);
-void wpi_tx_intr(struct wpi_softc *, struct wpi_rx_desc *,
- struct wpi_rx_data *);
+void wpi_tx_intr(struct wpi_softc *, struct wpi_rx_desc *);
void wpi_cmd_intr(struct wpi_softc *, struct wpi_rx_desc *);
void wpi_notif_intr(struct wpi_softc *);
int wpi_intr(void *);
@@ -147,11 +145,10 @@ int wpi_reset(struct wpi_softc *);
void wpi_hw_config(struct wpi_softc *);
int wpi_init(struct ifnet *);
void wpi_stop(struct ifnet *, int);
-
-/* rate control algorithm: should be moved to net80211 */
-void wpi_amrr_init(struct wpi_amrr *);
+void wpi_iter_func(void *, struct ieee80211_node *);
void wpi_amrr_timeout(void *);
-void wpi_amrr_ratectl(void *, struct ieee80211_node *);
+void wpi_newassoc(struct ieee80211com *, struct ieee80211_node *,
+ int);
#define WPI_DEBUG
@@ -332,13 +329,15 @@ wpi_attach(struct device *parent, struct device *self, void *aux)
if_attach(ifp);
ieee80211_ifattach(ifp);
ic->ic_node_alloc = wpi_node_alloc;
- ic->ic_node_copy = wpi_node_copy;
+ ic->ic_newassoc = wpi_newassoc;
/* override state transition machine */
sc->sc_newstate = ic->ic_newstate;
ic->ic_newstate = wpi_newstate;
ieee80211_media_init(ifp, wpi_media_change, ieee80211_media_status);
+ sc->amrr.amrr_min_success_threshold = 1;
+ sc->amrr.amrr_max_success_threshold = 15;
timeout_set(&sc->amrr_ch, wpi_amrr_timeout, sc);
sc->powerhook = powerhook_establish(wpi_power, sc);
@@ -737,26 +736,15 @@ wpi_free_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring)
}
}
-/* ARGSUSED */
struct ieee80211_node *
wpi_node_alloc(struct ieee80211com *ic)
{
- struct wpi_amrr *amrr;
+ struct wpi_node *wn;
- amrr = malloc(sizeof (struct wpi_amrr), M_DEVBUF, M_NOWAIT);
- if (amrr != NULL) {
- bzero(amrr, sizeof (struct wpi_amrr));
- wpi_amrr_init(amrr);
- }
- return (struct ieee80211_node *)amrr;
-}
-
-void
-wpi_node_copy(struct ieee80211com *ic, struct ieee80211_node *dst,
- const struct ieee80211_node *src)
-{
- *dst = *src;
- wpi_amrr_init((struct wpi_amrr *)dst);
+ wn = malloc(sizeof (struct wpi_node), M_DEVBUF, M_NOWAIT);
+ if (wn != NULL)
+ bzero(wn, sizeof (struct wpi_node));
+ return (struct ieee80211_node *)wn;
}
int
@@ -838,6 +826,11 @@ wpi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
return error;
}
+ if (ic->ic_opmode == IEEE80211_M_STA) {
+ /* fake a join to init the tx rate */
+ wpi_newassoc(ic, ic->ic_bss, 1);
+ }
+
/* start automatic rate control timer */
if (ic->ic_fixed_rate == -1)
timeout_add(&sc->amrr_ch, hz / 2);
@@ -1207,15 +1200,14 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
}
void
-wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
- struct wpi_rx_data *data)
+wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = &ic->ic_if;
struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3];
- struct wpi_tx_data *txdata = &ring->data[desc->idx];
+ struct wpi_tx_data *data = &ring->data[desc->idx];
struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1);
- struct wpi_amrr *amrr = (struct wpi_amrr *)txdata->ni;
+ struct wpi_node *wn = (struct wpi_node *)data->ni;
DPRINTFN(4, ("tx done: qid=%d idx=%d retries=%d nkill=%d rate=%x "
"duration=%d status=%x\n", desc->qid, desc->idx, stat->ntries,
@@ -1227,18 +1219,18 @@ wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
* XXX we should not count mgmt frames since they're always sent at
* the lowest available bit-rate.
*/
- amrr->txcnt++;
+ wn->amn.amn_txcnt++;
if (stat->ntries > 0) {
DPRINTFN(3, ("tx intr ntries %d\n", stat->ntries));
- amrr->retrycnt++;
+ wn->amn.amn_retrycnt++;
}
- bus_dmamap_unload(sc->sc_dmat, txdata->map);
+ bus_dmamap_unload(sc->sc_dmat, data->map);
- m_freem(txdata->m);
- txdata->m = NULL;
- ieee80211_release_node(ic, txdata->ni);
- txdata->ni = NULL;
+ m_freem(data->m);
+ data->m = NULL;
+ ieee80211_release_node(ic, data->ni);
+ data->ni = NULL;
if ((letoh32(stat->status) & 0xff) != 1)
ifp->if_oerrors++;
@@ -1302,7 +1294,7 @@ wpi_notif_intr(struct wpi_softc *sc)
case WPI_TX_DONE:
/* a 802.11 frame has been transmitted */
- wpi_tx_intr(sc, desc, data);
+ wpi_tx_intr(sc, desc);
break;
case WPI_UC_READY:
@@ -1990,7 +1982,7 @@ wpi_auth(struct wpi_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni = ic->ic_bss;
- struct wpi_node node;
+ struct wpi_node_info node;
int error;
/* update adapter's configuration */
@@ -2173,7 +2165,7 @@ wpi_config(struct wpi_softc *sc)
struct wpi_txpower txpower;
struct wpi_power power;
struct wpi_bluetooth bluetooth;
- struct wpi_node node;
+ struct wpi_node_info node;
int error;
/* Intel's binary only daemon is a joke.. */
@@ -2585,52 +2577,13 @@ wpi_stop(struct ifnet *ifp, int disable)
WPI_WRITE(sc, WPI_RESET, tmp | WPI_SW_RESET);
}
-/*-
- * 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
- */
-#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)
-
-#define WPI_AMRR_MIN_SUCCESS_THRESHOLD 1
-#define WPI_AMRR_MAX_SUCCESS_THRESHOLD 15
-
-/* XXX should reset all nodes on S_INIT */
void
-wpi_amrr_init(struct wpi_amrr *amrr)
+wpi_iter_func(void *arg, struct ieee80211_node *ni)
{
- struct ieee80211_node *ni = &amrr->ni;
- int i;
-
- amrr->success = 0;
- amrr->recovery = 0;
- amrr->txcnt = amrr->retrycnt = 0;
- amrr->success_threshold = WPI_AMRR_MIN_SUCCESS_THRESHOLD;
-
- /* set rate to some reasonable initial value */
- ni = &amrr->ni;
- for (i = ni->ni_rates.rs_nrates - 1;
- i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
- i--);
+ struct wpi_softc *sc = arg;
+ struct wpi_node *wn = (struct wpi_node *)ni;
- ni->ni_txrate = i;
+ ieee80211_amrr_choose(&sc->amrr, ni, &wn->amn);
}
void
@@ -2640,58 +2593,26 @@ wpi_amrr_timeout(void *arg)
struct ieee80211com *ic = &sc->sc_ic;
if (ic->ic_opmode == IEEE80211_M_STA)
- wpi_amrr_ratectl(NULL, ic->ic_bss);
+ wpi_iter_func(sc, ic->ic_bss);
else
- ieee80211_iterate_nodes(ic, wpi_amrr_ratectl, NULL);
+ ieee80211_iterate_nodes(ic, wpi_iter_func, sc);
timeout_add(&sc->amrr_ch, hz / 2);
}
-/* ARGSUSED */
void
-wpi_amrr_ratectl(void *arg, struct ieee80211_node *ni)
+wpi_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
{
- struct wpi_amrr *amrr = (struct wpi_amrr *)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);
- DPRINTFN(2, ("AMRR increasing rate %d (txcnt=%d "
- "retrycnt=%d)\n", ni->ni_txrate, amrr->txcnt,
- amrr->retrycnt));
- 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 >
- WPI_AMRR_MAX_SUCCESS_THRESHOLD)
- amrr->success_threshold =
- WPI_AMRR_MAX_SUCCESS_THRESHOLD;
- } else {
- amrr->success_threshold =
- WPI_AMRR_MIN_SUCCESS_THRESHOLD;
- }
- decrease_rate(ni);
- DPRINTFN(2, ("AMRR decreasing rate %d (txcnt=%d "
- "retrycnt=%d)\n", ni->ni_txrate, amrr->txcnt,
- amrr->retrycnt));
- need_change = 1;
- }
- amrr->recovery = 0; /* paper is incorrect */
- }
+ struct wpi_softc *sc = ic->ic_if.if_softc;
+ int i;
- if (is_enough(amrr) || need_change)
- reset_cnt(amrr);
+ ieee80211_amrr_node_init(&sc->amrr, &((struct wpi_node *)ni)->amn);
+
+ /* 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;
}
struct cfdriver wpi_cd = {