Track v0.9.20.3 hal:
o no more ds_vdata in tx/rx descriptors o split h/w tx/rx descriptor from s/w status o as part of the descriptor split change the rate control module api so the ath_buf is passed in to the module so it can fetch both descriptor and status information as needed o add some const poisoning Also for sample rate control algorithm: o split debug msgs (node, rate, any) o uniformly bounds check rate indices (and in some cases correct checks) o move array index ops to after bounds checking o use final tsi from the status block instead of the h/w descriptor o replace h/w descriptor struct's with proper mask+shift defs (this doesn't belong here; everything is known by the driver and should just be sent down so there's no h/w-specific knowledge) MFC after: 1 month
This commit is contained in:
parent
8b33360649
commit
65f9edeee1
@ -142,11 +142,12 @@ ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
|
||||
|
||||
void
|
||||
ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
|
||||
const struct ath_desc *ds, const struct ath_desc *ds0)
|
||||
const struct ath_buf *bf)
|
||||
{
|
||||
struct amrr_node *amn = ATH_NODE_AMRR(an);
|
||||
int sr = ds->ds_txstat.ts_shortretry;
|
||||
int lr = ds->ds_txstat.ts_longretry;
|
||||
const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
|
||||
int sr = ts->ts_shortretry;
|
||||
int lr = ts->ts_longretry;
|
||||
int retry_count = sr + lr;
|
||||
|
||||
amn->amn_tx_try0_cnt++;
|
||||
|
@ -159,16 +159,17 @@ ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
|
||||
|
||||
void
|
||||
ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
|
||||
const struct ath_desc *ds, const struct ath_desc *ds0)
|
||||
const struct ath_buf *bf)
|
||||
{
|
||||
struct onoe_node *on = ATH_NODE_ONOE(an);
|
||||
const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
|
||||
|
||||
if (ds->ds_txstat.ts_status == 0)
|
||||
if (ts->ts_status == 0)
|
||||
on->on_tx_ok++;
|
||||
else
|
||||
on->on_tx_err++;
|
||||
on->on_tx_retr += ds->ds_txstat.ts_shortretry
|
||||
+ ds->ds_txstat.ts_longretry;
|
||||
on->on_tx_retr += ts->ts_shortretry
|
||||
+ ts->ts_longretry;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -78,14 +78,18 @@ __FBSDID("$FreeBSD$");
|
||||
#define SAMPLE_DEBUG
|
||||
#ifdef SAMPLE_DEBUG
|
||||
enum {
|
||||
ATH_DEBUG_RATE = 0x00000010 /* rate control */
|
||||
ATH_DEBUG_NODE = 0x00080000, /* node management */
|
||||
ATH_DEBUG_RATE = 0x00000010, /* rate control */
|
||||
ATH_DEBUG_ANY = 0xffffffff
|
||||
};
|
||||
#define DPRINTF(sc, _fmt, ...) do { \
|
||||
if (sc->sc_debug & ATH_DEBUG_RATE) \
|
||||
printf(_fmt, __VA_ARGS__); \
|
||||
#define DPRINTF(sc, m, fmt, ...) do { \
|
||||
if (sc->sc_debug & (m)) \
|
||||
printf(fmt, __VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DPRINTF(sc, _fmt, ...)
|
||||
#define DPRINTF(sc, m, fmt, ...) do { \
|
||||
(void) sc; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -147,14 +151,14 @@ rate_to_ndx(struct sample_node *sn, int rate) {
|
||||
void
|
||||
ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
DPRINTF(sc, "%s:\n", __func__);
|
||||
DPRINTF(sc, ATH_DEBUG_NODE, "%s:\n", __func__);
|
||||
/* NB: assumed to be zero'd by caller */
|
||||
}
|
||||
|
||||
void
|
||||
ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
DPRINTF(sc, "%s:\n", __func__);
|
||||
DPRINTF(sc, ATH_DEBUG_NODE, "%s:\n", __func__);
|
||||
}
|
||||
|
||||
|
||||
@ -318,18 +322,19 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
|
||||
|
||||
if (change_rates) {
|
||||
if (best_ndx != sn->current_rate[size_bin]) {
|
||||
DPRINTF(sc, "%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d\n",
|
||||
__func__,
|
||||
ether_sprintf(an->an_node.ni_macaddr),
|
||||
packet_size_bins[size_bin],
|
||||
sn->rates[sn->current_rate[size_bin]].rate,
|
||||
sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time,
|
||||
sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time,
|
||||
sn->rates[best_ndx].rate,
|
||||
sn->stats[size_bin][best_ndx].average_tx_time,
|
||||
sn->stats[size_bin][best_ndx].perfect_tx_time,
|
||||
sn->packets_since_switch[size_bin],
|
||||
mrr);
|
||||
DPRINTF(sc, ATH_DEBUG_RATE,
|
||||
"%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d\n",
|
||||
__func__,
|
||||
ether_sprintf(an->an_node.ni_macaddr),
|
||||
packet_size_bins[size_bin],
|
||||
sn->rates[sn->current_rate[size_bin]].rate,
|
||||
sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time,
|
||||
sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time,
|
||||
sn->rates[best_ndx].rate,
|
||||
sn->stats[size_bin][best_ndx].average_tx_time,
|
||||
sn->stats[size_bin][best_ndx].perfect_tx_time,
|
||||
sn->packets_since_switch[size_bin],
|
||||
mrr);
|
||||
}
|
||||
sn->packets_since_switch[size_bin] = 0;
|
||||
sn->current_rate[size_bin] = best_ndx;
|
||||
@ -406,30 +411,51 @@ update_stats(struct ath_softc *sc, struct ath_node *an,
|
||||
|
||||
size_bin = size_to_bin(frame_size);
|
||||
size = bin_to_size(size_bin);
|
||||
|
||||
if (!(0 <= ndx0 && ndx0 < sn->num_rates)) {
|
||||
printf("%s: bogus ndx0 %d, max %u, mode %u\n",
|
||||
__func__, ndx0, sn->num_rates, sc->sc_curmode);
|
||||
return;
|
||||
}
|
||||
rate = sn->rates[ndx0].rate;
|
||||
|
||||
tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx0].rix,
|
||||
short_tries-1,
|
||||
short_tries,
|
||||
MIN(tries0, tries) - 1);
|
||||
tries_so_far += tries0;
|
||||
if (tries1 && tries0 < tries) {
|
||||
if (!(0 <= ndx1 && ndx1 < sn->num_rates)) {
|
||||
printf("%s: bogus ndx1 %d, max %u, mode %u\n",
|
||||
__func__, ndx1, sn->num_rates, sc->sc_curmode);
|
||||
return;
|
||||
}
|
||||
tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx1].rix,
|
||||
short_tries-1,
|
||||
short_tries,
|
||||
MIN(tries1 + tries_so_far, tries) - tries_so_far - 1);
|
||||
}
|
||||
tries_so_far += tries1;
|
||||
|
||||
if (tries2 && tries0 + tries1 < tries) {
|
||||
if (!(0 <= ndx2 && ndx2 < sn->num_rates)) {
|
||||
printf("%s: bogus ndx2 %d, max %u, mode %u\n",
|
||||
__func__, ndx2, sn->num_rates, sc->sc_curmode);
|
||||
return;
|
||||
}
|
||||
tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx2].rix,
|
||||
short_tries-1,
|
||||
short_tries,
|
||||
MIN(tries2 + tries_so_far, tries) - tries_so_far - 1);
|
||||
}
|
||||
|
||||
tries_so_far += tries2;
|
||||
|
||||
if (tries3 && tries0 + tries1 + tries2 < tries) {
|
||||
if (!(0 <= ndx3 && ndx3 < sn->num_rates)) {
|
||||
printf("%s: bogus ndx3 %d, max %u, mode %u\n",
|
||||
__func__, ndx3, sn->num_rates, sc->sc_curmode);
|
||||
return;
|
||||
}
|
||||
tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx3].rix,
|
||||
short_tries-1,
|
||||
short_tries,
|
||||
MIN(tries3 + tries_so_far, tries) - tries_so_far - 1);
|
||||
}
|
||||
if (sn->stats[size_bin][ndx0].total_packets < (100 / (100 - ssc->ath_smoothing_rate))) {
|
||||
@ -467,12 +493,14 @@ update_stats(struct ath_softc *sc, struct ath_node *an,
|
||||
|
||||
|
||||
if (ndx0 == sn->current_sample_ndx[size_bin]) {
|
||||
DPRINTF(sc, "%s: %s size %d sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d) status %d\n",
|
||||
__func__, ether_sprintf(an->an_node.ni_macaddr),
|
||||
size, rate, short_tries, tries, tt,
|
||||
sn->stats[size_bin][ndx0].average_tx_time,
|
||||
sn->stats[size_bin][ndx0].perfect_tx_time,
|
||||
status);
|
||||
DPRINTF(sc, ATH_DEBUG_RATE,
|
||||
"%s: %s size %d %s sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d)\n",
|
||||
__func__, ether_sprintf(an->an_node.ni_macaddr),
|
||||
size,
|
||||
status ? "FAIL" : "OK",
|
||||
rate, short_tries, tries, tt,
|
||||
sn->stats[size_bin][ndx0].average_tx_time,
|
||||
sn->stats[size_bin][ndx0].perfect_tx_time);
|
||||
sn->sample_tt[size_bin] = tt;
|
||||
sn->current_sample_ndx[size_bin] = -1;
|
||||
}
|
||||
@ -480,117 +508,124 @@ update_stats(struct ath_softc *sc, struct ath_node *an,
|
||||
|
||||
void
|
||||
ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
|
||||
const struct ath_desc *ds, const struct ath_desc *ds0)
|
||||
const struct ath_buf *bf)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct sample_node *sn = ATH_NODE_SAMPLE(an);
|
||||
const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0;
|
||||
const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
|
||||
const struct ath_desc *ds0 = &bf->bf_desc[0];
|
||||
int final_rate, short_tries, long_tries, frame_size;
|
||||
int ndx = -1;
|
||||
int mrr;
|
||||
|
||||
final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
|
||||
short_tries = ds->ds_txstat.ts_shortretry + 1;
|
||||
long_tries = ds->ds_txstat.ts_longretry + 1;
|
||||
final_rate = sc->sc_hwmap[ts->ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
|
||||
short_tries = ts->ts_shortretry;
|
||||
long_tries = ts->ts_longretry + 1;
|
||||
frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
|
||||
if (frame_size == 0) /* NB: should not happen */
|
||||
frame_size = 1500;
|
||||
|
||||
if (sn->num_rates <= 0) {
|
||||
DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d "
|
||||
"no rates yet\n",
|
||||
__func__, ether_sprintf(an->an_node.ni_macaddr),
|
||||
bin_to_size(size_to_bin(frame_size)),
|
||||
ds->ds_txstat.ts_status,
|
||||
short_tries, long_tries);
|
||||
DPRINTF(sc, ATH_DEBUG_RATE,
|
||||
"%s: %s size %d %s rate/try %d/%d no rates yet\n",
|
||||
__func__, ether_sprintf(an->an_node.ni_macaddr),
|
||||
bin_to_size(size_to_bin(frame_size)),
|
||||
ts->ts_status ? "FAIL" : "OK",
|
||||
short_tries, long_tries);
|
||||
return;
|
||||
}
|
||||
|
||||
mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);
|
||||
|
||||
if (sc->sc_mrretry && ds->ds_txstat.ts_status) {
|
||||
/* this packet failed */
|
||||
DPRINTF(sc, "%s: %s size %d rate/try %d/%d %d/%d %d/%d %d/%d status %s retries (%d/%d)\n",
|
||||
__func__,
|
||||
ether_sprintf(an->an_node.ni_macaddr),
|
||||
bin_to_size(size_to_bin(frame_size)),
|
||||
sc->sc_hwmap[ads->xmit_rate0].ieeerate,
|
||||
ads->xmit_tries0,
|
||||
sc->sc_hwmap[ads->xmit_rate1].ieeerate,
|
||||
ads->xmit_tries1,
|
||||
sc->sc_hwmap[ads->xmit_rate2].ieeerate,
|
||||
ads->xmit_tries2,
|
||||
sc->sc_hwmap[ads->xmit_rate3].ieeerate,
|
||||
ads->xmit_tries3,
|
||||
ds->ds_txstat.ts_status ? "FAIL" : "OK",
|
||||
short_tries,
|
||||
long_tries);
|
||||
if (ts->ts_status) { /* this packet failed */
|
||||
DPRINTF(sc, ATH_DEBUG_RATE,
|
||||
"%s: %s size %d rate/try [%d/%d %d/%d %d/%d %d/%d] FAIL tries [%d/%d]\n",
|
||||
__func__,
|
||||
ether_sprintf(an->an_node.ni_macaddr),
|
||||
bin_to_size(size_to_bin(frame_size)),
|
||||
sc->sc_hwmap[MS(ds0->ds_ctl3, AR_XmitRate0)].ieeerate,
|
||||
MS(ds0->ds_ctl2, AR_XmitDataTries0),
|
||||
sc->sc_hwmap[MS(ds0->ds_ctl3, AR_XmitRate1)].ieeerate,
|
||||
MS(ds0->ds_ctl2, AR_XmitDataTries1),
|
||||
sc->sc_hwmap[MS(ds0->ds_ctl3, AR_XmitRate2)].ieeerate,
|
||||
MS(ds0->ds_ctl2, AR_XmitDataTries2),
|
||||
sc->sc_hwmap[MS(ds0->ds_ctl3, AR_XmitRate3)].ieeerate,
|
||||
MS(ds0->ds_ctl2, AR_XmitDataTries3),
|
||||
short_tries, long_tries);
|
||||
}
|
||||
|
||||
if (!mrr || !(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) {
|
||||
/* only one rate was used */
|
||||
ndx = rate_to_ndx(sn, final_rate);
|
||||
DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d/%d\n",
|
||||
__func__, ether_sprintf(an->an_node.ni_macaddr),
|
||||
bin_to_size(size_to_bin(frame_size)),
|
||||
ds->ds_txstat.ts_status,
|
||||
ndx, short_tries, long_tries);
|
||||
if (ndx >= 0 && ndx < sn->num_rates) {
|
||||
update_stats(sc, an, frame_size,
|
||||
ndx, long_tries,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
short_tries, long_tries, ds->ds_txstat.ts_status);
|
||||
}
|
||||
mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);
|
||||
if (!mrr || !(ts->ts_rate & HAL_TXSTAT_ALTRATE)) {
|
||||
int ndx = rate_to_ndx(sn, final_rate);
|
||||
|
||||
/*
|
||||
* Only one rate was used; optimize work.
|
||||
*/
|
||||
DPRINTF(sc, ATH_DEBUG_RATE,
|
||||
"%s: %s size %d %s rate/try %d/%d/%d\n",
|
||||
__func__, ether_sprintf(an->an_node.ni_macaddr),
|
||||
bin_to_size(size_to_bin(frame_size)),
|
||||
ts->ts_status ? "FAIL" : "OK",
|
||||
final_rate, short_tries, long_tries);
|
||||
update_stats(sc, an, frame_size,
|
||||
ndx, long_tries,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
short_tries, long_tries, ts->ts_status);
|
||||
} else {
|
||||
int rate0, tries0, ndx0;
|
||||
int rate1, tries1, ndx1;
|
||||
int rate2, tries2, ndx2;
|
||||
int rate3, tries3, ndx3;
|
||||
int finalTSIdx = ads->final_ts_index;
|
||||
int finalTSIdx = ts->ts_finaltsi;
|
||||
|
||||
/*
|
||||
* Process intermediate rates that failed.
|
||||
*/
|
||||
|
||||
rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate;
|
||||
tries0 = ads->xmit_tries0;
|
||||
rate0 = sc->sc_hwmap[MS(ds0->ds_ctl3, AR_XmitRate0)].ieeerate;
|
||||
tries0 = MS(ds0->ds_ctl2, AR_XmitDataTries0);
|
||||
ndx0 = rate_to_ndx(sn, rate0);
|
||||
|
||||
rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate;
|
||||
tries1 = ads->xmit_tries1;
|
||||
|
||||
rate1 = sc->sc_hwmap[MS(ds0->ds_ctl3, AR_XmitRate1)].ieeerate;
|
||||
tries1 = MS(ds0->ds_ctl2, AR_XmitDataTries1);
|
||||
ndx1 = rate_to_ndx(sn, rate1);
|
||||
|
||||
rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate;
|
||||
tries2 = ads->xmit_tries2;
|
||||
|
||||
rate2 = sc->sc_hwmap[MS(ds0->ds_ctl3, AR_XmitRate2)].ieeerate;
|
||||
tries2 = MS(ds0->ds_ctl2, AR_XmitDataTries2);
|
||||
ndx2 = rate_to_ndx(sn, rate2);
|
||||
|
||||
rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate;
|
||||
tries3 = ads->xmit_tries3;
|
||||
|
||||
rate3 = sc->sc_hwmap[MS(ds0->ds_ctl3, AR_XmitRate3)].ieeerate;
|
||||
tries3 = MS(ds0->ds_ctl2, AR_XmitDataTries3);
|
||||
ndx3 = rate_to_ndx(sn, rate3);
|
||||
|
||||
|
||||
#if 1
|
||||
DPRINTF(sc, "%s: %s size %d finaltsidx %d tries %d status %d rate/try %d/%d %d/%d %d/%d %d/%d\n",
|
||||
__func__, ether_sprintf(an->an_node.ni_macaddr),
|
||||
bin_to_size(size_to_bin(frame_size)),
|
||||
finalTSIdx,
|
||||
long_tries,
|
||||
ds->ds_txstat.ts_status,
|
||||
rate0, tries0,
|
||||
rate1, tries1,
|
||||
rate2, tries2,
|
||||
rate3, tries3);
|
||||
DPRINTF(sc, ATH_DEBUG_RATE,
|
||||
"%s: %s size %d finaltsidx %d tries %d %s rate/try [%d/%d %d/%d %d/%d %d/%d]\n",
|
||||
__func__, ether_sprintf(an->an_node.ni_macaddr),
|
||||
bin_to_size(size_to_bin(frame_size)),
|
||||
finalTSIdx,
|
||||
long_tries,
|
||||
ts->ts_status ? "FAIL" : "OK",
|
||||
rate0, tries0,
|
||||
rate1, tries1,
|
||||
rate2, tries2,
|
||||
rate3, tries3);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NB: series > 0 are not penalized for failure
|
||||
* based on the try counts under the assumption
|
||||
* that losses are often bursty and since we
|
||||
* sample higher rates 1 try at a time doing so
|
||||
* may unfairly penalize them.
|
||||
*/
|
||||
if (tries0) {
|
||||
update_stats(sc, an, frame_size,
|
||||
ndx0, tries0,
|
||||
ndx1, tries1,
|
||||
ndx2, tries2,
|
||||
ndx3, tries3,
|
||||
short_tries, ds->ds_txstat.ts_longretry + 1,
|
||||
short_tries, long_tries,
|
||||
long_tries > tries0);
|
||||
long_tries -= tries0;
|
||||
}
|
||||
|
||||
if (tries1 && finalTSIdx > 0) {
|
||||
@ -599,8 +634,9 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
|
||||
ndx2, tries2,
|
||||
ndx3, tries3,
|
||||
0, 0,
|
||||
short_tries, ds->ds_txstat.ts_longretry + 1 - tries0,
|
||||
ds->ds_txstat.ts_status);
|
||||
short_tries, long_tries,
|
||||
ts->ts_status);
|
||||
long_tries -= tries1;
|
||||
}
|
||||
|
||||
if (tries2 && finalTSIdx > 1) {
|
||||
@ -609,8 +645,9 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
|
||||
ndx3, tries3,
|
||||
0, 0,
|
||||
0, 0,
|
||||
short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1,
|
||||
ds->ds_txstat.ts_status);
|
||||
short_tries, long_tries,
|
||||
ts->ts_status);
|
||||
long_tries -= tries2;
|
||||
}
|
||||
|
||||
if (tries3 && finalTSIdx > 2) {
|
||||
@ -619,8 +656,8 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1 - tries2,
|
||||
ds->ds_txstat.ts_status);
|
||||
short_tries, long_tries,
|
||||
ts->ts_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -628,8 +665,8 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
|
||||
void
|
||||
ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
|
||||
{
|
||||
DPRINTF(sc, "%s: %s isnew %d\n", __func__,
|
||||
ether_sprintf(an->an_node.ni_macaddr), isnew);
|
||||
DPRINTF(sc, ATH_DEBUG_NODE, "%s: %s isnew %d\n", __func__,
|
||||
ether_sprintf(an->an_node.ni_macaddr), isnew);
|
||||
if (isnew)
|
||||
ath_rate_ctl_reset(sc, &an->an_node);
|
||||
}
|
||||
@ -668,15 +705,16 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
|
||||
sn->static_rate_ndx = srate;
|
||||
}
|
||||
|
||||
DPRINTF(sc, "%s: %s size 1600 rate/tt", __func__, ether_sprintf(ni->ni_macaddr));
|
||||
DPRINTF(sc, ATH_DEBUG_RATE, "%s: %s size 1600 rate/tt",
|
||||
__func__, ether_sprintf(ni->ni_macaddr));
|
||||
|
||||
sn->num_rates = ni->ni_rates.rs_nrates;
|
||||
for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
|
||||
sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
|
||||
sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
|
||||
if (sn->rates[x].rix == 0xff) {
|
||||
DPRINTF(sc, "%s: ignore bogus rix at %d\n",
|
||||
__func__, x);
|
||||
DPRINTF(sc, ATH_DEBUG_RATE,
|
||||
"%s: ignore bogus rix at %d\n", __func__, x);
|
||||
continue;
|
||||
}
|
||||
sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
|
||||
@ -684,11 +722,10 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
|
||||
rt->info[sn->rates[x].rix].rateCode |
|
||||
rt->info[sn->rates[x].rix].shortPreamble;
|
||||
|
||||
DPRINTF(sc, " %d/%d", sn->rates[x].rate,
|
||||
calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix,
|
||||
0,0));
|
||||
DPRINTF(sc, ATH_DEBUG_RATE, " %d/%d", sn->rates[x].rate,
|
||||
calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix, 0,0));
|
||||
}
|
||||
DPRINTF(sc, "%s\n", "");
|
||||
DPRINTF(sc, ATH_DEBUG_RATE, "%s\n", "");
|
||||
|
||||
/* set the visible bit-rate to the lowest one available */
|
||||
ni->ni_txrate = 0;
|
||||
@ -724,14 +761,15 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
|
||||
sn->current_rate[y] = ndx;
|
||||
}
|
||||
|
||||
DPRINTF(sc, "%s: %s %d rates %d%sMbps (%dus)- %d%sMbps (%dus)\n",
|
||||
__func__, ether_sprintf(ni->ni_macaddr),
|
||||
sn->num_rates,
|
||||
sn->rates[0].rate/2, sn->rates[0].rate % 0x1 ? ".5" : "",
|
||||
sn->stats[1][0].perfect_tx_time,
|
||||
sn->rates[sn->num_rates-1].rate/2,
|
||||
sn->rates[sn->num_rates-1].rate % 0x1 ? ".5" : "",
|
||||
sn->stats[1][sn->num_rates-1].perfect_tx_time
|
||||
DPRINTF(sc, ATH_DEBUG_RATE,
|
||||
"%s: %s %d rates %d%sMbps (%dus)- %d%sMbps (%dus)\n",
|
||||
__func__, ether_sprintf(ni->ni_macaddr),
|
||||
sn->num_rates,
|
||||
sn->rates[0].rate/2, sn->rates[0].rate % 0x1 ? ".5" : "",
|
||||
sn->stats[1][0].perfect_tx_time,
|
||||
sn->rates[sn->num_rates-1].rate/2,
|
||||
sn->rates[sn->num_rates-1].rate % 0x1 ? ".5" : "",
|
||||
sn->stats[1][sn->num_rates-1].perfect_tx_time
|
||||
);
|
||||
|
||||
if (sn->static_rate_ndx != -1)
|
||||
@ -789,7 +827,7 @@ ath_rate_attach(struct ath_softc *sc)
|
||||
{
|
||||
struct sample_softc *osc;
|
||||
|
||||
DPRINTF(sc, "%s:\n", __func__);
|
||||
DPRINTF(sc, ATH_DEBUG_ANY, "%s:\n", __func__);
|
||||
osc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO);
|
||||
if (osc == NULL)
|
||||
return NULL;
|
||||
|
@ -107,77 +107,36 @@ struct sample_node {
|
||||
#define WIFI_CW_MIN 31
|
||||
#define WIFI_CW_MAX 1023
|
||||
|
||||
struct ar5212_desc {
|
||||
/*
|
||||
* tx_control_0
|
||||
*/
|
||||
u_int32_t frame_len:12;
|
||||
u_int32_t reserved_12_15:4;
|
||||
u_int32_t xmit_power:6;
|
||||
u_int32_t rts_cts_enable:1;
|
||||
u_int32_t veol:1;
|
||||
u_int32_t clear_dest_mask:1;
|
||||
u_int32_t ant_mode_xmit:4;
|
||||
u_int32_t inter_req:1;
|
||||
u_int32_t encrypt_key_valid:1;
|
||||
u_int32_t cts_enable:1;
|
||||
/*
|
||||
* Definitions for pulling the rate and trie counts from
|
||||
* a 5212 h/w descriptor. These Don't belong here; the
|
||||
* driver should record this information so the rate control
|
||||
* code doesn't go groveling around in the descriptor bits.
|
||||
*/
|
||||
#define ds_ctl2 ds_hw[0]
|
||||
#define ds_ctl3 ds_hw[1]
|
||||
|
||||
/*
|
||||
* tx_control_1
|
||||
*/
|
||||
u_int32_t buf_len:12;
|
||||
u_int32_t more:1;
|
||||
u_int32_t encrypt_key_index:7;
|
||||
u_int32_t frame_type:4;
|
||||
u_int32_t no_ack:1;
|
||||
u_int32_t comp_proc:2;
|
||||
u_int32_t comp_iv_len:2;
|
||||
u_int32_t comp_icv_len:2;
|
||||
u_int32_t reserved_31:1;
|
||||
/* TX ds_ctl2 */
|
||||
#define AR_XmitDataTries0 0x000f0000 /* series 0 max attempts */
|
||||
#define AR_XmitDataTries0_S 16
|
||||
#define AR_XmitDataTries1 0x00f00000 /* series 1 max attempts */
|
||||
#define AR_XmitDataTries1_S 20
|
||||
#define AR_XmitDataTries2 0x0f000000 /* series 2 max attempts */
|
||||
#define AR_XmitDataTries2_S 24
|
||||
#define AR_XmitDataTries3 0xf0000000 /* series 3 max attempts */
|
||||
#define AR_XmitDataTries3_S 28
|
||||
|
||||
/*
|
||||
* tx_control_2
|
||||
*/
|
||||
u_int32_t rts_duration:15;
|
||||
u_int32_t duration_update_enable:1;
|
||||
u_int32_t xmit_tries0:4;
|
||||
u_int32_t xmit_tries1:4;
|
||||
u_int32_t xmit_tries2:4;
|
||||
u_int32_t xmit_tries3:4;
|
||||
/* TX ds_ctl3 */
|
||||
#define AR_XmitRate0 0x0000001f /* series 0 tx rate */
|
||||
#define AR_XmitRate0_S 0
|
||||
#define AR_XmitRate1 0x000003e0 /* series 1 tx rate */
|
||||
#define AR_XmitRate1_S 5
|
||||
#define AR_XmitRate2 0x00007c00 /* series 2 tx rate */
|
||||
#define AR_XmitRate2_S 10
|
||||
#define AR_XmitRate3 0x000f8000 /* series 3 tx rate */
|
||||
#define AR_XmitRate3_S 15
|
||||
|
||||
/*
|
||||
* tx_control_3
|
||||
*/
|
||||
u_int32_t xmit_rate0:5;
|
||||
u_int32_t xmit_rate1:5;
|
||||
u_int32_t xmit_rate2:5;
|
||||
u_int32_t xmit_rate3:5;
|
||||
u_int32_t rts_cts_rate:5;
|
||||
u_int32_t reserved_25_31:7;
|
||||
|
||||
/*
|
||||
* tx_status_0
|
||||
*/
|
||||
u_int32_t frame_xmit_ok:1;
|
||||
u_int32_t excessive_retries:1;
|
||||
u_int32_t fifo_underrun:1;
|
||||
u_int32_t filtered:1;
|
||||
u_int32_t rts_fail_count:4;
|
||||
u_int32_t data_fail_count:4;
|
||||
u_int32_t virt_coll_count:4;
|
||||
u_int32_t send_timestamp:16;
|
||||
|
||||
/*
|
||||
* tx_status_1
|
||||
*/
|
||||
u_int32_t done:1;
|
||||
u_int32_t seq_num:12;
|
||||
u_int32_t ack_sig_strength:8;
|
||||
u_int32_t final_ts_index:2;
|
||||
u_int32_t comp_success:1;
|
||||
u_int32_t xmit_antenna:1;
|
||||
u_int32_t reserved_25_31_x:7;
|
||||
} __packed;
|
||||
#define MS(_v, _f) (((_v) & (_f)) >> _f##_S)
|
||||
|
||||
/*
|
||||
* Calculate the transmit duration of a frame.
|
||||
@ -195,18 +154,16 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc,
|
||||
int tt = 0;
|
||||
int x = 0;
|
||||
int cw = WIFI_CW_MIN;
|
||||
int cix = rt->info[rix].controlRate;
|
||||
int cix;
|
||||
|
||||
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
|
||||
|
||||
if (!rt->info[rix].rateKbps) {
|
||||
printf("rix %d (%d) bad ratekbps %d mode %u\n",
|
||||
rix, rt->info[rix].dot11Rate,
|
||||
rt->info[rix].rateKbps,
|
||||
sc->sc_curmode);
|
||||
|
||||
if (rix >= rt->rateCount) {
|
||||
printf("bogus rix %d, max %u, mode %u\n",
|
||||
rix, rt->rateCount, sc->sc_curmode);
|
||||
return 0;
|
||||
}
|
||||
cix = rt->info[rix].controlRate;
|
||||
/*
|
||||
* XXX getting mac/phy level timings should be fixed for turbo
|
||||
* rates, and there is probably a way to get this from the
|
||||
@ -250,18 +207,15 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc,
|
||||
}
|
||||
|
||||
if (rts || cts) {
|
||||
int ctsrate = rt->info[cix].rateCode;
|
||||
int ctsrate;
|
||||
int ctsduration = 0;
|
||||
|
||||
if (!rt->info[cix].rateKbps) {
|
||||
printf("cix %d (%d) bad ratekbps %d mode %u\n",
|
||||
cix, rt->info[cix].dot11Rate,
|
||||
rt->info[cix].rateKbps,
|
||||
sc->sc_curmode);
|
||||
return 0;
|
||||
}
|
||||
/* NB: this is intentionally not a runtime check */
|
||||
KASSERT(cix < rt->rateCount,
|
||||
("bogus cix %d, max %u, mode %u\n", cix, rt->rateCount,
|
||||
sc->sc_curmode));
|
||||
|
||||
ctsrate |= rt->info[cix].shortPreamble;
|
||||
ctsrate = rt->info[cix].rateCode | rt->info[cix].shortPreamble;
|
||||
if (rts) /* SIFS + CTS */
|
||||
ctsduration += rt->info[cix].spAckDuration;
|
||||
|
||||
|
@ -258,8 +258,8 @@ enum {
|
||||
if (sc->sc_debug & ATH_DEBUG_KEYCACHE) \
|
||||
ath_keyprint(sc, __func__, ix, hk, mac); \
|
||||
} while (0)
|
||||
static void ath_printrxbuf(struct ath_buf *bf, u_int ix, int);
|
||||
static void ath_printtxbuf(struct ath_buf *bf, u_int qnum, u_int ix, int done);
|
||||
static void ath_printrxbuf(const struct ath_buf *bf, u_int ix, int);
|
||||
static void ath_printtxbuf(const struct ath_buf *bf, u_int qnum, u_int ix, int done);
|
||||
#else
|
||||
#define IFF_DUMPPKTS(sc, m) \
|
||||
((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
|
||||
@ -2758,7 +2758,6 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
|
||||
ds = bf->bf_desc;
|
||||
ds->ds_link = bf->bf_daddr; /* link to self */
|
||||
ds->ds_data = bf->bf_segs[0].ds_addr;
|
||||
ds->ds_vdata = mtod(m, void *); /* for radar */
|
||||
ath_hal_setuprxdesc(ah, ds
|
||||
, m->m_len /* buffer size */
|
||||
, 0
|
||||
@ -2856,7 +2855,7 @@ ath_setdefantenna(struct ath_softc *sc, u_int antenna)
|
||||
|
||||
static int
|
||||
ath_rx_tap(struct ath_softc *sc, struct mbuf *m,
|
||||
const struct ath_desc *ds, u_int64_t tsf, int16_t nf)
|
||||
const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf)
|
||||
{
|
||||
u_int8_t rix;
|
||||
|
||||
@ -2871,17 +2870,16 @@ ath_rx_tap(struct ath_softc *sc, struct mbuf *m,
|
||||
sc->sc_stats.ast_rx_tooshort++;
|
||||
return 0;
|
||||
}
|
||||
sc->sc_rx_th.wr_tsf = htole64(
|
||||
ath_extend_tsf(ds->ds_rxstat.rs_tstamp, tsf));
|
||||
rix = ds->ds_rxstat.rs_rate;
|
||||
sc->sc_rx_th.wr_tsf = htole64(ath_extend_tsf(rs->rs_tstamp, tsf));
|
||||
rix = rs->rs_rate;
|
||||
sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags;
|
||||
if (ds->ds_rxstat.rs_status & HAL_RXERR_CRC)
|
||||
if (rs->rs_status & HAL_RXERR_CRC)
|
||||
sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_BADFCS;
|
||||
/* XXX propagate other error flags from descriptor */
|
||||
sc->sc_rx_th.wr_rate = sc->sc_hwmap[rix].ieeerate;
|
||||
sc->sc_rx_th.wr_antsignal = ds->ds_rxstat.rs_rssi + nf;
|
||||
sc->sc_rx_th.wr_antsignal = rs->rs_rssi + nf;
|
||||
sc->sc_rx_th.wr_antnoise = nf;
|
||||
sc->sc_rx_th.wr_antenna = ds->ds_rxstat.rs_antenna;
|
||||
sc->sc_rx_th.wr_antenna = rs->rs_antenna;
|
||||
|
||||
bpf_mtap2(sc->sc_drvbpf, &sc->sc_rx_th, sc->sc_rx_th_len, m);
|
||||
|
||||
@ -2900,6 +2898,7 @@ ath_rx_proc(void *arg, int npending)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ath_desc *ds;
|
||||
struct ath_rx_status *rs;
|
||||
struct mbuf *m;
|
||||
struct ieee80211_node *ni;
|
||||
struct ath_node *an;
|
||||
@ -2949,8 +2948,9 @@ ath_rx_proc(void *arg, int npending)
|
||||
* on. All this is necessary because of our use of
|
||||
* a self-linked list to avoid rx overruns.
|
||||
*/
|
||||
rs = &bf->bf_status.ds_rxstat;
|
||||
status = ath_hal_rxprocdesc(ah, ds,
|
||||
bf->bf_daddr, PA2DESC(sc, ds->ds_link));
|
||||
bf->bf_daddr, PA2DESC(sc, ds->ds_link), rs);
|
||||
#ifdef ATH_DEBUG
|
||||
if (sc->sc_debug & ATH_DEBUG_RECV_DESC)
|
||||
ath_printrxbuf(bf, 0, status == HAL_OK);
|
||||
@ -2958,7 +2958,7 @@ ath_rx_proc(void *arg, int npending)
|
||||
if (status == HAL_EINPROGRESS)
|
||||
break;
|
||||
STAILQ_REMOVE_HEAD(&sc->sc_rxbuf, bf_list);
|
||||
if (ds->ds_rxstat.rs_more) {
|
||||
if (rs->rs_more) {
|
||||
/*
|
||||
* Frame spans multiple descriptors; this
|
||||
* cannot happen yet as we don't support
|
||||
@ -2970,18 +2970,18 @@ ath_rx_proc(void *arg, int npending)
|
||||
goto rx_next;
|
||||
}
|
||||
/* fall thru for monitor mode handling... */
|
||||
} else if (ds->ds_rxstat.rs_status != 0) {
|
||||
if (ds->ds_rxstat.rs_status & HAL_RXERR_CRC)
|
||||
} else if (rs->rs_status != 0) {
|
||||
if (rs->rs_status & HAL_RXERR_CRC)
|
||||
sc->sc_stats.ast_rx_crcerr++;
|
||||
if (ds->ds_rxstat.rs_status & HAL_RXERR_FIFO)
|
||||
if (rs->rs_status & HAL_RXERR_FIFO)
|
||||
sc->sc_stats.ast_rx_fifoerr++;
|
||||
if (ds->ds_rxstat.rs_status & HAL_RXERR_PHY) {
|
||||
if (rs->rs_status & HAL_RXERR_PHY) {
|
||||
sc->sc_stats.ast_rx_phyerr++;
|
||||
phyerr = ds->ds_rxstat.rs_phyerr & 0x1f;
|
||||
phyerr = rs->rs_phyerr & 0x1f;
|
||||
sc->sc_stats.ast_rx_phy[phyerr]++;
|
||||
goto rx_next;
|
||||
}
|
||||
if (ds->ds_rxstat.rs_status & HAL_RXERR_DECRYPT) {
|
||||
if (rs->rs_status & HAL_RXERR_DECRYPT) {
|
||||
/*
|
||||
* Decrypt error. If the error occurred
|
||||
* because there was no hardware key, then
|
||||
@ -2992,18 +2992,18 @@ ath_rx_proc(void *arg, int npending)
|
||||
*
|
||||
* XXX do key cache faulting
|
||||
*/
|
||||
if (ds->ds_rxstat.rs_keyix == HAL_RXKEYIX_INVALID)
|
||||
if (rs->rs_keyix == HAL_RXKEYIX_INVALID)
|
||||
goto rx_accept;
|
||||
sc->sc_stats.ast_rx_badcrypt++;
|
||||
}
|
||||
if (ds->ds_rxstat.rs_status & HAL_RXERR_MIC) {
|
||||
if (rs->rs_status & HAL_RXERR_MIC) {
|
||||
sc->sc_stats.ast_rx_badmic++;
|
||||
/*
|
||||
* Do minimal work required to hand off
|
||||
* the 802.11 header for notifcation.
|
||||
*/
|
||||
/* XXX frag's and qos frames */
|
||||
len = ds->ds_rxstat.rs_datalen;
|
||||
len = rs->rs_datalen;
|
||||
if (len >= sizeof (struct ieee80211_frame)) {
|
||||
bus_dmamap_sync(sc->sc_dmat,
|
||||
bf->bf_dmamap,
|
||||
@ -3011,8 +3011,7 @@ ath_rx_proc(void *arg, int npending)
|
||||
ieee80211_notify_michael_failure(ic,
|
||||
mtod(m, struct ieee80211_frame *),
|
||||
sc->sc_splitmic ?
|
||||
ds->ds_rxstat.rs_keyix-32 :
|
||||
ds->ds_rxstat.rs_keyix
|
||||
rs->rs_keyix-32 : rs->rs_keyix
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -3024,13 +3023,13 @@ ath_rx_proc(void *arg, int npending)
|
||||
* interesting (e.g. crc).
|
||||
*/
|
||||
if (bpf_peers_present(sc->sc_drvbpf) &&
|
||||
(ds->ds_rxstat.rs_status & sc->sc_monpass)) {
|
||||
(rs->rs_status & sc->sc_monpass)) {
|
||||
bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
|
||||
BUS_DMASYNC_POSTREAD);
|
||||
/* NB: bpf needs the mbuf length setup */
|
||||
len = ds->ds_rxstat.rs_datalen;
|
||||
len = rs->rs_datalen;
|
||||
m->m_pkthdr.len = m->m_len = len;
|
||||
(void) ath_rx_tap(sc, m, ds, tsf, nf);
|
||||
(void) ath_rx_tap(sc, m, rs, tsf, nf);
|
||||
}
|
||||
/* XXX pass MIC errors up for s/w reclaculation */
|
||||
goto rx_next;
|
||||
@ -3049,13 +3048,13 @@ ath_rx_proc(void *arg, int npending)
|
||||
bf->bf_m = NULL;
|
||||
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
len = ds->ds_rxstat.rs_datalen;
|
||||
len = rs->rs_datalen;
|
||||
m->m_pkthdr.len = m->m_len = len;
|
||||
|
||||
sc->sc_stats.ast_ant_rx[ds->ds_rxstat.rs_antenna]++;
|
||||
sc->sc_stats.ast_ant_rx[rs->rs_antenna]++;
|
||||
|
||||
if (bpf_peers_present(sc->sc_drvbpf) &&
|
||||
!ath_rx_tap(sc, m, ds, tsf, nf)) {
|
||||
!ath_rx_tap(sc, m, rs, tsf, nf)) {
|
||||
m_freem(m); /* XXX reclaim */
|
||||
goto rx_next;
|
||||
}
|
||||
@ -3074,8 +3073,8 @@ ath_rx_proc(void *arg, int npending)
|
||||
|
||||
if (IFF_DUMPPKTS(sc, ATH_DEBUG_RECV)) {
|
||||
ieee80211_dump_pkt(mtod(m, caddr_t), len,
|
||||
sc->sc_hwmap[ds->ds_rxstat.rs_rate].ieeerate,
|
||||
ds->ds_rxstat.rs_rssi);
|
||||
sc->sc_hwmap[rs->rs_rate].ieeerate,
|
||||
rs->rs_rssi);
|
||||
}
|
||||
|
||||
m_adj(m, -IEEE80211_CRC_LEN);
|
||||
@ -3087,19 +3086,18 @@ ath_rx_proc(void *arg, int npending)
|
||||
*/
|
||||
ni = ieee80211_find_rxnode_withkey(ic,
|
||||
mtod(m, const struct ieee80211_frame_min *),
|
||||
ds->ds_rxstat.rs_keyix == HAL_RXKEYIX_INVALID ?
|
||||
IEEE80211_KEYIX_NONE : ds->ds_rxstat.rs_keyix);
|
||||
rs->rs_keyix == HAL_RXKEYIX_INVALID ?
|
||||
IEEE80211_KEYIX_NONE : rs->rs_keyix);
|
||||
/*
|
||||
* Track rx rssi and do any rx antenna management.
|
||||
*/
|
||||
an = ATH_NODE(ni);
|
||||
ATH_RSSI_LPF(an->an_avgrssi, ds->ds_rxstat.rs_rssi);
|
||||
ATH_RSSI_LPF(sc->sc_halstats.ns_avgrssi, ds->ds_rxstat.rs_rssi);
|
||||
ATH_RSSI_LPF(an->an_avgrssi, rs->rs_rssi);
|
||||
ATH_RSSI_LPF(sc->sc_halstats.ns_avgrssi, rs->rs_rssi);
|
||||
/*
|
||||
* Send frame up for processing.
|
||||
*/
|
||||
type = ieee80211_input(ic, m, ni,
|
||||
ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp);
|
||||
type = ieee80211_input(ic, m, ni, rs->rs_rssi, rs->rs_tstamp);
|
||||
ieee80211_free_node(ni);
|
||||
if (sc->sc_diversity) {
|
||||
/*
|
||||
@ -3107,10 +3105,9 @@ ath_rx_proc(void *arg, int npending)
|
||||
* antenna if diversity chooses the other antenna 3
|
||||
* times in a row.
|
||||
*/
|
||||
if (sc->sc_defant != ds->ds_rxstat.rs_antenna) {
|
||||
if (sc->sc_defant != rs->rs_antenna) {
|
||||
if (++sc->sc_rxotherant >= 3)
|
||||
ath_setdefantenna(sc,
|
||||
ds->ds_rxstat.rs_antenna);
|
||||
ath_setdefantenna(sc, rs->rs_antenna);
|
||||
} else
|
||||
sc->sc_rxotherant = 0;
|
||||
}
|
||||
@ -3122,7 +3119,7 @@ ath_rx_proc(void *arg, int npending)
|
||||
* periodic beacon frames to trigger the poll event.
|
||||
*/
|
||||
if (type == IEEE80211_FC0_TYPE_DATA) {
|
||||
sc->sc_rxrate = ds->ds_rxstat.rs_rate;
|
||||
sc->sc_rxrate = rs->rs_rate;
|
||||
ath_led_event(sc, ATH_LED_RX);
|
||||
} else if (ticks - sc->sc_ledevent >= sc->sc_ledidle)
|
||||
ath_led_event(sc, ATH_LED_POLL);
|
||||
@ -3133,7 +3130,7 @@ ath_rx_proc(void *arg, int npending)
|
||||
* This assumes the rx key is always setup when associated.
|
||||
*/
|
||||
if (ic->ic_opmode == IEEE80211_M_STA &&
|
||||
ds->ds_rxstat.rs_keyix != HAL_RXKEYIX_INVALID)
|
||||
rs->rs_keyix != HAL_RXKEYIX_INVALID)
|
||||
ngood++;
|
||||
rx_next:
|
||||
STAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
|
||||
@ -3918,6 +3915,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ath_buf *bf;
|
||||
struct ath_desc *ds, *ds0;
|
||||
struct ath_tx_status *ts;
|
||||
struct ieee80211_node *ni;
|
||||
struct ath_node *an;
|
||||
int sr, lr, pri, nacked;
|
||||
@ -3938,7 +3936,8 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
}
|
||||
ds0 = &bf->bf_desc[0];
|
||||
ds = &bf->bf_desc[bf->bf_nseg - 1];
|
||||
status = ath_hal_txprocdesc(ah, ds);
|
||||
ts = &bf->bf_status.ds_txstat;
|
||||
status = ath_hal_txprocdesc(ah, ds, ts);
|
||||
#ifdef ATH_DEBUG
|
||||
if (sc->sc_debug & ATH_DEBUG_XMIT_DESC)
|
||||
ath_printtxbuf(bf, txq->axq_qnum, 0, status == HAL_OK);
|
||||
@ -3955,44 +3954,43 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
ni = bf->bf_node;
|
||||
if (ni != NULL) {
|
||||
an = ATH_NODE(ni);
|
||||
if (ds->ds_txstat.ts_status == 0) {
|
||||
u_int8_t txant = ds->ds_txstat.ts_antenna;
|
||||
if (ts->ts_status == 0) {
|
||||
u_int8_t txant = ts->ts_antenna;
|
||||
sc->sc_stats.ast_ant_tx[txant]++;
|
||||
sc->sc_ant_tx[txant]++;
|
||||
if (ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)
|
||||
if (ts->ts_rate & HAL_TXSTAT_ALTRATE)
|
||||
sc->sc_stats.ast_tx_altrate++;
|
||||
sc->sc_stats.ast_tx_rssi =
|
||||
ds->ds_txstat.ts_rssi;
|
||||
sc->sc_stats.ast_tx_rssi = ts->ts_rssi;
|
||||
ATH_RSSI_LPF(sc->sc_halstats.ns_avgtxrssi,
|
||||
ds->ds_txstat.ts_rssi);
|
||||
ts->ts_rssi);
|
||||
pri = M_WME_GETAC(bf->bf_m);
|
||||
if (pri >= WME_AC_VO)
|
||||
ic->ic_wme.wme_hipri_traffic++;
|
||||
ni->ni_inact = ni->ni_inact_reload;
|
||||
} else {
|
||||
if (ds->ds_txstat.ts_status & HAL_TXERR_XRETRY)
|
||||
if (ts->ts_status & HAL_TXERR_XRETRY)
|
||||
sc->sc_stats.ast_tx_xretries++;
|
||||
if (ds->ds_txstat.ts_status & HAL_TXERR_FIFO)
|
||||
if (ts->ts_status & HAL_TXERR_FIFO)
|
||||
sc->sc_stats.ast_tx_fifoerr++;
|
||||
if (ds->ds_txstat.ts_status & HAL_TXERR_FILT)
|
||||
if (ts->ts_status & HAL_TXERR_FILT)
|
||||
sc->sc_stats.ast_tx_filtered++;
|
||||
}
|
||||
sr = ds->ds_txstat.ts_shortretry;
|
||||
lr = ds->ds_txstat.ts_longretry;
|
||||
sr = ts->ts_shortretry;
|
||||
lr = ts->ts_longretry;
|
||||
sc->sc_stats.ast_tx_shortretry += sr;
|
||||
sc->sc_stats.ast_tx_longretry += lr;
|
||||
/*
|
||||
* Hand the descriptor to the rate control algorithm.
|
||||
*/
|
||||
if ((ds->ds_txstat.ts_status & HAL_TXERR_FILT) == 0 &&
|
||||
if ((ts->ts_status & HAL_TXERR_FILT) == 0 &&
|
||||
(bf->bf_flags & HAL_TXDESC_NOACK) == 0) {
|
||||
/*
|
||||
* If frame was ack'd update the last rx time
|
||||
* used to workaround phantom bmiss interrupts.
|
||||
*/
|
||||
if (ds->ds_txstat.ts_status == 0)
|
||||
if (ts->ts_status == 0)
|
||||
nacked++;
|
||||
ath_rate_tx_complete(sc, an, ds, ds0);
|
||||
ath_rate_tx_complete(sc, an, bf);
|
||||
}
|
||||
/*
|
||||
* Reclaim reference to node.
|
||||
@ -4141,7 +4139,8 @@ ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
#ifdef ATH_DEBUG
|
||||
if (sc->sc_debug & ATH_DEBUG_RESET) {
|
||||
ath_printtxbuf(bf, txq->axq_qnum, ix,
|
||||
ath_hal_txprocdesc(ah, bf->bf_desc) == HAL_OK);
|
||||
ath_hal_txprocdesc(ah, bf->bf_desc,
|
||||
&bf->bf_status.ds_txstat) == HAL_OK);
|
||||
ieee80211_dump_pkt(mtod(bf->bf_m, caddr_t),
|
||||
bf->bf_m->m_len, 0, -1);
|
||||
}
|
||||
@ -4206,7 +4205,8 @@ ath_draintxq(struct ath_softc *sc)
|
||||
struct ath_buf *bf = STAILQ_FIRST(&sc->sc_bbuf);
|
||||
if (bf != NULL && bf->bf_m != NULL) {
|
||||
ath_printtxbuf(bf, sc->sc_bhalq, 0,
|
||||
ath_hal_txprocdesc(ah, bf->bf_desc) == HAL_OK);
|
||||
ath_hal_txprocdesc(ah, bf->bf_desc,
|
||||
&bf->bf_status.ds_txstat) == HAL_OK);
|
||||
ieee80211_dump_pkt(mtod(bf->bf_m, caddr_t),
|
||||
bf->bf_m->m_len, 0, -1);
|
||||
}
|
||||
@ -4241,8 +4241,9 @@ ath_stoprecv(struct ath_softc *sc)
|
||||
ix = 0;
|
||||
STAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
|
||||
struct ath_desc *ds = bf->bf_desc;
|
||||
struct ath_rx_status *rs = &bf->bf_status.ds_rxstat;
|
||||
HAL_STATUS status = ath_hal_rxprocdesc(ah, ds,
|
||||
bf->bf_daddr, PA2DESC(sc, ds->ds_link));
|
||||
bf->bf_daddr, PA2DESC(sc, ds->ds_link), rs);
|
||||
if (status == HAL_OK || (sc->sc_debug & ATH_DEBUG_FATAL))
|
||||
ath_printrxbuf(bf, ix, status == HAL_OK);
|
||||
ix++;
|
||||
@ -5040,35 +5041,37 @@ ath_setcurmode(struct ath_softc *sc, enum ieee80211_phymode mode)
|
||||
|
||||
#ifdef ATH_DEBUG
|
||||
static void
|
||||
ath_printrxbuf(struct ath_buf *bf, u_int ix, int done)
|
||||
ath_printrxbuf(const struct ath_buf *bf, u_int ix, int done)
|
||||
{
|
||||
struct ath_desc *ds;
|
||||
const struct ath_rx_status *rs = &bf->bf_status.ds_rxstat;
|
||||
const struct ath_desc *ds;
|
||||
int i;
|
||||
|
||||
for (i = 0, ds = bf->bf_desc; i < bf->bf_nseg; i++, ds++) {
|
||||
printf("R[%2u] (DS.V:%p DS.P:%p) L:%08x D:%08x%s\n"
|
||||
" %08x %08x %08x %08x\n",
|
||||
ix, ds, (struct ath_desc *)bf->bf_daddr + i,
|
||||
ix, ds, (const struct ath_desc *)bf->bf_daddr + i,
|
||||
ds->ds_link, ds->ds_data,
|
||||
!done ? "" : (ds->ds_rxstat.rs_status == 0) ? " *" : " !",
|
||||
!done ? "" : (rs->rs_status == 0) ? " *" : " !",
|
||||
ds->ds_ctl0, ds->ds_ctl1,
|
||||
ds->ds_hw[0], ds->ds_hw[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ath_printtxbuf(struct ath_buf *bf, u_int qnum, u_int ix, int done)
|
||||
ath_printtxbuf(const struct ath_buf *bf, u_int qnum, u_int ix, int done)
|
||||
{
|
||||
struct ath_desc *ds;
|
||||
const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
|
||||
const struct ath_desc *ds;
|
||||
int i;
|
||||
|
||||
printf("Q%u[%3u]", qnum, ix);
|
||||
for (i = 0, ds = bf->bf_desc; i < bf->bf_nseg; i++, ds++) {
|
||||
printf(" (DS.V:%p DS.P:%p) L:%08x D:%08x F:04%x%s\n"
|
||||
" %08x %08x %08x %08x %08x %08x\n",
|
||||
ds, (struct ath_desc *)bf->bf_daddr + i,
|
||||
ds, (const struct ath_desc *)bf->bf_daddr + i,
|
||||
ds->ds_link, ds->ds_data, bf->bf_flags,
|
||||
!done ? "" : (ds->ds_txstat.ts_status == 0) ? " *" : " !",
|
||||
!done ? "" : (ts->ts_status == 0) ? " *" : " !",
|
||||
ds->ds_ctl0, ds->ds_ctl1,
|
||||
ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3]);
|
||||
}
|
||||
|
@ -135,6 +135,7 @@ void ath_rate_setupxtxdesc(struct ath_softc *, struct ath_node *,
|
||||
* for packets that were successfully sent and for those that
|
||||
* failed (consult the descriptor for details).
|
||||
*/
|
||||
struct ath_buf;
|
||||
void ath_rate_tx_complete(struct ath_softc *, struct ath_node *,
|
||||
const struct ath_desc *last, const struct ath_desc *first);
|
||||
const struct ath_buf *);
|
||||
#endif /* _ATH_RATECTRL_H_ */
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <sys/taskqueue.h>
|
||||
|
||||
#include <contrib/dev/ath/ah.h>
|
||||
#include <contrib/dev/ath/ah_desc.h>
|
||||
#include <net80211/ieee80211_radiotap.h>
|
||||
#include <dev/ath/if_athioctl.h>
|
||||
#include <dev/ath/if_athrate.h>
|
||||
@ -102,6 +103,7 @@ struct ath_buf {
|
||||
int bf_nseg;
|
||||
int bf_flags; /* tx descriptor flags */
|
||||
struct ath_desc *bf_desc; /* virtual addr of desc */
|
||||
struct ath_desc_status bf_status; /* tx/rx status */
|
||||
bus_addr_t bf_daddr; /* physical addr of desc */
|
||||
bus_dmamap_t bf_dmamap; /* DMA map for mbuf chain */
|
||||
struct mbuf *bf_m; /* mbuf for buf */
|
||||
@ -550,8 +552,8 @@ void ath_intr(void *);
|
||||
|
||||
#define ath_hal_setuprxdesc(_ah, _ds, _size, _intreq) \
|
||||
((*(_ah)->ah_setupRxDesc)((_ah), (_ds), (_size), (_intreq)))
|
||||
#define ath_hal_rxprocdesc(_ah, _ds, _dspa, _dsnext) \
|
||||
((*(_ah)->ah_procRxDesc)((_ah), (_ds), (_dspa), (_dsnext), 0))
|
||||
#define ath_hal_rxprocdesc(_ah, _ds, _dspa, _dsnext, _rs) \
|
||||
((*(_ah)->ah_procRxDesc)((_ah), (_ds), (_dspa), (_dsnext), 0, (_rs)))
|
||||
#define ath_hal_setuptxdesc(_ah, _ds, _plen, _hlen, _atype, _txpow, \
|
||||
_txr0, _txtr0, _keyix, _ant, _flags, \
|
||||
_rtsrate, _rtsdura) \
|
||||
@ -564,8 +566,8 @@ void ath_intr(void *);
|
||||
(_txr1), (_txtr1), (_txr2), (_txtr2), (_txr3), (_txtr3)))
|
||||
#define ath_hal_filltxdesc(_ah, _ds, _l, _first, _last, _ds0) \
|
||||
((*(_ah)->ah_fillTxDesc)((_ah), (_ds), (_l), (_first), (_last), (_ds0)))
|
||||
#define ath_hal_txprocdesc(_ah, _ds) \
|
||||
((*(_ah)->ah_procTxDesc)((_ah), (_ds)))
|
||||
#define ath_hal_txprocdesc(_ah, _ds, _ts) \
|
||||
((*(_ah)->ah_procTxDesc)((_ah), (_ds), (_ts)))
|
||||
#define ath_hal_gettxintrtxqs(_ah, _txqs) \
|
||||
((*(_ah)->ah_getTxIntrQueue)((_ah), (_txqs)))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user