summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2006-06-18 18:44:05 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2006-06-18 18:44:05 +0000
commitce9d7316d9fd1b1e65ddb9109f5e0490aca171fa (patch)
tree7235b72ebf581012f577ff435d18734a644c88d9 /sys/dev
parentb6efe24e3cd0a45a2c3b9be9b804f53c1db0152e (diff)
- implement new ic_updateslot() callback.
- in hostap mode, we defer update of the slot time until all associated STAs are notified with updated beacons.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/rt2560.c88
-rw-r--r--sys/dev/ic/rt2560var.h8
-rw-r--r--sys/dev/ic/rt2661.c74
-rw-r--r--sys/dev/ic/rt2661reg.h9
-rw-r--r--sys/dev/ic/rt2661var.h10
5 files changed, 159 insertions, 30 deletions
diff --git a/sys/dev/ic/rt2560.c b/sys/dev/ic/rt2560.c
index 889018ae38a..50ea6735500 100644
--- a/sys/dev/ic/rt2560.c
+++ b/sys/dev/ic/rt2560.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rt2560.c,v 1.20 2006/06/18 12:32:46 damien Exp $ */
+/* $OpenBSD: rt2560.c,v 1.21 2006/06/18 18:44:04 damien Exp $ */
/*-
* Copyright (c) 2005, 2006
@@ -132,7 +132,8 @@ void rt2560_set_chan(struct rt2560_softc *,
void rt2560_disable_rf_tune(struct rt2560_softc *);
void rt2560_enable_tsf_sync(struct rt2560_softc *);
void rt2560_update_plcp(struct rt2560_softc *);
-void rt2560_update_slot(struct rt2560_softc *);
+void rt2560_updateslot(struct ieee80211com *);
+void rt2560_set_slottime(struct rt2560_softc *);
void rt2560_set_basicrates(struct rt2560_softc *);
void rt2560_update_led(struct rt2560_softc *, int, int);
void rt2560_set_bssid(struct rt2560_softc *, uint8_t *);
@@ -314,6 +315,7 @@ rt2560_attach(void *xsc, int id)
ieee80211_ifattach(ifp);
ic->ic_node_alloc = rt2560_node_alloc;
ic->ic_node_copy = rt2560_node_copy;
+ ic->ic_updateslot = rt2560_updateslot;
/* override state transition machine */
sc->sc_newstate = ic->ic_newstate;
@@ -337,12 +339,16 @@ rt2560_attach(void *xsc, int id)
* Make sure the interface is shutdown during reboot.
*/
sc->sc_sdhook = shutdownhook_establish(rt2560_shutdown, sc);
- if (sc->sc_sdhook == NULL)
- printf(": WARNING: unable to establish shutdown hook\n");
- sc->sc_powerhook = powerhook_establish(rt2560_power, sc);
- if (sc->sc_powerhook == NULL)
- printf(": WARNING: unable to establish power hook\n");
+ if (sc->sc_sdhook == NULL) {
+ printf("%s: WARNING: unable to establish shutdown hook\n",
+ sc->sc_dev.dv_xname);
+ }
+ sc->sc_powerhook = powerhook_establish(rt2560_power, sc);
+ if (sc->sc_powerhook == NULL) {
+ printf("%s: WARNING: unable to establish power hook\n",
+ sc->sc_dev.dv_xname);
+ }
return 0;
fail5: rt2560_free_tx_ring(sc, &sc->bcnq);
@@ -810,7 +816,8 @@ rt2560_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
ni = ic->ic_bss;
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
- rt2560_update_slot(sc);
+ rt2560_update_plcp(sc);
+ rt2560_set_slottime(sc);
rt2560_set_basicrates(sc);
rt2560_set_bssid(sc, ni->ni_bssid);
}
@@ -1319,8 +1326,8 @@ rt2560_rx_intr(struct rt2560_softc *sc)
}
/*
- * This function is called periodically in IBSS mode when a new beacon must be
- * sent out.
+ * This function is called in HostAP or IBSS modes when it's time to send a
+ * new beacon (every ni_intval milliseconds).
*/
void
rt2560_beacon_expire(struct rt2560_softc *sc)
@@ -1334,7 +1341,22 @@ rt2560_beacon_expire(struct rt2560_softc *sc)
data = &sc->bcnq.data[sc->bcnq.next];
-#if NBPFILTER > 0
+ if (sc->sc_flags & RT2560_UPDATE_SLOT) {
+ sc->sc_flags &= ~RT2560_UPDATE_SLOT;
+ sc->sc_flags |= RT2560_SET_SLOTTIME;
+ } else if (sc->sc_flags & RT2560_SET_SLOTTIME) {
+ sc->sc_flags &= ~RT2560_SET_SLOTTIME;
+ rt2560_set_slottime(sc);
+ }
+
+ if (ic->ic_curmode == IEEE80211_MODE_11G) {
+ /* update ERP Information Element */
+ *sc->erp = ic->ic_bss->ni_erp;
+ bus_dmamap_sync(sc->sc_dmat, data->map, 0,
+ data->map->dm_mapsize, BUS_DMASYNC_PREWRITE);
+ }
+
+#if defined(RT2560_DEBUG) && NBPFILTER > 0
if (ic->ic_rawbpf != NULL)
bpf_mtap(ic->ic_rawbpf, data->m, BPF_DIRECTION_OUT);
#endif
@@ -1481,7 +1503,7 @@ rt2560_txtime(int len, int rate, uint32_t flags)
uint16_t txtime;
if (RAL_RATE_IS_OFDM(rate)) {
- /* IEEE Std 802.11a-1999, pp. 37 */
+ /* IEEE Std 802.11g-2003, pp. 44 */
txtime = (8 + 4 * len + 3 + rate - 1) / rate;
txtime = 16 + 4 + 4 * txtime + 6;
} else {
@@ -1569,6 +1591,7 @@ int
rt2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0,
struct ieee80211_node *ni)
{
+ struct ieee80211com *ic = &sc->sc_ic;
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
int rate, error;
@@ -1600,6 +1623,23 @@ rt2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0,
sc->bcnq.cur * RT2560_TX_DESC_SIZE, RT2560_TX_DESC_SIZE,
BUS_DMASYNC_PREWRITE);
+ /*
+ * Store pointer to ERP Information Element so that we can update it
+ * dynamically when the slot time changes.
+ * XXX: this is ugly since it depends on how net80211 builds beacon
+ * frames but ieee80211_beacon_alloc() don't store offsets for us.
+ */
+ if (ic->ic_curmode == IEEE80211_MODE_11G) {
+ sc->erp =
+ mtod(m0, uint8_t *) +
+ sizeof (struct ieee80211_frame) +
+ 8 + 2 + 2 + 2 + ni->ni_esslen + 2 + 1 +
+ ((ic->ic_opmode == IEEE80211_M_IBSS) ? 3 : 6) +
+ 2 + ni->ni_rates.rs_nrates +
+ ((ni->ni_rates.rs_nrates > IEEE80211_RATE_SIZE) ? 2 : 0) +
+ 2;
+ }
+
return 0;
}
@@ -2378,12 +2418,28 @@ rt2560_update_plcp(struct rt2560_softc *sc)
(ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long"));
}
+void
+rt2560_updateslot(struct ieee80211com *ic)
+{
+ struct rt2560_softc *sc = ic->ic_if.if_softc;
+
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
+ /*
+ * In HostAP mode, we defer setting of new slot time until
+ * updated ERP Information Element has propagated to all
+ * associated STAs.
+ */
+ sc->sc_flags |= RT2560_UPDATE_SLOT;
+ } else
+ rt2560_set_slottime(sc);
+}
+
/*
- * IEEE 802.11a uses short slot time. Refer to IEEE Std 802.11-1999 pp. 85 to
- * know how these values are computed.
+ * IEEE 802.11a (and possibly 802.11g) use short slot time. Refer to
+ * IEEE Std 802.11-1999 pp. 85 to know how these values are computed.
*/
void
-rt2560_update_slot(struct rt2560_softc *sc)
+rt2560_set_slottime(struct rt2560_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
uint8_t slottime;
@@ -2679,7 +2735,7 @@ rt2560_init(struct ifnet *ifp)
rt2560_set_txantenna(sc, 1);
rt2560_set_rxantenna(sc, 1);
- rt2560_update_slot(sc);
+ rt2560_set_slottime(sc);
rt2560_update_plcp(sc);
rt2560_update_led(sc, 0, 0);
diff --git a/sys/dev/ic/rt2560var.h b/sys/dev/ic/rt2560var.h
index 0cb08cec456..f9f4a751735 100644
--- a/sys/dev/ic/rt2560var.h
+++ b/sys/dev/ic/rt2560var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rt2560var.h,v 1.3 2006/06/02 04:30:40 robert Exp $ */
+/* $OpenBSD: rt2560var.h,v 1.4 2006/06/18 18:44:04 damien Exp $ */
/*-
* Copyright (c) 2005, 2006
@@ -114,7 +114,9 @@ struct rt2560_softc {
struct timeout rssadapt_ch;
int sc_flags;
-#define RT2560_ENABLED (1 << 0)
+#define RT2560_ENABLED (1 << 0)
+#define RT2560_UPDATE_SLOT (1 << 1)
+#define RT2560_SET_SLOTTIME (1 << 2)
int sc_tx_timer;
@@ -141,6 +143,8 @@ struct rt2560_softc {
int tx_ant;
int nb_ant;
+ uint8_t *erp;
+
#if NBPFILTER > 0
caddr_t sc_drvbpf;
diff --git a/sys/dev/ic/rt2661.c b/sys/dev/ic/rt2661.c
index 5603be2ab1a..eb8725a5879 100644
--- a/sys/dev/ic/rt2661.c
+++ b/sys/dev/ic/rt2661.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rt2661.c,v 1.22 2006/06/18 12:32:46 damien Exp $ */
+/* $OpenBSD: rt2661.c,v 1.23 2006/06/18 18:44:04 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -138,7 +138,8 @@ void rt2661_set_chan(struct rt2661_softc *,
void rt2661_set_bssid(struct rt2661_softc *, const uint8_t *);
void rt2661_set_macaddr(struct rt2661_softc *, const uint8_t *);
void rt2661_update_promisc(struct rt2661_softc *);
-void rt2661_update_slot(struct rt2661_softc *);
+void rt2661_updateslot(struct ieee80211com *);
+void rt2661_set_slottime(struct rt2661_softc *);
const char *rt2661_get_rf(int);
void rt2661_read_eeprom(struct rt2661_softc *);
int rt2661_bbp_init(struct rt2661_softc *);
@@ -314,6 +315,7 @@ rt2661_attach(void *xsc, int id)
ieee80211_ifattach(ifp);
ic->ic_node_alloc = rt2661_node_alloc;
ic->ic_node_copy = rt2661_node_copy;
+ ic->ic_updateslot = rt2661_updateslot;
/* override state transition machine */
sc->sc_newstate = ic->ic_newstate;
@@ -812,7 +814,7 @@ rt2661_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
ni = ic->ic_bss;
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
- rt2661_update_slot(sc);
+ rt2661_set_slottime(sc);
rt2661_enable_mrr(sc);
rt2661_set_txpreamble(sc);
rt2661_set_basicrates(sc);
@@ -1168,10 +1170,30 @@ skip: desc->flags |= htole32(RT2661_RX_BUSY);
rt2661_start(ifp);
}
+/*
+ * This function is called in HostAP or IBSS modes when it's time to send a
+ * new beacon (every ni_intval milliseconds).
+ */
void
rt2661_mcu_beacon_expire(struct rt2661_softc *sc)
{
- /* do nothing */
+ struct ieee80211com *ic = &sc->sc_ic;
+
+ if (sc->sc_flags & RT2661_UPDATE_SLOT) {
+ sc->sc_flags &= ~RT2661_UPDATE_SLOT;
+ sc->sc_flags |= RT2661_SET_SLOTTIME;
+ } else if (sc->sc_flags & RT2661_SET_SLOTTIME) {
+ sc->sc_flags &= ~RT2661_SET_SLOTTIME;
+ rt2661_set_slottime(sc);
+ }
+
+ if (ic->ic_curmode == IEEE80211_MODE_11G) {
+ /* update ERP Information Element */
+ RAL_WRITE_1(sc, sc->erp_csr, ic->ic_bss->ni_erp);
+ RAL_RW_BARRIER_1(sc, sc->erp_csr);
+ }
+
+ DPRINTFN(15, ("beacon expired\n"));
}
void
@@ -1339,7 +1361,7 @@ rt2661_txtime(int len, int rate, uint32_t flags)
uint16_t txtime;
if (RAL_RATE_IS_OFDM(rate)) {
- /* IEEE Std 802.11a-1999, pp. 37 */
+ /* IEEE Std 802.11g-2003, pp. 44 */
txtime = (8 + 4 * len + 3 + rate - 1) / rate;
txtime = 16 + 4 + 4 * txtime + 6;
} else {
@@ -2291,7 +2313,23 @@ rt2661_update_promisc(struct rt2661_softc *sc)
}
void
-rt2661_update_slot(struct rt2661_softc *sc)
+rt2661_updateslot(struct ieee80211com *ic)
+{
+ struct rt2661_softc *sc = ic->ic_if.if_softc;
+
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
+ /*
+ * In HostAP mode, we defer setting of new slot time until
+ * updated ERP Information Element has propagated to all
+ * associated STAs.
+ */
+ sc->sc_flags |= RT2661_UPDATE_SLOT;
+ } else
+ rt2661_set_slottime(sc);
+}
+
+void
+rt2661_set_slottime(struct rt2661_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
uint8_t slottime;
@@ -2302,6 +2340,8 @@ rt2661_update_slot(struct rt2661_softc *sc)
tmp = RAL_READ(sc, RT2661_MAC_CSR9);
tmp = (tmp & ~0xff) | slottime;
RAL_WRITE(sc, RT2661_MAC_CSR9, tmp);
+
+ DPRINTF(("setting slot time to %uus\n", slottime));
}
const char *
@@ -2814,11 +2854,12 @@ int
rt2661_prepare_beacon(struct rt2661_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_node *ni = ic->ic_bss;
struct rt2661_tx_desc desc;
struct mbuf *m0;
int rate;
- m0 = ieee80211_beacon_alloc(ic, ic->ic_bss);
+ m0 = ieee80211_beacon_alloc(ic, ni);
if (m0 == NULL) {
printf("%s: could not allocate beacon frame\n",
sc->sc_dev.dv_xname);
@@ -2826,7 +2867,7 @@ rt2661_prepare_beacon(struct rt2661_softc *sc)
}
/* send beacons at the lowest available rate */
- rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan) ? 12 : 2;
+ rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2;
rt2661_setup_tx_desc(sc, &desc, RT2661_TX_TIMESTAMP, RT2661_TX_HWSEQ,
m0->m_pkthdr.len, rate, NULL, 0, RT2661_QID_MGT);
@@ -2840,6 +2881,23 @@ rt2661_prepare_beacon(struct rt2661_softc *sc)
m_freem(m0);
+ /*
+ * Store offset of ERP Information Element so that we can update it
+ * dynamically when the slot time changes.
+ * XXX: this is ugly since it depends on how net80211 builds beacon
+ * frames but ieee80211_beacon_alloc() don't store offsets for us.
+ */
+ if (ic->ic_curmode == IEEE80211_MODE_11G) {
+ sc->erp_csr =
+ RT2661_HW_BEACON_BASE0 + 24 +
+ sizeof (struct ieee80211_frame) +
+ 8 + 2 + 2 + 2 + ni->ni_esslen + 2 + 1 +
+ ((ic->ic_opmode == IEEE80211_M_IBSS) ? 3 : 6) +
+ 2 + ni->ni_rates.rs_nrates +
+ ((ni->ni_rates.rs_nrates > IEEE80211_RATE_SIZE) ? 2 : 0) +
+ 2;
+ }
+
return 0;
}
diff --git a/sys/dev/ic/rt2661reg.h b/sys/dev/ic/rt2661reg.h
index d99d15c005f..bc3f93e842d 100644
--- a/sys/dev/ic/rt2661reg.h
+++ b/sys/dev/ic/rt2661reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rt2661reg.h,v 1.7 2006/06/14 19:31:47 damien Exp $ */
+/* $OpenBSD: rt2661reg.h,v 1.8 2006/06/18 18:44:04 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -324,6 +324,13 @@ struct rt2661_rx_desc {
#define RAL_WRITE(sc, reg, val) \
bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))
+#define RAL_WRITE_1(sc, reg, val) \
+ bus_space_write_1((sc)->sc_st, (sc)->sc_sh, (reg), (val))
+
+#define RAL_RW_BARRIER_1(sc, reg) \
+ bus_space_barrier((sc)->sc_st, (sc)->sc_sh, (reg), 1, \
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
+
#define RAL_WRITE_REGION_1(sc, offset, datap, count) \
bus_space_write_region_1((sc)->sc_st, (sc)->sc_sh, (offset), \
(datap), (count))
diff --git a/sys/dev/ic/rt2661var.h b/sys/dev/ic/rt2661var.h
index 3d76c96ea25..8cebb86ebdb 100644
--- a/sys/dev/ic/rt2661var.h
+++ b/sys/dev/ic/rt2661var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rt2661var.h,v 1.6 2006/06/08 19:58:44 damien Exp $ */
+/* $OpenBSD: rt2661var.h,v 1.7 2006/06/18 18:44:04 damien Exp $ */
/*-
* Copyright (c) 2006
@@ -108,8 +108,10 @@ struct rt2661_softc {
int sc_id;
int sc_flags;
-#define RT2661_ENABLED (1 << 0)
-#define RT2661_FWLOADED (1 << 1)
+#define RT2661_ENABLED (1 << 0)
+#define RT2661_FWLOADED (1 << 1)
+#define RT2661_UPDATE_SLOT (1 << 2)
+#define RT2661_SET_SLOTTIME (1 << 3)
int sc_tx_timer;
@@ -144,6 +146,8 @@ struct rt2661_softc {
int ncalls;
int avg_rssi;
+ uint32_t erp_csr;
+
uint8_t bbp18;
uint8_t bbp21;
uint8_t bbp22;