diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2009-11-22 08:52:46 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2009-11-22 08:52:46 +0000 |
commit | f034446e6c2a41aecbb99fa974a785aae3412a97 (patch) | |
tree | 5046e900d25aa10bc179882f66bff79f8a35f182 /sys/dev | |
parent | 80f574b976d71bef7c21cf88aa5222cfca5312d6 (diff) |
fix RTS/CTS and CTS-to-self protection modes.
fix 802.11a TXTIME computation (802.11a has a 16us SIFS interval
but does not have the 6us signal extension that ERP-OFDM has so
we can use the same code for 11a and 11g provided that we add
the SIFS nterval in the athn_txtime() function itself.)
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/athn.c | 60 | ||||
-rw-r--r-- | sys/dev/ic/athnvar.h | 62 |
2 files changed, 68 insertions, 54 deletions
diff --git a/sys/dev/ic/athn.c b/sys/dev/ic/athn.c index de1405bfcaa..50e292d05be 100644 --- a/sys/dev/ic/athn.c +++ b/sys/dev/ic/athn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: athn.c,v 1.13 2009/11/21 16:36:59 damien Exp $ */ +/* $OpenBSD: athn.c,v 1.14 2009/11/22 08:52:45 damien Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> @@ -1382,8 +1382,6 @@ athn_set_phy(struct athn_softc *sc, struct ieee80211_channel *c, AR_WRITE(sc, AR_GTXTO, SM(AR_GTXTO_TIMEOUT_LIMIT, 25)); AR_WRITE(sc, AR_CST, SM(AR_CST_TIMEOUT_LIMIT, 15)); - /* Set Short Interframe Space. */ - sc->sifs = IEEE80211_IS_CHAN_5GHZ(c) ? 16 : 10; } int @@ -3247,18 +3245,22 @@ athn_txtime(struct athn_softc *sc, int len, int ridx, u_int flags) /* XXX HT. */ if (athn_rates[ridx].phy == IEEE80211_T_OFDM) { txtime = divround(8 + 4 * len + 3, athn_rates[ridx].rate); - txtime = 16 + 4 + 4 * txtime + 6; + /* SIFS is 10us for 11g but Signal Extension adds 6us. */ + txtime = 16 + 4 + 4 * txtime + 16; } else { txtime = divround(16 * len, athn_rates[ridx].rate); if (ridx != ATHN_RIDX_CCK1 && (flags & IEEE80211_F_SHPREAMBLE)) txtime += 72 + 24; else txtime += 144 + 48; + txtime += 10; /* 10us SIFS. */ } return (txtime); #undef divround } +int athn_prot = 0; + int athn_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) { @@ -3475,14 +3477,17 @@ athn_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) if (totlen > ic->ic_rtsthreshold) { ds->ds_ctl0 |= AR_TXC0_RTS_ENABLE; } else if ((ic->ic_flags & IEEE80211_F_USEPROT) && - ATHN_IS_OFDM_RIDX(ridx[0])) { + athn_rates[ridx[0]].phy == IEEE80211_T_OFDM) { if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) ds->ds_ctl0 |= AR_TXC0_RTS_ENABLE; else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) ds->ds_ctl0 |= AR_TXC0_CTS_ENABLE; } } - + if (ds->ds_ctl0 & (AR_TXC0_RTS_ENABLE | AR_TXC0_CTS_ENABLE)) { + /* Disable multi-rate retries when protection is used. */ + ridx[1] = ridx[2] = ridx[3] = ridx[0]; + } /* Setup multi-rate retries. */ for (i = 0; i < 4; i++) { series[i].tries = 1; /* XXX more for last. */ @@ -3497,7 +3502,7 @@ athn_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) /* Compute duration for each series. */ for (i = 0; i < 4; i++) { series[i].dur = athn_txtime(sc, IEEE80211_ACK_LEN, - ridx[i], ic->ic_flags) + sc->sifs; + athn_rates[ridx[i]].rspridx, ic->ic_flags); } } @@ -3545,16 +3550,35 @@ athn_tx(struct athn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) #endif if (ds->ds_ctl0 & (AR_TXC0_RTS_ENABLE | AR_TXC0_CTS_ENABLE)) { + uint8_t protridx, hwrate; + uint16_t dur = 0; + /* Use the same protection mode for all tries. */ if (ds->ds_ctl0 & AR_TXC0_RTS_ENABLE) { ds->ds_ctl4 |= AR_TXC4_RTSCTS_QUAL01; ds->ds_ctl5 |= AR_TXC5_RTSCTS_QUAL23; } + /* Select protection rate (suboptimal but ok.) */ + protridx = (ic->ic_curmode == IEEE80211_MODE_11A) ? + ATHN_RIDX_OFDM6 : ATHN_RIDX_CCK2; + if (ds->ds_ctl0 & AR_TXC0_RTS_ENABLE) { + /* Account for CTS duration. */ + dur += athn_txtime(sc, IEEE80211_ACK_LEN, + athn_rates[protridx].rspridx, ic->ic_flags); + } + dur += athn_txtime(sc, totlen, ridx[0], ic->ic_flags); + if (!(ds->ds_ctl1 & AR_TXC1_NO_ACK)) { + /* Account for ACK duration. */ + dur += athn_txtime(sc, IEEE80211_ACK_LEN, + athn_rates[ridx[0]].rspridx, ic->ic_flags); + } /* Write protection frame duration and rate. */ - ds->ds_ctl2 |= SM(AR_TXC2_BURST_DUR, 0 /* XXX */); - ds->ds_ctl7 |= SM(AR_TXC7_RTSCTS_RATE, - athn_rates[0].hwrate /* XXX */); - /* XXX short preamble. */ + ds->ds_ctl2 |= SM(AR_TXC2_BURST_DUR, dur); + hwrate = athn_rates[protridx].hwrate; + if (protridx == ATHN_RIDX_CCK2 && + (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) + hwrate |= 0x04; + ds->ds_ctl7 |= SM(AR_TXC7_RTSCTS_RATE, hwrate); } /* Finalize first Tx descriptor and fill others (if any.) */ @@ -4259,6 +4283,7 @@ athn_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew) if (athn_rates[ridx].rate == rate) break; an->ridx[i] = ridx; + DPRINTFN(2, ("rate %d index %d\n", rate, ridx)); /* Compute fallback rate for retries. */ an->fallback[i] = i; @@ -4269,18 +4294,7 @@ athn_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew) break; } } -#if 0 - /* Compute rate for protection frames. */ - an->ctlridx[i] = athn_rates[ridx].ctlridx; - for (j = i; j >= 0; j--) { - if ((rs->rs_rates[j] & IEEE80211_RATE_BASIC) && - athn_rates[an->ridx[j]].phy == - athn_rates[an->ridx[i]].phy) { - an->ctlridx[i] = an->ridx[j]; - break; - } - } -#endif + DPRINTFN(2, ("%d fallbacks to %d\n", i, an->fallback[i])); } } diff --git a/sys/dev/ic/athnvar.h b/sys/dev/ic/athnvar.h index e441ce36e8d..b1c53ca2a37 100644 --- a/sys/dev/ic/athnvar.h +++ b/sys/dev/ic/athnvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: athnvar.h,v 1.5 2009/11/19 19:19:59 damien Exp $ */ +/* $OpenBSD: athnvar.h,v 1.6 2009/11/22 08:52:45 damien Exp $ */ /*- * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> @@ -108,46 +108,47 @@ struct athn_rxq { /* Software rate indexes. */ #define ATHN_RIDX_CCK1 0 +#define ATHN_RIDX_CCK2 1 #define ATHN_RIDX_OFDM6 4 #define ATHN_RIDX_MCS0 12 #define ATHN_RIDX_MCS15 27 #define ATHN_RIDX_MAX 27 -#define ATHN_IS_OFDM_RIDX(ridx) (athn_rates[ridx].phy == IEEE80211_T_OFDM) #define ATHN_IS_HT_RIDX(ridx) ((ridx) >= ATHN_RIDX_MCS0) static const struct athn_rate { uint8_t rate; /* Rate in 500Kbps unit or MCS if 0x80. */ uint8_t hwrate; /* HW representation. */ + uint8_t rspridx; /* Control Response Frame rate index. */ enum ieee80211_phytype phy; } athn_rates[] = { - { 2, 0x1b, IEEE80211_T_DS }, - { 4, 0x1a, IEEE80211_T_DS }, - { 11, 0x19, IEEE80211_T_DS }, - { 22, 0x18, IEEE80211_T_DS }, - { 12, 0x0b, IEEE80211_T_OFDM }, - { 18, 0x0f, IEEE80211_T_OFDM }, - { 24, 0x0a, IEEE80211_T_OFDM }, - { 36, 0x0e, IEEE80211_T_OFDM }, - { 48, 0x09, IEEE80211_T_OFDM }, - { 72, 0x0d, IEEE80211_T_OFDM }, - { 96, 0x08, IEEE80211_T_OFDM }, - { 108, 0x0c, IEEE80211_T_OFDM }, - { 0x80, 0x80, IEEE80211_T_OFDM }, - { 0x81, 0x81, IEEE80211_T_OFDM }, - { 0x82, 0x82, IEEE80211_T_OFDM }, - { 0x83, 0x83, IEEE80211_T_OFDM }, - { 0x84, 0x84, IEEE80211_T_OFDM }, - { 0x85, 0x85, IEEE80211_T_OFDM }, - { 0x86, 0x86, IEEE80211_T_OFDM }, - { 0x87, 0x87, IEEE80211_T_OFDM }, - { 0x88, 0x88, IEEE80211_T_OFDM }, - { 0x89, 0x89, IEEE80211_T_OFDM }, - { 0x8a, 0x8a, IEEE80211_T_OFDM }, - { 0x8b, 0x8b, IEEE80211_T_OFDM }, - { 0x8c, 0x8c, IEEE80211_T_OFDM }, - { 0x8d, 0x8d, IEEE80211_T_OFDM }, - { 0x8e, 0x8e, IEEE80211_T_OFDM }, - { 0x8f, 0x8f, IEEE80211_T_OFDM } + { 2, 0x1b, 0, IEEE80211_T_DS }, + { 4, 0x1a, 1, IEEE80211_T_DS }, + { 11, 0x19, 1, IEEE80211_T_DS }, + { 22, 0x18, 1, IEEE80211_T_DS }, + { 12, 0x0b, 4, IEEE80211_T_OFDM }, + { 18, 0x0f, 4, IEEE80211_T_OFDM }, + { 24, 0x0a, 6, IEEE80211_T_OFDM }, + { 36, 0x0e, 6, IEEE80211_T_OFDM }, + { 48, 0x09, 8, IEEE80211_T_OFDM }, + { 72, 0x0d, 8, IEEE80211_T_OFDM }, + { 96, 0x08, 8, IEEE80211_T_OFDM }, + { 108, 0x0c, 8, IEEE80211_T_OFDM }, + { 0x80, 0x80, 8, IEEE80211_T_OFDM }, + { 0x81, 0x81, 8, IEEE80211_T_OFDM }, + { 0x82, 0x82, 8, IEEE80211_T_OFDM }, + { 0x83, 0x83, 8, IEEE80211_T_OFDM }, + { 0x84, 0x84, 8, IEEE80211_T_OFDM }, + { 0x85, 0x85, 8, IEEE80211_T_OFDM }, + { 0x86, 0x86, 8, IEEE80211_T_OFDM }, + { 0x87, 0x87, 8, IEEE80211_T_OFDM }, + { 0x88, 0x88, 8, IEEE80211_T_OFDM }, + { 0x89, 0x89, 8, IEEE80211_T_OFDM }, + { 0x8a, 0x8a, 8, IEEE80211_T_OFDM }, + { 0x8b, 0x8b, 8, IEEE80211_T_OFDM }, + { 0x8c, 0x8c, 8, IEEE80211_T_OFDM }, + { 0x8d, 0x8d, 8, IEEE80211_T_OFDM }, + { 0x8e, 0x8e, 8, IEEE80211_T_OFDM }, + { 0x8f, 0x8f, 8, IEEE80211_T_OFDM } }; struct athn_series { @@ -429,7 +430,6 @@ struct athn_softc { struct athn_ops ops; int fixed_ridx; - int sifs; int16_t def_nf; struct { |