diff options
Diffstat (limited to 'sys/dev/ral/rt2560.c')
-rw-r--r-- | sys/dev/ral/rt2560.c | 1221 |
1 files changed, 537 insertions, 684 deletions
diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c index 63f7de0..1536a35 100644 --- a/sys/dev/ral/rt2560.c +++ b/sys/dev/ral/rt2560.c @@ -52,8 +52,10 @@ __FBSDID("$FreeBSD$"); #include <net/if_types.h> #include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_phy.h> #include <net80211/ieee80211_radiotap.h> #include <net80211/ieee80211_regdomain.h> +#include <net80211/ieee80211_amrr.h> #include <netinet/in.h> #include <netinet/in_systm.h> @@ -61,7 +63,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip.h> #include <netinet/if_ether.h> -#include <dev/ral/if_ralrate.h> #include <dev/ral/rt2560reg.h> #include <dev/ral/rt2560var.h> @@ -69,15 +70,26 @@ __FBSDID("$FreeBSD$"); ((rssi) > (RT2560_NOISE_FLOOR + (sc)->rssi_corr) ? \ ((rssi) - RT2560_NOISE_FLOOR - (sc)->rssi_corr) : 0) +#define RAL_DEBUG #ifdef RAL_DEBUG -#define DPRINTF(x) do { if (ral_debug > 0) printf x; } while (0) -#define DPRINTFN(n, x) do { if (ral_debug >= (n)) printf x; } while (0) -extern int ral_debug; +#define DPRINTF(sc, fmt, ...) do { \ + if (sc->sc_debug > 0) \ + printf(fmt, __VA_ARGS__); \ +} while (0) +#define DPRINTFN(sc, n, fmt, ...) do { \ + if (sc->sc_debug >= (n)) \ + printf(fmt, __VA_ARGS__); \ +} while (0) #else -#define DPRINTF(x) -#define DPRINTFN(n, x) +#define DPRINTF(sc, fmt, ...) +#define DPRINTFN(sc, n, fmt, ...) #endif +static struct ieee80211vap *rt2560_vap_create(struct ieee80211com *, + const char name[IFNAMSIZ], int unit, int opmode, + int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], + const uint8_t mac[IEEE80211_ADDR_LEN]); +static void rt2560_vap_delete(struct ieee80211vap *); static void rt2560_dma_map_addr(void *, bus_dma_segment_t *, int, int); static int rt2560_alloc_tx_ring(struct rt2560_softc *, @@ -94,10 +106,8 @@ static void rt2560_free_rx_ring(struct rt2560_softc *, struct rt2560_rx_ring *); static struct ieee80211_node *rt2560_node_alloc( struct ieee80211_node_table *); -static int rt2560_media_change(struct ifnet *); -static void rt2560_iter_func(void *, struct ieee80211_node *); -static void rt2560_update_rssadapt(void *); -static int rt2560_newstate(struct ieee80211com *, +static void rt2560_newassoc(struct ieee80211_node *, int); +static int rt2560_newstate(struct ieee80211vap *, enum ieee80211_state, int); static uint16_t rt2560_eeprom_read(struct rt2560_softc *, uint8_t); static void rt2560_encryption_intr(struct rt2560_softc *); @@ -105,16 +115,12 @@ static void rt2560_tx_intr(struct rt2560_softc *); static void rt2560_prio_intr(struct rt2560_softc *); static void rt2560_decryption_intr(struct rt2560_softc *); static void rt2560_rx_intr(struct rt2560_softc *); -static void rt2560_beacon_update(struct ieee80211com *, int item); +static void rt2560_beacon_update(struct ieee80211vap *, int item); static void rt2560_beacon_expire(struct rt2560_softc *); static void rt2560_wakeup_expire(struct rt2560_softc *); -static uint8_t rt2560_rxrate(struct rt2560_rx_desc *); -static int rt2560_ack_rate(struct ieee80211com *, int); static void rt2560_scan_start(struct ieee80211com *); static void rt2560_scan_end(struct ieee80211com *); static void rt2560_set_channel(struct ieee80211com *); -static uint16_t rt2560_txtime(int, int, uint32_t); -static uint8_t rt2560_plcp_signal(int); static void rt2560_setup_tx_desc(struct rt2560_softc *, struct rt2560_tx_desc *, uint32_t, int, int, int, bus_addr_t); @@ -122,13 +128,11 @@ static int rt2560_tx_bcn(struct rt2560_softc *, struct mbuf *, struct ieee80211_node *); static int rt2560_tx_mgt(struct rt2560_softc *, struct mbuf *, struct ieee80211_node *); -static struct mbuf *rt2560_get_rts(struct rt2560_softc *, - struct ieee80211_frame *, uint16_t); static int rt2560_tx_data(struct rt2560_softc *, struct mbuf *, struct ieee80211_node *); +static void rt2560_start_locked(struct ifnet *); static void rt2560_start(struct ifnet *); static void rt2560_watchdog(void *); -static int rt2560_reset(struct ifnet *); static int rt2560_ioctl(struct ifnet *, u_long, caddr_t); static void rt2560_bbp_write(struct rt2560_softc *, uint8_t, uint8_t); @@ -148,13 +152,15 @@ static void rt2560_update_led(struct rt2560_softc *, int, int); static void rt2560_set_bssid(struct rt2560_softc *, const uint8_t *); static void rt2560_set_macaddr(struct rt2560_softc *, uint8_t *); static void rt2560_get_macaddr(struct rt2560_softc *, uint8_t *); -static void rt2560_update_promisc(struct rt2560_softc *); +static void rt2560_update_promisc(struct ifnet *); static const char *rt2560_get_rf(int); static void rt2560_read_config(struct rt2560_softc *); static int rt2560_bbp_init(struct rt2560_softc *); static void rt2560_set_txantenna(struct rt2560_softc *, int); static void rt2560_set_rxantenna(struct rt2560_softc *, int); +static void rt2560_init_locked(struct rt2560_softc *); static void rt2560_init(void *); +static void rt2560_stop_locked(struct rt2560_softc *); static int rt2560_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); @@ -192,9 +198,10 @@ int rt2560_attach(device_t dev, int id) { struct rt2560_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211com *ic; struct ifnet *ifp; - int error, bands; + int error; + uint8_t bands; sc->sc_dev = dev; @@ -202,14 +209,10 @@ rt2560_attach(device_t dev, int id) MTX_DEF | MTX_RECURSE); callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0); - callout_init(&sc->rssadapt_ch, CALLOUT_MPSAFE); /* retrieve RT2560 rev. no */ sc->asic_rev = RAL_READ(sc, RT2560_CSR0); - /* retrieve MAC address */ - rt2560_get_macaddr(sc, ic->ic_myaddr); - /* retrieve RF rev. no and various other things from EEPROM */ rt2560_read_config(sc); @@ -249,11 +252,15 @@ rt2560_attach(device_t dev, int id) goto fail5; } - ifp = sc->sc_ifp = if_alloc(IFT_ETHER); + ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); if (ifp == NULL) { device_printf(sc->sc_dev, "can not if_alloc()\n"); goto fail6; } + ic = ifp->if_l2com; + + /* retrieve MAC address */ + rt2560_get_macaddr(sc, ic->ic_myaddr); ifp->if_softc = sc; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); @@ -266,48 +273,47 @@ rt2560_attach(device_t dev, int id) IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; + ic->ic_opmode = IEEE80211_M_STA; ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ - ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ - ic->ic_state = IEEE80211_S_INIT; /* set device capabilities */ ic->ic_caps = - IEEE80211_C_IBSS | /* IBSS mode supported */ - IEEE80211_C_MONITOR | /* monitor mode supported */ - IEEE80211_C_HOSTAP | /* HostAp mode supported */ - IEEE80211_C_TXPMGT | /* tx power management */ - IEEE80211_C_SHPREAMBLE | /* short preamble supported */ - IEEE80211_C_SHSLOT | /* short slot time supported */ - IEEE80211_C_BGSCAN | /* bg scanning support */ - IEEE80211_C_WPA; /* 802.11i */ + IEEE80211_C_IBSS /* ibss, nee adhoc, mode */ + | IEEE80211_C_HOSTAP /* hostap mode */ + | IEEE80211_C_MONITOR /* monitor mode */ + | IEEE80211_C_AHDEMO /* adhoc demo mode */ + | IEEE80211_C_WDS /* 4-address traffic works */ + | IEEE80211_C_SHPREAMBLE /* short preamble supported */ + | IEEE80211_C_SHSLOT /* short slot time supported */ + | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ + | IEEE80211_C_BGSCAN /* capable of bg scanning */ +#ifdef notyet + | IEEE80211_C_TXFRAG /* handle tx frags */ +#endif + ; bands = 0; setbit(&bands, IEEE80211_MODE_11B); setbit(&bands, IEEE80211_MODE_11G); if (sc->rf_rev == RT2560_RF_5222) setbit(&bands, IEEE80211_MODE_11A); - ieee80211_init_channels(ic, 0, CTRY_DEFAULT, bands, 0, 1); + ieee80211_init_channels(ic, NULL, &bands); ieee80211_ifattach(ic); + ic->ic_newassoc = rt2560_newassoc; + ic->ic_raw_xmit = rt2560_raw_xmit; + ic->ic_updateslot = rt2560_update_slot; + ic->ic_update_promisc = rt2560_update_promisc; + ic->ic_node_alloc = rt2560_node_alloc; ic->ic_scan_start = rt2560_scan_start; ic->ic_scan_end = rt2560_scan_end; ic->ic_set_channel = rt2560_set_channel; - ic->ic_node_alloc = rt2560_node_alloc; - ic->ic_updateslot = rt2560_update_slot; - ic->ic_reset = rt2560_reset; - /* enable s/w bmiss handling in sta mode */ - ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; - /* override state transition machine */ - sc->sc_newstate = ic->ic_newstate; - ic->ic_newstate = rt2560_newstate; - ic->ic_raw_xmit = rt2560_raw_xmit; - ic->ic_update_beacon = rt2560_beacon_update; - ieee80211_media_init(ic, rt2560_media_change, ieee80211_media_status); + ic->ic_vap_create = rt2560_vap_create; + ic->ic_vap_delete = rt2560_vap_delete; - bpfattach2(ifp, DLT_IEEE802_11_RADIO, - sizeof (struct ieee80211_frame) + sizeof (sc->sc_txtap), - &sc->sc_drvbpf); + bpfattach(ifp, DLT_IEEE802_11_RADIO, + sizeof (struct ieee80211_frame) + sizeof (sc->sc_txtap)); sc->sc_rxtap_len = sizeof sc->sc_rxtap; sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); @@ -320,8 +326,11 @@ rt2560_attach(device_t dev, int id) /* * Add a few sysctl knobs. */ - sc->dwelltime = 200; - +#ifdef RAL_DEBUG + SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "debug", CTLFLAG_RW, &sc->sc_debug, 0, "debug msgs"); +#endif SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "txantenna", CTLFLAG_RW, &sc->tx_ant, 0, "tx antenna (0=auto)"); @@ -330,11 +339,6 @@ rt2560_attach(device_t dev, int id) SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "rxantenna", CTLFLAG_RW, &sc->rx_ant, 0, "rx antenna (0=auto)"); - SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "dwell", - CTLFLAG_RW, &sc->dwelltime, 0, - "channel dwell time (ms) for AP/station scanning"); - if (bootverbose) ieee80211_announce(ic); @@ -354,11 +358,10 @@ int rt2560_detach(void *xsc) { struct rt2560_softc *sc = xsc; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = ic->ic_ifp; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; rt2560_stop(sc); - callout_stop(&sc->rssadapt_ch); bpfdetach(ifp); ieee80211_ifdetach(ic); @@ -376,17 +379,88 @@ rt2560_detach(void *xsc) return 0; } +static struct ieee80211vap * +rt2560_vap_create(struct ieee80211com *ic, + const char name[IFNAMSIZ], int unit, int opmode, int flags, + const uint8_t bssid[IEEE80211_ADDR_LEN], + const uint8_t mac[IEEE80211_ADDR_LEN]) +{ + struct ifnet *ifp = ic->ic_ifp; + struct rt2560_vap *rvp; + struct ieee80211vap *vap; + + switch (opmode) { + case IEEE80211_M_STA: + case IEEE80211_M_IBSS: + case IEEE80211_M_AHDEMO: + case IEEE80211_M_MONITOR: + case IEEE80211_M_HOSTAP: + if (!TAILQ_EMPTY(&ic->ic_vaps)) { + if_printf(ifp, "only 1 vap supported\n"); + return NULL; + } + if (opmode == IEEE80211_M_STA) + flags |= IEEE80211_CLONE_NOBEACONS; + break; + case IEEE80211_M_WDS: + if (TAILQ_EMPTY(&ic->ic_vaps) || + ic->ic_opmode != IEEE80211_M_HOSTAP) { + if_printf(ifp, "wds only supported in ap mode\n"); + return NULL; + } + /* + * Silently remove any request for a unique + * bssid; WDS vap's always share the local + * mac address. + */ + flags &= ~IEEE80211_CLONE_BSSID; + break; + default: + if_printf(ifp, "unknown opmode %d\n", opmode); + return NULL; + } + rvp = (struct rt2560_vap *) malloc(sizeof(struct rt2560_vap), + M_80211_VAP, M_NOWAIT | M_ZERO); + if (rvp == NULL) + return NULL; + vap = &rvp->ral_vap; + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); + + /* override state transition machine */ + rvp->ral_newstate = vap->iv_newstate; + vap->iv_newstate = rt2560_newstate; + vap->iv_update_beacon = rt2560_beacon_update; + + ieee80211_amrr_init(&rvp->amrr, vap, + IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, + IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, + 500 /* ms */); + + /* complete setup */ + ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); + if (TAILQ_FIRST(&ic->ic_vaps) == vap) + ic->ic_opmode = opmode; + return vap; +} + +static void +rt2560_vap_delete(struct ieee80211vap *vap) +{ + struct rt2560_vap *rvp = RT2560_VAP(vap); + + ieee80211_amrr_cleanup(&rvp->amrr); + ieee80211_vap_detach(vap); + free(rvp, M_80211_VAP); +} + void rt2560_resume(void *xsc) { struct rt2560_softc *sc = xsc; - struct ifnet *ifp = sc->sc_ic.ic_ifp; + struct ifnet *ifp = sc->sc_ifp; - if (ifp->if_flags & IFF_UP) { - ifp->if_init(ifp->if_softc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ifp->if_start(ifp); - } + if (ifp->if_flags & IFF_UP) + rt2560_init(sc); } static void @@ -702,117 +776,68 @@ rt2560_node_alloc(struct ieee80211_node_table *nt) return (rn != NULL) ? &rn->ni : NULL; } -static int -rt2560_media_change(struct ifnet *ifp) -{ - struct rt2560_softc *sc = ifp->if_softc; - int error; - - error = ieee80211_media_change(ifp); - - if (error == ENETRESET) { - if ((ifp->if_flags & IFF_UP) && - (ifp->if_drv_flags & IFF_DRV_RUNNING)) - rt2560_init(sc); - } - return error; -} - -/* - * This function is called for each node present in the node station table. - */ static void -rt2560_iter_func(void *arg, struct ieee80211_node *ni) +rt2560_newassoc(struct ieee80211_node *ni, int isnew) { - struct rt2560_node *rn = (struct rt2560_node *)ni; + struct ieee80211vap *vap = ni->ni_vap; - ral_rssadapt_updatestats(&rn->rssadapt); -} - -/* - * This function is called periodically (every 100ms) in RUN state to update - * the rate adaptation statistics. - */ -static void -rt2560_update_rssadapt(void *arg) -{ - struct rt2560_softc *sc = arg; - struct ieee80211com *ic = &sc->sc_ic; - - RAL_LOCK(sc); - - ieee80211_iterate_nodes(&ic->ic_sta, rt2560_iter_func, arg); - callout_reset(&sc->rssadapt_ch, hz / 10, rt2560_update_rssadapt, sc); - - RAL_UNLOCK(sc); + ieee80211_amrr_node_init(&RT2560_VAP(vap)->amrr, + &RT2560_NODE(ni)->amrr, ni); } static int -rt2560_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) +rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { - struct rt2560_softc *sc = ic->ic_ifp->if_softc; - enum ieee80211_state ostate; - struct ieee80211_node *ni; - struct mbuf *m; - int error = 0; + struct rt2560_vap *rvp = RT2560_VAP(vap); + struct ifnet *ifp = vap->iv_ic->ic_ifp; + struct rt2560_softc *sc = ifp->if_softc; + int error; - ostate = ic->ic_state; + if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) { + /* abort TSF synchronization */ + RAL_WRITE(sc, RT2560_CSR14, 0); - switch (nstate) { - case IEEE80211_S_INIT: - callout_stop(&sc->rssadapt_ch); + /* turn association led off */ + rt2560_update_led(sc, 0, 0); + } - if (ostate == IEEE80211_S_RUN) { - /* abort TSF synchronization */ - RAL_WRITE(sc, RT2560_CSR14, 0); + error = rvp->ral_newstate(vap, nstate, arg); - /* turn association led off */ - rt2560_update_led(sc, 0, 0); - } - break; - case IEEE80211_S_RUN: - ni = ic->ic_bss; + if (error == 0 && nstate == IEEE80211_S_RUN) { + struct ieee80211_node *ni = vap->iv_bss; + struct mbuf *m; - if (ic->ic_opmode != IEEE80211_M_MONITOR) { + if (vap->iv_opmode != IEEE80211_M_MONITOR) { rt2560_update_plcp(sc); rt2560_set_basicrates(sc); rt2560_set_bssid(sc, ni->ni_bssid); } - if (ic->ic_opmode == IEEE80211_M_HOSTAP || - ic->ic_opmode == IEEE80211_M_IBSS) { - m = ieee80211_beacon_alloc(ni, &sc->sc_bo); + if (vap->iv_opmode == IEEE80211_M_HOSTAP || + vap->iv_opmode == IEEE80211_M_IBSS) { + m = ieee80211_beacon_alloc(ni, &rvp->ral_bo); if (m == NULL) { - device_printf(sc->sc_dev, - "could not allocate beacon\n"); - error = ENOBUFS; - break; + if_printf(ifp, "could not allocate beacon\n"); + return ENOBUFS; } - ieee80211_ref_node(ni); error = rt2560_tx_bcn(sc, m, ni); if (error != 0) - break; + return error; } /* turn assocation led on */ rt2560_update_led(sc, 1, 0); - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - callout_reset(&sc->rssadapt_ch, hz / 10, - rt2560_update_rssadapt, sc); - + if (vap->iv_opmode != IEEE80211_M_MONITOR) { + if (vap->iv_opmode == IEEE80211_M_STA) { + /* fake a join to init the tx rate */ + rt2560_newassoc(ni, 1); + } rt2560_enable_tsf_sync(sc); } - break; - case IEEE80211_S_SCAN: - case IEEE80211_S_AUTH: - case IEEE80211_S_ASSOC: - default: - break; } - - return (error != 0) ? error : sc->sc_newstate(ic, nstate, arg); + return error; } /* @@ -912,8 +937,8 @@ rt2560_encryption_intr(struct rt2560_softc *sc) desc->flags |= htole32(RT2560_TX_VALID); desc->flags |= htole32(RT2560_TX_BUSY); - DPRINTFN(15, ("encryption done idx=%u\n", - sc->txq.next_encrypt)); + DPRINTFN(sc, 15, "encryption done idx=%u\n", + sc->txq.next_encrypt); sc->txq.next_encrypt = (sc->txq.next_encrypt + 1) % RT2560_TX_RING_COUNT; @@ -929,11 +954,13 @@ rt2560_encryption_intr(struct rt2560_softc *sc) static void rt2560_tx_intr(struct rt2560_softc *sc) { - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = ic->ic_ifp; + struct ifnet *ifp = sc->sc_ifp; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; struct rt2560_node *rn; + struct mbuf *m; + uint32_t flags; + int retrycnt; bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map, BUS_DMASYNC_POSTREAD); @@ -942,36 +969,43 @@ rt2560_tx_intr(struct rt2560_softc *sc) desc = &sc->txq.desc[sc->txq.next]; data = &sc->txq.data[sc->txq.next]; - if ((le32toh(desc->flags) & RT2560_TX_BUSY) || - (le32toh(desc->flags) & RT2560_TX_CIPHER_BUSY) || - !(le32toh(desc->flags) & RT2560_TX_VALID)) + flags = le32toh(desc->flags); + if ((flags & RT2560_TX_BUSY) || + (flags & RT2560_TX_CIPHER_BUSY) || + !(flags & RT2560_TX_VALID)) break; rn = (struct rt2560_node *)data->ni; + m = data->m; - switch (le32toh(desc->flags) & RT2560_TX_RESULT_MASK) { + switch (flags & RT2560_TX_RESULT_MASK) { case RT2560_TX_SUCCESS: - DPRINTFN(10, ("data frame sent successfully\n")); - if (data->id.id_node != NULL) { - ral_rssadapt_raise_rate(ic, &rn->rssadapt, - &data->id); - } + DPRINTFN(sc, 10, "%s\n", "data frame sent successfully"); + if (data->rix != IEEE80211_FIXED_RATE_NONE) + ieee80211_amrr_tx_complete(&rn->amrr, + IEEE80211_AMRR_SUCCESS, 0); ifp->if_opackets++; break; case RT2560_TX_SUCCESS_RETRY: - DPRINTFN(9, ("data frame sent after %u retries\n", - (le32toh(desc->flags) >> 5) & 0x7)); + retrycnt = RT2560_TX_RETRYCNT(flags); + + DPRINTFN(sc, 9, "data frame sent after %u retries\n", + retrycnt); + if (data->rix != IEEE80211_FIXED_RATE_NONE) + ieee80211_amrr_tx_complete(&rn->amrr, + IEEE80211_AMRR_SUCCESS, retrycnt); ifp->if_opackets++; break; case RT2560_TX_FAIL_RETRY: - DPRINTFN(9, ("sending data frame failed (too much " - "retries)\n")); - if (data->id.id_node != NULL) { - ral_rssadapt_lower_rate(ic, data->ni, - &rn->rssadapt, &data->id); - } + retrycnt = RT2560_TX_RETRYCNT(flags); + + DPRINTFN(sc, 9, "data frame failed after %d retries\n", + retrycnt); + if (data->rix != IEEE80211_FIXED_RATE_NONE) + ieee80211_amrr_tx_complete(&rn->amrr, + IEEE80211_AMRR_FAILURE, retrycnt); ifp->if_oerrors++; break; @@ -979,14 +1013,14 @@ rt2560_tx_intr(struct rt2560_softc *sc) case RT2560_TX_FAIL_OTHER: default: device_printf(sc->sc_dev, "sending data frame failed " - "0x%08x\n", le32toh(desc->flags)); + "0x%08x\n", flags); ifp->if_oerrors++; } bus_dmamap_sync(sc->txq.data_dmat, data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->txq.data_dmat, data->map); - m_freem(data->m); + m_freem(m); data->m = NULL; ieee80211_free_node(data->ni); data->ni = NULL; @@ -994,7 +1028,7 @@ rt2560_tx_intr(struct rt2560_softc *sc) /* descriptor is no longer valid */ desc->flags &= ~htole32(RT2560_TX_VALID); - DPRINTFN(15, ("tx done idx=%u\n", sc->txq.next)); + DPRINTFN(sc, 15, "tx done idx=%u\n", sc->txq.next); sc->txq.queued--; sc->txq.next = (sc->txq.next + 1) % RT2560_TX_RING_COUNT; @@ -1011,15 +1045,14 @@ rt2560_tx_intr(struct rt2560_softc *sc) if ((sc->sc_flags & (RT2560_F_DATA_OACTIVE | RT2560_F_PRIO_OACTIVE)) == 0) ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - rt2560_start(ifp); + rt2560_start_locked(ifp); } } static void rt2560_prio_intr(struct rt2560_softc *sc) { - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = ic->ic_ifp; + struct ifnet *ifp = sc->sc_ifp; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; struct ieee80211_node *ni; @@ -1039,17 +1072,17 @@ rt2560_prio_intr(struct rt2560_softc *sc) switch (flags & RT2560_TX_RESULT_MASK) { case RT2560_TX_SUCCESS: - DPRINTFN(10, ("mgt frame sent successfully\n")); + DPRINTFN(sc, 10, "%s\n", "mgt frame sent successfully"); break; case RT2560_TX_SUCCESS_RETRY: - DPRINTFN(9, ("mgt frame sent after %u retries\n", - (flags >> 5) & 0x7)); + DPRINTFN(sc, 9, "mgt frame sent after %u retries\n", + (flags >> 5) & 0x7); break; case RT2560_TX_FAIL_RETRY: - DPRINTFN(9, ("sending mgt frame failed (too much " - "retries)\n")); + DPRINTFN(sc, 9, "%s\n", + "sending mgt frame failed (too much retries)"); break; case RT2560_TX_FAIL_INVALID: @@ -1072,7 +1105,7 @@ rt2560_prio_intr(struct rt2560_softc *sc) /* descriptor is no longer valid */ desc->flags &= ~htole32(RT2560_TX_VALID); - DPRINTFN(15, ("prio done idx=%u\n", sc->prioq.next)); + DPRINTFN(sc, 15, "prio done idx=%u\n", sc->prioq.next); sc->prioq.queued--; sc->prioq.next = (sc->prioq.next + 1) % RT2560_PRIO_RING_COUNT; @@ -1096,25 +1129,24 @@ rt2560_prio_intr(struct rt2560_softc *sc) if ((sc->sc_flags & (RT2560_F_DATA_OACTIVE | RT2560_F_PRIO_OACTIVE)) == 0) ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - rt2560_start(ifp); + rt2560_start_locked(ifp); } } /* * Some frames were processed by the hardware cipher engine and are ready for - * transmission to the IEEE802.11 layer. + * handoff to the IEEE802.11 layer. */ static void rt2560_decryption_intr(struct rt2560_softc *sc) { - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = ic->ic_ifp; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; struct rt2560_rx_desc *desc; struct rt2560_rx_data *data; bus_addr_t physaddr; struct ieee80211_frame *wh; struct ieee80211_node *ni; - struct rt2560_node *rn; struct mbuf *mnew, *m; int hw, error; @@ -1193,7 +1225,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc) m->m_pkthdr.len = m->m_len = (le32toh(desc->flags) >> 16) & 0xfff; - if (bpf_peers_present(sc->sc_drvbpf)) { + if (bpf_peers_present(ifp->if_bpf)) { struct rt2560_rx_radiotap_header *tap = &sc->sc_rxtap; uint32_t tsf_lo, tsf_hi; @@ -1204,13 +1236,12 @@ rt2560_decryption_intr(struct rt2560_softc *sc) tap->wr_tsf = htole64(((uint64_t)tsf_hi << 32) | tsf_lo); tap->wr_flags = 0; - tap->wr_rate = rt2560_rxrate(desc); - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); + tap->wr_rate = ieee80211_plcp2rate(desc->rate, + le32toh(desc->flags) & RT2560_RX_OFDM); tap->wr_antenna = sc->rx_ant; tap->wr_antsignal = RT2560_RSSI(sc, desc->rssi); - bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m); + bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); } sc->sc_flags |= RT2560_F_INPUT_RUNNING; @@ -1218,24 +1249,19 @@ rt2560_decryption_intr(struct rt2560_softc *sc) wh = mtod(m, struct ieee80211_frame *); ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); - - /* send the frame to the 802.11 layer */ - ieee80211_input(ic, m, ni, RT2560_RSSI(sc, desc->rssi), - RT2560_NOISE_FLOOR, 0); - - /* give rssi to the rate adatation algorithm */ - rn = (struct rt2560_node *)ni; - ral_rssadapt_input(ic, ni, &rn->rssadapt, - RT2560_RSSI(sc, desc->rssi)); - - /* node is no longer needed */ - ieee80211_free_node(ni); + if (ni != NULL) { + (void) ieee80211_input(ni, m, + RT2560_RSSI(sc, desc->rssi), RT2560_NOISE_FLOOR, 0); + ieee80211_free_node(ni); + } else + (void) ieee80211_input_all(ic, m, + RT2560_RSSI(sc, desc->rssi), RT2560_NOISE_FLOOR, 0); RAL_LOCK(sc); sc->sc_flags &= ~RT2560_F_INPUT_RUNNING; skip: desc->flags = htole32(RT2560_RX_BUSY); - DPRINTFN(15, ("decryption done idx=%u\n", sc->rxq.cur_decrypt)); + DPRINTFN(sc, 15, "decryption done idx=%u\n", sc->rxq.cur_decrypt); sc->rxq.cur_decrypt = (sc->rxq.cur_decrypt + 1) % RT2560_RX_RING_COUNT; @@ -1274,20 +1300,20 @@ rt2560_rx_intr(struct rt2560_softc *sc) * This should not happen since we did not request * to receive those frames when we filled RXCSR0. */ - DPRINTFN(5, ("PHY or CRC error flags 0x%08x\n", - le32toh(desc->flags))); + DPRINTFN(sc, 5, "PHY or CRC error flags 0x%08x\n", + le32toh(desc->flags)); data->drop = 1; } if (((le32toh(desc->flags) >> 16) & 0xfff) > MCLBYTES) { - DPRINTFN(5, ("bad length\n")); + DPRINTFN(sc, 5, "%s\n", "bad length"); data->drop = 1; } /* mark the frame for decryption */ desc->flags |= htole32(RT2560_RX_CIPHER_BUSY); - DPRINTFN(15, ("rx done idx=%u\n", sc->rxq.cur)); + DPRINTFN(sc, 15, "rx done idx=%u\n", sc->rxq.cur); sc->rxq.cur = (sc->rxq.cur + 1) % RT2560_RX_RING_COUNT; } @@ -1300,10 +1326,10 @@ rt2560_rx_intr(struct rt2560_softc *sc) } static void -rt2560_beacon_update(struct ieee80211com *ic, int item) +rt2560_beacon_update(struct ieee80211vap *vap, int item) { - struct rt2560_softc *sc = ic->ic_ifp->if_softc; - struct ieee80211_beacon_offsets *bo = &sc->sc_bo; + struct rt2560_vap *rvp = RT2560_VAP(vap); + struct ieee80211_beacon_offsets *bo = &rvp->ral_bo; setbit(bo->bo_flags, item); } @@ -1315,7 +1341,10 @@ rt2560_beacon_update(struct ieee80211com *ic, int item) static void rt2560_beacon_expire(struct rt2560_softc *sc) { - struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + struct rt2560_vap *rvp = RT2560_VAP(vap); struct rt2560_tx_data *data; if (ic->ic_opmode != IEEE80211_M_IBSS && @@ -1332,14 +1361,12 @@ rt2560_beacon_expire(struct rt2560_softc *sc) bus_dmamap_sync(sc->bcnq.data_dmat, data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->bcnq.data_dmat, data->map); - ieee80211_beacon_update(data->ni, &sc->sc_bo, data->m, 1); - - if (bpf_peers_present(ic->ic_rawbpf)) - bpf_mtap(ic->ic_rawbpf, data->m); + /* XXX 1 =>'s mcast frames which means all PS sta's will wakeup! */ + ieee80211_beacon_update(data->ni, &rvp->ral_bo, data->m, 1); rt2560_tx_bcn(sc, data->m, data->ni); - DPRINTFN(15, ("beacon expired\n")); + DPRINTFN(sc, 15, "%s", "beacon expired\n"); sc->bcnq.next = (sc->bcnq.next + 1) % RT2560_BEACON_RING_COUNT; } @@ -1348,7 +1375,7 @@ rt2560_beacon_expire(struct rt2560_softc *sc) static void rt2560_wakeup_expire(struct rt2560_softc *sc) { - DPRINTFN(2, ("wakeup expired\n")); + DPRINTFN(sc, 2, "%s", "wakeup expired\n"); } void @@ -1401,137 +1428,16 @@ rt2560_intr(void *arg) RAL_UNLOCK(sc); } -/* quickly determine if a given rate is CCK or OFDM */ -#define RAL_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) - -#define RAL_ACK_SIZE 14 /* 10 + 4(FCS) */ -#define RAL_CTS_SIZE 14 /* 10 + 4(FCS) */ - #define RAL_SIFS 10 /* us */ #define RT2560_TXRX_TURNAROUND 10 /* us */ -/* - * This function is only used by the Rx radiotap code. - */ -static uint8_t -rt2560_rxrate(struct rt2560_rx_desc *desc) -{ - if (le32toh(desc->flags) & RT2560_RX_OFDM) { - /* reverse function of rt2560_plcp_signal */ - switch (desc->rate) { - case 0xb: return 12; - case 0xf: return 18; - case 0xa: return 24; - case 0xe: return 36; - case 0x9: return 48; - case 0xd: return 72; - case 0x8: return 96; - case 0xc: return 108; - } - } else { - if (desc->rate == 10) - return 2; - if (desc->rate == 20) - return 4; - if (desc->rate == 55) - return 11; - if (desc->rate == 110) - return 22; - } - return 2; /* should not get there */ -} - -/* - * Return the expected ack rate for a frame transmitted at rate `rate'. - * XXX: this should depend on the destination node basic rate set. - */ -static int -rt2560_ack_rate(struct ieee80211com *ic, int rate) -{ - switch (rate) { - /* CCK rates */ - case 2: - return 2; - case 4: - case 11: - case 22: - return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate; - - /* OFDM rates */ - case 12: - case 18: - return 12; - case 24: - case 36: - return 24; - case 48: - case 72: - case 96: - case 108: - return 48; - } - - /* default to 1Mbps */ - return 2; -} - -/* - * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'. - * The function automatically determines the operating mode depending on the - * given rate. `flags' indicates whether short preamble is in use or not. - */ -static uint16_t -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 */ - txtime = (8 + 4 * len + 3 + rate - 1) / rate; - txtime = 16 + 4 + 4 * txtime + 6; - } else { - /* IEEE Std 802.11b-1999, pp. 28 */ - txtime = (16 * len + rate - 1) / rate; - if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) - txtime += 72 + 24; - else - txtime += 144 + 48; - } - - return txtime; -} - -static uint8_t -rt2560_plcp_signal(int rate) -{ - switch (rate) { - /* CCK rates (returned values are device-dependent) */ - case 2: return 0x0; - case 4: return 0x1; - case 11: return 0x2; - case 22: return 0x3; - - /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ - case 12: return 0xb; - case 18: return 0xf; - case 24: return 0xa; - case 36: return 0xe; - case 48: return 0x9; - case 72: return 0xd; - case 96: return 0x8; - case 108: return 0xc; - - /* unsupported rates (should not get there) */ - default: return 0xff; - } -} - static void rt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc, uint32_t flags, int len, int rate, int encrypt, bus_addr_t physaddr) { - struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; uint16_t plcp_length; int remainder; @@ -1545,11 +1451,11 @@ rt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc, RT2560_LOGCWMAX(8)); /* setup PLCP fields */ - desc->plcp_signal = rt2560_plcp_signal(rate); + desc->plcp_signal = ieee80211_rate2plcp(rate); desc->plcp_service = 4; len += IEEE80211_CRC_LEN; - if (RAL_RATE_IS_OFDM(rate)) { + if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) { desc->flags |= htole32(RT2560_TX_OFDM); plcp_length = len & 0xfff; @@ -1579,7 +1485,9 @@ static int rt2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) { - struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211com *ic = ni->ni_ic; + struct ifnet *ifp = sc->sc_ifp; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; bus_dma_segment_t segs[RT2560_MAX_SCATTER]; @@ -1588,7 +1496,8 @@ rt2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0, desc = &sc->bcnq.desc[sc->bcnq.cur]; data = &sc->bcnq.data[sc->bcnq.cur]; - rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2; + /* XXX maybe a separate beacon rate? */ + rate = vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)].mgmtrate; error = bus_dmamap_load_mbuf_sg(sc->bcnq.data_dmat, data->map, m0, segs, &nsegs, BUS_DMA_NOWAIT); @@ -1599,7 +1508,7 @@ rt2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0, return error; } - if (bpf_peers_present(sc->sc_drvbpf)) { + if (bpf_peers_present(ifp->if_bpf)) { struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap; tap->wt_flags = 0; @@ -1608,7 +1517,7 @@ rt2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0, tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); tap->wt_antenna = sc->tx_ant; - bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0); + bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); } data->m = m0; @@ -1617,8 +1526,8 @@ rt2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0, rt2560_setup_tx_desc(sc, desc, RT2560_TX_IFS_NEWBACKOFF | RT2560_TX_TIMESTAMP, m0->m_pkthdr.len, rate, 0, segs->ds_addr); - DPRINTFN(10, ("sending beacon frame len=%u idx=%u rate=%u\n", - m0->m_pkthdr.len, sc->bcnq.cur, rate)); + DPRINTFN(sc, 10, "sending beacon frame len=%u idx=%u rate=%u\n", + m0->m_pkthdr.len, sc->bcnq.cur, rate); bus_dmamap_sync(sc->bcnq.data_dmat, data->map, BUS_DMASYNC_PREWRITE); bus_dmamap_sync(sc->bcnq.desc_dmat, sc->bcnq.desc_map, @@ -1633,7 +1542,9 @@ static int rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) { - struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211com *ic = ni->ni_ic; + struct ifnet *ifp = sc->sc_ifp; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; struct ieee80211_frame *wh; @@ -1646,12 +1557,12 @@ rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0, desc = &sc->prioq.desc[sc->prioq.cur]; data = &sc->prioq.data[sc->prioq.cur]; - rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2; + rate = vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)].mgmtrate; wh = mtod(m0, struct ieee80211_frame *); if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - k = ieee80211_crypto_encap(ic, ni, m0); + k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { m_freem(m0); return ENOBUFS; @@ -1667,7 +1578,7 @@ rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0, return error; } - if (bpf_peers_present(sc->sc_drvbpf)) { + if (bpf_peers_present(ifp->if_bpf)) { struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap; tap->wt_flags = 0; @@ -1676,19 +1587,21 @@ rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0, tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); tap->wt_antenna = sc->tx_ant; - bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0); + bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); } data->m = m0; data->ni = ni; + /* management frames are not taken into account for amrr */ + data->rix = IEEE80211_FIXED_RATE_NONE; wh = mtod(m0, struct ieee80211_frame *); if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { flags |= RT2560_TX_ACK; - dur = rt2560_txtime(RAL_ACK_SIZE, rate, ic->ic_flags) + - RAL_SIFS; + dur = ieee80211_ack_duration(sc->sc_rates, + rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE); *(uint16_t *)wh->i_dur = htole16(dur); /* tell hardware to add timestamp for probe responses */ @@ -1706,8 +1619,8 @@ rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0, bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map, BUS_DMASYNC_PREWRITE); - DPRINTFN(10, ("sending mgt frame len=%u idx=%u rate=%u\n", - m0->m_pkthdr.len, sc->prioq.cur, rate)); + DPRINTFN(sc, 10, "sending mgt frame len=%u idx=%u rate=%u\n", + m0->m_pkthdr.len, sc->prioq.cur, rate); /* kick prio */ sc->prioq.queued++; @@ -1718,10 +1631,80 @@ rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0, } static int +rt2560_sendprot(struct rt2560_softc *sc, + const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate) +{ + struct ieee80211com *ic = ni->ni_ic; + const struct ieee80211_frame *wh; + struct rt2560_tx_desc *desc; + struct rt2560_tx_data *data; + struct mbuf *mprot; + int protrate, ackrate, pktlen, flags, isshort, error; + uint16_t dur; + bus_dma_segment_t segs[RT2560_MAX_SCATTER]; + int nsegs; + + KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY, + ("protection %d", prot)); + + wh = mtod(m, const struct ieee80211_frame *); + pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; + + protrate = ieee80211_ctl_rate(sc->sc_rates, rate); + ackrate = ieee80211_ack_rate(sc->sc_rates, rate); + + isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; + dur = ieee80211_compute_duration(sc->sc_rates, pktlen, rate, isshort); + + ieee80211_ack_duration(sc->sc_rates, rate, isshort); + flags = RT2560_TX_MORE_FRAG; + if (prot == IEEE80211_PROT_RTSCTS) { + /* NB: CTS is the same size as an ACK */ + dur += ieee80211_ack_duration(sc->sc_rates, rate, isshort); + flags |= RT2560_TX_ACK; + mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur); + } else { + mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); + } + if (mprot == NULL) { + /* XXX stat + msg */ + return ENOBUFS; + } + + desc = &sc->txq.desc[sc->txq.cur_encrypt]; + data = &sc->txq.data[sc->txq.cur_encrypt]; + + error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map, + mprot, segs, &nsegs, 0); + if (error != 0) { + device_printf(sc->sc_dev, + "could not map mbuf (error %d)\n", error); + m_freem(mprot); + return error; + } + + data->m = mprot; + data->ni = ieee80211_ref_node(ni); + /* ctl frames are not taken into account for amrr */ + data->rix = IEEE80211_FIXED_RATE_NONE; + + rt2560_setup_tx_desc(sc, desc, flags, mprot->m_pkthdr.len, protrate, 1, + segs->ds_addr); + + bus_dmamap_sync(sc->txq.data_dmat, data->map, + BUS_DMASYNC_PREWRITE); + + sc->txq.queued++; + sc->txq.cur_encrypt = (sc->txq.cur_encrypt + 1) % RT2560_TX_RING_COUNT; + + return 0; +} + +static int rt2560_tx_raw(struct rt2560_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) { - struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; bus_dma_segment_t segs[RT2560_MAX_SCATTER]; @@ -1734,10 +1717,26 @@ rt2560_tx_raw(struct rt2560_softc *sc, struct mbuf *m0, rate = params->ibp_rate0 & IEEE80211_RATE_VAL; /* XXX validate */ if (rate == 0) { + /* XXX fall back to mcast/mgmt rate? */ m_freem(m0); return EINVAL; } + flags = 0; + if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) + flags |= RT2560_TX_ACK; + if (params->ibp_flags & (IEEE80211_BPF_RTS|IEEE80211_BPF_CTS)) { + error = rt2560_sendprot(sc, m0, ni, + params->ibp_flags & IEEE80211_BPF_RTS ? + IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY, + rate); + if (error) { + m_freem(m0); + return error; + } + flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS; + } + error = bus_dmamap_load_mbuf_sg(sc->prioq.data_dmat, data->map, m0, segs, &nsegs, 0); if (error != 0) { @@ -1747,7 +1746,7 @@ rt2560_tx_raw(struct rt2560_softc *sc, struct mbuf *m0, return error; } - if (bpf_peers_present(sc->sc_drvbpf)) { + if (bpf_peers_present(ifp->if_bpf)) { struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap; tap->wt_flags = 0; @@ -1756,16 +1755,12 @@ rt2560_tx_raw(struct rt2560_softc *sc, struct mbuf *m0, tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); tap->wt_antenna = sc->tx_ant; - bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0); + bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); } data->m = m0; data->ni = ni; - flags = 0; - if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) - flags |= RT2560_TX_ACK; - /* XXX need to setup descriptor ourself */ rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, (params->ibp_flags & IEEE80211_BPF_CRYPTO) != 0, @@ -1775,8 +1770,8 @@ rt2560_tx_raw(struct rt2560_softc *sc, struct mbuf *m0, bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map, BUS_DMASYNC_PREWRITE); - DPRINTFN(10, ("sending raw frame len=%u idx=%u rate=%u\n", - m0->m_pkthdr.len, sc->prioq.cur, rate)); + DPRINTFN(sc, 10, "sending raw frame len=%u idx=%u rate=%u\n", + m0->m_pkthdr.len, sc->prioq.cur, rate); /* kick prio */ sc->prioq.queued++; @@ -1786,70 +1781,40 @@ rt2560_tx_raw(struct rt2560_softc *sc, struct mbuf *m0, return 0; } -/* - * Build a RTS control frame. - */ -static struct mbuf * -rt2560_get_rts(struct rt2560_softc *sc, struct ieee80211_frame *wh, - uint16_t dur) -{ - struct ieee80211_frame_rts *rts; - struct mbuf *m; - - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == NULL) { - sc->sc_ic.ic_stats.is_tx_nobuf++; - device_printf(sc->sc_dev, "could not allocate RTS frame\n"); - return NULL; - } - - rts = mtod(m, struct ieee80211_frame_rts *); - - rts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL | - IEEE80211_FC0_SUBTYPE_RTS; - rts->i_fc[1] = IEEE80211_FC1_DIR_NODS; - *(uint16_t *)rts->i_dur = htole16(dur); - IEEE80211_ADDR_COPY(rts->i_ra, wh->i_addr1); - IEEE80211_ADDR_COPY(rts->i_ta, wh->i_addr2); - - m->m_pkthdr.len = m->m_len = sizeof (struct ieee80211_frame_rts); - - return m; -} - static int rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) { - struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211com *ic = ni->ni_ic; + struct ifnet *ifp = sc->sc_ifp; struct rt2560_tx_desc *desc; struct rt2560_tx_data *data; - struct rt2560_node *rn; struct ieee80211_frame *wh; + const struct ieee80211_txparam *tp; struct ieee80211_key *k; struct mbuf *mnew; bus_dma_segment_t segs[RT2560_MAX_SCATTER]; uint16_t dur; - uint32_t flags = 0; + uint32_t flags; int nsegs, rate, error; wh = mtod(m0, struct ieee80211_frame *); - if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) { - rate = ic->ic_fixed_rate; + tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; + if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { + rate = tp->mcastrate; + } else if (m0->m_flags & M_EAPOL) { + rate = tp->mgmtrate; + } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { + rate = tp->ucastrate; } else { - struct ieee80211_rateset *rs; - - rs = &ni->ni_rates; - rn = (struct rt2560_node *)ni; - ni->ni_txrate = ral_rssadapt_choose(&rn->rssadapt, rs, wh, - m0->m_pkthdr.len, NULL, 0); - rate = rs->rs_rates[ni->ni_txrate]; + (void) ieee80211_amrr_choose(ni, &RT2560_NODE(ni)->amrr); + rate = ni->ni_txrate; } - rate &= IEEE80211_RATE_VAL; if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - k = ieee80211_crypto_encap(ic, ni, m0); + k = ieee80211_crypto_encap(ni, m0); if (k == NULL) { m_freem(m0); return ENOBUFS; @@ -1859,66 +1824,22 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, wh = mtod(m0, struct ieee80211_frame *); } - /* - * IEEE Std 802.11-1999, pp 82: "A STA shall use an RTS/CTS exchange - * for directed frames only when the length of the MPDU is greater - * than the length threshold indicated by [...]" ic_rtsthreshold. - */ - if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && - m0->m_pkthdr.len > ic->ic_rtsthreshold) { - struct mbuf *m; - uint16_t dur; - int rtsrate, ackrate; - - rtsrate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2; - ackrate = rt2560_ack_rate(ic, rate); - - dur = rt2560_txtime(m0->m_pkthdr.len + 4, rate, ic->ic_flags) + - rt2560_txtime(RAL_CTS_SIZE, rtsrate, ic->ic_flags) + - rt2560_txtime(RAL_ACK_SIZE, ackrate, ic->ic_flags) + - 3 * RAL_SIFS; - - m = rt2560_get_rts(sc, wh, dur); - - desc = &sc->txq.desc[sc->txq.cur_encrypt]; - data = &sc->txq.data[sc->txq.cur_encrypt]; - - error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map, - m, segs, &nsegs, 0); - if (error != 0) { - device_printf(sc->sc_dev, - "could not map mbuf (error %d)\n", error); - m_freem(m); - m_freem(m0); - return error; + flags = 0; + if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { + int prot = IEEE80211_PROT_NONE; + if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) + prot = IEEE80211_PROT_RTSCTS; + else if ((ic->ic_flags & IEEE80211_F_USEPROT) && + ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) + prot = ic->ic_protmode; + if (prot != IEEE80211_PROT_NONE) { + error = rt2560_sendprot(sc, m0, ni, prot, rate); + if (error) { + m_freem(m0); + return error; + } + flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS; } - - /* avoid multiple free() of the same node for each fragment */ - ieee80211_ref_node(ni); - - data->m = m; - data->ni = ni; - - /* RTS frames are not taken into account for rssadapt */ - data->id.id_node = NULL; - - rt2560_setup_tx_desc(sc, desc, RT2560_TX_ACK | - RT2560_TX_MORE_FRAG, m->m_pkthdr.len, rtsrate, 1, - segs->ds_addr); - - bus_dmamap_sync(sc->txq.data_dmat, data->map, - BUS_DMASYNC_PREWRITE); - - sc->txq.queued++; - sc->txq.cur_encrypt = - (sc->txq.cur_encrypt + 1) % RT2560_TX_RING_COUNT; - - /* - * IEEE Std 802.11-1999: when an RTS/CTS exchange is used, the - * asynchronous data frame shall be transmitted after the CTS - * frame and a SIFS period. - */ - flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS; } data = &sc->txq.data[sc->txq.cur_encrypt]; @@ -1955,35 +1876,32 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, wh = mtod(m0, struct ieee80211_frame *); } - if (bpf_peers_present(sc->sc_drvbpf)) { + if (bpf_peers_present(ifp->if_bpf)) { struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap; tap->wt_flags = 0; tap->wt_rate = rate; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); tap->wt_antenna = sc->tx_ant; - bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0); + bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); } data->m = m0; data->ni = ni; /* remember link conditions for rate adaptation algorithm */ - if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { - data->id.id_len = m0->m_pkthdr.len; - data->id.id_rateidx = ni->ni_txrate; - data->id.id_node = ni; - data->id.id_rssi = ni->ni_rssi; + if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) { + data->rix = ni->ni_txrate; + /* XXX probably need last rssi value and not avg */ + data->rssi = ic->ic_node_getrssi(ni); } else - data->id.id_node = NULL; + data->rix = IEEE80211_FIXED_RATE_NONE; if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { flags |= RT2560_TX_ACK; - dur = rt2560_txtime(RAL_ACK_SIZE, rt2560_ack_rate(ic, rate), - ic->ic_flags) + RAL_SIFS; + dur = ieee80211_ack_duration(sc->sc_rates, + rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE); *(uint16_t *)wh->i_dur = htole16(dur); } @@ -1994,8 +1912,8 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map, BUS_DMASYNC_PREWRITE); - DPRINTFN(10, ("sending data frame len=%u idx=%u rate=%u\n", - m0->m_pkthdr.len, sc->txq.cur_encrypt, rate)); + DPRINTFN(sc, 10, "sending data frame len=%u idx=%u rate=%u\n", + m0->m_pkthdr.len, sc->txq.cur_encrypt, rate); /* kick encrypt */ sc->txq.queued++; @@ -2006,113 +1924,50 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, } static void -rt2560_start(struct ifnet *ifp) +rt2560_start_locked(struct ifnet *ifp) { struct rt2560_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - struct mbuf *m0; - struct ether_header *eh; + struct mbuf *m; struct ieee80211_node *ni; - RAL_LOCK(sc); - - /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - RAL_UNLOCK(sc); - return; - } + RAL_LOCK_ASSERT(sc); for (;;) { - IF_POLL(&ic->ic_mgtq, m0); - if (m0 != NULL) { - if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - sc->sc_flags |= RT2560_F_PRIO_OACTIVE; - break; - } - IF_DEQUEUE(&ic->ic_mgtq, m0); - - ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif; - m0->m_pkthdr.rcvif = NULL; - - if (bpf_peers_present(ic->ic_rawbpf)) - bpf_mtap(ic->ic_rawbpf, m0); - - if (rt2560_tx_mgt(sc, m0, ni) != 0) { - ieee80211_free_node(ni); - break; - } - } else { - if (ic->ic_state != IEEE80211_S_RUN) - break; - IFQ_DRV_DEQUEUE(&ifp->if_snd, m0); - if (m0 == NULL) - break; - if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) { - IFQ_DRV_PREPEND(&ifp->if_snd, m0); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - sc->sc_flags |= RT2560_F_DATA_OACTIVE; - break; - } - /* - * Cancel any background scan. - */ - if (ic->ic_flags & IEEE80211_F_SCAN) - ieee80211_cancel_scan(ic); - - if (m0->m_len < sizeof (struct ether_header) && - !(m0 = m_pullup(m0, sizeof (struct ether_header)))) - continue; - - eh = mtod(m0, struct ether_header *); - ni = ieee80211_find_txnode(ic, eh->ether_dhost); - if (ni == NULL) { - m_freem(m0); - continue; - } - if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) && - (m0->m_flags & M_PWR_SAV) == 0) { - /* - * Station in power save mode; pass the frame - * to the 802.11 layer and continue. We'll get - * the frame back when the time is right. - */ - ieee80211_pwrsave(ni, m0); - /* - * If we're in power save mode 'cuz of a bg - * scan cancel it so the traffic can flow. - * The packet we just queued will automatically - * get sent when we drop out of power save. - * XXX locking - */ - if (ic->ic_flags & IEEE80211_F_SCAN) - ieee80211_cancel_scan(ic); - ieee80211_free_node(ni); - continue; - } + IFQ_DRV_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) + break; + if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) { + IFQ_DRV_PREPEND(&ifp->if_snd, m); + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + sc->sc_flags |= RT2560_F_DATA_OACTIVE; + break; + } - BPF_MTAP(ifp, m0); + ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; + m = ieee80211_encap(ni, m); + if (m == NULL) { + ieee80211_free_node(ni); + ifp->if_oerrors++; + continue; + } - m0 = ieee80211_encap(ic, m0, ni); - if (m0 == NULL) { - ieee80211_free_node(ni); - continue; - } - - if (bpf_peers_present(ic->ic_rawbpf)) - bpf_mtap(ic->ic_rawbpf, m0); - - if (rt2560_tx_data(sc, m0, ni) != 0) { - ieee80211_free_node(ni); - ifp->if_oerrors++; - break; - } + if (rt2560_tx_data(sc, m, ni) != 0) { + ieee80211_free_node(ni); + ifp->if_oerrors++; + break; } sc->sc_tx_timer = 5; - ic->ic_lastdata = ticks; } +} +static void +rt2560_start(struct ifnet *ifp) +{ + struct rt2560_softc *sc = ifp->if_softc; + + RAL_LOCK(sc); + rt2560_start_locked(ifp); RAL_UNLOCK(sc); } @@ -2122,81 +1977,60 @@ rt2560_watchdog(void *arg) struct rt2560_softc *sc = arg; struct ifnet *ifp = sc->sc_ifp; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + RAL_LOCK_ASSERT(sc); + + KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running")); + + if (sc->sc_invalid) /* card ejected */ return; rt2560_encryption_intr(sc); rt2560_tx_intr(sc); - if (sc->sc_tx_timer > 0) { - if (--sc->sc_tx_timer == 0) { - device_printf(sc->sc_dev, "device timeout\n"); - rt2560_init(sc); - ifp->if_oerrors++; - /* watchdog timeout is set in rt2560_init() */ - return; - } + if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { + if_printf(ifp, "device timeout\n"); + rt2560_init_locked(sc); + ifp->if_oerrors++; + /* NB: callout is reset in rt2560_init() */ + return; } callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc); } -/* - * This function allows for fast channel switching in monitor mode (used by - * net-mgmt/kismet). In IBSS mode, we must explicitly reset the interface to - * generate a new beacon frame. - */ -static int -rt2560_reset(struct ifnet *ifp) -{ - struct rt2560_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - - if (ic->ic_opmode != IEEE80211_M_MONITOR) - return ENETRESET; - - rt2560_set_chan(sc, ic->ic_curchan); - - return 0; -} - static int rt2560_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct rt2560_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; - int error = 0; - - + struct ieee80211com *ic = ifp->if_l2com; + struct ifreq *ifr = (struct ifreq *) data; + int error = 0, startall = 0; + RAL_LOCK(sc); switch (cmd) { case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { - RAL_LOCK(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - rt2560_update_promisc(sc); - else - rt2560_init(sc); - RAL_UNLOCK(sc); + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { + rt2560_init_locked(sc); + startall = 1; + } else + rt2560_update_promisc(ifp); } else { if (ifp->if_drv_flags & IFF_DRV_RUNNING) - rt2560_stop(sc); + rt2560_stop_locked(sc); } - break; - + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); + break; default: - error = ieee80211_ioctl(ic, cmd, data); - } - - if (error == ENETRESET) { - if ((ifp->if_flags & IFF_UP) && - (ifp->if_drv_flags & IFF_DRV_RUNNING) && - (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)) - rt2560_init(sc); - error = 0; + error = ether_ioctl(ifp, cmd, data); + break; } + RAL_UNLOCK(sc); - + if (startall) + ieee80211_start_all(ic); return error; } @@ -2219,7 +2053,7 @@ rt2560_bbp_write(struct rt2560_softc *sc, uint8_t reg, uint8_t val) tmp = RT2560_BBP_WRITE | RT2560_BBP_BUSY | reg << 8 | val; RAL_WRITE(sc, RT2560_BBPCSR, tmp); - DPRINTFN(15, ("BBP R%u <- 0x%02x\n", reg, val)); + DPRINTFN(sc, 15, "BBP R%u <- 0x%02x\n", reg, val); } static uint8_t @@ -2275,19 +2109,21 @@ rt2560_rf_write(struct rt2560_softc *sc, uint8_t reg, uint32_t val) /* remember last written value in sc */ sc->rf_regs[reg] = val; - DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff)); + DPRINTFN(sc, 15, "RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff); } static void rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c) { - struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; uint8_t power, tmp; u_int i, chan; chan = ieee80211_chan2ieee(ic, c); - if (chan == 0 || chan == IEEE80211_CHAN_ANY) - return; + KASSERT(chan != 0 && chan != IEEE80211_CHAN_ANY, ("chan 0x%x", chan)); + + sc->sc_rates = ieee80211_get_ratetable(c); if (IEEE80211_IS_CHAN_2GHZ(c)) power = min(sc->txpow[chan - 1], 31); @@ -2297,7 +2133,7 @@ rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c) /* adjust txpower using ifconfig settings */ power -= (100 - ic->ic_txpowlimit) / 8; - DPRINTFN(2, ("setting channel to %u, txpower to %u\n", chan, power)); + DPRINTFN(sc, 2, "setting channel to %u, txpower to %u\n", chan, power); switch (sc->rf_rev) { case RT2560_RF_2522: @@ -2362,7 +2198,8 @@ rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c) printf("unknown ral rev=%d\n", sc->rf_rev); } - if (ic->ic_state != IEEE80211_S_SCAN) { + /* XXX */ + if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { /* set Japan filter bit for channel 14 */ tmp = rt2560_bbp_read(sc, 70); @@ -2385,6 +2222,11 @@ rt2560_set_channel(struct ieee80211com *ic) RAL_LOCK(sc); rt2560_set_chan(sc, ic->ic_curchan); + + sc->sc_txtap.wt_chan_freq = htole16(ic->ic_curchan->ic_freq); + sc->sc_txtap.wt_chan_flags = htole16(ic->ic_curchan->ic_flags); + sc->sc_rxtap.wr_chan_freq = htole16(ic->ic_curchan->ic_freq); + sc->sc_rxtap.wr_chan_flags = htole16(ic->ic_curchan->ic_flags); RAL_UNLOCK(sc); } @@ -2406,7 +2248,7 @@ rt2560_disable_rf_tune(struct rt2560_softc *sc) tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE; rt2560_rf_write(sc, RAL_RF3, tmp); - DPRINTFN(2, ("disabling RF autotune\n")); + DPRINTFN(sc, 2, "%s", "disabling RF autotune\n"); } #endif @@ -2417,20 +2259,22 @@ rt2560_disable_rf_tune(struct rt2560_softc *sc) static void rt2560_enable_tsf_sync(struct rt2560_softc *sc) { - struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint16_t logcwmin, preload; uint32_t tmp; /* first, disable TSF synchronization */ RAL_WRITE(sc, RT2560_CSR14, 0); - tmp = 16 * ic->ic_bss->ni_intval; + tmp = 16 * vap->iv_bss->ni_intval; RAL_WRITE(sc, RT2560_CSR12, tmp); RAL_WRITE(sc, RT2560_CSR13, 0); logcwmin = 5; - preload = (ic->ic_opmode == IEEE80211_M_STA) ? 384 : 1024; + preload = (vap->iv_opmode == IEEE80211_M_STA) ? 384 : 1024; tmp = logcwmin << 16 | preload; RAL_WRITE(sc, RT2560_BCNOCSR, tmp); @@ -2443,13 +2287,14 @@ rt2560_enable_tsf_sync(struct rt2560_softc *sc) RT2560_ENABLE_BEACON_GENERATOR; RAL_WRITE(sc, RT2560_CSR14, tmp); - DPRINTF(("enabling TSF synchronization\n")); + DPRINTF(sc, "%s", "enabling TSF synchronization\n"); } static void rt2560_update_plcp(struct rt2560_softc *sc) { - struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; /* no short preamble for 1Mbps */ RAL_WRITE(sc, RT2560_PLCP1MCSR, 0x00700400); @@ -2466,8 +2311,8 @@ rt2560_update_plcp(struct rt2560_softc *sc) RAL_WRITE(sc, RT2560_PLCP11MCSR, 0x000b840b); } - DPRINTF(("updating PLCP for %s preamble\n", - (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long")); + DPRINTF(sc, "updating PLCP for %s preamble\n", + (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long"); } /* @@ -2478,7 +2323,7 @@ static void rt2560_update_slot(struct ifnet *ifp) { struct rt2560_softc *sc = ifp->if_softc; - struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211com *ic = ifp->if_l2com; uint8_t slottime; uint16_t tx_sifs, tx_pifs, tx_difs, eifs; uint32_t tmp; @@ -2521,13 +2366,14 @@ rt2560_update_slot(struct ifnet *ifp) tmp = eifs << 16 | tx_difs; RAL_WRITE(sc, RT2560_CSR19, tmp); - DPRINTF(("setting slottime to %uus\n", slottime)); + DPRINTF(sc, "setting slottime to %uus\n", slottime); } static void rt2560_set_basicrates(struct rt2560_softc *sc) { - struct ieee80211com *ic = &sc->sc_ic; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; /* update basic rate set */ if (ic->ic_curmode == IEEE80211_MODE_11B) { @@ -2563,7 +2409,7 @@ rt2560_set_bssid(struct rt2560_softc *sc, const uint8_t *bssid) tmp = bssid[4] | bssid[5] << 8; RAL_WRITE(sc, RT2560_CSR6, tmp); - DPRINTF(("setting BSSID to %6D\n", bssid, ":")); + DPRINTF(sc, "setting BSSID to %6D\n", bssid, ":"); } static void @@ -2577,7 +2423,7 @@ rt2560_set_macaddr(struct rt2560_softc *sc, uint8_t *addr) tmp = addr[4] | addr[5] << 8; RAL_WRITE(sc, RT2560_CSR4, tmp); - DPRINTF(("setting MAC address to %6D\n", addr, ":")); + DPRINTF(sc, "setting MAC address to %6D\n", addr, ":"); } static void @@ -2597,9 +2443,9 @@ rt2560_get_macaddr(struct rt2560_softc *sc, uint8_t *addr) } static void -rt2560_update_promisc(struct rt2560_softc *sc) +rt2560_update_promisc(struct ifnet *ifp) { - struct ifnet *ifp = sc->sc_ic.ic_ifp; + struct rt2560_softc *sc = ifp->if_softc; uint32_t tmp; tmp = RAL_READ(sc, RT2560_RXCSR0); @@ -2610,8 +2456,8 @@ rt2560_update_promisc(struct rt2560_softc *sc) RAL_WRITE(sc, RT2560_RXCSR0, tmp); - DPRINTF(("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? - "entering" : "leaving")); + DPRINTF(sc, "%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? + "entering" : "leaving"); } static const char * @@ -2669,8 +2515,8 @@ rt2560_read_config(struct rt2560_softc *sc) sc->rssi_corr = RT2560_DEFAULT_RSSI_CORR; else sc->rssi_corr = val & 0xff; - DPRINTF(("rssi correction %d, calibrate 0x%02x\n", - sc->rssi_corr, val)); + DPRINTF(sc, "rssi correction %d, calibrate 0x%02x\n", + sc->rssi_corr, val); } @@ -2690,10 +2536,11 @@ rt2560_scan_end(struct ieee80211com *ic) { struct ifnet *ifp = ic->ic_ifp; struct rt2560_softc *sc = ifp->if_softc; + struct ieee80211vap *vap = ic->ic_scan->ss_vap; rt2560_enable_tsf_sync(sc); /* XXX keep local copy */ - rt2560_set_bssid(sc, ic->ic_bss->ni_bssid); + rt2560_set_bssid(sc, vap->iv_bss->ni_bssid); } static int @@ -2779,20 +2626,18 @@ rt2560_set_rxantenna(struct rt2560_softc *sc, int antenna) } static void -rt2560_init(void *priv) +rt2560_init_locked(struct rt2560_softc *sc) { #define N(a) (sizeof (a) / sizeof ((a)[0])) - struct rt2560_softc *sc = priv; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = ic->ic_ifp; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; uint32_t tmp; int i; + RAL_LOCK_ASSERT(sc); + rt2560_stop_locked(sc); - rt2560_stop(sc); - - RAL_LOCK(sc); /* setup tx rings */ tmp = RT2560_PRIO_RING_COUNT << 24 | RT2560_ATIM_RING_COUNT << 16 | @@ -2866,35 +2711,38 @@ rt2560_init(void *priv) ifp->if_drv_flags |= IFF_DRV_RUNNING; callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc); +#undef N +} - if (ic->ic_opmode != IEEE80211_M_MONITOR) { - if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) - ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - } else - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); +static void +rt2560_init(void *priv) +{ + struct rt2560_softc *sc = priv; + struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = ifp->if_l2com; + RAL_LOCK(sc); + rt2560_init_locked(sc); RAL_UNLOCK(sc); -#undef N + + ieee80211_start_all(ic); } -void -rt2560_stop(void *arg) +static void +rt2560_stop_locked(struct rt2560_softc *sc) { - struct rt2560_softc *sc = arg; - struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = ic->ic_ifp; + struct ifnet *ifp = sc->sc_ifp; volatile int *flags = &sc->sc_flags; - while (*flags & RT2560_F_INPUT_RUNNING) { - tsleep(sc, 0, "ralrunning", hz/10); - } + RAL_LOCK_ASSERT(sc); - RAL_LOCK(sc); + while (*flags & RT2560_F_INPUT_RUNNING) + msleep(sc, &sc->sc_mtx, 0, "ralrunning", hz/10); callout_stop(&sc->watchdog_ch); + sc->sc_tx_timer = 0; if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - ieee80211_new_state(ic, IEEE80211_S_INIT, -1); ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); /* abort Tx */ @@ -2917,9 +2765,16 @@ rt2560_stop(void *arg) rt2560_reset_tx_ring(sc, &sc->bcnq); rt2560_reset_rx_ring(sc, &sc->rxq); } - sc->sc_tx_timer = 0; sc->sc_flags &= ~(RT2560_F_PRIO_OACTIVE | RT2560_F_DATA_OACTIVE); +} +void +rt2560_stop(void *arg) +{ + struct rt2560_softc *sc = arg; + + RAL_LOCK(sc); + rt2560_stop_locked(sc); RAL_UNLOCK(sc); } @@ -2942,15 +2797,13 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, } if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) { ifp->if_drv_flags |= IFF_DRV_OACTIVE; + sc->sc_flags |= RT2560_F_PRIO_OACTIVE; RAL_UNLOCK(sc); m_freem(m); ieee80211_free_node(ni); return ENOBUFS; /* XXX */ } - if (bpf_peers_present(ic->ic_rawbpf)) - bpf_mtap(ic->ic_rawbpf, m); - ifp->if_opackets++; if (params == NULL) { |