summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2009-11-22 08:52:46 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2009-11-22 08:52:46 +0000
commitf034446e6c2a41aecbb99fa974a785aae3412a97 (patch)
tree5046e900d25aa10bc179882f66bff79f8a35f182 /sys/dev
parent80f574b976d71bef7c21cf88aa5222cfca5312d6 (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.c60
-rw-r--r--sys/dev/ic/athnvar.h62
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 {