summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2008-04-27 19:02:00 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2008-04-27 19:02:00 +0000
commitb74fdae31cbf487ae8ab20ee733fbe4a67bf50bb (patch)
treec2284b24c6372a3e44330d59e1b8ddda2e8666ea
parent3d245af8182de9c1f4255b677e31e5c592e12585 (diff)
fix rate control.
-rw-r--r--sys/dev/pci/if_iwn.c84
-rw-r--r--sys/dev/pci/if_iwnreg.h10
2 files changed, 63 insertions, 31 deletions
diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c
index 11eb562932e..3fd3df146f1 100644
--- a/sys/dev/pci/if_iwn.c
+++ b/sys/dev/pci/if_iwn.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: if_iwn.c,v 1.18 2008/04/16 18:32:15 damien Exp $ */
+/* $OpenBSD: if_iwn.c,v 1.19 2008/04/27 19:01:59 damien Exp $ */
/*-
- * Copyright (c) 2007
+ * Copyright (c) 2007,2008
* Damien Bergamini <damien.bergamini@free.fr>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -133,7 +133,9 @@ void iwn_start(struct ifnet *);
void iwn_watchdog(struct ifnet *);
int iwn_ioctl(struct ifnet *, u_long, caddr_t);
int iwn_cmd(struct iwn_softc *, int, const void *, int, int);
-int iwn_setup_node_mrr(struct iwn_softc *, uint8_t, int);
+int iwn_setup_node_mrr(struct iwn_softc *,
+ const struct ieee80211_node *, uint8_t);
+int iwn_set_fixed_rate(struct iwn_softc *, uint8_t, uint8_t, int);
int iwn_set_key(struct ieee80211com *, struct ieee80211_node *,
struct ieee80211_key *);
void iwn_updateedca(struct ieee80211com *);
@@ -1806,9 +1808,9 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
if (!IWN_RATE_IS_OFDM(rate))
tx->rflags |= IWN_RFLAG_CCK;
} else {
- tx->ridx = 0;
+ tx->ridx = ni->ni_rates.rs_nrates - ni->ni_txrate - 1;
/* tell adapter to ignore rflags */
- tx->flags |= htole32(IWN_TX_USE_NODE_RATE);
+ tx->flags |= htole32(IWN_TX_MRR_INDEX);
}
/* copy and trim IEEE802.11 header */
@@ -2221,11 +2223,13 @@ iwn_cmd(struct iwn_softc *sc, int code, const void *buf, int size, int async)
* Configure hardware multi-rate retries for one node.
*/
int
-iwn_setup_node_mrr(struct iwn_softc *sc, uint8_t id, int async)
+iwn_setup_node_mrr(struct iwn_softc *sc, const struct ieee80211_node *ni,
+ uint8_t id)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ const struct ieee80211_rateset *rs = &ni->ni_rates;
struct iwn_cmd_mrr mrr;
- int i, ridx;
+ uint8_t rate;
+ int i, r;
memset(&mrr, 0, sizeof mrr);
mrr.id = id;
@@ -2234,18 +2238,48 @@ iwn_setup_node_mrr(struct iwn_softc *sc, uint8_t id, int async)
mrr.ampdu_disable = 3;
mrr.ampdu_limit = 4000;
- if (id == IWN_ID_BSS)
- ridx = IWN_OFDM54;
- else if (ic->ic_curmode == IEEE80211_MODE_11A)
- ridx = IWN_OFDM6;
- else
- ridx = IWN_CCK1;
- for (i = 0; i < IWN_MAX_TX_RETRIES; i++) {
- mrr.table[i].rate = iwn_ridx_to_plcp[ridx];
+ r = rs->rs_nrates - 1;
+ for (i = 0; i < IWN_MAX_TX_RETRIES && r >= 0; i++, r--) {
+ rate = rs->rs_rates[r] & IEEE80211_RATE_VAL;
+ DPRINTF(("retry #%d: rate %d\n", i, rate));
+ mrr.table[i].rate = iwn_plcp_signal(rate);
+ mrr.table[i].rflags = IWN_RFLAG_ANT_B;
+ if (!IWN_RATE_IS_OFDM(rate))
+ mrr.table[i].rflags |= IWN_RFLAG_CCK;
+ }
+ /* pad with the lowest available bit-rate */
+ for (; i < IWN_MAX_TX_RETRIES; i++) {
+ rate = rs->rs_rates[0] & IEEE80211_RATE_VAL;
+ DPRINTF(("retry #%d: rate %d\n", i, rate));
+ mrr.table[i].rate = iwn_plcp_signal(rate);
mrr.table[i].rflags = IWN_RFLAG_ANT_B;
- if (ridx <= IWN_CCK11)
+ if (!IWN_RATE_IS_OFDM(rate))
mrr.table[i].rflags |= IWN_RFLAG_CCK;
- ridx = iwn_prev_ridx[ridx];
+ }
+ return iwn_cmd(sc, IWN_CMD_NODE_MRR_SETUP, &mrr, sizeof mrr, 1);
+}
+
+int
+iwn_set_fixed_rate(struct iwn_softc *sc, uint8_t id, uint8_t rate, int async)
+{
+ struct iwn_cmd_mrr mrr;
+ int i;
+
+ memset(&mrr, 0, sizeof mrr);
+ mrr.id = id;
+ mrr.ssmask = 2;
+ mrr.dsmask = 3;
+ mrr.ampdu_disable = 3;
+ mrr.ampdu_limit = 4000;
+
+ /* to setup a fixed rate, make all retries use the same rate.. */
+ mrr.table[0].rate = iwn_plcp_signal(rate);
+ mrr.table[0].rflags = IWN_RFLAG_ANT_B;
+ if (!IWN_RATE_IS_OFDM(rate))
+ mrr.table[0].rflags |= IWN_RFLAG_CCK;
+ for (i = 1; i < IWN_MAX_TX_RETRIES; i++) {
+ mrr.table[i].rate = mrr.table[0].rate;
+ mrr.table[i].rflags = mrr.table[0].rflags;
}
return iwn_cmd(sc, IWN_CMD_NODE_MRR_SETUP, &mrr, sizeof mrr, async);
}
@@ -2876,6 +2910,7 @@ iwn_auth(struct iwn_softc *sc)
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni = ic->ic_bss;
struct iwn_node_info node;
+ uint8_t rate;
int error;
/* update adapter's configuration */
@@ -2932,8 +2967,9 @@ iwn_auth(struct iwn_softc *sc)
sc->sc_dev.dv_xname);
return error;
}
- DPRINTF(("setting MRR for node %d\n", node.id));
- if ((error = iwn_setup_node_mrr(sc, node.id, 1)) != 0) {
+ DPRINTF(("setting fixed rate for node %d\n", node.id));
+ rate = (ic->ic_curmode == IEEE80211_MODE_11A) ? 12 : 2;
+ if ((error = iwn_set_fixed_rate(sc, node.id, rate, 1)) != 0) {
printf("%s: could not setup MRR for broadcast node\n",
sc->sc_dev.dv_xname, node.id);
return error;
@@ -3002,7 +3038,7 @@ iwn_run(struct iwn_softc *sc)
return error;
}
DPRINTF(("setting MRR for node %d\n", node.id));
- if ((error = iwn_setup_node_mrr(sc, node.id, 1)) != 0) {
+ if ((error = iwn_setup_node_mrr(sc, ni, node.id)) != 0) {
printf("%s: could not setup MRR for node %d\n",
sc->sc_dev.dv_xname, node.id);
return error;
@@ -3212,6 +3248,7 @@ iwn_config(struct iwn_softc *sc)
struct iwn_power power;
struct iwn_bluetooth bluetooth;
struct iwn_node_info node;
+ uint8_t rate;
int error;
/* set power mode */
@@ -3299,8 +3336,9 @@ iwn_config(struct iwn_softc *sc)
sc->sc_dev.dv_xname);
return error;
}
- DPRINTF(("setting MRR for node %d\n", node.id));
- if ((error = iwn_setup_node_mrr(sc, node.id, 0)) != 0) {
+ DPRINTF(("setting fixed rate for node %d\n", node.id));
+ rate = (ic->ic_curmode == IEEE80211_MODE_11A) ? 12 : 2;
+ if ((error = iwn_set_fixed_rate(sc, node.id, rate, 0)) != 0) {
printf("%s: could not setup MRR for node %d\n",
sc->sc_dev.dv_xname, node.id);
return error;
diff --git a/sys/dev/pci/if_iwnreg.h b/sys/dev/pci/if_iwnreg.h
index 4c6a2ded126..6f3e859d029 100644
--- a/sys/dev/pci/if_iwnreg.h
+++ b/sys/dev/pci/if_iwnreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_iwnreg.h,v 1.9 2007/11/27 20:59:40 damien Exp $ */
+/* $OpenBSD: if_iwnreg.h,v 1.10 2008/04/27 19:01:59 damien Exp $ */
/*-
* Copyright (c) 2007
@@ -397,7 +397,7 @@ struct iwn_cmd_data {
#define IWN_TX_NEED_RTS (1 << 1)
#define IWN_TX_NEED_CTS (1 << 2)
#define IWN_TX_NEED_ACK (1 << 3)
-#define IWN_TX_USE_NODE_RATE (1 << 4)
+#define IWN_TX_MRR_INDEX (1 << 4)
#define IWN_TX_FULL_TXOP (1 << 7)
#define IWN_TX_BT_DISABLE (1 << 12) /* bluetooth coexistence */
#define IWN_TX_AUTO_SEQ (1 << 13)
@@ -898,12 +898,6 @@ static const uint8_t iwn_ridx_to_plcp[] = {
0xd, 0xf, 0x5, 0x7, 0x9, 0xb, 0x1, 0x3, 0x3 /* OFDM R1-R4 */
};
-/* allow fallback from CCK11 to OFDM9 and from OFDM6 to CCK5 */
-static const uint8_t iwn_prev_ridx[] = {
- 0, 0, 1, 5, /* CCK */
- 2, 4, 3, 6, 7, 8, 9, 10, 10 /* OFDM */
-};
-
#define IWN_MAX_PWR_INDEX 107
/*