Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/bwi/if_bwi.c
Context not available. | |||||
const uint8_t [IEEE80211_ADDR_LEN], | const uint8_t [IEEE80211_ADDR_LEN], | ||||
const uint8_t [IEEE80211_ADDR_LEN]); | const uint8_t [IEEE80211_ADDR_LEN]); | ||||
static void bwi_vap_delete(struct ieee80211vap *); | static void bwi_vap_delete(struct ieee80211vap *); | ||||
static void bwi_init(void *); | static void bwi_init(struct bwi_softc *); | ||||
static int bwi_ioctl(struct ifnet *, u_long, caddr_t); | static void bwi_parent(struct ieee80211com *); | ||||
static void bwi_start(struct ifnet *); | static int bwi_transmit(struct ieee80211com *, struct mbuf *); | ||||
static void bwi_start_locked(struct ifnet *); | static void bwi_start_locked(struct bwi_softc *); | ||||
static int bwi_raw_xmit(struct ieee80211_node *, struct mbuf *, | static int bwi_raw_xmit(struct ieee80211_node *, struct mbuf *, | ||||
const struct ieee80211_bpf_params *); | const struct ieee80211_bpf_params *); | ||||
static void bwi_watchdog(void *); | static void bwi_watchdog(void *); | ||||
Context not available. | |||||
int | int | ||||
bwi_attach(struct bwi_softc *sc) | bwi_attach(struct bwi_softc *sc) | ||||
{ | { | ||||
struct ieee80211com *ic; | struct ieee80211com *ic = &sc->sc_ic; | ||||
device_t dev = sc->sc_dev; | device_t dev = sc->sc_dev; | ||||
struct ifnet *ifp; | |||||
struct bwi_mac *mac; | struct bwi_mac *mac; | ||||
struct bwi_phy *phy; | struct bwi_phy *phy; | ||||
int i, error; | int i, error; | ||||
uint8_t bands; | uint8_t bands; | ||||
uint8_t macaddr[IEEE80211_ADDR_LEN]; | |||||
BWI_LOCK_INIT(sc); | BWI_LOCK_INIT(sc); | ||||
Context not available. | |||||
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq", | taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq", | ||||
device_get_nameunit(dev)); | device_get_nameunit(dev)); | ||||
TASK_INIT(&sc->sc_restart_task, 0, bwi_restart, sc); | TASK_INIT(&sc->sc_restart_task, 0, bwi_restart, sc); | ||||
callout_init_mtx(&sc->sc_calib_ch, &sc->sc_mtx, 0); | callout_init_mtx(&sc->sc_calib_ch, &sc->sc_mtx, 0); | ||||
mbufq_init(&sc->sc_snd, ifqmaxlen); | |||||
/* | /* | ||||
* Initialize sysctl variables | * Initialize sysctl variables | ||||
Context not available. | |||||
if (error) | if (error) | ||||
goto fail; | goto fail; | ||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); | |||||
if (ifp == NULL) { | |||||
device_printf(dev, "can not if_alloc()\n"); | |||||
error = ENOSPC; | |||||
goto fail; | |||||
} | |||||
ic = ifp->if_l2com; | |||||
/* set these up early for if_printf use */ | |||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev)); | |||||
ifp->if_softc = sc; | |||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |||||
ifp->if_init = bwi_init; | |||||
ifp->if_ioctl = bwi_ioctl; | |||||
ifp->if_start = bwi_start; | |||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); | |||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; | |||||
IFQ_SET_READY(&ifp->if_snd); | |||||
callout_init_mtx(&sc->sc_watchdog_timer, &sc->sc_mtx, 0); | callout_init_mtx(&sc->sc_watchdog_timer, &sc->sc_mtx, 0); | ||||
/* | /* | ||||
Context not available. | |||||
setbit(&bands, IEEE80211_MODE_11G); | setbit(&bands, IEEE80211_MODE_11G); | ||||
} | } | ||||
bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, macaddr); | bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_macaddr); | ||||
if (IEEE80211_IS_MULTICAST(macaddr)) { | if (IEEE80211_IS_MULTICAST(ic->ic_macaddr)) { | ||||
bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, macaddr); | bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_macaddr); | ||||
if (IEEE80211_IS_MULTICAST(macaddr)) { | if (IEEE80211_IS_MULTICAST(ic->ic_macaddr)) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"invalid MAC address: %6D\n", | "invalid MAC address: %6D\n", | ||||
macaddr, ":"); | ic->ic_macaddr, ":"); | ||||
} | } | ||||
} | } | ||||
} else if (phy->phy_mode == IEEE80211_MODE_11A) { | } else if (phy->phy_mode == IEEE80211_MODE_11A) { | ||||
Context not available. | |||||
/* XXX use locale */ | /* XXX use locale */ | ||||
ieee80211_init_channels(ic, NULL, &bands); | ieee80211_init_channels(ic, NULL, &bands); | ||||
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_caps = IEEE80211_C_STA | | ic->ic_caps = IEEE80211_C_STA | | ||||
Context not available. | |||||
IEEE80211_C_BGSCAN | | IEEE80211_C_BGSCAN | | ||||
IEEE80211_C_MONITOR; | IEEE80211_C_MONITOR; | ||||
ic->ic_opmode = IEEE80211_M_STA; | ic->ic_opmode = IEEE80211_M_STA; | ||||
ieee80211_ifattach(ic, macaddr); | ieee80211_ifattach(ic); | ||||
ic->ic_headroom = sizeof(struct bwi_txbuf_hdr); | ic->ic_headroom = sizeof(struct bwi_txbuf_hdr); | ||||
Context not available. | |||||
ic->ic_scan_start = bwi_scan_start; | ic->ic_scan_start = bwi_scan_start; | ||||
ic->ic_scan_end = bwi_scan_end; | ic->ic_scan_end = bwi_scan_end; | ||||
ic->ic_set_channel = bwi_set_channel; | ic->ic_set_channel = bwi_set_channel; | ||||
ic->ic_transmit = bwi_transmit; | |||||
ic->ic_parent = bwi_parent; | |||||
sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); | sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan); | ||||
Context not available. | |||||
int | int | ||||
bwi_detach(struct bwi_softc *sc) | bwi_detach(struct bwi_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
int i; | int i; | ||||
bwi_stop(sc, 1); | bwi_stop(sc, 1); | ||||
Context not available. | |||||
for (i = 0; i < sc->sc_nmac; ++i) | for (i = 0; i < sc->sc_nmac; ++i) | ||||
bwi_mac_detach(&sc->sc_mac[i]); | bwi_mac_detach(&sc->sc_mac[i]); | ||||
bwi_dma_free(sc); | bwi_dma_free(sc); | ||||
if_free(ifp); | |||||
taskqueue_free(sc->sc_tq); | taskqueue_free(sc->sc_tq); | ||||
mbufq_drain(&sc->sc_snd); | |||||
BWI_LOCK_DESTROY(sc); | BWI_LOCK_DESTROY(sc); | ||||
Context not available. | |||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ | if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ | ||||
return NULL; | return NULL; | ||||
bvp = (struct bwi_vap *) malloc(sizeof(struct bwi_vap), | bvp = malloc(sizeof(struct bwi_vap), M_80211_VAP, M_WAITOK | M_ZERO); | ||||
M_80211_VAP, M_WAITOK | M_ZERO); | |||||
if (bvp == NULL) | |||||
return NULL; | |||||
vap = &bvp->bv_vap; | vap = &bvp->bv_vap; | ||||
/* enable s/w bmiss handling for sta mode */ | /* enable s/w bmiss handling for sta mode */ | ||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, | ieee80211_vap_setup(ic, vap, name, unit, opmode, | ||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac); | flags | IEEE80211_CLONE_NOBEACONS, bssid); | ||||
/* override default methods */ | /* override default methods */ | ||||
bvp->bv_newstate = vap->iv_newstate; | bvp->bv_newstate = vap->iv_newstate; | ||||
Context not available. | |||||
ieee80211_ratectl_init(vap); | ieee80211_ratectl_init(vap); | ||||
/* complete setup */ | /* complete setup */ | ||||
ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status); | ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status, | ||||
mac); | |||||
ic->ic_opmode = opmode; | ic->ic_opmode = opmode; | ||||
return vap; | return vap; | ||||
} | } | ||||
Context not available. | |||||
void | void | ||||
bwi_resume(struct bwi_softc *sc) | bwi_resume(struct bwi_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
if (ifp->if_flags & IFF_UP) | if (sc->sc_ic.ic_nrunning > 0) | ||||
bwi_init(sc); | bwi_init(sc); | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
static void | static void | ||||
bwi_init(void *xsc) | bwi_init(struct bwi_softc *sc) | ||||
{ | { | ||||
struct bwi_softc *sc = xsc; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
BWI_LOCK(sc); | BWI_LOCK(sc); | ||||
bwi_init_statechg(sc, 1); | bwi_init_statechg(sc, 1); | ||||
BWI_UNLOCK(sc); | BWI_UNLOCK(sc); | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | if (sc->sc_flags & BWI_F_RUNNING) | ||||
ieee80211_start_all(ic); /* start all vap's */ | ieee80211_start_all(ic); /* start all vap's */ | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
bwi_init_statechg(struct bwi_softc *sc, int statechg) | bwi_init_statechg(struct bwi_softc *sc, int statechg) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct bwi_mac *mac; | struct bwi_mac *mac; | ||||
int error; | int error; | ||||
BWI_ASSERT_LOCKED(sc); | |||||
bwi_stop_locked(sc, statechg); | bwi_stop_locked(sc, statechg); | ||||
bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST); | bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST); | ||||
Context not available. | |||||
mac = &sc->sc_mac[0]; | mac = &sc->sc_mac[0]; | ||||
error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL); | error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL); | ||||
if (error) { | if (error) { | ||||
if_printf(ifp, "%s: error %d on regwin switch\n", | device_printf(sc->sc_dev, "%s: error %d on regwin switch\n", | ||||
__func__, error); | __func__, error); | ||||
goto bad; | goto bad; | ||||
} | } | ||||
error = bwi_mac_init(mac); | error = bwi_mac_init(mac); | ||||
if (error) { | if (error) { | ||||
if_printf(ifp, "%s: error %d on MAC init\n", __func__, error); | device_printf(sc->sc_dev, "%s: error %d on MAC init\n", | ||||
__func__, error); | |||||
goto bad; | goto bad; | ||||
} | } | ||||
Context not available. | |||||
bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN); | bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN); | ||||
bwi_set_bssid(sc, bwi_zero_addr); /* Clear BSSID */ | bwi_set_bssid(sc, bwi_zero_addr); /* Clear BSSID */ | ||||
bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, IF_LLADDR(ifp)); | bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, sc->sc_ic.ic_macaddr); | ||||
bwi_mac_reset_hwkeys(mac); | bwi_mac_reset_hwkeys(mac); | ||||
Context not available. | |||||
CSR_READ_4(sc, BWI_TXSTATUS1); | CSR_READ_4(sc, BWI_TXSTATUS1); | ||||
} | } | ||||
if (i == NRETRY) | if (i == NRETRY) | ||||
if_printf(ifp, "%s: can't drain TX status\n", __func__); | device_printf(sc->sc_dev, | ||||
"%s: can't drain TX status\n", __func__); | |||||
#undef NRETRY | #undef NRETRY | ||||
} | } | ||||
Context not available. | |||||
/* Start MAC */ | /* Start MAC */ | ||||
error = bwi_mac_start(mac); | error = bwi_mac_start(mac); | ||||
if (error) { | if (error) { | ||||
if_printf(ifp, "%s: error %d starting MAC\n", __func__, error); | device_printf(sc->sc_dev, "%s: error %d starting MAC\n", | ||||
__func__, error); | |||||
goto bad; | goto bad; | ||||
} | } | ||||
/* Clear stop flag before enabling interrupt */ | /* Clear stop flag before enabling interrupt */ | ||||
sc->sc_flags &= ~BWI_F_STOP; | sc->sc_flags &= ~BWI_F_STOP; | ||||
sc->sc_flags |= BWI_F_RUNNING; | |||||
ifp->if_drv_flags |= IFF_DRV_RUNNING; | |||||
callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc); | callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc); | ||||
/* Enable intrs */ | /* Enable intrs */ | ||||
Context not available. | |||||
bwi_stop_locked(sc, 1); | bwi_stop_locked(sc, 1); | ||||
} | } | ||||
static int | static void | ||||
bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) | bwi_parent(struct ieee80211com *ic) | ||||
{ | { | ||||
#define IS_RUNNING(ifp) \ | struct bwi_softc *sc = ic->ic_softc; | ||||
((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) | int startall = 0; | ||||
struct bwi_softc *sc = ifp->if_softc; | |||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct ifreq *ifr = (struct ifreq *) data; | |||||
int error = 0, startall = 0; | |||||
switch (cmd) { | BWI_LOCK(sc); | ||||
case SIOCSIFFLAGS: | if (ic->ic_nrunning > 0) { | ||||
BWI_LOCK(sc); | struct bwi_mac *mac; | ||||
if (IS_RUNNING(ifp)) { | int promisc = -1; | ||||
struct bwi_mac *mac; | |||||
int promisc = -1; | |||||
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, | ||||
("current regwin type %d", | ("current regwin type %d", | ||||
sc->sc_cur_regwin->rw_type)); | sc->sc_cur_regwin->rw_type)); | ||||
mac = (struct bwi_mac *)sc->sc_cur_regwin; | mac = (struct bwi_mac *)sc->sc_cur_regwin; | ||||
if ((ifp->if_flags & IFF_PROMISC) && | if (ic->ic_promisc > 0 && (sc->sc_flags & BWI_F_PROMISC) == 0) { | ||||
(sc->sc_flags & BWI_F_PROMISC) == 0) { | promisc = 1; | ||||
promisc = 1; | sc->sc_flags |= BWI_F_PROMISC; | ||||
sc->sc_flags |= BWI_F_PROMISC; | } else if (ic->ic_promisc == 0 && | ||||
} else if ((ifp->if_flags & IFF_PROMISC) == 0 && | (sc->sc_flags & BWI_F_PROMISC) != 0) { | ||||
(sc->sc_flags & BWI_F_PROMISC)) { | promisc = 0; | ||||
promisc = 0; | sc->sc_flags &= ~BWI_F_PROMISC; | ||||
sc->sc_flags &= ~BWI_F_PROMISC; | |||||
} | |||||
if (promisc >= 0) | |||||
bwi_mac_set_promisc(mac, promisc); | |||||
} | } | ||||
if (ifp->if_flags & IFF_UP) { | if (promisc >= 0) | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { | bwi_mac_set_promisc(mac, promisc); | ||||
bwi_init_statechg(sc, 1); | } | ||||
startall = 1; | if (ic->ic_nrunning > 0) { | ||||
} | if ((sc->sc_flags & BWI_F_RUNNING) == 0) { | ||||
} else { | bwi_init_statechg(sc, 1); | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) | startall = 1; | ||||
bwi_stop_locked(sc, 1); | |||||
} | } | ||||
BWI_UNLOCK(sc); | } else if (sc->sc_flags & BWI_F_RUNNING) | ||||
if (startall) | bwi_stop_locked(sc, 1); | ||||
ieee80211_start_all(ic); | BWI_UNLOCK(sc); | ||||
break; | if (startall) | ||||
case SIOCGIFMEDIA: | ieee80211_start_all(ic); | ||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); | |||||
break; | |||||
case SIOCGIFADDR: | |||||
error = ether_ioctl(ifp, cmd, data); | |||||
break; | |||||
default: | |||||
error = EINVAL; | |||||
break; | |||||
} | |||||
return error; | |||||
#undef IS_RUNNING | |||||
} | } | ||||
static void | static int | ||||
bwi_start(struct ifnet *ifp) | bwi_transmit(struct ieee80211com *ic, struct mbuf *m) | ||||
{ | { | ||||
struct bwi_softc *sc = ifp->if_softc; | struct bwi_softc *sc = ic->ic_softc; | ||||
int error; | |||||
BWI_LOCK(sc); | BWI_LOCK(sc); | ||||
bwi_start_locked(ifp); | if ((sc->sc_flags & BWI_F_RUNNING) == 0) { | ||||
BWI_UNLOCK(sc); | |||||
return (ENXIO); | |||||
} | |||||
error = mbufq_enqueue(&sc->sc_snd, m); | |||||
if (error) { | |||||
BWI_UNLOCK(sc); | |||||
return (error); | |||||
} | |||||
bwi_start_locked(sc); | |||||
BWI_UNLOCK(sc); | BWI_UNLOCK(sc); | ||||
return (0); | |||||
} | } | ||||
static void | static void | ||||
bwi_start_locked(struct ifnet *ifp) | bwi_start_locked(struct bwi_softc *sc) | ||||
{ | { | ||||
struct bwi_softc *sc = ifp->if_softc; | |||||
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; | ||||
struct ieee80211_frame *wh; | struct ieee80211_frame *wh; | ||||
struct ieee80211_node *ni; | struct ieee80211_node *ni; | ||||
struct ieee80211_key *k; | |||||
struct mbuf *m; | struct mbuf *m; | ||||
int trans, idx; | int trans, idx; | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | BWI_ASSERT_LOCKED(sc); | ||||
return; | |||||
trans = 0; | trans = 0; | ||||
idx = tbd->tbd_idx; | idx = tbd->tbd_idx; | ||||
while (tbd->tbd_buf[idx].tb_mbuf == NULL) { | while (tbd->tbd_buf[idx].tb_mbuf == NULL && | ||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m); /* XXX: LOCK */ | tbd->tbd_used + BWI_TX_NSPRDESC < BWI_TX_NDESC && | ||||
if (m == NULL) | (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { | ||||
break; | |||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; | ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; | ||||
wh = mtod(m, struct ieee80211_frame *); | wh = mtod(m, struct ieee80211_frame *); | ||||
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 && | ||||
k = ieee80211_crypto_encap(ni, m); | ieee80211_crypto_encap(ni, m) == NULL) { | ||||
if (k == NULL) { | if_inc_counter(ni->ni_vap->iv_ifp, | ||||
ieee80211_free_node(ni); | IFCOUNTER_OERRORS, 1); | ||||
m_freem(m); | ieee80211_free_node(ni); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | m_freem(m); | ||||
continue; | continue; | ||||
} | |||||
} | } | ||||
wh = NULL; /* Catch any invalid use */ | |||||
if (bwi_encap(sc, idx, m, ni) != 0) { | if (bwi_encap(sc, idx, m, ni) != 0) { | ||||
/* 'm' is freed in bwi_encap() if we reach here */ | /* 'm' is freed in bwi_encap() if we reach here */ | ||||
if (ni != NULL) | if (ni != NULL) { | ||||
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); | } else | ||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1); | |||||
continue; | continue; | ||||
} | } | ||||
trans = 1; | trans = 1; | ||||
tbd->tbd_used++; | tbd->tbd_used++; | ||||
idx = (idx + 1) % BWI_TX_NDESC; | idx = (idx + 1) % BWI_TX_NDESC; | ||||
} | |||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | |||||
if (tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) { | |||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
break; | |||||
} | |||||
} | |||||
tbd->tbd_idx = idx; | tbd->tbd_idx = idx; | ||||
if (trans) | if (trans) | ||||
sc->sc_tx_timer = 5; | sc->sc_tx_timer = 5; | ||||
} | } | ||||
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 bwi_softc *sc = ic->ic_softc; | ||||
struct bwi_softc *sc = ifp->if_softc; | |||||
/* XXX wme? */ | /* XXX wme? */ | ||||
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; | ||||
int idx, error; | int idx, error; | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { | if ((sc->sc_flags & BWI_F_RUNNING) == 0) { | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
m_freem(m); | m_freem(m); | ||||
return ENETDOWN; | return ENETDOWN; | ||||
Context not available. | |||||
error = bwi_encap_raw(sc, idx, m, ni, params); | error = bwi_encap_raw(sc, idx, m, ni, params); | ||||
} | } | ||||
if (error == 0) { | if (error == 0) { | ||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); | tbd->tbd_used++; | ||||
if (++tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) | |||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE; | |||||
tbd->tbd_idx = (idx + 1) % BWI_TX_NDESC; | tbd->tbd_idx = (idx + 1) % BWI_TX_NDESC; | ||||
sc->sc_tx_timer = 5; | sc->sc_tx_timer = 5; | ||||
} else { | } else | ||||
/* NB: m is reclaimed on encap failure */ | /* NB: m is reclaimed on encap failure */ | ||||
ieee80211_free_node(ni); | ieee80211_free_node(ni); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | |||||
} | |||||
BWI_UNLOCK(sc); | BWI_UNLOCK(sc); | ||||
return error; | return error; | ||||
} | } | ||||
Context not available. | |||||
bwi_watchdog(void *arg) | bwi_watchdog(void *arg) | ||||
{ | { | ||||
struct bwi_softc *sc; | struct bwi_softc *sc; | ||||
struct ifnet *ifp; | |||||
sc = arg; | sc = arg; | ||||
ifp = sc->sc_ifp; | |||||
BWI_ASSERT_LOCKED(sc); | BWI_ASSERT_LOCKED(sc); | ||||
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, "watchdog timeout\n"); | device_printf(sc->sc_dev, "watchdog timeout\n"); | ||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); | counter_u64_add(sc->sc_ic.ic_oerrors, 1); | ||||
taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task); | taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task); | ||||
} | } | ||||
callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc); | callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc); | ||||
Context not available. | |||||
static void | static void | ||||
bwi_stop_locked(struct bwi_softc *sc, int statechg) | bwi_stop_locked(struct bwi_softc *sc, int statechg) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct bwi_mac *mac; | struct bwi_mac *mac; | ||||
int i, error, pwr_off = 0; | int i, error, pwr_off = 0; | ||||
Context not available. | |||||
sc->sc_led_blinking = 0; | sc->sc_led_blinking = 0; | ||||
sc->sc_flags |= BWI_F_STOP; | sc->sc_flags |= BWI_F_STOP; | ||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) { | if (sc->sc_flags & BWI_F_RUNNING) { | ||||
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, | ||||
("current regwin type %d", sc->sc_cur_regwin->rw_type)); | ("current regwin type %d", sc->sc_cur_regwin->rw_type)); | ||||
mac = (struct bwi_mac *)sc->sc_cur_regwin; | mac = (struct bwi_mac *)sc->sc_cur_regwin; | ||||
Context not available. | |||||
sc->sc_tx_timer = 0; | sc->sc_tx_timer = 0; | ||||
callout_stop(&sc->sc_watchdog_timer); | callout_stop(&sc->sc_watchdog_timer); | ||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); | sc->sc_flags &= ~BWI_F_RUNNING; | ||||
} | } | ||||
void | void | ||||
Context not available. | |||||
bwi_intr(void *xsc) | bwi_intr(void *xsc) | ||||
{ | { | ||||
struct bwi_softc *sc = xsc; | struct bwi_softc *sc = xsc; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct bwi_mac *mac; | struct bwi_mac *mac; | ||||
uint32_t intr_status; | uint32_t intr_status; | ||||
uint32_t txrx_intr_status[BWI_TXRX_NRING]; | uint32_t txrx_intr_status[BWI_TXRX_NRING]; | ||||
Context not available. | |||||
BWI_LOCK(sc); | BWI_LOCK(sc); | ||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || | if ((sc->sc_flags & BWI_F_RUNNING) == 0 || | ||||
(sc->sc_flags & BWI_F_STOP)) { | (sc->sc_flags & BWI_F_STOP)) { | ||||
BWI_UNLOCK(sc); | BWI_UNLOCK(sc); | ||||
return; | return; | ||||
Context not available. | |||||
i, txrx_intr_status[i]); | i, txrx_intr_status[i]); | ||||
if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) { | if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) { | ||||
if_printf(ifp, | device_printf(sc->sc_dev, | ||||
"%s: intr fatal TX/RX (%d) error 0x%08x\n", | "%s: intr fatal TX/RX (%d) error 0x%08x\n", | ||||
__func__, i, txrx_intr_status[i]); | __func__, i, txrx_intr_status[i]); | ||||
txrx_error = 1; | txrx_error = 1; | ||||
Context not available. | |||||
*/ | */ | ||||
if (intr_status & BWI_INTR_PHY_TXERR) { | if (intr_status & BWI_INTR_PHY_TXERR) { | ||||
if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) { | if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) { | ||||
if_printf(ifp, "%s: intr PHY TX error\n", __func__); | device_printf(sc->sc_dev, "%s: intr PHY TX error\n", | ||||
__func__); | |||||
taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task); | taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task); | ||||
BWI_UNLOCK(sc); | BWI_UNLOCK(sc); | ||||
return; | return; | ||||
Context not available. | |||||
bwi_mac_config_ps(mac); | bwi_mac_config_ps(mac); | ||||
if (intr_status & BWI_INTR_EO_ATIM) | if (intr_status & BWI_INTR_EO_ATIM) | ||||
if_printf(ifp, "EO_ATIM\n"); | device_printf(sc->sc_dev, "EO_ATIM\n"); | ||||
if (intr_status & BWI_INTR_PMQ) { | if (intr_status & BWI_INTR_PMQ) { | ||||
for (;;) { | for (;;) { | ||||
Context not available. | |||||
} | } | ||||
if (intr_status & BWI_INTR_NOISE) | if (intr_status & BWI_INTR_NOISE) | ||||
if_printf(ifp, "intr noise\n"); | device_printf(sc->sc_dev, "intr noise\n"); | ||||
if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) { | if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) { | ||||
rx_data = sc->sc_rxeof(sc); | rx_data = sc->sc_rxeof(sc); | ||||
Context not available. | |||||
static void | static void | ||||
bwi_scan_start(struct ieee80211com *ic) | bwi_scan_start(struct ieee80211com *ic) | ||||
{ | { | ||||
struct bwi_softc *sc = ic->ic_ifp->if_softc; | struct bwi_softc *sc = ic->ic_softc; | ||||
BWI_LOCK(sc); | BWI_LOCK(sc); | ||||
/* Enable MAC beacon promiscuity */ | /* Enable MAC beacon promiscuity */ | ||||
Context not available. | |||||
static void | static void | ||||
bwi_set_channel(struct ieee80211com *ic) | bwi_set_channel(struct ieee80211com *ic) | ||||
{ | { | ||||
struct bwi_softc *sc = ic->ic_ifp->if_softc; | struct bwi_softc *sc = ic->ic_softc; | ||||
struct ieee80211_channel *c = ic->ic_curchan; | struct ieee80211_channel *c = ic->ic_curchan; | ||||
struct bwi_mac *mac; | struct bwi_mac *mac; | ||||
Context not available. | |||||
static void | static void | ||||
bwi_scan_end(struct ieee80211com *ic) | bwi_scan_end(struct ieee80211com *ic) | ||||
{ | { | ||||
struct bwi_softc *sc = ic->ic_ifp->if_softc; | struct bwi_softc *sc = ic->ic_softc; | ||||
BWI_LOCK(sc); | BWI_LOCK(sc); | ||||
CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN); | CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN); | ||||
Context not available. | |||||
{ | { | ||||
struct bwi_vap *bvp = BWI_VAP(vap); | struct bwi_vap *bvp = BWI_VAP(vap); | ||||
struct ieee80211com *ic= vap->iv_ic; | struct ieee80211com *ic= vap->iv_ic; | ||||
struct ifnet *ifp = ic->ic_ifp; | struct bwi_softc *sc = ic->ic_softc; | ||||
enum ieee80211_state ostate = vap->iv_state; | enum ieee80211_state ostate = vap->iv_state; | ||||
struct bwi_softc *sc = ifp->if_softc; | |||||
struct bwi_mac *mac; | struct bwi_mac *mac; | ||||
int error; | int error; | ||||
Context not available. | |||||
{ | { | ||||
struct bwi_ring_data *rd = &sc->sc_rx_rdata; | struct bwi_ring_data *rd = &sc->sc_rx_rdata; | ||||
struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
int idx, rx_data = 0; | int idx, rx_data = 0; | ||||
idx = rbd->rbd_idx; | idx = rbd->rbd_idx; | ||||
Context not available. | |||||
BUS_DMASYNC_POSTREAD); | BUS_DMASYNC_POSTREAD); | ||||
if (bwi_newbuf(sc, idx, 0)) { | if (bwi_newbuf(sc, idx, 0)) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | counter_u64_add(ic->ic_ierrors, 1); | ||||
goto next; | goto next; | ||||
} | } | ||||
Context not available. | |||||
buflen = le16toh(hdr->rxh_buflen); | buflen = le16toh(hdr->rxh_buflen); | ||||
if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) { | if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) { | ||||
if_printf(ifp, "%s: zero length data, hdr_extra %d\n", | device_printf(sc->sc_dev, | ||||
__func__, hdr_extra); | "%s: zero length data, hdr_extra %d\n", | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | __func__, hdr_extra); | ||||
counter_u64_add(ic->ic_ierrors, 1); | |||||
m_freem(m); | m_freem(m); | ||||
goto next; | goto next; | ||||
} | } | ||||
Context not available. | |||||
rssi = bwi_calc_rssi(sc, hdr); | rssi = bwi_calc_rssi(sc, hdr); | ||||
noise = bwi_calc_noise(sc); | noise = bwi_calc_noise(sc); | ||||
m->m_pkthdr.rcvif = ifp; | |||||
m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr); | m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr); | ||||
m_adj(m, sizeof(*hdr) + wh_ofs); | m_adj(m, sizeof(*hdr) + wh_ofs); | ||||
Context not available. | |||||
{ | { | ||||
struct bwi_ring_data *rd; | struct bwi_ring_data *rd; | ||||
struct bwi_txbuf_data *tbd; | struct bwi_txbuf_data *tbd; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
uint32_t state, val; | uint32_t state, val; | ||||
int i; | int i; | ||||
Context not available. | |||||
DELAY(1000); | DELAY(1000); | ||||
} | } | ||||
if (i == NRETRY) { | if (i == NRETRY) { | ||||
if_printf(ifp, "%s: wait for TX ring(%d) stable timed out\n", | device_printf(sc->sc_dev, | ||||
__func__, ring_idx); | "%s: wait for TX ring(%d) stable timed out\n", | ||||
__func__, ring_idx); | |||||
} | } | ||||
CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0); | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0); | ||||
Context not available. | |||||
DELAY(1000); | DELAY(1000); | ||||
} | } | ||||
if (i == NRETRY) | if (i == NRETRY) | ||||
if_printf(ifp, "%s: reset TX ring (%d) timed out\n", | device_printf(sc->sc_dev, "%s: reset TX ring (%d) timed out\n", | ||||
__func__, ring_idx); | __func__, ring_idx); | ||||
#undef NRETRY | #undef NRETRY | ||||
Context not available. | |||||
struct ieee80211_node *ni) | struct ieee80211_node *ni) | ||||
{ | { | ||||
struct ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING]; | struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING]; | ||||
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; | ||||
struct bwi_txbuf *tb = &tbd->tbd_buf[idx]; | struct bwi_txbuf *tb = &tbd->tbd_buf[idx]; | ||||
Context not available. | |||||
*/ | */ | ||||
M_PREPEND(m, sizeof(*hdr), M_NOWAIT); | M_PREPEND(m, sizeof(*hdr), M_NOWAIT); | ||||
if (m == NULL) { | if (m == NULL) { | ||||
if_printf(ifp, "%s: prepend TX header failed\n", __func__); | device_printf(sc->sc_dev, "%s: prepend TX header failed\n", | ||||
__func__); | |||||
return ENOBUFS; | return ENOBUFS; | ||||
} | } | ||||
hdr = mtod(m, struct bwi_txbuf_hdr *); | hdr = mtod(m, struct bwi_txbuf_hdr *); | ||||
Context not available. | |||||
error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, tb->tb_dmap, m, | error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, tb->tb_dmap, m, | ||||
bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT); | bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT); | ||||
if (error && error != EFBIG) { | if (error && error != EFBIG) { | ||||
if_printf(ifp, "%s: can't load TX buffer (1) %d\n", | device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n", | ||||
__func__, error); | __func__, error); | ||||
goto back; | goto back; | ||||
} | } | ||||
Context not available. | |||||
m_new = m_defrag(m, M_NOWAIT); | m_new = m_defrag(m, M_NOWAIT); | ||||
if (m_new == NULL) { | if (m_new == NULL) { | ||||
if_printf(ifp, "%s: can't defrag TX buffer\n", | device_printf(sc->sc_dev, | ||||
__func__); | "%s: can't defrag TX buffer\n", __func__); | ||||
error = ENOBUFS; | error = ENOBUFS; | ||||
goto back; | goto back; | ||||
} else { | } else { | ||||
Context not available. | |||||
bwi_dma_buf_addr, &paddr, | bwi_dma_buf_addr, &paddr, | ||||
BUS_DMA_NOWAIT); | BUS_DMA_NOWAIT); | ||||
if (error) { | if (error) { | ||||
if_printf(ifp, "%s: can't load TX buffer (2) %d\n", | device_printf(sc->sc_dev, | ||||
"%s: can't load TX buffer (2) %d\n", | |||||
__func__, error); | __func__, error); | ||||
goto back; | goto back; | ||||
} | } | ||||
Context not available. | |||||
bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m, | bwi_encap_raw(struct bwi_softc *sc, int idx, 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 ieee80211vap *vap = ni->ni_vap; | struct ieee80211vap *vap = ni->ni_vap; | ||||
struct ieee80211com *ic = ni->ni_ic; | struct ieee80211com *ic = ni->ni_ic; | ||||
struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING]; | struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING]; | ||||
Context not available. | |||||
*/ | */ | ||||
M_PREPEND(m, sizeof(*hdr), M_NOWAIT); | M_PREPEND(m, sizeof(*hdr), M_NOWAIT); | ||||
if (m == NULL) { | if (m == NULL) { | ||||
if_printf(ifp, "%s: prepend TX header failed\n", __func__); | device_printf(sc->sc_dev, "%s: prepend TX header failed\n", | ||||
__func__); | |||||
return ENOBUFS; | return ENOBUFS; | ||||
} | } | ||||
hdr = mtod(m, struct bwi_txbuf_hdr *); | hdr = mtod(m, struct bwi_txbuf_hdr *); | ||||
Context not available. | |||||
struct mbuf *m_new; | struct mbuf *m_new; | ||||
if (error != EFBIG) { | if (error != EFBIG) { | ||||
if_printf(ifp, "%s: can't load TX buffer (1) %d\n", | device_printf(sc->sc_dev, | ||||
"%s: can't load TX buffer (1) %d\n", | |||||
__func__, error); | __func__, error); | ||||
goto back; | goto back; | ||||
} | } | ||||
m_new = m_defrag(m, M_NOWAIT); | m_new = m_defrag(m, M_NOWAIT); | ||||
if (m_new == NULL) { | if (m_new == NULL) { | ||||
if_printf(ifp, "%s: can't defrag TX buffer\n", | device_printf(sc->sc_dev, | ||||
__func__); | "%s: can't defrag TX buffer\n", __func__); | ||||
error = ENOBUFS; | error = ENOBUFS; | ||||
goto back; | goto back; | ||||
} | } | ||||
Context not available. | |||||
bwi_dma_buf_addr, &paddr, | bwi_dma_buf_addr, &paddr, | ||||
BUS_DMA_NOWAIT); | BUS_DMA_NOWAIT); | ||||
if (error) { | if (error) { | ||||
if_printf(ifp, "%s: can't load TX buffer (2) %d\n", | device_printf(sc->sc_dev, | ||||
"%s: can't load TX buffer (2) %d\n", | |||||
__func__, error); | __func__, error); | ||||
goto back; | goto back; | ||||
} | } | ||||
Context not available. | |||||
static void | static void | ||||
bwi_txeof_status32(struct bwi_softc *sc) | bwi_txeof_status32(struct bwi_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
uint32_t val, ctrl_base; | uint32_t val, ctrl_base; | ||||
int end_idx; | int end_idx; | ||||
Context not available. | |||||
CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX, | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX, | ||||
end_idx * sizeof(struct bwi_desc32)); | end_idx * sizeof(struct bwi_desc32)); | ||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) | bwi_start_locked(sc); | ||||
ifp->if_start(ifp); | |||||
} | } | ||||
static void | static void | ||||
Context not available. | |||||
static void | static void | ||||
_bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt) | _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct bwi_txbuf_data *tbd; | struct bwi_txbuf_data *tbd; | ||||
struct bwi_txbuf *tb; | struct bwi_txbuf *tb; | ||||
int ring_idx, buf_idx; | int ring_idx, buf_idx; | ||||
Context not available. | |||||
struct ieee80211vap *vap; | struct ieee80211vap *vap; | ||||
if (tx_id == 0) { | if (tx_id == 0) { | ||||
if_printf(ifp, "%s: zero tx id\n", __func__); | device_printf(sc->sc_dev, "%s: zero tx id\n", __func__); | ||||
return; | return; | ||||
} | } | ||||
Context not available. | |||||
bus_dmamap_unload(sc->sc_buf_dtag, tb->tb_dmap); | bus_dmamap_unload(sc->sc_buf_dtag, tb->tb_dmap); | ||||
ni = tb->tb_ni; | if ((ni = tb->tb_ni) != NULL) { | ||||
if (tb->tb_ni != NULL) { | |||||
const struct bwi_txbuf_hdr *hdr = | const struct bwi_txbuf_hdr *hdr = | ||||
mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *); | mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *); | ||||
vap = ni->ni_vap; | vap = ni->ni_vap; | ||||
Context not available. | |||||
(data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS : | (data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS : | ||||
IEEE80211_RATECTL_TX_FAILURE, &acked, NULL); | IEEE80211_RATECTL_TX_FAILURE, &acked, NULL); | ||||
} | } | ||||
ieee80211_tx_complete(ni, tb->tb_mbuf, !acked); | |||||
/* | |||||
* Do any tx complete callback. Note this must | |||||
* be done before releasing the node reference. | |||||
*/ | |||||
if (tb->tb_mbuf->m_flags & M_TXCB) | |||||
ieee80211_process_callback(ni, tb->tb_mbuf, !acked); | |||||
ieee80211_free_node(tb->tb_ni); | |||||
tb->tb_ni = NULL; | tb->tb_ni = NULL; | ||||
} | } else | ||||
m_freem(tb->tb_mbuf); | m_freem(tb->tb_mbuf); | ||||
tb->tb_mbuf = NULL; | tb->tb_mbuf = NULL; | ||||
if (tbd->tbd_used == 0) | if (tbd->tbd_used == 0) | ||||
sc->sc_tx_timer = 0; | sc->sc_tx_timer = 0; | ||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; | |||||
} | } | ||||
static void | static void | ||||
Context not available. | |||||
static void | static void | ||||
bwi_txeof(struct bwi_softc *sc) | bwi_txeof(struct bwi_softc *sc) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
for (;;) { | for (;;) { | ||||
uint32_t tx_status0, tx_status1; | uint32_t tx_status0, tx_status1; | ||||
Context not available. | |||||
data_txcnt); | data_txcnt); | ||||
} | } | ||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) | bwi_start_locked(sc); | ||||
ifp->if_start(ifp); | |||||
} | } | ||||
static int | static int | ||||
Context not available. | |||||
static void | static void | ||||
bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid) | bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct bwi_mac *mac; | struct bwi_mac *mac; | ||||
struct bwi_myaddr_bssid buf; | struct bwi_myaddr_bssid buf; | ||||
const uint8_t *p; | const uint8_t *p; | ||||
Context not available. | |||||
bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid); | bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid); | ||||
bcopy(IF_LLADDR(ifp), buf.myaddr, sizeof(buf.myaddr)); | bcopy(sc->sc_ic.ic_macaddr, buf.myaddr, sizeof(buf.myaddr)); | ||||
bcopy(bssid, buf.bssid, sizeof(buf.bssid)); | bcopy(bssid, buf.bssid, sizeof(buf.bssid)); | ||||
n = sizeof(buf) / sizeof(val); | n = sizeof(buf) / sizeof(val); | ||||
Context not available. | |||||
struct bwi_mac *mac; | struct bwi_mac *mac; | ||||
BWI_LOCK(sc); | BWI_LOCK(sc); | ||||
if (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) { | if (sc->sc_flags & BWI_F_RUNNING) { | ||||
DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__); | DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__); | ||||
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, | ||||
Context not available. | |||||
bwi_calibrate(void *xsc) | bwi_calibrate(void *xsc) | ||||
{ | { | ||||
struct bwi_softc *sc = xsc; | struct bwi_softc *sc = xsc; | ||||
#ifdef INVARIANTS | |||||
struct ifnet *ifp = sc->sc_ifp; | |||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
#endif | |||||
struct bwi_mac *mac; | struct bwi_mac *mac; | ||||
BWI_ASSERT_LOCKED(sc); | BWI_ASSERT_LOCKED(sc); | ||||
KASSERT(ic->ic_opmode != IEEE80211_M_MONITOR, | KASSERT(sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR, | ||||
("opmode %d", ic->ic_opmode)); | ("opmode %d", sc->sc_ic.ic_opmode)); | ||||
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, | ||||
("current regwin type %d", sc->sc_cur_regwin->rw_type)); | ("current regwin type %d", sc->sc_cur_regwin->rw_type)); | ||||
Context not available. | |||||
static void | static void | ||||
bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate) | bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate) | ||||
{ | { | ||||
struct ifnet *ifp = sc->sc_ifp; | struct ieee80211com *ic = &sc->sc_ic; | ||||
struct ieee80211com *ic = ifp->if_l2com; | |||||
uint16_t val; | uint16_t val; | ||||
int i; | int i; | ||||
Context not available. | |||||
sc->sc_led_blinking = 0; | sc->sc_led_blinking = 0; | ||||
} | } | ||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) | if ((sc->sc_flags & BWI_F_RUNNING) == 0) | ||||
return; | return; | ||||
val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL); | val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL); | ||||
Context not available. | |||||
bwi_restart(void *xsc, int pending) | bwi_restart(void *xsc, int pending) | ||||
{ | { | ||||
struct bwi_softc *sc = xsc; | struct bwi_softc *sc = xsc; | ||||
struct ifnet *ifp = sc->sc_ifp; | |||||
if_printf(ifp, "%s begin, help!\n", __func__); | device_printf(sc->sc_dev, "%s begin, help!\n", __func__); | ||||
BWI_LOCK(sc); | BWI_LOCK(sc); | ||||
bwi_init_statechg(xsc, 0); | bwi_init_statechg(sc, 0); | ||||
#if 0 | #if 0 | ||||
bwi_start_locked(ifp); | bwi_start_locked(sc); | ||||
#endif | #endif | ||||
BWI_UNLOCK(sc); | BWI_UNLOCK(sc); | ||||
} | } | ||||
Context not available. |