Rework the rate-lowering hack:

* Update sc_txpending[] when a packet is written, even before we issue the TX
  command, since it may be active when we issue the TX command for the
  following packet.
* Do not lower the rate in ni_txrate or id_rateidx, because these are used to
  keep track of sc_txpending[], and could cause us to get "stuck" at the lower
  rate.
This commit is contained in:
mycroft 2004-07-22 20:06:05 +00:00
parent 3a862ed4bf
commit 94e3bc2cef
2 changed files with 20 additions and 19 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: wi.c,v 1.170 2004/07/22 19:56:55 mycroft Exp $ */
/* $NetBSD: wi.c,v 1.171 2004/07/22 20:06:05 mycroft Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.170 2004/07/22 19:56:55 mycroft Exp $");
__KERNEL_RCSID(0, "$NetBSD: wi.c,v 1.171 2004/07/22 20:06:05 mycroft Exp $");
#define WI_HERMES_AUTOINC_WAR /* Work around data write autoinc bug. */
#define WI_HERMES_STATS_WAR /* Work around stats counter bug. */
@ -128,7 +128,7 @@ STATIC void wi_node_free(struct ieee80211com *, struct ieee80211_node *);
STATIC void wi_raise_rate(struct ieee80211com *, struct ieee80211_rssdesc *);
STATIC void wi_lower_rate(struct ieee80211com *, struct ieee80211_rssdesc *);
STATIC void wi_choose_rate(struct ieee80211com *, struct ieee80211_node *,
STATIC int wi_choose_rate(struct ieee80211com *, struct ieee80211_node *,
struct ieee80211_frame *, u_int);
STATIC void wi_rssadapt_updatestats_cb(void *, struct ieee80211_node *);
STATIC void wi_rssadapt_updatestats(void *);
@ -866,7 +866,7 @@ wi_stop(struct ifnet *ifp, int disable)
*
* TBD Adapt fragmentation threshold.
*/
STATIC void
STATIC int
wi_choose_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
struct ieee80211_frame *wh, u_int len)
{
@ -885,6 +885,8 @@ wi_choose_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
((ic->ic_if.if_flags & IFF_DEBUG) == 0) ? NULL : ic->ic_if.if_xname,
do_not_adapt);
ni->ni_txrate = rateidx;
if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
/* choose the slowest pending rate so that we don't
* accidentally send a packet on the MAC's queue
@ -892,11 +894,11 @@ wi_choose_rate(struct ieee80211com *ic, struct ieee80211_node *ni,
* packets w/ rate when enqueued or dequeued.
*/
for (i = 0; i < rateidx && sc->sc_txpending[i] == 0; i++);
ni->ni_txrate = i;
} else
ni->ni_txrate = rateidx;
rateidx = i;
}
splx(s);
return;
return (rateidx);
}
STATIC void
@ -944,7 +946,7 @@ wi_start(struct ifnet *ifp)
struct ieee80211_rssdesc *id;
struct mbuf *m0;
struct wi_frame frmhdr;
int cur, fid, off;
int cur, fid, off, rateidx;
if (!sc->sc_enabled || sc->sc_invalid)
return;
@ -1041,7 +1043,8 @@ wi_start(struct ifnet *ifp)
frmhdr.wi_tx_ctl |= htole16(WI_TXCNTL_NOCRYPT);
}
wi_choose_rate(ic, ni, wh, m0->m_pkthdr.len);
rateidx = wi_choose_rate(ic, ni, wh, m0->m_pkthdr.len);
rs = &ni->ni_rates;
#if NBPFILTER > 0
if (sc->sc_drvbpf) {
@ -1049,7 +1052,7 @@ wi_start(struct ifnet *ifp)
struct wi_tx_radiotap_header *tap = &sc->sc_txtap;
tap->wt_rate = ni->ni_rates.rs_rates[ni->ni_txrate];
tap->wt_rate = rs->rs_rates[ni->ni_txrate];
tap->wt_chan_freq =
htole16(ic->ic_bss->ni_chan->ic_freq);
tap->wt_chan_flags =
@ -1065,20 +1068,20 @@ wi_start(struct ifnet *ifp)
bpf_mtap(sc->sc_drvbpf, &mb);
}
#endif
rs = &ni->ni_rates;
rd = SLIST_FIRST(&sc->sc_rssdfree);
id = &rd->rd_desc;
id->id_len = m0->m_pkthdr.len;
sc->sc_txd[cur].d_rate = id->id_rateidx = ni->ni_txrate;
id->id_rateidx = ni->ni_txrate;
id->id_rssi = ni->ni_rssi;
frmhdr.wi_tx_idx = rd - sc->sc_rssd;
if (ic->ic_opmode == IEEE80211_M_HOSTAP)
frmhdr.wi_tx_rate = 5 * (rs->rs_rates[ni->ni_txrate] &
frmhdr.wi_tx_rate = 5 * (rs->rs_rates[rateidx] &
IEEE80211_RATE_VAL);
else if (sc->sc_flags & WI_FLAGS_RSSADAPTSTA)
(void)wi_write_txrate(sc, rs->rs_rates[ni->ni_txrate]);
(void)wi_write_txrate(sc, rs->rs_rates[rateidx]);
m_copydata(m0, 0, sizeof(struct ieee80211_frame),
(caddr_t)&frmhdr.wi_whdr);
@ -1096,6 +1099,7 @@ wi_start(struct ifnet *ifp)
}
m_freem(m0);
sc->sc_txd[cur].d_len = off;
sc->sc_txpending[ni->ni_txrate]++;
if (sc->sc_txcur == cur) {
if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
printf("%s: xmit failed\n",
@ -1103,7 +1107,6 @@ wi_start(struct ifnet *ifp)
sc->sc_txd[cur].d_len = 0;
goto next;
}
sc->sc_txpending[ni->ni_txrate]++;
sc->sc_tx_timer = 5;
ifp->if_timer = 1;
}
@ -1663,7 +1666,6 @@ wi_txalloc_intr(struct wi_softc *sc)
printf("%s: xmit failed\n", sc->sc_dev.dv_xname);
sc->sc_txd[cur].d_len = 0;
} else {
sc->sc_txpending[sc->sc_txd[cur].d_rate]++;
sc->sc_tx_timer = 5;
ifp->if_timer = 1;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: wivar.h,v 1.43 2004/02/10 00:59:38 dyoung Exp $ */
/* $NetBSD: wivar.h,v 1.44 2004/07/22 20:06:05 mycroft Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@ -126,7 +126,6 @@ struct wi_softc {
struct sc_txdesc {
int d_fid;
int d_len;
int d_rate;
} sc_txd[WI_NTXBUF];
int sc_txnext;
int sc_txcur;