diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2006-06-18 18:44:05 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2006-06-18 18:44:05 +0000 |
commit | ce9d7316d9fd1b1e65ddb9109f5e0490aca171fa (patch) | |
tree | 7235b72ebf581012f577ff435d18734a644c88d9 /sys/dev | |
parent | b6efe24e3cd0a45a2c3b9be9b804f53c1db0152e (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.c | 88 | ||||
-rw-r--r-- | sys/dev/ic/rt2560var.h | 8 | ||||
-rw-r--r-- | sys/dev/ic/rt2661.c | 74 | ||||
-rw-r--r-- | sys/dev/ic/rt2661reg.h | 9 | ||||
-rw-r--r-- | sys/dev/ic/rt2661var.h | 10 |
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; |