Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ral/rt2860.c
Context not available. | |||||
static int rt2860_tx_raw(struct rt2860_softc *, struct mbuf *, | static int rt2860_tx_raw(struct rt2860_softc *, struct mbuf *, | ||||
struct ieee80211_node *, | struct ieee80211_node *, | ||||
const struct ieee80211_bpf_params *params); | const struct ieee80211_bpf_params *params); | ||||
static void rt2860_start(struct ifnet *); | static int rt2860_transmit(struct ieee80211com *, struct mbuf *); | ||||
static void rt2860_start_locked(struct ifnet *); | static void rt2860_start(struct rt2860_softc *); | ||||
static void rt2860_watchdog(void *); | static void rt2860_watchdog(void *); | ||||
static int rt2860_ioctl(struct ifnet *, u_long, caddr_t); | static void rt2860_parent(struct ieee80211com *); | ||||
static void rt2860_mcu_bbp_write(struct rt2860_softc *, uint8_t, uint8_t); | static void rt2860_mcu_bbp_write(struct rt2860_softc *, uint8_t, uint8_t); | ||||
static uint8_t rt2860_mcu_bbp_read(struct rt2860_softc *, uint8_t); | static uint8_t rt2860_mcu_bbp_read(struct rt2860_softc *, uint8_t); | ||||
static void rt2860_rf_write(struct rt2860_softc *, uint8_t, uint32_t); | static void rt2860_rf_write(struct rt2860_softc *, uint8_t, uint32_t); | ||||
Context not available. | |||||
static void rt2860_set_macaddr(struct rt2860_softc *, const uint8_t *); | static void rt2860_set_macaddr(struct rt2860_softc *, const uint8_t *); | ||||
static void rt2860_update_promisc(struct ieee80211com *); | static void rt2860_update_promisc(struct ieee80211com *); | ||||
static void rt2860_updateslot(struct ieee80211com *); | static void rt2860_updateslot(struct ieee80211com *); | ||||
static void rt2860_updateprot(struct ifnet *); | static void rt2860_updateprot(struct rt2860_softc *); | ||||
static int rt2860_updateedca(struct ieee80211com *); | static int rt2860_updateedca(struct ieee80211com *); | ||||
#ifdef HW_CRYPTO | #ifdef HW_CRYPTO | ||||
static int rt2860_set_key(struct ieee80211com *, struct ieee80211_node *, | static int rt2860_set_key(struct ieee80211com *, struct ieee80211_node *, | ||||
Context not available. | |||||
rt2860_attach(device_t dev, int id) | rt2860_attach(device_t dev, int id) | ||||
{ | { | ||||
struct rt2860_softc *sc = device_get_softc(dev); | struct rt2860_softc *sc = device_get_softc(dev); | ||||
struct ieee80211com *ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ifnet *ifp; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
int error, ntries, qid; | int error, ntries, qid; | ||||
uint8_t bands; | uint8_t bands; | ||||
uint8_t macaddr[IEEE80211_ADDR_LEN]; | |||||
sc->sc_dev = dev; | sc->sc_dev = dev; | ||||
sc->sc_debug = 0; | sc->sc_debug = 0; | ||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); | |||||
if (ifp == NULL) { | |||||
device_printf(sc->sc_dev, "can not if_alloc()\n"); | |||||
return ENOMEM; | |||||
} | |||||
ic = ifp->if_l2com; | |||||
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, | mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, | ||||
MTX_DEF | MTX_RECURSE); | MTX_DEF | MTX_RECURSE); | ||||
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0); | callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0); | ||||
mbufq_init(&sc->sc_snd, ifqmaxlen); | |||||
/* wait for NIC to initialize */ | /* wait for NIC to initialize */ | ||||
for (ntries = 0; ntries < 100; ntries++) { | for (ntries = 0; ntries < 100; ntries++) { | ||||
Context not available. | |||||
sc->sc_flags |= RT2860_ADVANCED_PS; | sc->sc_flags |= RT2860_ADVANCED_PS; | ||||
/* retrieve RF rev. no and various other things from EEPROM */ | /* retrieve RF rev. no and various other things from EEPROM */ | ||||
rt2860_read_eeprom(sc, macaddr); | rt2860_read_eeprom(sc, ic->ic_macaddr); | ||||
device_printf(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), " | device_printf(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), " | ||||
"RF %s (MIMO %dT%dR), address %6D\n", | "RF %s (MIMO %dT%dR), address %6D\n", | ||||
sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev), | sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev), | ||||
sc->ntxchains, sc->nrxchains, macaddr, ":"); | sc->ntxchains, sc->nrxchains, ic->ic_macaddr, ":"); | ||||
/* | /* | ||||
* Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings. | * Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings. | ||||
Context not available. | |||||
sc->mgtqid = (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) ? | sc->mgtqid = (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) ? | ||||
WME_AC_VO : 5; | WME_AC_VO : 5; | ||||
ifp->if_softc = sc; | |||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | |||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |||||
ifp->if_init = rt2860_init; | |||||
ifp->if_ioctl = rt2860_ioctl; | |||||
ifp->if_start = rt2860_start; | |||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); | |||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; | |||||
IFQ_SET_READY(&ifp->if_snd); | |||||
ic->ic_ifp = ifp; | |||||
ic->ic_softc = sc; | ic->ic_softc = sc; | ||||
ic->ic_name = device_get_nameunit(dev); | ic->ic_name = device_get_nameunit(dev); | ||||
ic->ic_opmode = IEEE80211_M_STA; | ic->ic_opmode = IEEE80211_M_STA; | ||||
Context not available. | |||||
setbit(&bands, IEEE80211_MODE_11A); | setbit(&bands, IEEE80211_MODE_11A); | ||||
ieee80211_init_channels(ic, NULL, &bands); | ieee80211_init_channels(ic, NULL, &bands); | ||||
ieee80211_ifattach(ic, macaddr); | ieee80211_ifattach(ic); | ||||
ic->ic_wme.wme_update = rt2860_updateedca; | ic->ic_wme.wme_update = rt2860_updateedca; | ||||
ic->ic_scan_start = rt2860_scan_start; | ic->ic_scan_start = rt2860_scan_start; | ||||
Context not available. | |||||
sc->sc_node_free = ic->ic_node_free; | sc->sc_node_free = ic->ic_node_free; | ||||
ic->ic_node_free = rt2860_node_free; | ic->ic_node_free = rt2860_node_free; | ||||
ic->ic_newassoc = rt2860_newassoc; | ic->ic_newassoc = rt2860_newassoc; | ||||
ic->ic_transmit = rt2860_transmit; | |||||
ic->ic_parent = rt2860_parent; | |||||
ic->ic_vap_create = rt2860_vap_create; | ic->ic_vap_create = rt2860_vap_create; | ||||
ic->ic_vap_delete = rt2860_vap_delete; | ic->ic_vap_delete = rt2860_vap_delete; | ||||
Context not available. | |||||
fail2: while (--qid >= 0) | fail2: while (--qid >= 0) | ||||
rt2860_free_tx_ring(sc, &sc->txq[qid]); | rt2860_free_tx_ring(sc, &sc->txq[qid]); | ||||
fail1: mtx_destroy(&sc->sc_mtx); | fail1: mtx_destroy(&sc->sc_mtx); | ||||
if_free(ifp); | |||||
return error; | return error; | ||||
} | } | ||||
Context not available. | |||||
rt2860_detach(void *xsc) | rt2860_detach(void *xsc) | ||||
{ | { | ||||
struct rt2860_softc *sc = xsc; | struct rt2860_softc *sc = xsc; | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
int qid; | int qid; | ||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
Context not available. | |||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
ieee80211_ifdetach(ic); | ieee80211_ifdetach(ic); | ||||
mbufq_drain(&sc->sc_snd); | |||||
for (qid = 0; qid < 6; qid++) | for (qid = 0; qid < 6; qid++) | ||||
rt2860_free_tx_ring(sc, &sc->txq[qid]); | rt2860_free_tx_ring(sc, &sc->txq[qid]); | ||||
rt2860_free_rx_ring(sc, &sc->rxq); | rt2860_free_rx_ring(sc, &sc->rxq); | ||||
rt2860_free_tx_pool(sc); | rt2860_free_tx_pool(sc); | ||||
if_free(ifp); | |||||
mtx_destroy(&sc->sc_mtx); | mtx_destroy(&sc->sc_mtx); | ||||
return 0; | return 0; | ||||
Context not available. | |||||
rt2860_resume(void *xsc) | rt2860_resume(void *xsc) | ||||
{ | { | ||||
struct rt2860_softc *sc = xsc; | struct rt2860_softc *sc = xsc; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
if (ifp->if_flags & IFF_UP) | if (sc->sc_ic.ic_nrunning > 0) | ||||
rt2860_init(sc); | rt2860_init(sc); | ||||
} | } | ||||
Context not available. | |||||
const uint8_t bssid[IEEE80211_ADDR_LEN], | const uint8_t bssid[IEEE80211_ADDR_LEN], | ||||
const uint8_t mac[IEEE80211_ADDR_LEN]) | const uint8_t mac[IEEE80211_ADDR_LEN]) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct rt2860_softc *sc = ic->ic_softc; | ||||
struct rt2860_vap *rvp; | struct rt2860_vap *rvp; | ||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
Context not available. | |||||
case IEEE80211_M_MBSS: | case IEEE80211_M_MBSS: | ||||
/* XXXRP: TBD */ | /* XXXRP: TBD */ | ||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) { | if (!TAILQ_EMPTY(&ic->ic_vaps)) { | ||||
if_printf(ifp, "only 1 vap supported\n"); | device_printf(sc->sc_dev, "only 1 vap supported\n"); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
if (opmode == IEEE80211_M_STA) | if (opmode == IEEE80211_M_STA) | ||||
Context not available. | |||||
case IEEE80211_M_WDS: | case IEEE80211_M_WDS: | ||||
if (TAILQ_EMPTY(&ic->ic_vaps) || | if (TAILQ_EMPTY(&ic->ic_vaps) || | ||||
ic->ic_opmode != IEEE80211_M_HOSTAP) { | ic->ic_opmode != IEEE80211_M_HOSTAP) { | ||||
if_printf(ifp, "wds only supported in ap mode\n"); | device_printf(sc->sc_dev, | ||||
"wds only supported in ap mode\n"); | |||||
return NULL; | return NULL; | ||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
flags &= ~IEEE80211_CLONE_BSSID; | flags &= ~IEEE80211_CLONE_BSSID; | ||||
break; | break; | ||||
default: | default: | ||||
if_printf(ifp, "unknown opmode %d\n", opmode); | device_printf(sc->sc_dev, "unknown opmode %d\n", opmode); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_NOWAIT | M_ZERO); | rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_WAITOK | M_ZERO); | ||||
if (rvp == NULL) | |||||
return NULL; | |||||
vap = &rvp->ral_vap; | vap = &rvp->ral_vap; | ||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); | ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); | ||||
/* override state transition machine */ | /* override state transition machine */ | ||||
rvp->ral_newstate = vap->iv_newstate; | rvp->ral_newstate = vap->iv_newstate; | ||||
Context not available. | |||||
ieee80211_ratectl_init(vap); | ieee80211_ratectl_init(vap); | ||||
/* complete setup */ | /* complete setup */ | ||||
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); | ieee80211_vap_attach(vap, ieee80211_media_change, | ||||
ieee80211_media_status, mac); | |||||
if (TAILQ_FIRST(&ic->ic_vaps) == vap) | if (TAILQ_FIRST(&ic->ic_vaps) == vap) | ||||
ic->ic_opmode = opmode; | ic->ic_opmode = opmode; | ||||
return vap; | return vap; | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_updatestats(struct rt2860_softc *sc) | rt2860_updatestats(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
/* | /* | ||||
* In IBSS or HostAP modes (when the hardware sends beacons), the | * In IBSS or HostAP modes (when the hardware sends beacons), the | ||||
Context not available. | |||||
rt2860_newassoc(struct ieee80211_node *ni, int isnew) | rt2860_newassoc(struct ieee80211_node *ni, int isnew) | ||||
{ | { | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct rt2860_softc *sc = ic->ic_ifp->if_softc; | struct rt2860_softc *sc = ic->ic_softc; | ||||
uint8_t wcid; | uint8_t wcid; | ||||
wcid = IEEE80211_AID(ni->ni_associd); | wcid = IEEE80211_AID(ni->ni_associd); | ||||
Context not available. | |||||
rt2860_node_free(struct ieee80211_node *ni) | rt2860_node_free(struct ieee80211_node *ni) | ||||
{ | { | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct rt2860_softc *sc = ic->ic_ifp->if_softc; | struct rt2860_softc *sc = ic->ic_softc; | ||||
uint8_t wcid; | uint8_t wcid; | ||||
if (ni->ni_associd != 0) { | if (ni->ni_associd != 0) { | ||||
Context not available. | |||||
{ | { | ||||
struct rt2860_vap *rvp = RT2860_VAP(vap); | struct rt2860_vap *rvp = RT2860_VAP(vap); | ||||
struct ieee80211com *ic = vap->iv_ic; | struct ieee80211com *ic = vap->iv_ic; | ||||
struct rt2860_softc *sc = ic->ic_ifp->if_softc; | struct rt2860_softc *sc = ic->ic_softc; | ||||
uint32_t tmp; | uint32_t tmp; | ||||
int error; | int error; | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_drain_stats_fifo(struct rt2860_softc *sc) | rt2860_drain_stats_fifo(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
uint32_t stat; | uint32_t stat; | ||||
int retrycnt; | int retrycnt; | ||||
Context not available. | |||||
} else { | } else { | ||||
ieee80211_ratectl_tx_complete(ni->ni_vap, ni, | ieee80211_ratectl_tx_complete(ni->ni_vap, ni, | ||||
IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); | IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | if_inc_counter(ni->ni_vap->iv_ifp, | ||||
IFCOUNTER_OERRORS, 1); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_tx_intr(struct rt2860_softc *sc, int qid) | rt2860_tx_intr(struct rt2860_softc *sc, int qid) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct rt2860_tx_ring *ring = &sc->txq[qid]; | struct rt2860_tx_ring *ring = &sc->txq[qid]; | ||||
uint32_t hw; | uint32_t hw; | ||||
Context not available. | |||||
ieee80211_process_callback(data->ni, data->m, | ieee80211_process_callback(data->ni, data->m, | ||||
0); | 0); | ||||
} | } | ||||
m_freem(data->m); | ieee80211_tx_complete(data->ni, data->m, 0); | ||||
ieee80211_free_node(data->ni); | data->ni = NULL; | ||||
data->m = NULL; | data->m = NULL; | ||||
data->ni = NULL; | |||||
SLIST_INSERT_HEAD(&sc->data_pool, data, next); | SLIST_INSERT_HEAD(&sc->data_pool, data, next); | ||||
ring->data[ring->next] = NULL; | ring->data[ring->next] = NULL; | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | |||||
} | } | ||||
ring->queued--; | ring->queued--; | ||||
ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT; | ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT; | ||||
Context not available. | |||||
sc->sc_tx_timer = 0; | sc->sc_tx_timer = 0; | ||||
if (ring->queued < RT2860_TX_RING_COUNT) | if (ring->queued < RT2860_TX_RING_COUNT) | ||||
sc->qfullmsk &= ~(1 << qid); | sc->qfullmsk &= ~(1 << qid); | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | rt2860_start(sc); | ||||
rt2860_start_locked(ifp); | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
rt2860_rx_intr(struct rt2860_softc *sc) | rt2860_rx_intr(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct rt2860_rx_radiotap_header *tap; | struct rt2860_rx_radiotap_header *tap; | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct mbuf *m, *m1; | struct mbuf *m, *m1; | ||||
Context not available. | |||||
if (__predict_false(rxd->flags & | if (__predict_false(rxd->flags & | ||||
htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { | htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto skip; | goto skip; | ||||
} | } | ||||
Context not available. | |||||
/* report MIC failures to net80211 for TKIP */ | /* report MIC failures to net80211 for TKIP */ | ||||
ic->ic_stats.is_rx_locmicfail++; | ic->ic_stats.is_rx_locmicfail++; | ||||
ieee80211_michael_mic_failure(ic, 0/* XXX */); | ieee80211_michael_mic_failure(ic, 0/* XXX */); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto skip; | goto skip; | ||||
} | } | ||||
#endif | #endif | ||||
Context not available. | |||||
m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); | m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); | ||||
if (__predict_false(m1 == NULL)) { | if (__predict_false(m1 == NULL)) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto skip; | goto skip; | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
/* physical address may have changed */ | /* physical address may have changed */ | ||||
rxd->sdp0 = htole32(physaddr); | rxd->sdp0 = htole32(physaddr); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto skip; | goto skip; | ||||
} | } | ||||
Context not available. | |||||
rxwi = mtod(m, struct rt2860_rxwi *); | rxwi = mtod(m, struct rt2860_rxwi *); | ||||
/* finalize mbuf */ | /* finalize mbuf */ | ||||
m->m_pkthdr.rcvif = ifp; | |||||
m->m_data = (caddr_t)(rxwi + 1); | m->m_data = (caddr_t)(rxwi + 1); | ||||
m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff; | m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff; | ||||
Context not available. | |||||
#endif | #endif | ||||
/* check if protection mode has changed */ | /* check if protection mode has changed */ | ||||
if ((sc->sc_ic_flags ^ ic->ic_flags) & IEEE80211_F_USEPROT) { | if ((sc->sc_ic_flags ^ ic->ic_flags) & IEEE80211_F_USEPROT) { | ||||
rt2860_updateprot(ic); | rt2860_updateprot(sc); | ||||
sc->sc_ic_flags = ic->ic_flags; | sc->sc_ic_flags = ic->ic_flags; | ||||
} | } | ||||
#endif | #endif | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_gp_intr(struct rt2860_softc *sc) | rt2860_gp_intr(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
DPRINTFN(2, ("GP timeout state=%d\n", vap->iv_state)); | DPRINTFN(2, ("GP timeout state=%d\n", vap->iv_state)); | ||||
Context not available. | |||||
static int | static int | ||||
rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct rt2860_tx_ring *ring; | struct rt2860_tx_ring *ring; | ||||
struct rt2860_tx_data *data; | struct rt2860_tx_data *data; | ||||
Context not available. | |||||
const struct ieee80211_bpf_params *params) | const struct ieee80211_bpf_params *params) | ||||
{ | { | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct ifnet *ifp = ic->ic_ifp; | struct rt2860_softc *sc = ic->ic_softc; | ||||
struct rt2860_softc *sc = ifp->if_softc; | |||||
int error; | int error; | ||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
/* prevent management frames from being sent if we're not ready */ | /* prevent management frames from being sent if we're not ready */ | ||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { | if (!(sc->sc_flags & RT2860_RUNNNING)) { | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
m_freem(m); | m_freem(m); | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
Context not available. | |||||
if (error != 0) { | if (error != 0) { | ||||
/* NB: m is reclaimed on tx failure */ | /* NB: m is reclaimed on tx failure */ | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
} | } | ||||
sc->sc_tx_timer = 5; | sc->sc_tx_timer = 5; | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
Context not available. | |||||
rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m, | rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m, | ||||
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) | struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct rt2860_tx_ring *ring; | struct rt2860_tx_ring *ring; | ||||
struct rt2860_tx_data *data; | struct rt2860_tx_data *data; | ||||
Context not available. | |||||
return 0; | return 0; | ||||
} | } | ||||
static void | static int | ||||
rt2860_start(struct ifnet *ifp) | rt2860_transmit(struct ieee80211com *ic, struct mbuf *m) | ||||
{ | { | ||||
struct rt2860_softc *sc = ifp->if_softc; | struct rt2860_softc *sc = ic->ic_softc; | ||||
int error; | |||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
rt2860_start_locked(ifp); | if ((sc->sc_flags & RT2860_RUNNNING) == 0) { | ||||
RAL_UNLOCK(sc); | |||||
return (ENXIO); | |||||
} | |||||
error = mbufq_enqueue(&sc->sc_snd, m); | |||||
if (error) { | |||||
RAL_UNLOCK(sc); | |||||
return (error); | |||||
} | |||||
rt2860_start(sc); | |||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
return (0); | |||||
} | } | ||||
static void | static void | ||||
rt2860_start_locked(struct ifnet *ifp) | rt2860_start(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct rt2860_softc *sc = ifp->if_softc; | |||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
RAL_LOCK_ASSERT(sc); | RAL_LOCK_ASSERT(sc); | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || | if ((sc->sc_flags & RT2860_RUNNNING) == 0) | ||||
(ifp->if_drv_flags & IFF_DRV_OACTIVE)) | |||||
return; | return; | ||||
for (;;) { | while (!SLIST_EMPTY(&sc->data_pool) && sc->qfullmsk == 0 && | ||||
if (SLIST_EMPTY(&sc->data_pool) || sc->qfullmsk != 0) { | (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { | ||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
break; | |||||
} | |||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m); | |||||
if (m == NULL) | |||||
break; | |||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; | ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; | ||||
if (rt2860_tx(sc, m, ni) != 0) { | if (rt2860_tx(sc, m, ni) != 0) { | ||||
if_inc_counter(ni->ni_vap->iv_ifp, | |||||
IFCOUNTER_OERRORS, 1); | |||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
continue; | continue; | ||||
} | } | ||||
sc->sc_tx_timer = 5; | sc->sc_tx_timer = 5; | ||||
Context not available. | |||||
rt2860_watchdog(void *arg) | rt2860_watchdog(void *arg) | ||||
{ | { | ||||
struct rt2860_softc *sc = arg; | struct rt2860_softc *sc = arg; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
RAL_LOCK_ASSERT(sc); | RAL_LOCK_ASSERT(sc); | ||||
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running")); | KASSERT(sc->sc_flags & RT2860_RUNNNING, ("not running")); | ||||
if (sc->sc_invalid) /* card ejected */ | if (sc->sc_invalid) /* card ejected */ | ||||
return; | return; | ||||
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { | if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { | ||||
if_printf(ifp, "device timeout\n"); | device_printf(sc->sc_dev, "device timeout\n"); | ||||
rt2860_stop_locked(sc); | rt2860_stop_locked(sc); | ||||
rt2860_init_locked(sc); | rt2860_init_locked(sc); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | counter_u64_add(sc->sc_ic.ic_oerrors, 1); | ||||
return; | return; | ||||
} | } | ||||
callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); | callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); | ||||
} | } | ||||
static int | static void | ||||
rt2860_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | rt2860_parent(struct ieee80211com *ic) | ||||
{ | { | ||||
struct rt2860_softc *sc = ifp->if_softc; | struct rt2860_softc *sc = ic->ic_softc; | ||||
struct ieee80211com *ic = ifp->if_l2com; | int startall = 0; | ||||
struct ifreq *ifr = (struct ifreq *)data; | |||||
int error = 0, startall = 0; | |||||
switch (cmd) { | RAL_LOCK(sc); | ||||
case SIOCSIFFLAGS: | if (ic->ic_nrunning> 0) { | ||||
RAL_LOCK(sc); | if (!(sc->sc_flags & RT2860_RUNNNING)) { | ||||
if (ifp->if_flags & IFF_UP) { | rt2860_init_locked(sc); | ||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { | startall = 1; | ||||
rt2860_init_locked(sc); | } else | ||||
startall = 1; | rt2860_update_promisc(ic); | ||||
} else | } else if (sc->sc_flags & RT2860_RUNNNING) | ||||
rt2860_update_promisc(ic); | rt2860_stop_locked(sc); | ||||
} else { | RAL_UNLOCK(sc); | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (startall) | ||||
rt2860_stop_locked(sc); | ieee80211_start_all(ic); | ||||
} | |||||
RAL_UNLOCK(sc); | |||||
if (startall) | |||||
ieee80211_start_all(ic); | |||||
break; | |||||
case SIOCGIFMEDIA: | |||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); | |||||
break; | |||||
case SIOCSIFADDR: | |||||
error = ether_ioctl(ifp, cmd, data); | |||||
break; | |||||
default: | |||||
error = EINVAL; | |||||
break; | |||||
} | |||||
return error; | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_set_txpreamble(struct rt2860_softc *sc) | rt2860_set_txpreamble(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
tmp = RAL_READ(sc, RT2860_AUTO_RSP_CFG); | tmp = RAL_READ(sc, RT2860_AUTO_RSP_CFG); | ||||
Context not available. | |||||
const struct ieee80211_rateset *rs) | const struct ieee80211_rateset *rs) | ||||
{ | { | ||||
#define RV(r) ((r) & IEEE80211_RATE_VAL) | #define RV(r) ((r) & IEEE80211_RATE_VAL) | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint32_t mask = 0; | uint32_t mask = 0; | ||||
uint8_t rate; | uint8_t rate; | ||||
int i; | int i; | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_scan_start(struct ieee80211com *ic) | rt2860_scan_start(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct rt2860_softc *sc = ic->ic_softc; | ||||
struct rt2860_softc *sc = ifp->if_softc; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); | tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_scan_end(struct ieee80211com *ic) | rt2860_scan_end(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct rt2860_softc *sc = ic->ic_softc; | ||||
struct rt2860_softc *sc = ifp->if_softc; | |||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
if (vap->iv_state == IEEE80211_S_RUN) { | if (vap->iv_state == IEEE80211_S_RUN) { | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_set_channel(struct ieee80211com *ic) | rt2860_set_channel(struct ieee80211com *ic) | ||||
{ | { | ||||
struct ifnet *ifp = ic->ic_ifp; | struct rt2860_softc *sc = ic->ic_softc; | ||||
struct rt2860_softc *sc = ifp->if_softc; | |||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
rt2860_switch_chan(sc, ic->ic_curchan); | rt2860_switch_chan(sc, ic->ic_curchan); | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
rt2860_updateprot(struct ifnet *ifp) | rt2860_updateprot(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct rt2860_softc *sc = ifp->if_softc; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; | tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; | ||||
Context not available. | |||||
tmp = RAL_READ(sc, RT2860_RX_FILTR_CFG); | tmp = RAL_READ(sc, RT2860_RX_FILTR_CFG); | ||||
tmp &= ~RT2860_DROP_NOT_MYBSS; | tmp &= ~RT2860_DROP_NOT_MYBSS; | ||||
if (!(ic->ic_ifp->if_flags & IFF_PROMISC)) | if (ic->ic_promisc == 0) | ||||
tmp |= RT2860_DROP_NOT_MYBSS; | tmp |= RT2860_DROP_NOT_MYBSS; | ||||
RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); | RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); | ||||
} | } | ||||
Context not available. | |||||
static int | static int | ||||
rt2860_updateedca(struct ieee80211com *ic) | rt2860_updateedca(struct ieee80211com *ic) | ||||
{ | { | ||||
struct rt2860_softc *sc = ic->ic_ifp->if_softc; | struct rt2860_softc *sc = ic->ic_softc; | ||||
const struct wmeParams *wmep; | const struct wmeParams *wmep; | ||||
int aci; | int aci; | ||||
Context not available. | |||||
static int8_t | static int8_t | ||||
rt2860_rssi2dbm(struct rt2860_softc *sc, uint8_t rssi, uint8_t rxchain) | rt2860_rssi2dbm(struct rt2860_softc *sc, uint8_t rssi, uint8_t rxchain) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211_channel *c = ic->ic_curchan; | struct ieee80211_channel *c = ic->ic_curchan; | ||||
int delta; | int delta; | ||||
Context not available. | |||||
static int | static int | ||||
rt2860_txrx_enable(struct rt2860_softc *sc) | rt2860_txrx_enable(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
int ntries; | int ntries; | ||||
Context not available. | |||||
rt2860_init(void *arg) | rt2860_init(void *arg) | ||||
{ | { | ||||
struct rt2860_softc *sc = arg; | struct rt2860_softc *sc = arg; | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
RAL_LOCK(sc); | RAL_LOCK(sc); | ||||
rt2860_init_locked(sc); | rt2860_init_locked(sc); | ||||
RAL_UNLOCK(sc); | RAL_UNLOCK(sc); | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (sc->sc_flags & RT2860_RUNNNING) | ||||
ieee80211_start_all(ic); | ieee80211_start_all(ic); | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_init_locked(struct rt2860_softc *sc) | rt2860_init_locked(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
uint32_t tmp; | uint32_t tmp; | ||||
uint8_t bbp1, bbp3; | uint8_t bbp1, bbp3; | ||||
int i, qid, ridx, ntries, error; | int i, qid, ridx, ntries, error; | ||||
Context not available. | |||||
return; | return; | ||||
} | } | ||||
rt2860_set_macaddr(sc, IF_LLADDR(ifp)); | rt2860_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); | ||||
/* init Tx power for all Tx rates (from EEPROM) */ | /* init Tx power for all Tx rates (from EEPROM) */ | ||||
for (ridx = 0; ridx < 5; ridx++) { | for (ridx = 0; ridx < 5; ridx++) { | ||||
Context not available. | |||||
RAL_WRITE(sc, RT2860_TX_RTS_CFG, tmp); | RAL_WRITE(sc, RT2860_TX_RTS_CFG, tmp); | ||||
/* setup initial protection mode */ | /* setup initial protection mode */ | ||||
rt2860_updateprot(ifp); | rt2860_updateprot(sc); | ||||
/* turn radio LED on */ | /* turn radio LED on */ | ||||
rt2860_set_leds(sc, RT2860_LED_RADIO); | rt2860_set_leds(sc, RT2860_LED_RADIO); | ||||
Context not available. | |||||
if (sc->sc_flags & RT2860_ADVANCED_PS) | if (sc->sc_flags & RT2860_ADVANCED_PS) | ||||
rt2860_mcu_cmd(sc, RT2860_MCU_CMD_PSLEVEL, sc->pslevel, 0); | rt2860_mcu_cmd(sc, RT2860_MCU_CMD_PSLEVEL, sc->pslevel, 0); | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | sc->sc_flags |= RT2860_RUNNNING; | ||||
ifp->if_drv_flags |= IFF_DRV_RUNNING; | |||||
callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); | callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_stop_locked(struct rt2860_softc *sc) | rt2860_stop_locked(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
uint32_t tmp; | uint32_t tmp; | ||||
int qid; | int qid; | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (sc->sc_flags & RT2860_RUNNNING) | ||||
rt2860_set_leds(sc, 0); /* turn all LEDs off */ | rt2860_set_leds(sc, 0); /* turn all LEDs off */ | ||||
callout_stop(&sc->watchdog_ch); | callout_stop(&sc->watchdog_ch); | ||||
sc->sc_tx_timer = 0; | sc->sc_tx_timer = 0; | ||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | sc->sc_flags &= ~RT2860_RUNNNING; | ||||
/* disable interrupts */ | /* disable interrupts */ | ||||
RAL_WRITE(sc, RT2860_INT_MASK, 0); | RAL_WRITE(sc, RT2860_INT_MASK, 0); | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c) | rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
u_int chan, group; | u_int chan, group; | ||||
chan = ieee80211_chan2ieee(ic, c); | chan = ieee80211_chan2ieee(ic, c); | ||||
Context not available. | |||||
static void | static void | ||||
rt2860_enable_tsf_sync(struct rt2860_softc *sc) | rt2860_enable_tsf_sync(struct rt2860_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); | ||||
uint32_t tmp; | uint32_t tmp; | ||||
Context not available. |