Revert the wifi ifnet changes until things are more baked and tested.
* 286410 * 286413 * 286416 The initial commit broke a variety of debug and features that aren't in the GENERIC kernels but are enabled in other platforms.
This commit is contained in:
parent
721b581722
commit
ba2c1fbc03
@ -488,7 +488,8 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
|
||||
#define RATE(ix) (DOT11RATE(ix) / 2)
|
||||
struct sample_node *sn = ATH_NODE_SAMPLE(an);
|
||||
struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
const HAL_RATE_TABLE *rt = sc->sc_currates;
|
||||
const int size_bin = size_to_bin(frameLen);
|
||||
int rix, mrr, best_rix, change_rates;
|
||||
@ -855,7 +856,8 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
|
||||
const struct ath_rc_series *rc, const struct ath_tx_status *ts,
|
||||
int frame_size, int nframes, int nbad)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct sample_node *sn = ATH_NODE_SAMPLE(an);
|
||||
int final_rix, short_tries, long_tries;
|
||||
const HAL_RATE_TABLE *rt = sc->sc_currates;
|
||||
@ -1301,7 +1303,8 @@ static int
|
||||
ath_rate_sysctl_stats(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct ath_softc *sc = arg1;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
int error, v;
|
||||
|
||||
v = 0;
|
||||
|
@ -134,7 +134,8 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc,
|
||||
int long_retries, int is_ht40)
|
||||
{
|
||||
const HAL_RATE_TABLE *rt = sc->sc_currates;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
int rts, cts;
|
||||
|
||||
unsigned t_slot = 20;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -134,7 +134,7 @@ int
|
||||
ath_beaconq_config(struct ath_softc *sc)
|
||||
{
|
||||
#define ATH_EXPONENT_TO_VALUE(v) ((1<<(v))-1)
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
HAL_TXQ_INFO qi;
|
||||
|
||||
@ -464,7 +464,7 @@ ath_beacon_proc(void *arg, int pending)
|
||||
}
|
||||
|
||||
if (sc->sc_stagbeacons) { /* staggered beacons */
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
uint32_t tsftu;
|
||||
|
||||
tsftu = ath_hal_gettsf32(ah) >> 10;
|
||||
@ -917,7 +917,7 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
|
||||
((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
|
||||
#define FUDGE 2
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211_node *ni;
|
||||
u_int32_t nexttbtt, intval, tsftu;
|
||||
u_int32_t nexttbtt_u8, intval_u8;
|
||||
|
@ -91,7 +91,9 @@ enum {
|
||||
|
||||
extern uint64_t ath_debug;
|
||||
|
||||
#define IFF_DUMPPKTS(sc, m) ((sc->sc_debug & (m))
|
||||
#define IFF_DUMPPKTS(sc, m) \
|
||||
((sc->sc_debug & (m)) || \
|
||||
(sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
|
||||
#define DPRINTF(sc, m, fmt, ...) do { \
|
||||
if (sc->sc_debug & (m)) \
|
||||
device_printf(sc->sc_dev, fmt, __VA_ARGS__); \
|
||||
@ -110,7 +112,8 @@ extern void ath_printtxstatbuf(struct ath_softc *sc, const struct ath_buf *bf,
|
||||
#else /* ATH_DEBUG */
|
||||
#define ATH_KTR(_sc, _km, _kf, ...) do { } while (0)
|
||||
|
||||
#define IFF_DUMPPKTS(sc, m) (0)
|
||||
#define IFF_DUMPPKTS(sc, m) \
|
||||
((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
|
||||
#define DPRINTF(sc, m, fmt, ...) do { \
|
||||
(void) sc; \
|
||||
} while (0)
|
||||
|
@ -425,7 +425,7 @@ int
|
||||
ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
|
||||
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
|
||||
{
|
||||
struct ath_softc *sc = vap->iv_ic->ic_softc;
|
||||
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
|
||||
|
||||
/*
|
||||
* Group key allocation must be handled specially for
|
||||
@ -493,7 +493,7 @@ ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
|
||||
int
|
||||
ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
|
||||
{
|
||||
struct ath_softc *sc = vap->iv_ic->ic_softc;
|
||||
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
const struct ieee80211_cipher *cip = k->wk_cipher;
|
||||
u_int keyix = k->wk_keyix;
|
||||
@ -538,7 +538,7 @@ int
|
||||
ath_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
|
||||
const u_int8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct ath_softc *sc = vap->iv_ic->ic_softc;
|
||||
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
|
||||
|
||||
return ath_keyset(sc, vap, k, vap->iv_bss);
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ extern void ath_freebuf(struct ath_softc *sc, struct ath_buf *bf);
|
||||
extern void ath_returnbuf_head(struct ath_softc *sc, struct ath_buf *bf);
|
||||
extern void ath_returnbuf_tail(struct ath_softc *sc, struct ath_buf *bf);
|
||||
|
||||
extern int ath_reset(struct ath_softc *, ATH_RESET_TYPE);
|
||||
extern int ath_reset(struct ifnet *, ATH_RESET_TYPE);
|
||||
extern void ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf,
|
||||
int fail);
|
||||
extern void ath_tx_update_ratectrl(struct ath_softc *sc,
|
||||
|
@ -154,7 +154,8 @@ __FBSDID("$FreeBSD$");
|
||||
u_int32_t
|
||||
ath_calcrxfilter(struct ath_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
u_int32_t rfilt;
|
||||
|
||||
rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST;
|
||||
@ -163,7 +164,7 @@ ath_calcrxfilter(struct ath_softc *sc)
|
||||
if (ic->ic_opmode != IEEE80211_M_STA)
|
||||
rfilt |= HAL_RX_FILTER_PROBEREQ;
|
||||
/* XXX ic->ic_monvaps != 0? */
|
||||
if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_promisc > 0)
|
||||
if (ic->ic_opmode == IEEE80211_M_MONITOR || (ifp->if_flags & IFF_PROMISC))
|
||||
rfilt |= HAL_RX_FILTER_PROM;
|
||||
|
||||
/*
|
||||
@ -329,7 +330,7 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
|
||||
int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
|
||||
{
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ath_softc *sc = vap->iv_ic->ic_softc;
|
||||
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
|
||||
uint64_t tsf_beacon_old, tsf_beacon;
|
||||
uint64_t nexttbtt;
|
||||
int64_t tsf_delta;
|
||||
@ -462,9 +463,10 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
|
||||
|
||||
#ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT
|
||||
static void
|
||||
ath_rx_tap_vendor(struct ath_softc *sc, struct mbuf *m,
|
||||
ath_rx_tap_vendor(struct ifnet *ifp, struct mbuf *m,
|
||||
const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf)
|
||||
{
|
||||
struct ath_softc *sc = ifp->if_softc;
|
||||
|
||||
/* Fill in the extension bitmap */
|
||||
sc->sc_rx_th.wr_ext_bitmap = htole32(1 << ATH_RADIOTAP_VENDOR_HEADER);
|
||||
@ -527,13 +529,14 @@ ath_rx_tap_vendor(struct ath_softc *sc, struct mbuf *m,
|
||||
#endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */
|
||||
|
||||
static void
|
||||
ath_rx_tap(struct ath_softc *sc, struct mbuf *m,
|
||||
ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
|
||||
const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf)
|
||||
{
|
||||
#define CHAN_HT20 htole32(IEEE80211_CHAN_HT20)
|
||||
#define CHAN_HT40U htole32(IEEE80211_CHAN_HT40U)
|
||||
#define CHAN_HT40D htole32(IEEE80211_CHAN_HT40D)
|
||||
#define CHAN_HT (CHAN_HT20|CHAN_HT40U|CHAN_HT40D)
|
||||
struct ath_softc *sc = ifp->if_softc;
|
||||
const HAL_RATE_TABLE *rt;
|
||||
uint8_t rix;
|
||||
|
||||
@ -557,7 +560,7 @@ ath_rx_tap(struct ath_softc *sc, struct mbuf *m,
|
||||
else if (IEEE80211_IS_CHAN_HT20(sc->sc_curchan))
|
||||
sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
|
||||
} else if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) { /* HT rate */
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
if ((rs->rs_flags & HAL_RX_2040) == 0)
|
||||
sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
|
||||
@ -614,7 +617,8 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
|
||||
{
|
||||
uint64_t rstamp;
|
||||
int len, type;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_node *ni;
|
||||
int is_good = 0;
|
||||
struct ath_rx_edma *re = &sc->sc_rxedma[qtype];
|
||||
@ -700,7 +704,7 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
|
||||
rs->rs_keyix-32 : rs->rs_keyix);
|
||||
}
|
||||
}
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
rx_error:
|
||||
/*
|
||||
* Cleanup any pending partial frame.
|
||||
@ -720,9 +724,9 @@ rx_error:
|
||||
/* NB: bpf needs the mbuf length setup */
|
||||
len = rs->rs_datalen;
|
||||
m->m_pkthdr.len = m->m_len = len;
|
||||
ath_rx_tap(sc, m, rs, rstamp, nf);
|
||||
ath_rx_tap(ifp, m, rs, rstamp, nf);
|
||||
#ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT
|
||||
ath_rx_tap_vendor(sc, m, rs, rstamp, nf);
|
||||
ath_rx_tap_vendor(ifp, m, rs, rstamp, nf);
|
||||
#endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */
|
||||
ieee80211_radiotap_rx_all(ic, m);
|
||||
}
|
||||
@ -745,6 +749,7 @@ rx_accept:
|
||||
sc->sc_stats.ast_rx_toobig++;
|
||||
m_freem(re->m_rxpending);
|
||||
}
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = len;
|
||||
re->m_rxpending = m;
|
||||
m = NULL;
|
||||
@ -761,8 +766,10 @@ rx_accept:
|
||||
re->m_rxpending = NULL;
|
||||
} else {
|
||||
/*
|
||||
* Normal single-descriptor receive; setup packet length.
|
||||
* Normal single-descriptor receive; setup
|
||||
* the rcvif and packet length.
|
||||
*/
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = len;
|
||||
}
|
||||
|
||||
@ -823,6 +830,7 @@ rx_accept:
|
||||
rs->rs_antenna |= 0x4;
|
||||
}
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||
sc->sc_stats.ast_ant_rx[rs->rs_antenna]++;
|
||||
|
||||
/*
|
||||
@ -833,9 +841,9 @@ rx_accept:
|
||||
* noise setting is filled in above.
|
||||
*/
|
||||
if (ieee80211_radiotap_active(ic)) {
|
||||
ath_rx_tap(sc, m, rs, rstamp, nf);
|
||||
ath_rx_tap(ifp, m, rs, rstamp, nf);
|
||||
#ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT
|
||||
ath_rx_tap_vendor(sc, m, rs, rstamp, nf);
|
||||
ath_rx_tap_vendor(ifp, m, rs, rstamp, nf);
|
||||
#endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */
|
||||
}
|
||||
|
||||
@ -983,9 +991,10 @@ ath_rx_proc(struct ath_softc *sc, int resched)
|
||||
((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
|
||||
((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
|
||||
struct ath_buf *bf;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
#endif
|
||||
struct ath_desc *ds;
|
||||
struct ath_rx_status *rs;
|
||||
@ -1180,10 +1189,15 @@ rx_proc_next:
|
||||
ATH_PCU_UNLOCK(sc);
|
||||
}
|
||||
|
||||
/* XXX check this inside of IF_LOCK? */
|
||||
if (resched && (ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
if (resched)
|
||||
ieee80211_ff_age_all(ic, 100);
|
||||
#endif
|
||||
if (!IFQ_IS_EMPTY(&ifp->if_snd))
|
||||
ath_tx_kick(sc);
|
||||
}
|
||||
#undef PA2DESC
|
||||
|
||||
/*
|
||||
* Put the hardware to sleep again if we're done with it.
|
||||
@ -1205,7 +1219,7 @@ rx_proc_next:
|
||||
sc->sc_rxproc_cnt--;
|
||||
ATH_PCU_UNLOCK(sc);
|
||||
}
|
||||
#undef PA2DESC
|
||||
|
||||
#undef ATH_RX_MAX
|
||||
|
||||
/*
|
||||
|
@ -579,8 +579,9 @@ static void
|
||||
ath_edma_recv_tasklet(void *arg, int npending)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *) arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
#endif
|
||||
|
||||
DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called; npending=%d\n",
|
||||
@ -616,9 +617,14 @@ ath_edma_recv_tasklet(void *arg, int npending)
|
||||
ath_power_restore_power_state(sc);
|
||||
ATH_UNLOCK(sc);
|
||||
|
||||
/* XXX inside IF_LOCK ? */
|
||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
ieee80211_ff_age_all(ic, 100);
|
||||
ieee80211_ff_age_all(ic, 100);
|
||||
#endif
|
||||
if (! IFQ_IS_EMPTY(&ifp->if_snd))
|
||||
ath_tx_kick(sc);
|
||||
}
|
||||
if (ath_dfs_tasklet_needed(sc, sc->sc_curchan))
|
||||
taskqueue_enqueue(sc->sc_tq, &sc->sc_dfstask);
|
||||
|
||||
|
@ -367,6 +367,7 @@ static int
|
||||
ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct ath_softc *sc = arg1;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
u_int32_t scale;
|
||||
int error;
|
||||
|
||||
@ -380,7 +381,8 @@ ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
|
||||
goto finish;
|
||||
|
||||
error = !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL :
|
||||
(sc->sc_running) ? ath_reset(sc, ATH_RESET_NOLOSS) : 0;
|
||||
(ifp->if_drv_flags & IFF_DRV_RUNNING) ?
|
||||
ath_reset(ifp, ATH_RESET_NOLOSS) : 0;
|
||||
|
||||
finish:
|
||||
ATH_LOCK(sc);
|
||||
@ -420,6 +422,7 @@ static int
|
||||
ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct ath_softc *sc = arg1;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
u_int rfkill;
|
||||
int error;
|
||||
@ -441,7 +444,8 @@ ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
|
||||
error = EINVAL;
|
||||
goto finish;
|
||||
}
|
||||
error = sc->sc_running ? ath_reset(sc, ATH_RESET_FULL) : 0;
|
||||
error = (ifp->if_drv_flags & IFF_DRV_RUNNING) ?
|
||||
ath_reset(ifp, ATH_RESET_FULL) : 0;
|
||||
|
||||
finish:
|
||||
ATH_LOCK(sc);
|
||||
@ -667,8 +671,8 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS)
|
||||
* doesn't reset ANI related registers, so it'll leave
|
||||
* things in an inconsistent state.
|
||||
*/
|
||||
if (sc->sc_running)
|
||||
ath_reset(sc, ATH_RESET_NOLOSS);
|
||||
if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ath_reset(sc->sc_ifp, ATH_RESET_NOLOSS);
|
||||
|
||||
error = 0;
|
||||
|
||||
|
@ -359,7 +359,7 @@ ath_tdma_update(struct ieee80211_node *ni,
|
||||
#define TU_TO_TSF(_tu) (((u_int64_t)(_tu)) << 10)
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ath_softc *sc = ic->ic_softc;
|
||||
struct ath_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
const HAL_RATE_TABLE *rt = sc->sc_currates;
|
||||
u_int64_t tsf, rstamp, nextslot, nexttbtt, nexttbtt_full;
|
||||
|
@ -1051,7 +1051,8 @@ ath_tx_calc_protection(struct ath_softc *sc, struct ath_buf *bf)
|
||||
uint16_t flags;
|
||||
int shortPreamble;
|
||||
const HAL_RATE_TABLE *rt = sc->sc_currates;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
flags = bf->bf_state.bfs_txflags;
|
||||
rix = bf->bf_state.bfs_rc[0].rix;
|
||||
@ -1544,7 +1545,8 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
{
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ath_hal *ah = sc->sc_ah;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams;
|
||||
int error, iswep, ismcast, isfrag, ismrr;
|
||||
int keyix, hdrlen, pktlen, try0 = 0;
|
||||
@ -2072,7 +2074,8 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
struct ath_buf *bf, struct mbuf *m0,
|
||||
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 ath_hal *ah = sc->sc_ah;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
int error, ismcast, ismrr;
|
||||
@ -2337,7 +2340,8 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ath_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ath_softc *sc = ifp->if_softc;
|
||||
struct ath_buf *bf;
|
||||
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
|
||||
int error = 0;
|
||||
@ -2360,9 +2364,10 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
|
||||
ATH_TX_LOCK(sc);
|
||||
|
||||
if (!sc->sc_running || sc->sc_invalid) {
|
||||
DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, r/i: %d/%d",
|
||||
__func__, sc->sc_running, sc->sc_invalid);
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) {
|
||||
DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, %s", __func__,
|
||||
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ?
|
||||
"!running" : "invalid");
|
||||
m_freem(m);
|
||||
error = ENETDOWN;
|
||||
goto bad;
|
||||
@ -2419,6 +2424,7 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
}
|
||||
}
|
||||
sc->sc_wd_timer = 5;
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
sc->sc_stats.ast_tx_raw++;
|
||||
|
||||
/*
|
||||
@ -2467,6 +2473,7 @@ bad:
|
||||
badbad:
|
||||
ATH_KTR(sc, ATH_KTR_TX, 2, "ath_raw_xmit: bad0: m=%p, params=%p",
|
||||
m, params);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
sc->sc_stats.ast_tx_raw_fail++;
|
||||
ieee80211_free_node(ni);
|
||||
|
||||
@ -5724,7 +5731,7 @@ int
|
||||
ath_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
|
||||
int dialogtoken, int baparamset, int batimeout)
|
||||
{
|
||||
struct ath_softc *sc = ni->ni_ic->ic_softc;
|
||||
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
|
||||
int tid = tap->txa_tid;
|
||||
struct ath_node *an = ATH_NODE(ni);
|
||||
struct ath_tid *atid = &an->an_tid[tid];
|
||||
@ -5802,7 +5809,7 @@ int
|
||||
ath_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
|
||||
int status, int code, int batimeout)
|
||||
{
|
||||
struct ath_softc *sc = ni->ni_ic->ic_softc;
|
||||
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
|
||||
int tid = tap->txa_tid;
|
||||
struct ath_node *an = ATH_NODE(ni);
|
||||
struct ath_tid *atid = &an->an_tid[tid];
|
||||
@ -5849,7 +5856,7 @@ ath_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
|
||||
void
|
||||
ath_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
|
||||
{
|
||||
struct ath_softc *sc = ni->ni_ic->ic_softc;
|
||||
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
|
||||
int tid = tap->txa_tid;
|
||||
struct ath_node *an = ATH_NODE(ni);
|
||||
struct ath_tid *atid = &an->an_tid[tid];
|
||||
@ -5984,7 +5991,7 @@ void
|
||||
ath_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
|
||||
int status)
|
||||
{
|
||||
struct ath_softc *sc = ni->ni_ic->ic_softc;
|
||||
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
|
||||
int tid = tap->txa_tid;
|
||||
struct ath_node *an = ATH_NODE(ni);
|
||||
struct ath_tid *atid = &an->an_tid[tid];
|
||||
@ -6057,7 +6064,7 @@ void
|
||||
ath_addba_response_timeout(struct ieee80211_node *ni,
|
||||
struct ieee80211_tx_ampdu *tap)
|
||||
{
|
||||
struct ath_softc *sc = ni->ni_ic->ic_softc;
|
||||
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
|
||||
int tid = tap->txa_tid;
|
||||
struct ath_node *an = ATH_NODE(ni);
|
||||
struct ath_tid *atid = &an->an_tid[tid];
|
||||
|
@ -537,6 +537,7 @@ ath_edma_dma_txteardown(struct ath_softc *sc)
|
||||
static void
|
||||
ath_edma_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int i;
|
||||
|
||||
DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__);
|
||||
@ -578,6 +579,9 @@ ath_edma_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
|
||||
|
||||
/* XXX dump out the frames */
|
||||
|
||||
IF_LOCK(&ifp->if_snd);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
IF_UNLOCK(&ifp->if_snd);
|
||||
sc->sc_wd_timer = 0;
|
||||
}
|
||||
|
||||
@ -830,6 +834,12 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched)
|
||||
|
||||
sc->sc_wd_timer = 0;
|
||||
|
||||
if (idx > 0) {
|
||||
IF_LOCK(&sc->sc_ifp->if_snd);
|
||||
sc->sc_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
IF_UNLOCK(&sc->sc_ifp->if_snd);
|
||||
}
|
||||
|
||||
/* Kick software scheduler */
|
||||
/*
|
||||
* XXX It's inefficient to do this if the FIFO queue is full,
|
||||
|
@ -555,8 +555,8 @@ struct ath_tx_methods {
|
||||
};
|
||||
|
||||
struct ath_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct ath_stats sc_stats; /* device statistics */
|
||||
struct ifnet *sc_ifp; /* interface common */
|
||||
struct ath_stats sc_stats; /* interface statistics */
|
||||
struct ath_tx_aggr_stats sc_aggr_stats;
|
||||
struct ath_intr_stats sc_intr_stats;
|
||||
uint64_t sc_debug;
|
||||
@ -650,8 +650,7 @@ struct ath_softc {
|
||||
/*
|
||||
* Second set of flags.
|
||||
*/
|
||||
u_int32_t sc_running : 1, /* initialized */
|
||||
sc_use_ent : 1,
|
||||
u_int32_t sc_use_ent : 1,
|
||||
sc_rx_stbc : 1,
|
||||
sc_tx_stbc : 1,
|
||||
sc_hasenforcetxop : 1, /* support enforce TxOP */
|
||||
|
@ -832,11 +832,11 @@ bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
|
||||
uint8_t fw_type)
|
||||
{
|
||||
const struct bwi_fwhdr *hdr;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (fw->datasize < sizeof(*hdr)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"invalid firmware (%s): invalid size %zu\n",
|
||||
fw->name, fw->datasize);
|
||||
if_printf(ifp, "invalid firmware (%s): invalid size %zu\n",
|
||||
fw->name, fw->datasize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -847,26 +847,25 @@ bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
|
||||
* Don't verify IV's size, it has different meaning
|
||||
*/
|
||||
if (be32toh(hdr->fw_size) != fw->datasize - sizeof(*hdr)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"invalid firmware (%s): size mismatch, "
|
||||
"fw %u, real %zu\n", fw->name,
|
||||
be32toh(hdr->fw_size), fw->datasize - sizeof(*hdr));
|
||||
if_printf(ifp, "invalid firmware (%s): size mismatch, "
|
||||
"fw %u, real %zu\n", fw->name,
|
||||
be32toh(hdr->fw_size),
|
||||
fw->datasize - sizeof(*hdr));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (hdr->fw_type != fw_type) {
|
||||
device_printf(sc->sc_dev,
|
||||
"invalid firmware (%s): type mismatch, "
|
||||
"fw \'%c\', target \'%c\'\n", fw->name,
|
||||
hdr->fw_type, fw_type);
|
||||
if_printf(ifp, "invalid firmware (%s): type mismatch, "
|
||||
"fw \'%c\', target \'%c\'\n", fw->name,
|
||||
hdr->fw_type, fw_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hdr->fw_gen != BWI_FW_GEN_1) {
|
||||
device_printf(sc->sc_dev,
|
||||
"invalid firmware (%s): wrong generation, "
|
||||
"fw %d, target %d\n", fw->name, hdr->fw_gen, BWI_FW_GEN_1);
|
||||
if_printf(ifp, "invalid firmware (%s): wrong generation, "
|
||||
"fw %d, target %d\n", fw->name,
|
||||
hdr->fw_gen, BWI_FW_GEN_1);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -1003,6 +1002,7 @@ static int
|
||||
bwi_mac_fw_load(struct bwi_mac *mac)
|
||||
{
|
||||
struct bwi_softc *sc = mac->mac_sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
const uint32_t *fw;
|
||||
uint16_t fw_rev;
|
||||
int fw_len, i;
|
||||
@ -1057,8 +1057,7 @@ bwi_mac_fw_load(struct bwi_mac *mac)
|
||||
DELAY(10);
|
||||
}
|
||||
if (i == NRETRY) {
|
||||
device_printf(sc->sc_dev,
|
||||
"firmware (ucode&pcm) loading timed out\n");
|
||||
if_printf(ifp, "firmware (ucode&pcm) loading timed out\n");
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
@ -1068,14 +1067,12 @@ bwi_mac_fw_load(struct bwi_mac *mac)
|
||||
|
||||
fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV);
|
||||
if (fw_rev > BWI_FW_VERSION3_REVMAX) {
|
||||
device_printf(sc->sc_dev,
|
||||
"firmware version 4 is not supported yet\n");
|
||||
if_printf(ifp, "firmware version 4 is not supported yet\n");
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
device_printf(sc->sc_dev,
|
||||
"firmware rev 0x%04x, patch level 0x%04x\n", fw_rev,
|
||||
MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
|
||||
if_printf(ifp, "firmware rev 0x%04x, patch level 0x%04x\n", fw_rev,
|
||||
MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1135,6 +1132,7 @@ static int
|
||||
bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
|
||||
{
|
||||
struct bwi_softc *sc = mac->mac_sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
const struct bwi_fwhdr *hdr;
|
||||
const struct bwi_fw_iv *iv;
|
||||
int n, i, iv_img_size;
|
||||
@ -1157,7 +1155,7 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
|
||||
int sz = 0;
|
||||
|
||||
if (iv_img_size < sizeof(iv->iv_ofs)) {
|
||||
device_printf(sc->sc_dev, "invalid IV image, ofs\n");
|
||||
if_printf(ifp, "invalid IV image, ofs\n");
|
||||
return EINVAL;
|
||||
}
|
||||
iv_img_size -= sizeof(iv->iv_ofs);
|
||||
@ -1167,7 +1165,7 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
|
||||
|
||||
ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK);
|
||||
if (ofs >= 0x1000) {
|
||||
device_printf(sc->sc_dev, "invalid ofs (0x%04x) "
|
||||
if_printf(ifp, "invalid ofs (0x%04x) "
|
||||
"for %dth iv\n", ofs, i);
|
||||
return EINVAL;
|
||||
}
|
||||
@ -1176,8 +1174,7 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
|
||||
uint32_t val32;
|
||||
|
||||
if (iv_img_size < sizeof(iv->iv_val.val32)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"invalid IV image, val32\n");
|
||||
if_printf(ifp, "invalid IV image, val32\n");
|
||||
return EINVAL;
|
||||
}
|
||||
iv_img_size -= sizeof(iv->iv_val.val32);
|
||||
@ -1189,8 +1186,7 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
|
||||
uint16_t val16;
|
||||
|
||||
if (iv_img_size < sizeof(iv->iv_val.val16)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"invalid IV image, val16\n");
|
||||
if_printf(ifp, "invalid IV image, val16\n");
|
||||
return EINVAL;
|
||||
}
|
||||
iv_img_size -= sizeof(iv->iv_val.val16);
|
||||
@ -1204,8 +1200,7 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
|
||||
}
|
||||
|
||||
if (iv_img_size != 0) {
|
||||
device_printf(sc->sc_dev, "invalid IV image, size left %d\n",
|
||||
iv_img_size);
|
||||
if_printf(ifp, "invalid IV image, size left %d\n", iv_img_size);
|
||||
return EINVAL;
|
||||
}
|
||||
return 0;
|
||||
@ -1214,19 +1209,19 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
|
||||
static int
|
||||
bwi_mac_fw_init(struct bwi_mac *mac)
|
||||
{
|
||||
device_t dev = mac->mac_sc->sc_dev;
|
||||
struct ifnet *ifp = mac->mac_sc->sc_ifp;
|
||||
int error;
|
||||
|
||||
error = bwi_mac_fw_load_iv(mac, mac->mac_iv);
|
||||
if (error) {
|
||||
device_printf(dev, "load IV failed\n");
|
||||
if_printf(ifp, "load IV failed\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
if (mac->mac_iv_ext != NULL) {
|
||||
error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext);
|
||||
if (error)
|
||||
device_printf(dev, "load ExtIV failed\n");
|
||||
if_printf(ifp, "load ExtIV failed\n");
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@ -1235,7 +1230,8 @@ static void
|
||||
bwi_mac_opmode_init(struct bwi_mac *mac)
|
||||
{
|
||||
struct bwi_softc *sc = mac->mac_sc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t mac_status;
|
||||
uint16_t pre_tbtt;
|
||||
|
||||
@ -1284,7 +1280,7 @@ bwi_mac_opmode_init(struct bwi_mac *mac)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ic->ic_promisc > 0)
|
||||
if (ic->ic_ifp->if_flags & IFF_PROMISC)
|
||||
mac_status |= BWI_MAC_STATUS_PROMISC;
|
||||
|
||||
CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status);
|
||||
@ -1335,7 +1331,8 @@ bwi_mac_bss_param_init(struct bwi_mac *mac)
|
||||
{
|
||||
struct bwi_softc *sc = mac->mac_sc;
|
||||
struct bwi_phy *phy = &mac->mac_phy;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
const struct ieee80211_rate_table *rt;
|
||||
struct bwi_retry_lim lim;
|
||||
uint16_t cw_min;
|
||||
@ -1918,7 +1915,8 @@ static void
|
||||
bwi_mac_lock(struct bwi_mac *mac)
|
||||
{
|
||||
struct bwi_softc *sc = mac->mac_sc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0,
|
||||
("mac_flags 0x%x", mac->mac_flags));
|
||||
@ -1941,7 +1939,8 @@ static void
|
||||
bwi_mac_unlock(struct bwi_mac *mac)
|
||||
{
|
||||
struct bwi_softc *sc = mac->mac_sc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED,
|
||||
("mac_flags 0x%x", mac->mac_flags));
|
||||
|
@ -429,7 +429,7 @@ static void
|
||||
bwi_phy_init_11b_rev2(struct bwi_mac *mac)
|
||||
{
|
||||
/* TODO:11B */
|
||||
device_printf(mac->mac_sc->sc_dev,
|
||||
if_printf(mac->mac_sc->sc_ifp,
|
||||
"%s is not implemented yet\n", __func__);
|
||||
}
|
||||
|
||||
|
@ -1260,6 +1260,7 @@ static void
|
||||
bwi_rf_lo_update_11g(struct bwi_mac *mac)
|
||||
{
|
||||
struct bwi_softc *sc = mac->mac_sc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct bwi_rf *rf = &mac->mac_rf;
|
||||
struct bwi_phy *phy = &mac->mac_phy;
|
||||
struct bwi_tpctl *tpctl = &mac->mac_tpctl;
|
||||
@ -1328,7 +1329,7 @@ bwi_rf_lo_update_11g(struct bwi_mac *mac)
|
||||
PHY_WRITE(mac, 0x812, 0xb2);
|
||||
}
|
||||
|
||||
if ((sc->sc_flags & BWI_F_RUNNING) == 0)
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac);
|
||||
PHY_WRITE(mac, 0x80f, 0x8078);
|
||||
|
||||
@ -1351,7 +1352,7 @@ bwi_rf_lo_update_11g(struct bwi_mac *mac)
|
||||
PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0);
|
||||
}
|
||||
|
||||
if ((sc->sc_flags & BWI_F_RUNNING) == 0)
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
tpctl = NULL;
|
||||
bwi_rf_lo_adjust(mac, tpctl);
|
||||
|
||||
@ -1461,7 +1462,7 @@ _bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
|
||||
static const int rf_lo_measure_order[RF_ATTEN_LISTSZ] =
|
||||
{ 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 10, 11, 12, 13 };
|
||||
|
||||
struct bwi_softc *sc = mac->mac_sc;
|
||||
struct ifnet *ifp = mac->mac_sc->sc_ifp;
|
||||
struct bwi_rf_lo lo_save, *lo;
|
||||
uint8_t devi_ctrl = 0;
|
||||
int idx, adj_rf7a = 0;
|
||||
@ -1475,7 +1476,7 @@ _bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
|
||||
for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) {
|
||||
uint16_t tp_ctrl2, rf7a;
|
||||
|
||||
if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
if (idx == 0) {
|
||||
bzero(&lo_save, sizeof(lo_save));
|
||||
} else if (init_rf_atten < 0) {
|
||||
|
@ -102,10 +102,10 @@ static struct ieee80211vap *bwi_vap_create(struct ieee80211com *,
|
||||
const uint8_t [IEEE80211_ADDR_LEN],
|
||||
const uint8_t [IEEE80211_ADDR_LEN]);
|
||||
static void bwi_vap_delete(struct ieee80211vap *);
|
||||
static void bwi_init(struct bwi_softc *);
|
||||
static void bwi_parent(struct ieee80211com *);
|
||||
static int bwi_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void bwi_start_locked(struct bwi_softc *);
|
||||
static void bwi_init(void *);
|
||||
static int bwi_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void bwi_start(struct ifnet *);
|
||||
static void bwi_start_locked(struct ifnet *);
|
||||
static int bwi_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static void bwi_watchdog(void *);
|
||||
@ -352,12 +352,14 @@ bwi_setup_desc32(struct bwi_softc *sc, struct bwi_desc32 *desc_array,
|
||||
int
|
||||
bwi_attach(struct bwi_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic;
|
||||
device_t dev = sc->sc_dev;
|
||||
struct ifnet *ifp;
|
||||
struct bwi_mac *mac;
|
||||
struct bwi_phy *phy;
|
||||
int i, error;
|
||||
uint8_t bands;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
BWI_LOCK_INIT(sc);
|
||||
|
||||
@ -369,8 +371,8 @@ bwi_attach(struct bwi_softc *sc)
|
||||
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
|
||||
device_get_nameunit(dev));
|
||||
TASK_INIT(&sc->sc_restart_task, 0, bwi_restart, sc);
|
||||
|
||||
callout_init_mtx(&sc->sc_calib_ch, &sc->sc_mtx, 0);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
/*
|
||||
* Initialize sysctl variables
|
||||
@ -448,6 +450,25 @@ bwi_attach(struct bwi_softc *sc)
|
||||
if (error)
|
||||
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);
|
||||
|
||||
/*
|
||||
@ -464,13 +485,13 @@ bwi_attach(struct bwi_softc *sc)
|
||||
setbit(&bands, IEEE80211_MODE_11G);
|
||||
}
|
||||
|
||||
bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_macaddr);
|
||||
if (IEEE80211_IS_MULTICAST(ic->ic_macaddr)) {
|
||||
bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_macaddr);
|
||||
if (IEEE80211_IS_MULTICAST(ic->ic_macaddr)) {
|
||||
bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, macaddr);
|
||||
if (IEEE80211_IS_MULTICAST(macaddr)) {
|
||||
bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, macaddr);
|
||||
if (IEEE80211_IS_MULTICAST(macaddr)) {
|
||||
device_printf(dev,
|
||||
"invalid MAC address: %6D\n",
|
||||
ic->ic_macaddr, ":");
|
||||
macaddr, ":");
|
||||
}
|
||||
}
|
||||
} else if (phy->phy_mode == IEEE80211_MODE_11A) {
|
||||
@ -489,6 +510,7 @@ bwi_attach(struct bwi_softc *sc)
|
||||
/* XXX use locale */
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ic->ic_ifp = ifp;
|
||||
ic->ic_softc = sc;
|
||||
ic->ic_name = device_get_nameunit(dev);
|
||||
ic->ic_caps = IEEE80211_C_STA |
|
||||
@ -498,7 +520,7 @@ bwi_attach(struct bwi_softc *sc)
|
||||
IEEE80211_C_BGSCAN |
|
||||
IEEE80211_C_MONITOR;
|
||||
ic->ic_opmode = IEEE80211_M_STA;
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, macaddr);
|
||||
|
||||
ic->ic_headroom = sizeof(struct bwi_txbuf_hdr);
|
||||
|
||||
@ -510,8 +532,6 @@ bwi_attach(struct bwi_softc *sc)
|
||||
ic->ic_scan_start = bwi_scan_start;
|
||||
ic->ic_scan_end = bwi_scan_end;
|
||||
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);
|
||||
|
||||
@ -557,7 +577,8 @@ fail:
|
||||
int
|
||||
bwi_detach(struct bwi_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
int i;
|
||||
|
||||
bwi_stop(sc, 1);
|
||||
@ -569,8 +590,8 @@ bwi_detach(struct bwi_softc *sc)
|
||||
for (i = 0; i < sc->sc_nmac; ++i)
|
||||
bwi_mac_detach(&sc->sc_mac[i]);
|
||||
bwi_dma_free(sc);
|
||||
if_free(ifp);
|
||||
taskqueue_free(sc->sc_tq);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
|
||||
BWI_LOCK_DESTROY(sc);
|
||||
|
||||
@ -588,11 +609,14 @@ bwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
|
||||
return NULL;
|
||||
bvp = malloc(sizeof(struct bwi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
bvp = (struct bwi_vap *) malloc(sizeof(struct bwi_vap),
|
||||
M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
if (bvp == NULL)
|
||||
return NULL;
|
||||
vap = &bvp->bv_vap;
|
||||
/* enable s/w bmiss handling for sta mode */
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode,
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid);
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
|
||||
|
||||
/* override default methods */
|
||||
bvp->bv_newstate = vap->iv_newstate;
|
||||
@ -603,8 +627,7 @@ bwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
ieee80211_ratectl_init(vap);
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status,
|
||||
mac);
|
||||
ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
}
|
||||
@ -628,8 +651,9 @@ bwi_suspend(struct bwi_softc *sc)
|
||||
void
|
||||
bwi_resume(struct bwi_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (sc->sc_ic.ic_nrunning > 0)
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
bwi_init(sc);
|
||||
}
|
||||
|
||||
@ -1193,26 +1217,27 @@ bwi_set_clock_delay(struct bwi_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
bwi_init(struct bwi_softc *sc)
|
||||
bwi_init(void *xsc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct bwi_softc *sc = xsc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
BWI_LOCK(sc);
|
||||
bwi_init_statechg(sc, 1);
|
||||
BWI_UNLOCK(sc);
|
||||
|
||||
if (sc->sc_flags & BWI_F_RUNNING)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic); /* start all vap's */
|
||||
}
|
||||
|
||||
static void
|
||||
bwi_init_statechg(struct bwi_softc *sc, int statechg)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct bwi_mac *mac;
|
||||
int error;
|
||||
|
||||
BWI_ASSERT_LOCKED(sc);
|
||||
|
||||
bwi_stop_locked(sc, statechg);
|
||||
|
||||
bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
|
||||
@ -1222,21 +1247,20 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
|
||||
mac = &sc->sc_mac[0];
|
||||
error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL);
|
||||
if (error) {
|
||||
device_printf(sc->sc_dev, "%s: error %d on regwin switch\n",
|
||||
if_printf(ifp, "%s: error %d on regwin switch\n",
|
||||
__func__, error);
|
||||
goto bad;
|
||||
}
|
||||
error = bwi_mac_init(mac);
|
||||
if (error) {
|
||||
device_printf(sc->sc_dev, "%s: error %d on MAC init\n",
|
||||
__func__, error);
|
||||
if_printf(ifp, "%s: error %d on MAC init\n", __func__, error);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN);
|
||||
|
||||
bwi_set_bssid(sc, bwi_zero_addr); /* Clear BSSID */
|
||||
bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, sc->sc_ic.ic_macaddr);
|
||||
bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, IF_LLADDR(ifp));
|
||||
|
||||
bwi_mac_reset_hwkeys(mac);
|
||||
|
||||
@ -1254,8 +1278,7 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
|
||||
CSR_READ_4(sc, BWI_TXSTATUS1);
|
||||
}
|
||||
if (i == NRETRY)
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: can't drain TX status\n", __func__);
|
||||
if_printf(ifp, "%s: can't drain TX status\n", __func__);
|
||||
#undef NRETRY
|
||||
}
|
||||
|
||||
@ -1265,14 +1288,14 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
|
||||
/* Start MAC */
|
||||
error = bwi_mac_start(mac);
|
||||
if (error) {
|
||||
device_printf(sc->sc_dev, "%s: error %d starting MAC\n",
|
||||
__func__, error);
|
||||
if_printf(ifp, "%s: error %d starting MAC\n", __func__, error);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Clear stop flag before enabling interrupt */
|
||||
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);
|
||||
|
||||
/* Enable intrs */
|
||||
@ -1282,110 +1305,135 @@ bad:
|
||||
bwi_stop_locked(sc, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
bwi_parent(struct ieee80211com *ic)
|
||||
{
|
||||
struct bwi_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
|
||||
BWI_LOCK(sc);
|
||||
if (ic->ic_nrunning > 0) {
|
||||
struct bwi_mac *mac;
|
||||
int promisc = -1;
|
||||
|
||||
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
|
||||
("current regwin type %d",
|
||||
sc->sc_cur_regwin->rw_type));
|
||||
mac = (struct bwi_mac *)sc->sc_cur_regwin;
|
||||
|
||||
if (ic->ic_promisc > 0 && (sc->sc_flags & BWI_F_PROMISC) == 0) {
|
||||
promisc = 1;
|
||||
sc->sc_flags |= BWI_F_PROMISC;
|
||||
} else if (ic->ic_promisc == 0 &&
|
||||
(sc->sc_flags & BWI_F_PROMISC) != 0) {
|
||||
promisc = 0;
|
||||
sc->sc_flags &= ~BWI_F_PROMISC;
|
||||
}
|
||||
|
||||
if (promisc >= 0)
|
||||
bwi_mac_set_promisc(mac, promisc);
|
||||
}
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
|
||||
bwi_init_statechg(sc, 1);
|
||||
startall = 1;
|
||||
}
|
||||
} else if (sc->sc_flags & BWI_F_RUNNING)
|
||||
bwi_stop_locked(sc, 1);
|
||||
BWI_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
}
|
||||
|
||||
static int
|
||||
bwi_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct bwi_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
#define IS_RUNNING(ifp) \
|
||||
((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
|
||||
struct bwi_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error = 0, startall = 0;
|
||||
|
||||
BWI_LOCK(sc);
|
||||
if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
BWI_LOCK(sc);
|
||||
if (IS_RUNNING(ifp)) {
|
||||
struct bwi_mac *mac;
|
||||
int promisc = -1;
|
||||
|
||||
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
|
||||
("current regwin type %d",
|
||||
sc->sc_cur_regwin->rw_type));
|
||||
mac = (struct bwi_mac *)sc->sc_cur_regwin;
|
||||
|
||||
if ((ifp->if_flags & IFF_PROMISC) &&
|
||||
(sc->sc_flags & BWI_F_PROMISC) == 0) {
|
||||
promisc = 1;
|
||||
sc->sc_flags |= BWI_F_PROMISC;
|
||||
} else if ((ifp->if_flags & IFF_PROMISC) == 0 &&
|
||||
(sc->sc_flags & BWI_F_PROMISC)) {
|
||||
promisc = 0;
|
||||
sc->sc_flags &= ~BWI_F_PROMISC;
|
||||
}
|
||||
|
||||
if (promisc >= 0)
|
||||
bwi_mac_set_promisc(mac, promisc);
|
||||
}
|
||||
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
bwi_init_statechg(sc, 1);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
bwi_stop_locked(sc, 1);
|
||||
}
|
||||
BWI_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
||||
break;
|
||||
case SIOCGIFADDR:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
BWI_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
bwi_start_locked(sc);
|
||||
BWI_UNLOCK(sc);
|
||||
return (0);
|
||||
return error;
|
||||
#undef IS_RUNNING
|
||||
}
|
||||
|
||||
static void
|
||||
bwi_start_locked(struct bwi_softc *sc)
|
||||
bwi_start(struct ifnet *ifp)
|
||||
{
|
||||
struct bwi_softc *sc = ifp->if_softc;
|
||||
|
||||
BWI_LOCK(sc);
|
||||
bwi_start_locked(ifp);
|
||||
BWI_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
bwi_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct bwi_softc *sc = ifp->if_softc;
|
||||
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_node *ni;
|
||||
struct ieee80211_key *k;
|
||||
struct mbuf *m;
|
||||
int trans, idx;
|
||||
|
||||
BWI_ASSERT_LOCKED(sc);
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
trans = 0;
|
||||
idx = tbd->tbd_idx;
|
||||
|
||||
while (tbd->tbd_buf[idx].tb_mbuf == NULL &&
|
||||
tbd->tbd_used + BWI_TX_NSPRDESC < BWI_TX_NDESC &&
|
||||
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
while (tbd->tbd_buf[idx].tb_mbuf == NULL) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m); /* XXX: LOCK */
|
||||
if (m == NULL)
|
||||
break;
|
||||
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
wh = mtod(m, struct ieee80211_frame *);
|
||||
if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 &&
|
||||
ieee80211_crypto_encap(ni, m) == NULL) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
m_freem(m);
|
||||
continue;
|
||||
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
|
||||
k = ieee80211_crypto_encap(ni, m);
|
||||
if (k == NULL) {
|
||||
ieee80211_free_node(ni);
|
||||
m_freem(m);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
wh = NULL; /* Catch any invalid use */
|
||||
|
||||
if (bwi_encap(sc, idx, m, ni) != 0) {
|
||||
/* 'm' is freed in bwi_encap() if we reach here */
|
||||
if (ni != NULL) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if (ni != NULL)
|
||||
ieee80211_free_node(ni);
|
||||
} else
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
trans = 1;
|
||||
tbd->tbd_used++;
|
||||
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;
|
||||
|
||||
if (trans)
|
||||
sc->sc_tx_timer = 5;
|
||||
}
|
||||
@ -1395,12 +1443,13 @@ bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct bwi_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct bwi_softc *sc = ifp->if_softc;
|
||||
/* XXX wme? */
|
||||
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
|
||||
int idx, error;
|
||||
|
||||
if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
ieee80211_free_node(ni);
|
||||
m_freem(m);
|
||||
return ENETDOWN;
|
||||
@ -1423,12 +1472,16 @@ bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
error = bwi_encap_raw(sc, idx, m, ni, params);
|
||||
}
|
||||
if (error == 0) {
|
||||
tbd->tbd_used++;
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
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;
|
||||
sc->sc_tx_timer = 5;
|
||||
} else
|
||||
} else {
|
||||
/* NB: m is reclaimed on encap failure */
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
BWI_UNLOCK(sc);
|
||||
return error;
|
||||
}
|
||||
@ -1437,12 +1490,14 @@ static void
|
||||
bwi_watchdog(void *arg)
|
||||
{
|
||||
struct bwi_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
|
||||
sc = arg;
|
||||
ifp = sc->sc_ifp;
|
||||
BWI_ASSERT_LOCKED(sc);
|
||||
if (sc->sc_tx_timer != 0 && --sc->sc_tx_timer == 0) {
|
||||
device_printf(sc->sc_dev, "watchdog timeout\n");
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_printf(ifp, "watchdog timeout\n");
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task);
|
||||
}
|
||||
callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc);
|
||||
@ -1459,6 +1514,7 @@ bwi_stop(struct bwi_softc *sc, int statechg)
|
||||
static void
|
||||
bwi_stop_locked(struct bwi_softc *sc, int statechg)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct bwi_mac *mac;
|
||||
int i, error, pwr_off = 0;
|
||||
|
||||
@ -1469,7 +1525,7 @@ bwi_stop_locked(struct bwi_softc *sc, int statechg)
|
||||
sc->sc_led_blinking = 0;
|
||||
sc->sc_flags |= BWI_F_STOP;
|
||||
|
||||
if (sc->sc_flags & BWI_F_RUNNING) {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
|
||||
("current regwin type %d", sc->sc_cur_regwin->rw_type));
|
||||
mac = (struct bwi_mac *)sc->sc_cur_regwin;
|
||||
@ -1501,13 +1557,14 @@ bwi_stop_locked(struct bwi_softc *sc, int statechg)
|
||||
|
||||
sc->sc_tx_timer = 0;
|
||||
callout_stop(&sc->sc_watchdog_timer);
|
||||
sc->sc_flags &= ~BWI_F_RUNNING;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
}
|
||||
|
||||
void
|
||||
bwi_intr(void *xsc)
|
||||
{
|
||||
struct bwi_softc *sc = xsc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct bwi_mac *mac;
|
||||
uint32_t intr_status;
|
||||
uint32_t txrx_intr_status[BWI_TXRX_NRING];
|
||||
@ -1515,7 +1572,7 @@ bwi_intr(void *xsc)
|
||||
|
||||
BWI_LOCK(sc);
|
||||
|
||||
if ((sc->sc_flags & BWI_F_RUNNING) == 0 ||
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
|
||||
(sc->sc_flags & BWI_F_STOP)) {
|
||||
BWI_UNLOCK(sc);
|
||||
return;
|
||||
@ -1558,7 +1615,7 @@ bwi_intr(void *xsc)
|
||||
i, txrx_intr_status[i]);
|
||||
|
||||
if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) {
|
||||
device_printf(sc->sc_dev,
|
||||
if_printf(ifp,
|
||||
"%s: intr fatal TX/RX (%d) error 0x%08x\n",
|
||||
__func__, i, txrx_intr_status[i]);
|
||||
txrx_error = 1;
|
||||
@ -1596,8 +1653,7 @@ bwi_intr(void *xsc)
|
||||
*/
|
||||
if (intr_status & BWI_INTR_PHY_TXERR) {
|
||||
if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) {
|
||||
device_printf(sc->sc_dev, "%s: intr PHY TX error\n",
|
||||
__func__);
|
||||
if_printf(ifp, "%s: intr PHY TX error\n", __func__);
|
||||
taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task);
|
||||
BWI_UNLOCK(sc);
|
||||
return;
|
||||
@ -1612,7 +1668,7 @@ bwi_intr(void *xsc)
|
||||
bwi_mac_config_ps(mac);
|
||||
|
||||
if (intr_status & BWI_INTR_EO_ATIM)
|
||||
device_printf(sc->sc_dev, "EO_ATIM\n");
|
||||
if_printf(ifp, "EO_ATIM\n");
|
||||
|
||||
if (intr_status & BWI_INTR_PMQ) {
|
||||
for (;;) {
|
||||
@ -1623,7 +1679,7 @@ bwi_intr(void *xsc)
|
||||
}
|
||||
|
||||
if (intr_status & BWI_INTR_NOISE)
|
||||
device_printf(sc->sc_dev, "intr noise\n");
|
||||
if_printf(ifp, "intr noise\n");
|
||||
|
||||
if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) {
|
||||
rx_data = sc->sc_rxeof(sc);
|
||||
@ -1672,7 +1728,7 @@ bwi_intr(void *xsc)
|
||||
static void
|
||||
bwi_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct bwi_softc *sc = ic->ic_softc;
|
||||
struct bwi_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
BWI_LOCK(sc);
|
||||
/* Enable MAC beacon promiscuity */
|
||||
@ -1683,7 +1739,7 @@ bwi_scan_start(struct ieee80211com *ic)
|
||||
static void
|
||||
bwi_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct bwi_softc *sc = ic->ic_softc;
|
||||
struct bwi_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ieee80211_channel *c = ic->ic_curchan;
|
||||
struct bwi_mac *mac;
|
||||
|
||||
@ -1709,7 +1765,7 @@ bwi_set_channel(struct ieee80211com *ic)
|
||||
static void
|
||||
bwi_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct bwi_softc *sc = ic->ic_softc;
|
||||
struct bwi_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
BWI_LOCK(sc);
|
||||
CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN);
|
||||
@ -1721,8 +1777,9 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct bwi_vap *bvp = BWI_VAP(vap);
|
||||
struct ieee80211com *ic= vap->iv_ic;
|
||||
struct bwi_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
enum ieee80211_state ostate = vap->iv_state;
|
||||
struct bwi_softc *sc = ifp->if_softc;
|
||||
struct bwi_mac *mac;
|
||||
int error;
|
||||
|
||||
@ -2568,7 +2625,8 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
|
||||
{
|
||||
struct bwi_ring_data *rd = &sc->sc_rx_rdata;
|
||||
struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
int idx, rx_data = 0;
|
||||
|
||||
idx = rbd->rbd_idx;
|
||||
@ -2587,7 +2645,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
|
||||
BUS_DMASYNC_POSTREAD);
|
||||
|
||||
if (bwi_newbuf(sc, idx, 0)) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto next;
|
||||
}
|
||||
|
||||
@ -2601,10 +2659,9 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
|
||||
|
||||
buflen = le16toh(hdr->rxh_buflen);
|
||||
if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: zero length data, hdr_extra %d\n",
|
||||
__func__, hdr_extra);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_printf(ifp, "%s: zero length data, hdr_extra %d\n",
|
||||
__func__, hdr_extra);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
m_freem(m);
|
||||
goto next;
|
||||
}
|
||||
@ -2613,6 +2670,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
|
||||
rssi = bwi_calc_rssi(sc, hdr);
|
||||
noise = bwi_calc_noise(sc);
|
||||
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr);
|
||||
m_adj(m, sizeof(*hdr) + wh_ofs);
|
||||
|
||||
@ -2746,6 +2804,7 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
|
||||
{
|
||||
struct bwi_ring_data *rd;
|
||||
struct bwi_txbuf_data *tbd;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t state, val;
|
||||
int i;
|
||||
|
||||
@ -2766,9 +2825,8 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
|
||||
DELAY(1000);
|
||||
}
|
||||
if (i == NRETRY) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: wait for TX ring(%d) stable timed out\n",
|
||||
__func__, ring_idx);
|
||||
if_printf(ifp, "%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);
|
||||
@ -2781,7 +2839,7 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
|
||||
DELAY(1000);
|
||||
}
|
||||
if (i == NRETRY)
|
||||
device_printf(sc->sc_dev, "%s: reset TX ring (%d) timed out\n",
|
||||
if_printf(ifp, "%s: reset TX ring (%d) timed out\n",
|
||||
__func__, ring_idx);
|
||||
|
||||
#undef NRETRY
|
||||
@ -2889,7 +2947,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
|
||||
struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
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 *tb = &tbd->tbd_buf[idx];
|
||||
@ -2965,8 +3024,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
|
||||
*/
|
||||
M_PREPEND(m, sizeof(*hdr), M_NOWAIT);
|
||||
if (m == NULL) {
|
||||
device_printf(sc->sc_dev, "%s: prepend TX header failed\n",
|
||||
__func__);
|
||||
if_printf(ifp, "%s: prepend TX header failed\n", __func__);
|
||||
return ENOBUFS;
|
||||
}
|
||||
hdr = mtod(m, struct bwi_txbuf_hdr *);
|
||||
@ -3015,7 +3073,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
|
||||
error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, tb->tb_dmap, m,
|
||||
bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
|
||||
if (error && error != EFBIG) {
|
||||
device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
|
||||
if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
|
||||
__func__, error);
|
||||
goto back;
|
||||
}
|
||||
@ -3025,8 +3083,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
|
||||
|
||||
m_new = m_defrag(m, M_NOWAIT);
|
||||
if (m_new == NULL) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: can't defrag TX buffer\n", __func__);
|
||||
if_printf(ifp, "%s: can't defrag TX buffer\n",
|
||||
__func__);
|
||||
error = ENOBUFS;
|
||||
goto back;
|
||||
} else {
|
||||
@ -3037,8 +3095,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
|
||||
bwi_dma_buf_addr, &paddr,
|
||||
BUS_DMA_NOWAIT);
|
||||
if (error) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: can't load TX buffer (2) %d\n",
|
||||
if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
|
||||
__func__, error);
|
||||
goto back;
|
||||
}
|
||||
@ -3080,6 +3137,7 @@ static int
|
||||
bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
|
||||
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING];
|
||||
@ -3146,8 +3204,7 @@ bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
|
||||
*/
|
||||
M_PREPEND(m, sizeof(*hdr), M_NOWAIT);
|
||||
if (m == NULL) {
|
||||
device_printf(sc->sc_dev, "%s: prepend TX header failed\n",
|
||||
__func__);
|
||||
if_printf(ifp, "%s: prepend TX header failed\n", __func__);
|
||||
return ENOBUFS;
|
||||
}
|
||||
hdr = mtod(m, struct bwi_txbuf_hdr *);
|
||||
@ -3195,15 +3252,14 @@ bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
|
||||
struct mbuf *m_new;
|
||||
|
||||
if (error != EFBIG) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: can't load TX buffer (1) %d\n",
|
||||
if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
|
||||
__func__, error);
|
||||
goto back;
|
||||
}
|
||||
m_new = m_defrag(m, M_NOWAIT);
|
||||
if (m_new == NULL) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: can't defrag TX buffer\n", __func__);
|
||||
if_printf(ifp, "%s: can't defrag TX buffer\n",
|
||||
__func__);
|
||||
error = ENOBUFS;
|
||||
goto back;
|
||||
}
|
||||
@ -3212,8 +3268,7 @@ bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
|
||||
bwi_dma_buf_addr, &paddr,
|
||||
BUS_DMA_NOWAIT);
|
||||
if (error) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: can't load TX buffer (2) %d\n",
|
||||
if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
|
||||
__func__, error);
|
||||
goto back;
|
||||
}
|
||||
@ -3257,6 +3312,7 @@ bwi_start_tx64(struct bwi_softc *sc, uint32_t tx_ctrl, int idx)
|
||||
static void
|
||||
bwi_txeof_status32(struct bwi_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t val, ctrl_base;
|
||||
int end_idx;
|
||||
|
||||
@ -3271,7 +3327,8 @@ bwi_txeof_status32(struct bwi_softc *sc)
|
||||
CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,
|
||||
end_idx * sizeof(struct bwi_desc32));
|
||||
|
||||
bwi_start_locked(sc);
|
||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
|
||||
ifp->if_start(ifp);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3283,6 +3340,7 @@ bwi_txeof_status64(struct bwi_softc *sc)
|
||||
static void
|
||||
_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 *tb;
|
||||
int ring_idx, buf_idx;
|
||||
@ -3290,7 +3348,7 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
if (tx_id == 0) {
|
||||
device_printf(sc->sc_dev, "%s: zero tx id\n", __func__);
|
||||
if_printf(ifp, "%s: zero tx id\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3311,7 +3369,8 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
|
||||
|
||||
bus_dmamap_unload(sc->sc_buf_dtag, tb->tb_dmap);
|
||||
|
||||
if ((ni = tb->tb_ni) != NULL) {
|
||||
ni = tb->tb_ni;
|
||||
if (tb->tb_ni != NULL) {
|
||||
const struct bwi_txbuf_hdr *hdr =
|
||||
mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *);
|
||||
vap = ni->ni_vap;
|
||||
@ -3329,14 +3388,24 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
|
||||
(data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS :
|
||||
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;
|
||||
} else
|
||||
m_freem(tb->tb_mbuf);
|
||||
}
|
||||
m_freem(tb->tb_mbuf);
|
||||
tb->tb_mbuf = NULL;
|
||||
|
||||
if (tbd->tbd_used == 0)
|
||||
sc->sc_tx_timer = 0;
|
||||
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3368,6 +3437,7 @@ bwi_txeof_status(struct bwi_softc *sc, int end_idx)
|
||||
static void
|
||||
bwi_txeof(struct bwi_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
for (;;) {
|
||||
uint32_t tx_status0, tx_status1;
|
||||
@ -3390,7 +3460,8 @@ bwi_txeof(struct bwi_softc *sc)
|
||||
data_txcnt);
|
||||
}
|
||||
|
||||
bwi_start_locked(sc);
|
||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
|
||||
ifp->if_start(ifp);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -3638,6 +3709,7 @@ bwi_regwin_enable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags)
|
||||
static void
|
||||
bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct bwi_mac *mac;
|
||||
struct bwi_myaddr_bssid buf;
|
||||
const uint8_t *p;
|
||||
@ -3650,7 +3722,7 @@ bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid)
|
||||
|
||||
bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid);
|
||||
|
||||
bcopy(sc->sc_ic.ic_macaddr, buf.myaddr, sizeof(buf.myaddr));
|
||||
bcopy(IF_LLADDR(ifp), buf.myaddr, sizeof(buf.myaddr));
|
||||
bcopy(bssid, buf.bssid, sizeof(buf.bssid));
|
||||
|
||||
n = sizeof(buf) / sizeof(val);
|
||||
@ -3673,7 +3745,7 @@ bwi_updateslot(struct ieee80211com *ic)
|
||||
struct bwi_mac *mac;
|
||||
|
||||
BWI_LOCK(sc);
|
||||
if (sc->sc_flags & BWI_F_RUNNING) {
|
||||
if (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__);
|
||||
|
||||
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
|
||||
@ -3689,12 +3761,16 @@ static void
|
||||
bwi_calibrate(void *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;
|
||||
|
||||
BWI_ASSERT_LOCKED(sc);
|
||||
|
||||
KASSERT(sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR,
|
||||
("opmode %d", sc->sc_ic.ic_opmode));
|
||||
KASSERT(ic->ic_opmode != IEEE80211_M_MONITOR,
|
||||
("opmode %d", ic->ic_opmode));
|
||||
|
||||
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
|
||||
("current regwin type %d", sc->sc_cur_regwin->rw_type));
|
||||
@ -3836,7 +3912,8 @@ bwi_led_onoff(const struct bwi_led *led, uint16_t val, int on)
|
||||
static void
|
||||
bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint16_t val;
|
||||
int i;
|
||||
|
||||
@ -3845,7 +3922,7 @@ bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
|
||||
sc->sc_led_blinking = 0;
|
||||
}
|
||||
|
||||
if ((sc->sc_flags & BWI_F_RUNNING) == 0)
|
||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
|
||||
@ -3973,12 +4050,13 @@ static void
|
||||
bwi_restart(void *xsc, int pending)
|
||||
{
|
||||
struct bwi_softc *sc = xsc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
device_printf(sc->sc_dev, "%s begin, help!\n", __func__);
|
||||
if_printf(ifp, "%s begin, help!\n", __func__);
|
||||
BWI_LOCK(sc);
|
||||
bwi_init_statechg(sc, 0);
|
||||
bwi_init_statechg(xsc, 0);
|
||||
#if 0
|
||||
bwi_start_locked(sc);
|
||||
bwi_start_locked(ifp);
|
||||
#endif
|
||||
BWI_UNLOCK(sc);
|
||||
}
|
||||
|
@ -541,11 +541,10 @@ struct bwi_vap {
|
||||
#define BWI_VAP(vap) ((struct bwi_vap *)(vap))
|
||||
|
||||
struct bwi_softc {
|
||||
struct ifnet *sc_ifp;
|
||||
uint32_t sc_flags; /* BWI_F_ */
|
||||
device_t sc_dev;
|
||||
struct mtx sc_mtx;
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
int sc_invalid;
|
||||
|
||||
uint32_t sc_cap; /* BWI_CAP_ */
|
||||
@ -648,7 +647,6 @@ struct bwi_softc {
|
||||
#define BWI_F_BUS_INITED 0x1
|
||||
#define BWI_F_PROMISC 0x2
|
||||
#define BWI_F_STOP 0x4
|
||||
#define BWI_F_RUNNING 0x8
|
||||
|
||||
#define BWI_DBG_MAC 0x00000001
|
||||
#define BWI_DBG_RF 0x00000002
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -656,6 +656,7 @@ struct bwn_pio_txqueue {
|
||||
uint16_t tq_size;
|
||||
uint16_t tq_used;
|
||||
uint16_t tq_free;
|
||||
uint8_t tq_stop;
|
||||
uint8_t tq_index;
|
||||
struct bwn_pio_txpkt tq_pkts[BWN_PIO_MAX_TXPACKETS];
|
||||
TAILQ_HEAD(, bwn_pio_txpkt) tq_pktlist;
|
||||
@ -896,18 +897,17 @@ struct bwn_vap {
|
||||
struct bwn_softc {
|
||||
device_t sc_dev;
|
||||
struct mtx sc_mtx;
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
unsigned sc_flags;
|
||||
#define BWN_FLAG_ATTACHED (1 << 0)
|
||||
#define BWN_FLAG_INVALID (1 << 1)
|
||||
#define BWN_FLAG_NEED_BEACON_TP (1 << 2)
|
||||
#define BWN_FLAG_RUNNING (1 << 3)
|
||||
unsigned sc_debug;
|
||||
|
||||
struct bwn_mac *sc_curmac;
|
||||
TAILQ_HEAD(, bwn_mac) sc_maclist;
|
||||
|
||||
uint8_t sc_macaddr[IEEE80211_ADDR_LEN];
|
||||
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
|
||||
unsigned int sc_filters;
|
||||
uint8_t sc_beacons[2];
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -152,22 +152,8 @@ struct ndisusb_task {
|
||||
};
|
||||
|
||||
struct ndis_softc {
|
||||
u_int ndis_80211:1,
|
||||
ndis_link:1,
|
||||
ndis_running:1;
|
||||
union {
|
||||
struct { /* Ethernet */
|
||||
struct ifnet *ifp;
|
||||
struct ifmedia ifmedia;
|
||||
int ndis_if_flags;
|
||||
};
|
||||
struct { /* Wireless */
|
||||
struct ieee80211com ndis_ic;
|
||||
struct callout ndis_scan_callout;
|
||||
int (*ndis_newstate)(struct ieee80211com *,
|
||||
enum ieee80211_state, int);
|
||||
};
|
||||
};
|
||||
struct ifnet *ifp;
|
||||
struct ifmedia ifmedia; /* media info */
|
||||
u_long ndis_hwassist;
|
||||
uint32_t ndis_v4tx;
|
||||
uint32_t ndis_v4rx;
|
||||
@ -194,6 +180,7 @@ struct ndis_softc {
|
||||
ndis_miniport_block *ndis_block;
|
||||
ndis_miniport_characteristics *ndis_chars;
|
||||
interface_type ndis_type;
|
||||
struct callout ndis_scan_callout;
|
||||
struct callout ndis_stat_callout;
|
||||
int ndis_maxpkts;
|
||||
ndis_oid *ndis_oids;
|
||||
@ -205,9 +192,13 @@ struct ndis_softc {
|
||||
int ndis_sc;
|
||||
ndis_cfg *ndis_regvals;
|
||||
struct nch ndis_cfglist_head;
|
||||
int ndis_80211;
|
||||
int ndis_link;
|
||||
uint32_t ndis_sts;
|
||||
uint32_t ndis_filter;
|
||||
int ndis_if_flags;
|
||||
int ndis_skip;
|
||||
|
||||
int ndis_devidx;
|
||||
interface_type ndis_iftype;
|
||||
driver_object *ndis_dobj;
|
||||
@ -226,9 +217,11 @@ struct ndis_softc {
|
||||
struct ndis_evt ndis_evt[NDIS_EVENTS];
|
||||
int ndis_evtpidx;
|
||||
int ndis_evtcidx;
|
||||
struct mbufq ndis_rxqueue;
|
||||
struct ifqueue ndis_rxqueue;
|
||||
kspin_lock ndis_rxlock;
|
||||
|
||||
int (*ndis_newstate)(struct ieee80211com *,
|
||||
enum ieee80211_state, int);
|
||||
int ndis_tx_timer;
|
||||
int ndis_hang_timer;
|
||||
|
||||
|
@ -127,14 +127,14 @@ static void ipw_intr(void *);
|
||||
static void ipw_dma_map_addr(void *, bus_dma_segment_t *, int, int);
|
||||
static const char * ipw_cmdname(int);
|
||||
static int ipw_cmd(struct ipw_softc *, uint32_t, void *, uint32_t);
|
||||
static int ipw_tx_start(struct ipw_softc *, struct mbuf *,
|
||||
static int ipw_tx_start(struct ifnet *, struct mbuf *,
|
||||
struct ieee80211_node *);
|
||||
static int ipw_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static int ipw_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void ipw_start(struct ipw_softc *);
|
||||
static void ipw_start(struct ifnet *);
|
||||
static void ipw_start_locked(struct ifnet *);
|
||||
static void ipw_watchdog(void *);
|
||||
static void ipw_parent(struct ieee80211com *);
|
||||
static int ipw_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void ipw_stop_master(struct ipw_softc *);
|
||||
static int ipw_enable(struct ipw_softc *);
|
||||
static int ipw_disable(struct ipw_softc *);
|
||||
@ -220,16 +220,18 @@ static int
|
||||
ipw_attach(device_t dev)
|
||||
{
|
||||
struct ipw_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
struct ieee80211_channel *c;
|
||||
uint16_t val;
|
||||
int error, i;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
sc->sc_dev = dev;
|
||||
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
|
||||
MTX_DEF | MTX_RECURSE);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
TASK_INIT(&sc->sc_init_task, 0, ipw_init_task, sc);
|
||||
callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0);
|
||||
|
||||
@ -266,6 +268,24 @@ ipw_attach(device_t dev)
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(dev, "can not if_alloc()\n");
|
||||
goto fail3;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
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 = ipw_init;
|
||||
ifp->if_ioctl = ipw_ioctl;
|
||||
ifp->if_start = ipw_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_name = device_get_nameunit(dev);
|
||||
ic->ic_opmode = IEEE80211_M_STA;
|
||||
@ -283,14 +303,14 @@ ipw_attach(device_t dev)
|
||||
|
||||
/* read MAC address from EEPROM */
|
||||
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 0);
|
||||
ic->ic_macaddr[0] = val >> 8;
|
||||
ic->ic_macaddr[1] = val & 0xff;
|
||||
macaddr[0] = val >> 8;
|
||||
macaddr[1] = val & 0xff;
|
||||
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 1);
|
||||
ic->ic_macaddr[2] = val >> 8;
|
||||
ic->ic_macaddr[3] = val & 0xff;
|
||||
macaddr[2] = val >> 8;
|
||||
macaddr[3] = val & 0xff;
|
||||
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 2);
|
||||
ic->ic_macaddr[4] = val >> 8;
|
||||
ic->ic_macaddr[5] = val & 0xff;
|
||||
macaddr[4] = val >> 8;
|
||||
macaddr[5] = val & 0xff;
|
||||
|
||||
/* set supported .11b channels (read from EEPROM) */
|
||||
if ((val = ipw_read_prom_word(sc, IPW_EEPROM_CHANNEL_LIST)) == 0)
|
||||
@ -309,17 +329,16 @@ ipw_attach(device_t dev)
|
||||
if (!(ipw_read_prom_word(sc, IPW_EEPROM_RADIO) & 8))
|
||||
sc->flags |= IPW_FLAG_HAS_RADIO_SWITCH;
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, macaddr);
|
||||
ic->ic_scan_start = ipw_scan_start;
|
||||
ic->ic_scan_end = ipw_scan_end;
|
||||
ic->ic_set_channel = ipw_set_channel;
|
||||
ic->ic_scan_curchan = ipw_scan_curchan;
|
||||
ic->ic_scan_mindwell = ipw_scan_mindwell;
|
||||
ic->ic_raw_xmit = ipw_raw_xmit;
|
||||
|
||||
ic->ic_vap_create = ipw_vap_create;
|
||||
ic->ic_vap_delete = ipw_vap_delete;
|
||||
ic->ic_transmit = ipw_transmit;
|
||||
ic->ic_parent = ipw_parent;
|
||||
|
||||
ieee80211_radiotap_attach(ic,
|
||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
|
||||
@ -347,13 +366,15 @@ ipw_attach(device_t dev)
|
||||
NULL, ipw_intr, sc, &sc->sc_ih);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "could not set up interrupt\n");
|
||||
goto fail3;
|
||||
goto fail4;
|
||||
}
|
||||
|
||||
if (bootverbose)
|
||||
ieee80211_announce(ic);
|
||||
|
||||
return 0;
|
||||
fail4:
|
||||
if_free(ifp);
|
||||
fail3:
|
||||
ipw_release(sc);
|
||||
fail2:
|
||||
@ -370,7 +391,8 @@ static int
|
||||
ipw_detach(device_t dev)
|
||||
{
|
||||
struct ipw_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
bus_teardown_intr(dev, sc->irq, sc->sc_ih);
|
||||
|
||||
@ -380,7 +402,6 @@ ipw_detach(device_t dev)
|
||||
ieee80211_ifdetach(ic);
|
||||
|
||||
callout_drain(&sc->sc_wdtimer);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
|
||||
ipw_release(sc);
|
||||
|
||||
@ -389,6 +410,8 @@ ipw_detach(device_t dev)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem),
|
||||
sc->mem);
|
||||
|
||||
if_free(ifp);
|
||||
|
||||
if (sc->sc_firmware != NULL) {
|
||||
firmware_put(sc->sc_firmware, FIRMWARE_UNLOAD);
|
||||
sc->sc_firmware = NULL;
|
||||
@ -405,7 +428,8 @@ ipw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct ipw_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
struct ipw_vap *ivp;
|
||||
struct ieee80211vap *vap;
|
||||
const struct firmware *fp;
|
||||
@ -463,17 +487,19 @@ ipw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ivp = malloc(sizeof(struct ipw_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
ivp = (struct ipw_vap *) malloc(sizeof(struct ipw_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (ivp == NULL)
|
||||
return NULL;
|
||||
vap = &ivp->vap;
|
||||
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
|
||||
/* override with driver methods */
|
||||
ivp->newstate = vap->iv_newstate;
|
||||
vap->iv_newstate = ipw_newstate;
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, ipw_media_status,
|
||||
mac);
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, ipw_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
}
|
||||
@ -801,7 +827,7 @@ static int
|
||||
ipw_suspend(device_t dev)
|
||||
{
|
||||
struct ipw_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
|
||||
ieee80211_suspend_all(ic);
|
||||
return 0;
|
||||
@ -811,7 +837,7 @@ static int
|
||||
ipw_resume(device_t dev)
|
||||
{
|
||||
struct ipw_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
|
||||
pci_write_config(dev, 0x41, 0, 1);
|
||||
|
||||
@ -840,7 +866,7 @@ ipw_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
||||
{
|
||||
struct ieee80211vap *vap = ifp->if_softc;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ipw_softc *sc = ic->ic_softc;
|
||||
struct ipw_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
/* read current transmission rate from adapter */
|
||||
vap->iv_bss->ni_txrate = ipw_cvtrate(
|
||||
@ -853,7 +879,8 @@ ipw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct ipw_vap *ivp = IPW_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ipw_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
enum ieee80211_state ostate;
|
||||
|
||||
DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
|
||||
@ -988,7 +1015,8 @@ static void
|
||||
ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
|
||||
{
|
||||
#define IEEESTATE(vap) ieee80211_state_name[vap->iv_state]
|
||||
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);
|
||||
uint32_t state;
|
||||
|
||||
@ -1090,7 +1118,8 @@ ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
|
||||
static void
|
||||
ipw_setcurchan(struct ipw_softc *sc, struct ieee80211_channel *chan)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
ic->ic_curchan = chan;
|
||||
ieee80211_radiotap_chan_change(ic);
|
||||
@ -1103,7 +1132,8 @@ ipw_setcurchan(struct ipw_softc *sc, struct ieee80211_channel *chan)
|
||||
static void
|
||||
ipw_fix_channel(struct ipw_softc *sc, struct mbuf *m)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_channel *c;
|
||||
struct ieee80211_frame *wh;
|
||||
uint8_t subtype;
|
||||
@ -1148,7 +1178,8 @@ static void
|
||||
ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
|
||||
struct ipw_soft_bd *sbd, struct ipw_soft_buf *sbuf)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct mbuf *mnew, *m;
|
||||
struct ieee80211_node *ni;
|
||||
bus_addr_t physaddr;
|
||||
@ -1170,7 +1201,7 @@ ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
|
||||
*/
|
||||
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (mnew == NULL) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1191,7 +1222,7 @@ ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
|
||||
panic("%s: could not load old rx mbuf",
|
||||
device_get_name(sc->sc_dev));
|
||||
}
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1202,6 +1233,9 @@ ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
|
||||
m = sbuf->m;
|
||||
sbuf->m = mnew;
|
||||
sbd->bd->physaddr = htole32(physaddr);
|
||||
|
||||
/* finalize mbuf */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len = le32toh(status->len);
|
||||
|
||||
rssi = status->rssi + IPW_RSSI_TO_DBM;
|
||||
@ -1330,6 +1364,7 @@ ipw_release_sbd(struct ipw_softc *sc, struct ipw_soft_bd *sbd)
|
||||
static void
|
||||
ipw_tx_intr(struct ipw_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ipw_soft_bd *sbd;
|
||||
uint32_t r, i;
|
||||
|
||||
@ -1340,6 +1375,10 @@ ipw_tx_intr(struct ipw_softc *sc)
|
||||
|
||||
for (i = (sc->txold + 1) % IPW_NTBD; i != r; i = (i + 1) % IPW_NTBD) {
|
||||
sbd = &sc->stbd_list[i];
|
||||
|
||||
if (sbd->type == IPW_SBD_TYPE_DATA)
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
|
||||
ipw_release_sbd(sc, sbd);
|
||||
sc->txfree++;
|
||||
}
|
||||
@ -1347,13 +1386,15 @@ ipw_tx_intr(struct ipw_softc *sc)
|
||||
/* remember what the firmware has processed */
|
||||
sc->txold = (r == 0) ? IPW_NTBD - 1 : r - 1;
|
||||
|
||||
ipw_start(sc);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ipw_start_locked(ifp);
|
||||
}
|
||||
|
||||
static void
|
||||
ipw_fatal_error_intr(struct ipw_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);
|
||||
|
||||
device_printf(sc->sc_dev, "firmware error\n");
|
||||
@ -1538,9 +1579,10 @@ ipw_cmd(struct ipw_softc *sc, uint32_t type, void *data, uint32_t len)
|
||||
}
|
||||
|
||||
static int
|
||||
ipw_tx_start(struct ipw_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
ipw_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ipw_soft_bd *sbd;
|
||||
@ -1694,42 +1736,38 @@ ipw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ipw_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
static void
|
||||
ipw_start(struct ifnet *ifp)
|
||||
{
|
||||
struct ipw_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
|
||||
IPW_LOCK(sc);
|
||||
if ((sc->flags & IPW_FLAG_RUNNING) == 0) {
|
||||
IPW_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
IPW_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
ipw_start(sc);
|
||||
ipw_start_locked(ifp);
|
||||
IPW_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ipw_start(struct ipw_softc *sc)
|
||||
ipw_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
IPW_LOCK_ASSERT(sc);
|
||||
|
||||
while (sc->txfree < 1 + IPW_MAX_NSEG &&
|
||||
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
if (sc->txfree < 1 + IPW_MAX_NSEG) {
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
break;
|
||||
}
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
if (ipw_tx_start(sc, m, ni) != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if (ipw_tx_start(ifp, m, ni) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
break;
|
||||
}
|
||||
/* start watchdog timer */
|
||||
@ -1741,14 +1779,15 @@ static void
|
||||
ipw_watchdog(void *arg)
|
||||
{
|
||||
struct ipw_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
IPW_LOCK_ASSERT(sc);
|
||||
|
||||
if (sc->sc_tx_timer > 0) {
|
||||
if (--sc->sc_tx_timer == 0) {
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
counter_u64_add(ic->ic_oerrors, 1);
|
||||
if_printf(ifp, "device timeout\n");
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
taskqueue_enqueue(taskqueue_swi, &sc->sc_init_task);
|
||||
}
|
||||
}
|
||||
@ -1764,27 +1803,45 @@ ipw_watchdog(void *arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sc->flags & IPW_FLAG_RUNNING)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
callout_reset(&sc->sc_wdtimer, hz, ipw_watchdog, sc);
|
||||
}
|
||||
|
||||
static void
|
||||
ipw_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
ipw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct ipw_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error = 0, startall = 0;
|
||||
|
||||
IPW_LOCK(sc);
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (!(sc->flags & IPW_FLAG_RUNNING)) {
|
||||
ipw_init_locked(sc);
|
||||
startall = 1;
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
IPW_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
ipw_init_locked(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ipw_stop_locked(sc);
|
||||
}
|
||||
} else if (sc->flags & IPW_FLAG_RUNNING)
|
||||
ipw_stop_locked(sc);
|
||||
IPW_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
IPW_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2000,7 +2057,8 @@ ipw_load_firmware(struct ipw_softc *sc, const char *fw, int size)
|
||||
static int
|
||||
ipw_setwepkeys(struct ipw_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 ipw_wep_key wepkey;
|
||||
struct ieee80211_key *wk;
|
||||
@ -2143,7 +2201,8 @@ done:
|
||||
static int
|
||||
ipw_setchannel(struct ipw_softc *sc, struct ieee80211_channel *chan)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t data;
|
||||
int error;
|
||||
|
||||
@ -2158,7 +2217,8 @@ ipw_setchannel(struct ipw_softc *sc, struct ieee80211_channel *chan)
|
||||
static void
|
||||
ipw_assoc(struct ieee80211com *ic, struct ieee80211vap *vap)
|
||||
{
|
||||
struct ipw_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = vap->iv_ic->ic_ifp;
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni = vap->iv_bss;
|
||||
struct ipw_security security;
|
||||
uint32_t data;
|
||||
@ -2249,8 +2309,9 @@ done:
|
||||
static void
|
||||
ipw_disassoc(struct ieee80211com *ic, struct ieee80211vap *vap)
|
||||
{
|
||||
struct ifnet *ifp = vap->iv_ic->ic_ifp;
|
||||
struct ieee80211_node *ni = vap->iv_bss;
|
||||
struct ipw_softc *sc = ic->ic_softc;
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
|
||||
IPW_LOCK(sc);
|
||||
DPRINTF(("Disassociate from %6D\n", ni->ni_bssid, ":"));
|
||||
@ -2284,20 +2345,22 @@ static void
|
||||
ipw_init(void *priv)
|
||||
{
|
||||
struct ipw_softc *sc = priv;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
IPW_LOCK(sc);
|
||||
ipw_init_locked(sc);
|
||||
IPW_UNLOCK(sc);
|
||||
|
||||
if (sc->flags & IPW_FLAG_RUNNING)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic); /* start all vap's */
|
||||
}
|
||||
|
||||
static void
|
||||
ipw_init_locked(struct ipw_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);
|
||||
const struct firmware *fp;
|
||||
const struct ipw_firmware_hdr *hdr;
|
||||
@ -2381,19 +2444,22 @@ ipw_init_locked(struct ipw_softc *sc)
|
||||
}
|
||||
|
||||
callout_reset(&sc->sc_wdtimer, hz, ipw_watchdog, sc);
|
||||
sc->flags |= IPW_FLAG_RUNNING;
|
||||
sc->flags &= ~IPW_FLAG_INIT_LOCKED;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
|
||||
sc->flags &=~ IPW_FLAG_INIT_LOCKED;
|
||||
return;
|
||||
|
||||
fail:
|
||||
ipw_stop_locked(sc);
|
||||
sc->flags &= ~IPW_FLAG_INIT_LOCKED;
|
||||
sc->flags &=~ IPW_FLAG_INIT_LOCKED;
|
||||
}
|
||||
|
||||
static int
|
||||
ipw_config(struct ipw_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ipw_configuration config;
|
||||
uint32_t data;
|
||||
int error;
|
||||
@ -2438,7 +2504,7 @@ ipw_config(struct ipw_softc *sc)
|
||||
IPW_CFG_PREAMBLE_AUTO | IPW_CFG_802_1x_ENABLE);
|
||||
if (ic->ic_opmode == IEEE80211_M_IBSS)
|
||||
config.flags |= htole32(IPW_CFG_IBSS_AUTO_START);
|
||||
if (ic->ic_promisc > 0)
|
||||
if (ifp->if_flags & IFF_PROMISC)
|
||||
config.flags |= htole32(IPW_CFG_PROMISCUOUS);
|
||||
config.bss_chan = htole32(0x3fff); /* channels 1-14 */
|
||||
config.ibss_chan = htole32(0x7ff); /* channels 1-11 */
|
||||
@ -2496,6 +2562,7 @@ ipw_stop(void *priv)
|
||||
static void
|
||||
ipw_stop_locked(struct ipw_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int i;
|
||||
|
||||
IPW_LOCK_ASSERT(sc);
|
||||
@ -2512,7 +2579,7 @@ ipw_stop_locked(struct ipw_softc *sc)
|
||||
ipw_release_sbd(sc, &sc->stbd_list[i]);
|
||||
|
||||
sc->sc_tx_timer = 0;
|
||||
sc->flags &= ~IPW_FLAG_RUNNING;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2610,7 +2677,8 @@ ipw_write_mem_1(struct ipw_softc *sc, bus_size_t offset, const uint8_t *datap,
|
||||
static void
|
||||
ipw_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct ipw_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
|
||||
IPW_LOCK(sc);
|
||||
ipw_scan(sc);
|
||||
@ -2620,7 +2688,8 @@ ipw_scan_start(struct ieee80211com *ic)
|
||||
static void
|
||||
ipw_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct ipw_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
|
||||
IPW_LOCK(sc);
|
||||
if (ic->ic_opmode == IEEE80211_M_MONITOR) {
|
||||
@ -2646,7 +2715,8 @@ ipw_scan_mindwell(struct ieee80211_scan_state *ss)
|
||||
static void
|
||||
ipw_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct ipw_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ipw_softc *sc = ifp->if_softc;
|
||||
|
||||
IPW_LOCK(sc);
|
||||
sc->flags &= ~IPW_FLAG_SCANNING;
|
||||
|
@ -87,8 +87,7 @@ struct ipw_vap {
|
||||
#define IPW_VAP(vap) ((struct ipw_vap *)(vap))
|
||||
|
||||
struct ipw_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
|
||||
struct mtx sc_mtx;
|
||||
@ -105,7 +104,6 @@ struct ipw_softc {
|
||||
#define IPW_FLAG_BUSY 0x0040
|
||||
#define IPW_FLAG_ASSOCIATING 0x0080
|
||||
#define IPW_FLAG_ASSOCIATED 0x0100
|
||||
#define IPW_FLAG_RUNNING 0x0200
|
||||
|
||||
struct resource *irq;
|
||||
struct resource *mem;
|
||||
|
@ -166,15 +166,14 @@ static void iwi_tx_intr(struct iwi_softc *, struct iwi_tx_ring *);
|
||||
static void iwi_intr(void *);
|
||||
static int iwi_cmd(struct iwi_softc *, uint8_t, void *, uint8_t);
|
||||
static void iwi_write_ibssnode(struct iwi_softc *, const u_int8_t [], int);
|
||||
static int iwi_tx_start(struct iwi_softc *, struct mbuf *,
|
||||
static int iwi_tx_start(struct ifnet *, struct mbuf *,
|
||||
struct ieee80211_node *, int);
|
||||
static int iwi_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static void iwi_start(struct iwi_softc *);
|
||||
static int iwi_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void iwi_start_locked(struct ifnet *);
|
||||
static void iwi_start(struct ifnet *);
|
||||
static void iwi_watchdog(void *);
|
||||
static int iwi_ioctl(struct ieee80211com *, u_long, void *);
|
||||
static void iwi_parent(struct ieee80211com *);
|
||||
static int iwi_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void iwi_stop_master(struct iwi_softc *);
|
||||
static int iwi_reset(struct iwi_softc *);
|
||||
static int iwi_load_ucode(struct iwi_softc *, const struct iwi_fw *);
|
||||
@ -270,15 +269,23 @@ static int
|
||||
iwi_attach(device_t dev)
|
||||
{
|
||||
struct iwi_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
uint16_t val;
|
||||
int i, error;
|
||||
uint8_t bands;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
sc->sc_dev = dev;
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(dev, "can not if_alloc()\n");
|
||||
return ENXIO;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
IWI_LOCK_INIT(sc);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
sc->sc_unr = new_unrhdr(1, IWI_MAX_IBSSNODE-1, &sc->sc_mtx);
|
||||
|
||||
@ -346,6 +353,17 @@ iwi_attach(device_t dev)
|
||||
|
||||
iwi_wme_init(sc);
|
||||
|
||||
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 = iwi_init;
|
||||
ifp->if_ioctl = iwi_ioctl;
|
||||
ifp->if_start = iwi_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_name = device_get_nameunit(dev);
|
||||
ic->ic_opmode = IEEE80211_M_STA;
|
||||
@ -367,14 +385,14 @@ iwi_attach(device_t dev)
|
||||
|
||||
/* read MAC address from EEPROM */
|
||||
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
|
||||
ic->ic_macaddr[0] = val & 0xff;
|
||||
ic->ic_macaddr[1] = val >> 8;
|
||||
macaddr[0] = val & 0xff;
|
||||
macaddr[1] = val >> 8;
|
||||
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 1);
|
||||
ic->ic_macaddr[2] = val & 0xff;
|
||||
ic->ic_macaddr[3] = val >> 8;
|
||||
macaddr[2] = val & 0xff;
|
||||
macaddr[3] = val >> 8;
|
||||
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 2);
|
||||
ic->ic_macaddr[4] = val & 0xff;
|
||||
ic->ic_macaddr[5] = val >> 8;
|
||||
macaddr[4] = val & 0xff;
|
||||
macaddr[5] = val >> 8;
|
||||
|
||||
bands = 0;
|
||||
setbit(&bands, IEEE80211_MODE_11B);
|
||||
@ -383,7 +401,7 @@ iwi_attach(device_t dev)
|
||||
setbit(&bands, IEEE80211_MODE_11A);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, macaddr);
|
||||
/* override default methods */
|
||||
ic->ic_node_alloc = iwi_node_alloc;
|
||||
sc->sc_node_free = ic->ic_node_free;
|
||||
@ -398,9 +416,6 @@ iwi_attach(device_t dev)
|
||||
|
||||
ic->ic_vap_create = iwi_vap_create;
|
||||
ic->ic_vap_delete = iwi_vap_delete;
|
||||
ic->ic_ioctl = iwi_ioctl;
|
||||
ic->ic_transmit = iwi_transmit;
|
||||
ic->ic_parent = iwi_parent;
|
||||
|
||||
ieee80211_radiotap_attach(ic,
|
||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
|
||||
@ -435,7 +450,8 @@ static int
|
||||
iwi_detach(device_t dev)
|
||||
{
|
||||
struct iwi_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
bus_teardown_intr(dev, sc->irq, sc->sc_ih);
|
||||
|
||||
@ -466,10 +482,11 @@ iwi_detach(device_t dev)
|
||||
sc->mem);
|
||||
|
||||
delete_unrhdr(sc->sc_unr);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
|
||||
IWI_LOCK_DESTROY(sc);
|
||||
|
||||
if_free(ifp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -479,7 +496,8 @@ iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct iwi_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct iwi_softc *sc = ifp->if_softc;
|
||||
struct iwi_vap *ivp;
|
||||
struct ieee80211vap *vap;
|
||||
int i;
|
||||
@ -501,9 +519,12 @@ iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
if (iwi_init_fw_dma(sc, i))
|
||||
return NULL;
|
||||
|
||||
ivp = malloc(sizeof(struct iwi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
ivp = (struct iwi_vap *) malloc(sizeof(struct iwi_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (ivp == NULL)
|
||||
return NULL;
|
||||
vap = &ivp->iwi_vap;
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
|
||||
/* override the default, the setting comes from the linux driver */
|
||||
vap->iv_bmissthreshold = 24;
|
||||
/* override with driver methods */
|
||||
@ -511,8 +532,7 @@ iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
vap->iv_newstate = iwi_newstate;
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status,
|
||||
mac);
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
}
|
||||
@ -839,7 +859,7 @@ static int
|
||||
iwi_suspend(device_t dev)
|
||||
{
|
||||
struct iwi_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
|
||||
ieee80211_suspend_all(ic);
|
||||
return 0;
|
||||
@ -849,7 +869,7 @@ static int
|
||||
iwi_resume(device_t dev)
|
||||
{
|
||||
struct iwi_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
|
||||
pci_write_config(dev, 0x41, 0, 1);
|
||||
|
||||
@ -875,7 +895,7 @@ static void
|
||||
iwi_node_free(struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct iwi_softc *sc = ic->ic_softc;
|
||||
struct iwi_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct iwi_node *in = (struct iwi_node *)ni;
|
||||
|
||||
if (in->in_station != -1) {
|
||||
@ -919,7 +939,7 @@ iwi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
||||
{
|
||||
struct ieee80211vap *vap = ifp->if_softc;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct iwi_softc *sc = ic->ic_softc;
|
||||
struct iwi_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
|
||||
/* read current transmission rate from adapter */
|
||||
@ -935,7 +955,8 @@ iwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct iwi_vap *ivp = IWI_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct iwi_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct iwi_softc *sc = ifp->if_softc;
|
||||
IWI_LOCK_DECL;
|
||||
|
||||
DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
|
||||
@ -1040,7 +1061,7 @@ iwi_wme_init(struct iwi_softc *sc)
|
||||
static int
|
||||
iwi_wme_setparams(struct iwi_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
const struct wmeParams *wmep;
|
||||
int ac;
|
||||
|
||||
@ -1074,7 +1095,7 @@ iwi_update_wme(void *arg, int npending)
|
||||
static int
|
||||
iwi_wme_update(struct ieee80211com *ic)
|
||||
{
|
||||
struct iwi_softc *sc = ic->ic_softc;
|
||||
struct iwi_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
|
||||
/*
|
||||
@ -1168,7 +1189,8 @@ iwi_read_prom_word(struct iwi_softc *sc, uint8_t addr)
|
||||
static void
|
||||
iwi_setcurchan(struct iwi_softc *sc, int chan)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
sc->curchan = chan;
|
||||
ieee80211_radiotap_chan_change(ic);
|
||||
@ -1178,7 +1200,8 @@ static void
|
||||
iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
|
||||
struct iwi_frame *frame)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct mbuf *mnew, *m;
|
||||
struct ieee80211_node *ni;
|
||||
int type, error, framelen;
|
||||
@ -1214,7 +1237,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
|
||||
*/
|
||||
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (mnew == NULL) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1235,7 +1258,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
|
||||
panic("%s: could not load old rx mbuf",
|
||||
device_get_name(sc->sc_dev));
|
||||
}
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1248,6 +1271,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
|
||||
CSR_WRITE_4(sc, data->reg, data->physaddr);
|
||||
|
||||
/* finalize mbuf */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len = sizeof (struct iwi_hdr) +
|
||||
sizeof (struct iwi_frame) + framelen;
|
||||
|
||||
@ -1386,7 +1410,8 @@ iwi_notif_link_quality(struct iwi_softc *sc, struct iwi_notif *notif)
|
||||
static void
|
||||
iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
|
||||
{
|
||||
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 iwi_notif_scan_channel *chan;
|
||||
struct iwi_notif_scan_complete *scan;
|
||||
@ -1607,33 +1632,47 @@ iwi_rx_intr(struct iwi_softc *sc)
|
||||
static void
|
||||
iwi_tx_intr(struct iwi_softc *sc, struct iwi_tx_ring *txq)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct iwi_tx_data *data;
|
||||
uint32_t hw;
|
||||
|
||||
hw = CSR_READ_4(sc, txq->csr_ridx);
|
||||
|
||||
while (txq->next != hw) {
|
||||
for (; txq->next != hw;) {
|
||||
data = &txq->data[txq->next];
|
||||
DPRINTFN(15, ("tx done idx=%u\n", txq->next));
|
||||
|
||||
bus_dmamap_sync(txq->data_dmat, data->map,
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(txq->data_dmat, data->map);
|
||||
ieee80211_tx_complete(data->ni, data->m, 0);
|
||||
data->ni = NULL;
|
||||
if (data->m->m_flags & M_TXCB)
|
||||
ieee80211_process_callback(data->ni, data->m, 0/*XXX*/);
|
||||
m_freem(data->m);
|
||||
data->m = NULL;
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
|
||||
DPRINTFN(15, ("tx done idx=%u\n", txq->next));
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
|
||||
txq->queued--;
|
||||
txq->next = (txq->next + 1) % IWI_TX_RING_COUNT;
|
||||
}
|
||||
|
||||
sc->sc_tx_timer = 0;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
||||
if (sc->sc_softled)
|
||||
iwi_led_event(sc, IWI_LED_TX);
|
||||
iwi_start(sc);
|
||||
|
||||
iwi_start_locked(ifp);
|
||||
}
|
||||
|
||||
static void
|
||||
iwi_fatal_error_intr(struct iwi_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);
|
||||
|
||||
device_printf(sc->sc_dev, "firmware error\n");
|
||||
@ -1649,8 +1688,10 @@ iwi_fatal_error_intr(struct iwi_softc *sc)
|
||||
static void
|
||||
iwi_radio_off_intr(struct iwi_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
ieee80211_runtask(&sc->sc_ic, &sc->sc_radiofftask);
|
||||
ieee80211_runtask(ic, &sc->sc_radiofftask);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1765,9 +1806,10 @@ iwi_write_ibssnode(struct iwi_softc *sc,
|
||||
}
|
||||
|
||||
static int
|
||||
iwi_tx_start(struct iwi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
|
||||
iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni,
|
||||
int ac)
|
||||
{
|
||||
struct iwi_softc *sc = ifp->if_softc;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct iwi_node *in = (struct iwi_node *)ni;
|
||||
@ -1810,10 +1852,9 @@ iwi_tx_start(struct iwi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
|
||||
in->in_station = alloc_unr(sc->sc_unr);
|
||||
if (in->in_station == -1) {
|
||||
/* h/w table is full */
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
m_freem(m0);
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return 0;
|
||||
}
|
||||
iwi_write_ibssnode(sc,
|
||||
@ -1939,139 +1980,141 @@ iwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iwi_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct iwi_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
IWI_LOCK_DECL;
|
||||
|
||||
IWI_LOCK(sc);
|
||||
if (!sc->sc_running) {
|
||||
IWI_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
IWI_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
iwi_start(sc);
|
||||
IWI_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
iwi_start(struct iwi_softc *sc)
|
||||
iwi_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct iwi_softc *sc = ifp->if_softc;
|
||||
struct mbuf *m;
|
||||
struct ieee80211_node *ni;
|
||||
int ac;
|
||||
|
||||
IWI_LOCK_ASSERT(sc);
|
||||
|
||||
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
ac = M_WME_GETAC(m);
|
||||
if (sc->txq[ac].queued > IWI_TX_RING_COUNT - 8) {
|
||||
/* there is no place left in this ring; tail drop */
|
||||
/* XXX tail drop */
|
||||
mbufq_prepend(&sc->sc_snd, m);
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
if (iwi_tx_start(sc, m, ni, ac) != 0) {
|
||||
if (iwi_tx_start(ifp, m, ni, ac) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
sc->sc_tx_timer = 5;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
iwi_start(struct ifnet *ifp)
|
||||
{
|
||||
struct iwi_softc *sc = ifp->if_softc;
|
||||
IWI_LOCK_DECL;
|
||||
|
||||
IWI_LOCK(sc);
|
||||
iwi_start_locked(ifp);
|
||||
IWI_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
iwi_watchdog(void *arg)
|
||||
{
|
||||
struct iwi_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
IWI_LOCK_ASSERT(sc);
|
||||
|
||||
if (sc->sc_tx_timer > 0) {
|
||||
if (--sc->sc_tx_timer == 0) {
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
counter_u64_add(ic->ic_oerrors, 1);
|
||||
if_printf(ifp, "device timeout\n");
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_runtask(ic, &sc->sc_restarttask);
|
||||
}
|
||||
}
|
||||
if (sc->sc_state_timer > 0) {
|
||||
if (--sc->sc_state_timer == 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"firmware stuck in state %d, resetting\n",
|
||||
if_printf(ifp, "firmware stuck in state %d, resetting\n",
|
||||
sc->fw_state);
|
||||
if (sc->fw_state == IWI_FW_SCANNING)
|
||||
if (sc->fw_state == IWI_FW_SCANNING) {
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
ieee80211_cancel_scan(TAILQ_FIRST(&ic->ic_vaps));
|
||||
}
|
||||
ieee80211_runtask(ic, &sc->sc_restarttask);
|
||||
sc->sc_state_timer = 3;
|
||||
}
|
||||
}
|
||||
if (sc->sc_busy_timer > 0) {
|
||||
if (--sc->sc_busy_timer == 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"firmware command timeout, resetting\n");
|
||||
if_printf(ifp, "firmware command timeout, resetting\n");
|
||||
ieee80211_runtask(ic, &sc->sc_restarttask);
|
||||
}
|
||||
}
|
||||
callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc);
|
||||
}
|
||||
|
||||
static void
|
||||
iwi_parent(struct ieee80211com *ic)
|
||||
{
|
||||
struct iwi_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
IWI_LOCK_DECL;
|
||||
|
||||
IWI_LOCK(sc);
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (!sc->sc_running) {
|
||||
iwi_init_locked(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else if (sc->sc_running)
|
||||
iwi_stop_locked(sc);
|
||||
IWI_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
}
|
||||
|
||||
static int
|
||||
iwi_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
|
||||
iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct ifreq *ifr = data;
|
||||
struct iwi_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
struct iwi_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error = 0, startall = 0;
|
||||
IWI_LOCK_DECL;
|
||||
|
||||
IWI_LOCK(sc);
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
IWI_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
iwi_init_locked(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
iwi_stop_locked(sc);
|
||||
}
|
||||
IWI_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
||||
break;
|
||||
case SIOCGIFADDR:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
case SIOCGIWISTATS:
|
||||
IWI_LOCK(sc);
|
||||
/* XXX validate permissions/memory/etc? */
|
||||
error = copyout(&sc->sc_linkqual, ifr->ifr_data,
|
||||
sizeof(struct iwi_notif_link_quality));
|
||||
IWI_UNLOCK(sc);
|
||||
break;
|
||||
case SIOCZIWISTATS:
|
||||
IWI_LOCK(sc);
|
||||
memset(&sc->sc_linkqual, 0,
|
||||
sizeof(struct iwi_notif_link_quality));
|
||||
IWI_UNLOCK(sc);
|
||||
error = 0;
|
||||
break;
|
||||
default:
|
||||
error = ENOTTY;
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
IWI_UNLOCK(sc);
|
||||
|
||||
return (error);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2550,7 +2593,8 @@ iwi_setwepkeys(struct iwi_softc *sc, struct ieee80211vap *vap)
|
||||
static int
|
||||
iwi_config(struct iwi_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct iwi_configuration config;
|
||||
struct iwi_rateset rs;
|
||||
struct iwi_txpower power;
|
||||
@ -2559,8 +2603,8 @@ iwi_config(struct iwi_softc *sc)
|
||||
|
||||
IWI_LOCK_ASSERT(sc);
|
||||
|
||||
DPRINTF(("Setting MAC address to %6D\n", ic->ic_macaddr, ":"));
|
||||
error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, ic->ic_macaddr,
|
||||
DPRINTF(("Setting MAC address to %6D\n", IF_LLADDR(ifp), ":"));
|
||||
error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp),
|
||||
IEEE80211_ADDR_LEN);
|
||||
if (error != 0)
|
||||
return error;
|
||||
@ -2680,7 +2724,7 @@ iwi_monitor_scan(void *arg, int npending)
|
||||
static int
|
||||
iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic;
|
||||
struct ieee80211_channel *chan;
|
||||
struct ieee80211_scan_state *ss;
|
||||
struct iwi_scan_ext scan;
|
||||
@ -2697,6 +2741,7 @@ iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan)
|
||||
}
|
||||
IWI_STATE_BEGIN(sc, IWI_FW_SCANNING);
|
||||
|
||||
ic = sc->sc_ifp->if_l2com;
|
||||
ss = ic->ic_scan;
|
||||
|
||||
memset(&scan, 0, sizeof scan);
|
||||
@ -3083,6 +3128,7 @@ error:
|
||||
static void
|
||||
iwi_init_locked(struct iwi_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct iwi_rx_data *data;
|
||||
int i;
|
||||
|
||||
@ -3156,7 +3202,8 @@ iwi_init_locked(struct iwi_softc *sc)
|
||||
}
|
||||
|
||||
callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc);
|
||||
sc->sc_running = 1;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
return;
|
||||
fail:
|
||||
IWI_STATE_END(sc, IWI_FW_LOADING);
|
||||
@ -3168,14 +3215,15 @@ static void
|
||||
iwi_init(void *priv)
|
||||
{
|
||||
struct iwi_softc *sc = priv;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
IWI_LOCK_DECL;
|
||||
|
||||
IWI_LOCK(sc);
|
||||
iwi_init_locked(sc);
|
||||
IWI_UNLOCK(sc);
|
||||
|
||||
if (sc->sc_running)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic);
|
||||
}
|
||||
|
||||
@ -3183,10 +3231,11 @@ static void
|
||||
iwi_stop_locked(void *priv)
|
||||
{
|
||||
struct iwi_softc *sc = priv;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
IWI_LOCK_ASSERT(sc);
|
||||
|
||||
sc->sc_running = 0;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
if (sc->sc_softled) {
|
||||
callout_stop(&sc->sc_ledtimer);
|
||||
@ -3247,7 +3296,7 @@ static void
|
||||
iwi_radio_on(void *arg, int pending)
|
||||
{
|
||||
struct iwi_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
|
||||
device_printf(sc->sc_dev, "radio turned on\n");
|
||||
|
||||
@ -3268,7 +3317,10 @@ iwi_rfkill_poll(void *arg)
|
||||
* it is enabled so we must poll for the latter.
|
||||
*/
|
||||
if (!iwi_getrfkill(sc)) {
|
||||
ieee80211_runtask(&sc->sc_ic, &sc->sc_radiontask);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
ieee80211_runtask(ic, &sc->sc_radiontask);
|
||||
return;
|
||||
}
|
||||
callout_reset(&sc->sc_rftimer, 2*hz, iwi_rfkill_poll, sc);
|
||||
@ -3278,7 +3330,7 @@ static void
|
||||
iwi_radio_off(void *arg, int pending)
|
||||
{
|
||||
struct iwi_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
IWI_LOCK_DECL;
|
||||
|
||||
device_printf(sc->sc_dev, "radio turned off\n");
|
||||
@ -3542,8 +3594,8 @@ iwi_scan_start(struct ieee80211com *ic)
|
||||
static void
|
||||
iwi_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct iwi_softc *sc = ic->ic_softc;
|
||||
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct iwi_softc *sc = ifp->if_softc;
|
||||
if (sc->fw_state == IWI_FW_IDLE)
|
||||
iwi_setcurchan(sc, ic->ic_curchan->ic_ieee);
|
||||
}
|
||||
@ -3552,7 +3604,8 @@ static void
|
||||
iwi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
|
||||
{
|
||||
struct ieee80211vap *vap = ss->ss_vap;
|
||||
struct iwi_softc *sc = vap->iv_ic->ic_softc;
|
||||
struct ifnet *ifp = vap->iv_ic->ic_ifp;
|
||||
struct iwi_softc *sc = ifp->if_softc;
|
||||
IWI_LOCK_DECL;
|
||||
|
||||
IWI_LOCK(sc);
|
||||
@ -3570,7 +3623,8 @@ iwi_scan_mindwell(struct ieee80211_scan_state *ss)
|
||||
static void
|
||||
iwi_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct iwi_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct iwi_softc *sc = ifp->if_softc;
|
||||
IWI_LOCK_DECL;
|
||||
|
||||
IWI_LOCK(sc);
|
||||
|
@ -125,13 +125,11 @@ struct iwi_vap {
|
||||
#define IWI_VAP(vap) ((struct iwi_vap *)(vap))
|
||||
|
||||
struct iwi_softc {
|
||||
struct mtx sc_mtx;
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
void (*sc_node_free)(struct ieee80211_node *);
|
||||
device_t sc_dev;
|
||||
|
||||
void (*sc_node_free)(struct ieee80211_node *);
|
||||
|
||||
struct mtx sc_mtx;
|
||||
uint8_t sc_mcast[IEEE80211_ADDR_LEN];
|
||||
struct unrhdr *sc_unr;
|
||||
|
||||
@ -195,8 +193,7 @@ struct iwi_softc {
|
||||
struct task sc_wmetask; /* set wme parameters */
|
||||
struct task sc_monitortask;
|
||||
|
||||
unsigned int sc_running : 1, /* initialized */
|
||||
sc_softled : 1, /* enable LED gpio status */
|
||||
unsigned int sc_softled : 1, /* enable LED gpio status */
|
||||
sc_ledstate: 1, /* LED on/off state */
|
||||
sc_blinking: 1; /* LED blink operation active */
|
||||
u_int sc_nictype; /* NIC type from EEPROM */
|
||||
|
@ -235,11 +235,10 @@ static int iwn_tx_data_raw(struct iwn_softc *, struct mbuf *,
|
||||
static void iwn_xmit_task(void *arg0, int pending);
|
||||
static int iwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static int iwn_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void iwn_start_locked(struct iwn_softc *);
|
||||
static void iwn_start(struct ifnet *);
|
||||
static void iwn_start_locked(struct ifnet *);
|
||||
static void iwn_watchdog(void *);
|
||||
static int iwn_ioctl(struct ieee80211com *, u_long , void *);
|
||||
static void iwn_parent(struct ieee80211com *);
|
||||
static int iwn_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static int iwn_cmd(struct iwn_softc *, int, const void *, int, int);
|
||||
static int iwn4965_add_node(struct iwn_softc *, struct iwn_node_info *,
|
||||
int);
|
||||
@ -337,7 +336,7 @@ static void iwn_radio_on(void *, int);
|
||||
static void iwn_radio_off(void *, int);
|
||||
static void iwn_panicked(void *, int);
|
||||
static void iwn_init_locked(struct iwn_softc *);
|
||||
static void iwn_init(struct iwn_softc *);
|
||||
static void iwn_init(void *);
|
||||
static void iwn_stop_locked(struct iwn_softc *);
|
||||
static void iwn_stop(struct iwn_softc *);
|
||||
static void iwn_scan_start(struct ieee80211com *);
|
||||
@ -407,7 +406,9 @@ iwn_attach(device_t dev)
|
||||
{
|
||||
struct iwn_softc *sc = (struct iwn_softc *)device_get_softc(dev);
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
int i, error, rid;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
sc->sc_dev = dev;
|
||||
|
||||
@ -463,7 +464,6 @@ iwn_attach(device_t dev)
|
||||
}
|
||||
|
||||
IWN_LOCK_INIT(sc);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
/* Read hardware revision and attach. */
|
||||
sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> IWN_HW_REV_TYPE_SHIFT)
|
||||
@ -549,7 +549,14 @@ iwn_attach(device_t dev)
|
||||
/* Clear pending interrupts. */
|
||||
IWN_WRITE(sc, IWN_INT, 0xffffffff);
|
||||
|
||||
ic = &sc->sc_ic;
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(dev, "can not allocate ifnet structure\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ic = ifp->if_l2com;
|
||||
ic->ic_ifp = ifp;
|
||||
ic->ic_softc = sc;
|
||||
ic->ic_name = device_get_nameunit(dev);
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
@ -574,7 +581,7 @@ iwn_attach(device_t dev)
|
||||
;
|
||||
|
||||
/* Read MAC address, channels, etc from EEPROM. */
|
||||
if ((error = iwn_read_eeprom(sc, ic->ic_macaddr)) != 0) {
|
||||
if ((error = iwn_read_eeprom(sc, macaddr)) != 0) {
|
||||
device_printf(dev, "could not read EEPROM, error %d\n",
|
||||
error);
|
||||
goto fail;
|
||||
@ -592,7 +599,7 @@ iwn_attach(device_t dev)
|
||||
if (bootverbose) {
|
||||
device_printf(dev, "MIMO %dT%dR, %.4s, address %6D\n",
|
||||
sc->ntxchains, sc->nrxchains, sc->eeprom_domain,
|
||||
ic->ic_macaddr, ":");
|
||||
macaddr, ":");
|
||||
}
|
||||
|
||||
if (sc->sc_flags & IWN_FLAG_HAS_11N) {
|
||||
@ -633,12 +640,19 @@ iwn_attach(device_t dev)
|
||||
;
|
||||
}
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
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 = iwn_init;
|
||||
ifp->if_ioctl = iwn_ioctl;
|
||||
ifp->if_start = iwn_start;
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
|
||||
ieee80211_ifattach(ic, macaddr);
|
||||
ic->ic_vap_create = iwn_vap_create;
|
||||
ic->ic_ioctl = iwn_ioctl;
|
||||
ic->ic_parent = iwn_parent;
|
||||
ic->ic_vap_delete = iwn_vap_delete;
|
||||
ic->ic_transmit = iwn_transmit;
|
||||
ic->ic_raw_xmit = iwn_raw_xmit;
|
||||
ic->ic_node_alloc = iwn_node_alloc;
|
||||
sc->sc_ampdu_rx_start = ic->ic_ampdu_rx_start;
|
||||
@ -1279,9 +1293,10 @@ iwn5000_attach(struct iwn_softc *sc, uint16_t pid)
|
||||
static void
|
||||
iwn_radiotap_attach(struct iwn_softc *sc)
|
||||
{
|
||||
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
|
||||
ieee80211_radiotap_attach(&sc->sc_ic,
|
||||
ieee80211_radiotap_attach(ic,
|
||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
|
||||
IWN_TX_RADIOTAP_PRESENT,
|
||||
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
|
||||
@ -1311,14 +1326,21 @@ iwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
struct iwn_softc *sc = ic->ic_softc;
|
||||
struct iwn_vap *ivp;
|
||||
struct ieee80211vap *vap;
|
||||
uint8_t mac1[IEEE80211_ADDR_LEN];
|
||||
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
|
||||
return NULL;
|
||||
|
||||
ivp = malloc(sizeof(struct iwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
IEEE80211_ADDR_COPY(mac1, mac);
|
||||
|
||||
ivp = (struct iwn_vap *) malloc(sizeof(struct iwn_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (ivp == NULL)
|
||||
return NULL;
|
||||
vap = &ivp->iv_vap;
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac1);
|
||||
ivp->ctx = IWN_RXON_BSS_CTX;
|
||||
IEEE80211_ADDR_COPY(ivp->macaddr, mac1);
|
||||
vap->iv_bmissthreshold = 10; /* override default */
|
||||
/* Override with driver methods. */
|
||||
ivp->iv_newstate = vap->iv_newstate;
|
||||
@ -1327,8 +1349,7 @@ iwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
ieee80211_ratectl_init(vap);
|
||||
/* Complete setup. */
|
||||
ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status,
|
||||
mac);
|
||||
ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
}
|
||||
@ -1369,19 +1390,24 @@ static int
|
||||
iwn_detach(device_t dev)
|
||||
{
|
||||
struct iwn_softc *sc = device_get_softc(dev);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic;
|
||||
int qid;
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
|
||||
|
||||
if (sc->sc_ic.ic_softc != NULL) {
|
||||
if (ifp != NULL) {
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
/* Free the mbuf queue and node references */
|
||||
IWN_LOCK(sc);
|
||||
iwn_xmit_queue_drain(sc);
|
||||
IWN_UNLOCK(sc);
|
||||
|
||||
ieee80211_draintask(&sc->sc_ic, &sc->sc_reinit_task);
|
||||
ieee80211_draintask(&sc->sc_ic, &sc->sc_radioon_task);
|
||||
ieee80211_draintask(&sc->sc_ic, &sc->sc_radiooff_task);
|
||||
ieee80211_draintask(ic, &sc->sc_reinit_task);
|
||||
ieee80211_draintask(ic, &sc->sc_radioon_task);
|
||||
ieee80211_draintask(ic, &sc->sc_radiooff_task);
|
||||
|
||||
iwn_stop(sc);
|
||||
|
||||
taskqueue_drain_all(sc->sc_tq);
|
||||
@ -1389,11 +1415,9 @@ iwn_detach(device_t dev)
|
||||
|
||||
callout_drain(&sc->watchdog_to);
|
||||
callout_drain(&sc->calib_to);
|
||||
ieee80211_ifdetach(&sc->sc_ic);
|
||||
ieee80211_ifdetach(ic);
|
||||
}
|
||||
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
|
||||
/* Uninstall interrupt handler. */
|
||||
if (sc->irq != NULL) {
|
||||
bus_teardown_intr(dev, sc->irq, sc->sc_ih);
|
||||
@ -1416,6 +1440,9 @@ iwn_detach(device_t dev)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
rman_get_rid(sc->mem), sc->mem);
|
||||
|
||||
if (ifp != NULL)
|
||||
if_free(ifp);
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n", __func__);
|
||||
IWN_LOCK_DESTROY(sc);
|
||||
return 0;
|
||||
@ -1434,8 +1461,9 @@ static int
|
||||
iwn_suspend(device_t dev)
|
||||
{
|
||||
struct iwn_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
|
||||
ieee80211_suspend_all(&sc->sc_ic);
|
||||
ieee80211_suspend_all(ic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1443,11 +1471,12 @@ static int
|
||||
iwn_resume(device_t dev)
|
||||
{
|
||||
struct iwn_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
|
||||
/* Clear device-specific "PCI retry timeout" register (41h). */
|
||||
pci_write_config(dev, 0x41, 0, 1);
|
||||
|
||||
ieee80211_resume_all(&sc->sc_ic);
|
||||
ieee80211_resume_all(ic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2356,7 +2385,8 @@ iwn_eeprom_channel_flags(struct iwn_eeprom_chan *channel)
|
||||
static void
|
||||
iwn_read_eeprom_band(struct iwn_softc *sc, int n)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
|
||||
const struct iwn_chan_band *band = &iwn_bands[n];
|
||||
struct ieee80211_channel *c;
|
||||
@ -2415,7 +2445,8 @@ iwn_read_eeprom_band(struct iwn_softc *sc, int n)
|
||||
static void
|
||||
iwn_read_eeprom_ht40(struct iwn_softc *sc, int n)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
|
||||
const struct iwn_chan_band *band = &iwn_bands[n];
|
||||
struct ieee80211_channel *c, *cent, *extc;
|
||||
@ -2483,7 +2514,8 @@ iwn_read_eeprom_ht40(struct iwn_softc *sc, int n)
|
||||
static void
|
||||
iwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
iwn_read_prom_data(sc, addr, &sc->eeprom_channels[n],
|
||||
iwn_bands[n].nchan * sizeof (struct iwn_eeprom_chan));
|
||||
@ -2551,7 +2583,8 @@ static void
|
||||
iwn_read_eeprom_enhinfo(struct iwn_softc *sc)
|
||||
{
|
||||
struct iwn_eeprom_enhinfo enhinfo[35];
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_channel *c;
|
||||
uint16_t val, base;
|
||||
int8_t maxpwr;
|
||||
@ -2934,7 +2967,8 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
struct iwn_rx_data *data)
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct iwn_rx_ring *ring = &sc->rxq;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_node *ni;
|
||||
@ -2981,14 +3015,14 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
if ((flags & IWN_RX_NOERROR) != IWN_RX_NOERROR) {
|
||||
DPRINTF(sc, IWN_DEBUG_RECV, "%s: RX flags error %x\n",
|
||||
__func__, flags);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
/* Discard frames that are too short. */
|
||||
if (len < sizeof (struct ieee80211_frame_ack)) {
|
||||
DPRINTF(sc, IWN_DEBUG_RECV, "%s: frame too short: %d\n",
|
||||
__func__, len);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2996,7 +3030,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
if (m1 == NULL) {
|
||||
DPRINTF(sc, IWN_DEBUG_ANY, "%s: no mbuf to restock ring\n",
|
||||
__func__);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
bus_dmamap_unload(ring->data_dmat, data->map);
|
||||
@ -3019,7 +3053,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
ring->desc[ring->cur] = htole32(paddr >> 8);
|
||||
bus_dmamap_sync(ring->data_dmat, ring->desc_dma.map,
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3031,6 +3065,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
|
||||
/* Finalize mbuf. */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_data = head;
|
||||
m->m_pkthdr.len = m->m_len = len;
|
||||
|
||||
@ -3124,6 +3159,7 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
struct iwn_rx_data *data)
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct iwn_node *wn;
|
||||
struct ieee80211_node *ni;
|
||||
struct iwn_compressed_ba *ba = (struct iwn_compressed_ba *)(desc + 1);
|
||||
@ -3204,10 +3240,12 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap;
|
||||
for (i = 0; bitmap; i++) {
|
||||
if ((bitmap & 1) == 0) {
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
tx_err ++;
|
||||
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
|
||||
IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
|
||||
} else {
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
tx_ok ++;
|
||||
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
|
||||
IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
|
||||
@ -3353,7 +3391,8 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,
|
||||
struct iwn_rx_data *data)
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
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 iwn_calib_state *calib = &sc->calib;
|
||||
struct iwn_stats *stats = (struct iwn_stats *)(desc + 1);
|
||||
@ -3526,6 +3565,7 @@ static void
|
||||
iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
|
||||
uint8_t status)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf];
|
||||
struct iwn_tx_data *data = &ring->data[desc->idx];
|
||||
struct mbuf *m;
|
||||
@ -3546,12 +3586,15 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
|
||||
/*
|
||||
* Update rate control statistics for the node.
|
||||
*/
|
||||
if (status & IWN_TX_FAIL)
|
||||
if (status & IWN_TX_FAIL) {
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_ratectl_tx_complete(vap, ni,
|
||||
IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
|
||||
else
|
||||
} else {
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
ieee80211_ratectl_tx_complete(vap, ni,
|
||||
IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Channels marked for "radar" require traffic to be received
|
||||
@ -3577,8 +3620,11 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
|
||||
sc->sc_tx_timer = 0;
|
||||
if (--ring->queued < IWN_TX_RING_LOMARK) {
|
||||
sc->qfullmsk &= ~(1 << ring->qid);
|
||||
if (sc->qfullmsk == 0)
|
||||
iwn_start_locked(sc);
|
||||
if (sc->qfullmsk == 0 &&
|
||||
(ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
iwn_start_locked(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
|
||||
@ -3623,6 +3669,7 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
|
||||
int ackfailcnt, void *stat)
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct iwn_tx_ring *ring = &sc->txq[qid];
|
||||
struct iwn_tx_data *data;
|
||||
struct mbuf *m;
|
||||
@ -3761,8 +3808,11 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
|
||||
sc->sc_tx_timer = 0;
|
||||
if (ring->queued < IWN_TX_RING_LOMARK) {
|
||||
sc->qfullmsk &= ~(1 << ring->qid);
|
||||
if (sc->qfullmsk == 0)
|
||||
iwn_start_locked(sc);
|
||||
if (sc->qfullmsk == 0 &&
|
||||
(ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
iwn_start_locked(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
|
||||
@ -3776,7 +3826,8 @@ static void
|
||||
iwn_notif_intr(struct iwn_softc *sc)
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
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 hw;
|
||||
|
||||
@ -3970,7 +4021,8 @@ iwn_wakeup_intr(struct iwn_softc *sc)
|
||||
static void
|
||||
iwn_rftoggle_intr(struct iwn_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp = IWN_READ(sc, IWN_GP_CNTRL);
|
||||
|
||||
IWN_LOCK_ASSERT(sc);
|
||||
@ -4049,6 +4101,7 @@ static void
|
||||
iwn_intr(void *arg)
|
||||
{
|
||||
struct iwn_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t r1, r2, tmp;
|
||||
|
||||
IWN_LOCK(sc);
|
||||
@ -4141,7 +4194,7 @@ iwn_intr(void *arg)
|
||||
|
||||
done:
|
||||
/* Re-enable interrupts. */
|
||||
if (sc->sc_flags & IWN_FLAG_RUNNING)
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);
|
||||
|
||||
IWN_UNLOCK(sc);
|
||||
@ -4625,7 +4678,9 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
|
||||
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
// struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
// struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct iwn_tx_cmd *cmd;
|
||||
struct iwn_cmd_data *tx;
|
||||
struct ieee80211_frame *wh;
|
||||
@ -4820,6 +4875,7 @@ static void
|
||||
iwn_xmit_task(void *arg0, int pending)
|
||||
{
|
||||
struct iwn_softc *sc = arg0;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
int error;
|
||||
@ -4851,9 +4907,8 @@ iwn_xmit_task(void *arg0, int pending)
|
||||
error = iwn_tx_data(sc, m, ni);
|
||||
|
||||
if (error != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4866,12 +4921,13 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct iwn_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct iwn_softc *sc = ifp->if_softc;
|
||||
int error = 0;
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_XMIT | IWN_DEBUG_TRACE, "->%s begin\n", __func__);
|
||||
|
||||
if ((sc->sc_flags & IWN_FLAG_RUNNING) == 0) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
ieee80211_free_node(ni);
|
||||
m_freem(m);
|
||||
return ENETDOWN;
|
||||
@ -4886,9 +4942,8 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
if (sc->sc_beacon_wait) {
|
||||
if (iwn_xmit_queue_enqueue(sc, m) != 0) {
|
||||
m_freem(m);
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
IWN_UNLOCK(sc);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
@ -4913,6 +4968,7 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
if (error != 0) {
|
||||
/* NB: m is reclaimed on tx failure */
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
} else
|
||||
sc->sc_tx_timer = 5;
|
||||
|
||||
@ -4923,32 +4979,20 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
iwn_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
static void
|
||||
iwn_start(struct ifnet *ifp)
|
||||
{
|
||||
struct iwn_softc *sc;
|
||||
int error;
|
||||
|
||||
sc = ic->ic_softc;
|
||||
struct iwn_softc *sc = ifp->if_softc;
|
||||
|
||||
IWN_LOCK(sc);
|
||||
if ((sc->sc_flags & IWN_FLAG_RUNNING) == 0) {
|
||||
IWN_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
IWN_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
iwn_start_locked(sc);
|
||||
iwn_start_locked(ifp);
|
||||
IWN_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
iwn_start_locked(struct iwn_softc *sc)
|
||||
iwn_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct iwn_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
@ -4963,16 +5007,27 @@ iwn_start_locked(struct iwn_softc *sc)
|
||||
}
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_XMIT, "%s: called\n", __func__);
|
||||
while (sc->qfullmsk == 0 &&
|
||||
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
|
||||
(ifp->if_drv_flags & IFF_DRV_OACTIVE))
|
||||
return;
|
||||
|
||||
for (;;) {
|
||||
if (sc->qfullmsk != 0) {
|
||||
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;
|
||||
if (iwn_tx_data(sc, m, ni) != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
} else
|
||||
sc->sc_tx_timer = 5;
|
||||
}
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_XMIT, "%s: done\n", __func__);
|
||||
}
|
||||
|
||||
@ -4980,11 +5035,12 @@ static void
|
||||
iwn_watchdog(void *arg)
|
||||
{
|
||||
struct iwn_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
IWN_LOCK_ASSERT(sc);
|
||||
|
||||
KASSERT(sc->sc_flags & IWN_FLAG_RUNNING, ("not running"));
|
||||
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
|
||||
|
||||
@ -4999,13 +5055,41 @@ iwn_watchdog(void *arg)
|
||||
}
|
||||
|
||||
static int
|
||||
iwn_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
|
||||
iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct ifreq *ifr = data;
|
||||
struct iwn_softc *sc = ic->ic_softc;
|
||||
int error = 0;
|
||||
|
||||
struct iwn_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error = 0, startall = 0, stop = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCGIFADDR:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
case SIOCSIFFLAGS:
|
||||
IWN_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
iwn_init_locked(sc);
|
||||
if (IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_RFKILL)
|
||||
startall = 1;
|
||||
else
|
||||
stop = 1;
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
iwn_stop_locked(sc);
|
||||
}
|
||||
IWN_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
else if (vap != NULL && stop)
|
||||
ieee80211_stop(vap);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
||||
break;
|
||||
case SIOCGIWNSTATS:
|
||||
IWN_LOCK(sc);
|
||||
/* XXX validate permissions/memory/etc? */
|
||||
@ -5019,35 +5103,10 @@ iwn_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
|
||||
IWN_UNLOCK(sc);
|
||||
break;
|
||||
default:
|
||||
error = ENOTTY;
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
iwn_parent(struct ieee80211com *ic)
|
||||
{
|
||||
struct iwn_softc *sc = ic->ic_softc;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
int startall = 0, stop = 0;
|
||||
|
||||
IWN_LOCK(sc);
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (!(sc->sc_flags & IWN_FLAG_RUNNING)) {
|
||||
iwn_init_locked(sc);
|
||||
if (IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_RFKILL)
|
||||
startall = 1;
|
||||
else
|
||||
stop = 1;
|
||||
}
|
||||
} else if (sc->sc_flags & IWN_FLAG_RUNNING)
|
||||
iwn_stop_locked(sc);
|
||||
IWN_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
else if (vap != NULL && stop)
|
||||
ieee80211_stop(vap);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -5281,7 +5340,8 @@ static int
|
||||
iwn_add_broadcast_node(struct iwn_softc *sc, int async)
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct iwn_node_info node;
|
||||
struct iwn_cmd_link_quality linkq;
|
||||
uint8_t txant;
|
||||
@ -5292,7 +5352,7 @@ iwn_add_broadcast_node(struct iwn_softc *sc, int async)
|
||||
sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
|
||||
|
||||
memset(&node, 0, sizeof node);
|
||||
IEEE80211_ADDR_COPY(node.macaddr, ieee80211broadcastaddr);
|
||||
IEEE80211_ADDR_COPY(node.macaddr, ifp->if_broadcastaddr);
|
||||
node.id = sc->broadcast_id;
|
||||
DPRINTF(sc, IWN_DEBUG_RESET, "%s: adding broadcast node\n", __func__);
|
||||
if ((error = ops->add_node(sc, &node, async)) != 0)
|
||||
@ -5441,7 +5501,8 @@ iwn_set_timing(struct iwn_softc *sc, struct ieee80211_node *ni)
|
||||
static void
|
||||
iwn4965_power_calibration(struct iwn_softc *sc, int temp)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
|
||||
|
||||
@ -5811,7 +5872,8 @@ iwn_collect_noise(struct iwn_softc *sc,
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
struct iwn_calib_state *calib = &sc->calib;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t val;
|
||||
int i;
|
||||
|
||||
@ -6444,8 +6506,9 @@ iwn5000_runtime_calib(struct iwn_softc *sc)
|
||||
static uint32_t
|
||||
iwn_get_rxon_ht_flags(struct iwn_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
uint32_t htflags = 0;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
if (! IEEE80211_IS_CHAN_HT(c))
|
||||
return (0);
|
||||
@ -6472,9 +6535,8 @@ static int
|
||||
iwn_config(struct iwn_softc *sc)
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
const uint8_t *macaddr;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t txmask;
|
||||
uint16_t rxchain;
|
||||
int error;
|
||||
@ -6556,9 +6618,8 @@ iwn_config(struct iwn_softc *sc)
|
||||
/* Set mode, channel, RX filter and enable RX. */
|
||||
sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
|
||||
memset(sc->rxon, 0, sizeof (struct iwn_rxon));
|
||||
macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr;
|
||||
IEEE80211_ADDR_COPY(sc->rxon->myaddr, macaddr);
|
||||
IEEE80211_ADDR_COPY(sc->rxon->wlap, macaddr);
|
||||
IEEE80211_ADDR_COPY(sc->rxon->myaddr, IF_LLADDR(ifp));
|
||||
IEEE80211_ADDR_COPY(sc->rxon->wlap, IF_LLADDR(ifp));
|
||||
sc->rxon->chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
|
||||
sc->rxon->flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
|
||||
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
|
||||
@ -6671,7 +6732,7 @@ iwn_get_active_dwell_time(struct iwn_softc *sc,
|
||||
static uint16_t
|
||||
iwn_limit_dwell(struct iwn_softc *sc, uint16_t dwell_time)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211vap *vap = NULL;
|
||||
int bintval = 0;
|
||||
|
||||
@ -6719,7 +6780,8 @@ static int
|
||||
iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap,
|
||||
struct ieee80211_scan_state *ss, struct ieee80211_channel *c)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_node *ni = vap->iv_bss;
|
||||
struct iwn_scan_hdr *hdr;
|
||||
struct iwn_cmd_data *tx;
|
||||
@ -6857,9 +6919,9 @@ iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap,
|
||||
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
|
||||
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
|
||||
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, vap->iv_ifp->if_broadcastaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(vap->iv_ifp));
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, vap->iv_ifp->if_broadcastaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(ifp));
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr);
|
||||
*(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */
|
||||
*(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */
|
||||
|
||||
@ -6978,7 +7040,8 @@ static int
|
||||
iwn_auth(struct iwn_softc *sc, struct ieee80211vap *vap)
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_node *ni = vap->iv_bss;
|
||||
int error;
|
||||
|
||||
@ -7050,7 +7113,8 @@ static int
|
||||
iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap)
|
||||
{
|
||||
struct iwn_ops *ops = &sc->ops;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_node *ni = vap->iv_bss;
|
||||
struct iwn_node_info node;
|
||||
int error;
|
||||
@ -8621,7 +8685,8 @@ static void
|
||||
iwn_radio_on(void *arg0, int pending)
|
||||
{
|
||||
struct iwn_softc *sc = arg0;
|
||||
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);
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
|
||||
@ -8636,7 +8701,8 @@ static void
|
||||
iwn_radio_off(void *arg0, int pending)
|
||||
{
|
||||
struct iwn_softc *sc = arg0;
|
||||
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);
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
|
||||
@ -8656,7 +8722,8 @@ static void
|
||||
iwn_panicked(void *arg0, int pending)
|
||||
{
|
||||
struct iwn_softc *sc = arg0;
|
||||
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);
|
||||
int error;
|
||||
|
||||
@ -8684,7 +8751,7 @@ iwn_panicked(void *arg0, int pending)
|
||||
}
|
||||
|
||||
/* Only run start once the NIC is in a useful state, like associated */
|
||||
iwn_start_locked(sc);
|
||||
iwn_start_locked(sc->sc_ifp);
|
||||
|
||||
IWN_UNLOCK(sc);
|
||||
}
|
||||
@ -8692,14 +8759,13 @@ iwn_panicked(void *arg0, int pending)
|
||||
static void
|
||||
iwn_init_locked(struct iwn_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int error;
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
|
||||
|
||||
IWN_LOCK_ASSERT(sc);
|
||||
|
||||
sc->sc_flags |= IWN_FLAG_RUNNING;
|
||||
|
||||
if ((error = iwn_hw_prepare(sc)) != 0) {
|
||||
device_printf(sc->sc_dev, "%s: hardware not ready, error %d\n",
|
||||
__func__, error);
|
||||
@ -8747,33 +8813,38 @@ iwn_init_locked(struct iwn_softc *sc)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
|
||||
callout_reset(&sc->watchdog_to, hz, iwn_watchdog, sc);
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
sc->sc_flags &= ~IWN_FLAG_RUNNING;
|
||||
iwn_stop_locked(sc);
|
||||
fail: iwn_stop_locked(sc);
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__);
|
||||
}
|
||||
|
||||
static void
|
||||
iwn_init(struct iwn_softc *sc)
|
||||
iwn_init(void *arg)
|
||||
{
|
||||
struct iwn_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
IWN_LOCK(sc);
|
||||
iwn_init_locked(sc);
|
||||
IWN_UNLOCK(sc);
|
||||
|
||||
if (sc->sc_flags & IWN_FLAG_RUNNING)
|
||||
ieee80211_start_all(&sc->sc_ic);
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic);
|
||||
}
|
||||
|
||||
static void
|
||||
iwn_stop_locked(struct iwn_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
IWN_LOCK_ASSERT(sc);
|
||||
|
||||
@ -8781,7 +8852,7 @@ iwn_stop_locked(struct iwn_softc *sc)
|
||||
sc->sc_tx_timer = 0;
|
||||
callout_stop(&sc->watchdog_to);
|
||||
callout_stop(&sc->calib_to);
|
||||
sc->sc_flags &= ~IWN_FLAG_RUNNING;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
/* Power OFF hardware. */
|
||||
iwn_hw_stop(sc);
|
||||
@ -8801,7 +8872,8 @@ iwn_stop(struct iwn_softc *sc)
|
||||
static void
|
||||
iwn_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct iwn_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct iwn_softc *sc = ifp->if_softc;
|
||||
|
||||
IWN_LOCK(sc);
|
||||
/* make the link LED blink while we're scanning */
|
||||
@ -8815,7 +8887,8 @@ iwn_scan_start(struct ieee80211com *ic)
|
||||
static void
|
||||
iwn_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct iwn_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct iwn_softc *sc = ifp->if_softc;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
|
||||
IWN_LOCK(sc);
|
||||
@ -8833,7 +8906,8 @@ static void
|
||||
iwn_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
const struct ieee80211_channel *c = ic->ic_curchan;
|
||||
struct iwn_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct iwn_softc *sc = ifp->if_softc;
|
||||
int error;
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
|
||||
@ -8890,7 +8964,8 @@ static void
|
||||
iwn_hw_reset(void *arg0, int pending)
|
||||
{
|
||||
struct iwn_softc *sc = arg0;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
|
||||
|
||||
|
@ -228,16 +228,18 @@ struct iwn_vap {
|
||||
enum ieee80211_state, int);
|
||||
int ctx;
|
||||
int beacon_int;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
};
|
||||
#define IWN_VAP(_vap) ((struct iwn_vap *)(_vap))
|
||||
|
||||
struct iwn_softc {
|
||||
device_t sc_dev;
|
||||
|
||||
struct ifnet *sc_ifp;
|
||||
int sc_debug;
|
||||
|
||||
struct mtx sc_mtx;
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
|
||||
u_int sc_flags;
|
||||
#define IWN_FLAG_HAS_OTPROM (1 << 1)
|
||||
@ -249,7 +251,6 @@ struct iwn_softc {
|
||||
#define IWN_FLAG_ADV_BTCOEX (1 << 8)
|
||||
#define IWN_FLAG_PAN_SUPPORT (1 << 9)
|
||||
#define IWN_FLAG_BTCOEX (1 << 10)
|
||||
#define IWN_FLAG_RUNNING (1 << 11)
|
||||
|
||||
uint8_t hw_type;
|
||||
/* subdevice_id used to adjust configuration */
|
||||
@ -319,6 +320,7 @@ struct iwn_softc {
|
||||
struct iwn_calib_state calib;
|
||||
int last_calib_ticks;
|
||||
struct callout watchdog_to;
|
||||
struct callout ct_kill_exit_to;
|
||||
struct iwn_fw_info fw;
|
||||
struct iwn_calib_info calibcmd[IWN5000_PHY_CALIB_MAX_RESULT];
|
||||
uint32_t errptr;
|
||||
|
@ -102,9 +102,13 @@ enum {
|
||||
(IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON))
|
||||
#define IFF_DUMPPKTS_RECV(sc, wh) \
|
||||
(((sc->malo_debug & MALO_DEBUG_RECV) && \
|
||||
((sc->malo_debug & MALO_DEBUG_RECV_ALL) || !IS_BEACON(wh))))
|
||||
((sc->malo_debug & MALO_DEBUG_RECV_ALL) || !IS_BEACON(wh))) || \
|
||||
(sc->malo_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == \
|
||||
(IFF_DEBUG|IFF_LINK2))
|
||||
#define IFF_DUMPPKTS_XMIT(sc) \
|
||||
(sc->malo_debug & MALO_DEBUG_XMIT)
|
||||
((sc->malo_debug & MALO_DEBUG_XMIT) || \
|
||||
(sc->malo_ifp->if_flags & (IFF_DEBUG | IFF_LINK2)) == \
|
||||
(IFF_DEBUG | IFF_LINK2))
|
||||
#define DPRINTF(sc, m, fmt, ...) do { \
|
||||
if (sc->malo_debug & (m)) \
|
||||
printf(fmt, __VA_ARGS__); \
|
||||
@ -126,10 +130,9 @@ static int malo_dma_setup(struct malo_softc *);
|
||||
static int malo_setup_hwdma(struct malo_softc *);
|
||||
static void malo_txq_init(struct malo_softc *, struct malo_txq *, int);
|
||||
static void malo_tx_cleanupq(struct malo_softc *, struct malo_txq *);
|
||||
static void malo_parent(struct ieee80211com *);
|
||||
static int malo_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void malo_start(struct malo_softc *);
|
||||
static void malo_start(struct ifnet *);
|
||||
static void malo_watchdog(void *);
|
||||
static int malo_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void malo_updateslot(struct ieee80211com *);
|
||||
static int malo_newstate(struct ieee80211vap *, enum ieee80211_state, int);
|
||||
static void malo_scan_start(struct ieee80211com *);
|
||||
@ -140,7 +143,7 @@ static int malo_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
static void malo_sysctlattach(struct malo_softc *);
|
||||
static void malo_announce(struct malo_softc *);
|
||||
static void malo_dma_cleanup(struct malo_softc *);
|
||||
static void malo_stop(struct malo_softc *);
|
||||
static void malo_stop_locked(struct ifnet *, int);
|
||||
static int malo_chan_set(struct malo_softc *, struct ieee80211_channel *);
|
||||
static int malo_mode_init(struct malo_softc *);
|
||||
static void malo_tx_proc(void *, int);
|
||||
@ -170,19 +173,30 @@ malo_bar0_write4(struct malo_softc *sc, bus_size_t off, uint32_t val)
|
||||
int
|
||||
malo_attach(uint16_t devid, struct malo_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->malo_ic;
|
||||
struct malo_hal *mh;
|
||||
int error;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
struct malo_hal *mh;
|
||||
uint8_t bands;
|
||||
|
||||
ifp = sc->malo_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->malo_dev, "can not if_alloc()\n");
|
||||
return ENOSPC;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
MALO_LOCK_INIT(sc);
|
||||
callout_init_mtx(&sc->malo_watchdog_timer, &sc->malo_mtx, 0);
|
||||
mbufq_init(&sc->malo_snd, ifqmaxlen);
|
||||
|
||||
/* set these up early for if_printf use */
|
||||
if_initname(ifp, device_get_name(sc->malo_dev),
|
||||
device_get_unit(sc->malo_dev));
|
||||
|
||||
mh = malo_hal_attach(sc->malo_dev, devid,
|
||||
sc->malo_io1h, sc->malo_io1t, sc->malo_dmat);
|
||||
if (mh == NULL) {
|
||||
device_printf(sc->malo_dev, "unable to attach HAL\n");
|
||||
if_printf(ifp, "unable to attach HAL\n");
|
||||
error = EIO;
|
||||
goto bad;
|
||||
}
|
||||
@ -195,13 +209,13 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
|
||||
*/
|
||||
error = malo_hal_fwload(mh, "malo8335-h", "malo8335-m");
|
||||
if (error != 0) {
|
||||
device_printf(sc->malo_dev, "unable to setup firmware\n");
|
||||
if_printf(ifp, "unable to setup firmware\n");
|
||||
goto bad1;
|
||||
}
|
||||
/* XXX gethwspecs() extracts correct informations? not maybe! */
|
||||
error = malo_hal_gethwspecs(mh, &sc->malo_hwspecs);
|
||||
if (error != 0) {
|
||||
device_printf(sc->malo_dev, "unable to fetch h/w specs\n");
|
||||
if_printf(ifp, "unable to fetch h/w specs\n");
|
||||
goto bad1;
|
||||
}
|
||||
|
||||
@ -237,8 +251,7 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
|
||||
*/
|
||||
error = malo_dma_setup(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->malo_dev,
|
||||
"failed to setup descriptors: %d\n", error);
|
||||
if_printf(ifp, "failed to setup descriptors: %d\n", error);
|
||||
goto bad1;
|
||||
}
|
||||
error = malo_setup_hwdma(sc); /* push to firmware */
|
||||
@ -248,11 +261,21 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
|
||||
sc->malo_tq = taskqueue_create_fast("malo_taskq", M_NOWAIT,
|
||||
taskqueue_thread_enqueue, &sc->malo_tq);
|
||||
taskqueue_start_threads(&sc->malo_tq, 1, PI_NET,
|
||||
"%s taskq", device_get_nameunit(sc->malo_dev));
|
||||
"%s taskq", ifp->if_xname);
|
||||
|
||||
TASK_INIT(&sc->malo_rxtask, 0, malo_rx_proc, sc);
|
||||
TASK_INIT(&sc->malo_txtask, 0, malo_tx_proc, sc);
|
||||
|
||||
ifp->if_softc = sc;
|
||||
ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
|
||||
ifp->if_start = malo_start;
|
||||
ifp->if_ioctl = malo_ioctl;
|
||||
ifp->if_init = malo_init;
|
||||
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_name = device_get_nameunit(sc->malo_dev);
|
||||
/* XXX not right but it's not used anywhere important */
|
||||
@ -267,7 +290,6 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
|
||||
| IEEE80211_C_TXPMGT /* capable of txpow mgt */
|
||||
| IEEE80211_C_WPA /* capable of WPA1+WPA2 */
|
||||
;
|
||||
IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->malo_hwspecs.macaddr);
|
||||
|
||||
/*
|
||||
* Transmit requires space in the packet for a special format transmit
|
||||
@ -279,17 +301,16 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
|
||||
sizeof(struct ieee80211_frame);
|
||||
|
||||
/* call MI attach routine. */
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, sc->malo_hwspecs.macaddr);
|
||||
/* override default methods */
|
||||
ic->ic_vap_create = malo_vap_create;
|
||||
ic->ic_vap_delete = malo_vap_delete;
|
||||
ic->ic_raw_xmit = malo_raw_xmit;
|
||||
ic->ic_updateslot = malo_updateslot;
|
||||
|
||||
ic->ic_scan_start = malo_scan_start;
|
||||
ic->ic_scan_end = malo_scan_end;
|
||||
ic->ic_set_channel = malo_set_channel;
|
||||
ic->ic_parent = malo_parent;
|
||||
ic->ic_transmit = malo_transmit;
|
||||
|
||||
sc->malo_invalid = 0; /* ready to go, enable int handling */
|
||||
|
||||
@ -314,6 +335,7 @@ bad2:
|
||||
bad1:
|
||||
malo_hal_detach(mh);
|
||||
bad:
|
||||
if_free(ifp);
|
||||
sc->malo_invalid = 1;
|
||||
|
||||
return error;
|
||||
@ -325,12 +347,12 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct malo_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct malo_vap *mvp;
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
|
||||
device_printf(sc->malo_dev, "multiple vaps not supported\n");
|
||||
if_printf(ifp, "multiple vaps not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
switch (opmode) {
|
||||
@ -341,13 +363,18 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
case IEEE80211_M_MONITOR:
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->malo_dev, "%s mode not supported\n",
|
||||
if_printf(ifp, "%s mode not supported\n",
|
||||
ieee80211_opmode_name[opmode]);
|
||||
return NULL; /* unsupported */
|
||||
}
|
||||
mvp = malloc(sizeof(struct malo_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
mvp = (struct malo_vap *) malloc(sizeof(struct malo_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (mvp == NULL) {
|
||||
if_printf(ifp, "cannot allocate vap state block\n");
|
||||
return NULL;
|
||||
}
|
||||
vap = &mvp->malo_vap;
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
|
||||
|
||||
/* override state transition machine */
|
||||
mvp->malo_newstate = vap->iv_newstate;
|
||||
@ -355,7 +382,7 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap,
|
||||
ieee80211_media_change, ieee80211_media_status, mac);
|
||||
ieee80211_media_change, ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
}
|
||||
@ -434,6 +461,7 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
|
||||
int nbuf, size_t bufsize, int ndesc, size_t descsize)
|
||||
{
|
||||
int error;
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
uint8_t *ds;
|
||||
|
||||
DPRINTF(sc, MALO_DEBUG_RESET,
|
||||
@ -460,8 +488,7 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
|
||||
NULL, /* lockarg */
|
||||
&dd->dd_dmat);
|
||||
if (error != 0) {
|
||||
device_printf(sc->malo_dev, "cannot allocate %s DMA tag\n",
|
||||
dd->dd_name);
|
||||
if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -469,8 +496,7 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
|
||||
error = bus_dmamem_alloc(dd->dd_dmat, (void**) &dd->dd_desc,
|
||||
BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dd->dd_dmamap);
|
||||
if (error != 0) {
|
||||
device_printf(sc->malo_dev,
|
||||
"unable to alloc memory for %u %s descriptors, "
|
||||
if_printf(ifp, "unable to alloc memory for %u %s descriptors, "
|
||||
"error %u\n", nbuf * ndesc, dd->dd_name, error);
|
||||
goto fail1;
|
||||
}
|
||||
@ -479,8 +505,7 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
|
||||
dd->dd_desc, dd->dd_desc_len,
|
||||
malo_load_cb, &dd->dd_desc_paddr, BUS_DMA_NOWAIT);
|
||||
if (error != 0) {
|
||||
device_printf(sc->malo_dev,
|
||||
"unable to map %s descriptors, error %u\n",
|
||||
if_printf(ifp, "unable to map %s descriptors, error %u\n",
|
||||
dd->dd_name, error);
|
||||
goto fail2;
|
||||
}
|
||||
@ -507,6 +532,7 @@ fail1:
|
||||
static int
|
||||
malo_rxdma_setup(struct malo_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
int error, bsize, i;
|
||||
struct malo_rxbuf *bf;
|
||||
struct malo_rxdesc *ds;
|
||||
@ -523,8 +549,7 @@ malo_rxdma_setup(struct malo_softc *sc)
|
||||
bsize = malo_rxbuf * sizeof(struct malo_rxbuf);
|
||||
bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO);
|
||||
if (bf == NULL) {
|
||||
device_printf(sc->malo_dev,
|
||||
"malloc of %u rx buffers failed\n", bsize);
|
||||
if_printf(ifp, "malloc of %u rx buffers failed\n", bsize);
|
||||
return error;
|
||||
}
|
||||
sc->malo_rxdma.dd_bufptr = bf;
|
||||
@ -537,9 +562,8 @@ malo_rxdma_setup(struct malo_softc *sc)
|
||||
error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT,
|
||||
&bf->bf_dmamap);
|
||||
if (error != 0) {
|
||||
device_printf(sc->malo_dev,
|
||||
"%s: unable to dmamap for rx buffer, error %d\n",
|
||||
__func__, error);
|
||||
if_printf(ifp, "%s: unable to dmamap for rx buffer, "
|
||||
"error %d\n", __func__, error);
|
||||
return error;
|
||||
}
|
||||
/* NB: tail is intentional to preserve descriptor order */
|
||||
@ -551,6 +575,7 @@ malo_rxdma_setup(struct malo_softc *sc)
|
||||
static int
|
||||
malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq)
|
||||
{
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
int error, bsize, i;
|
||||
struct malo_txbuf *bf;
|
||||
struct malo_txdesc *ds;
|
||||
@ -565,7 +590,7 @@ malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq)
|
||||
bsize = malo_txbuf * sizeof(struct malo_txbuf);
|
||||
bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO);
|
||||
if (bf == NULL) {
|
||||
device_printf(sc->malo_dev, "malloc of %u tx buffers failed\n",
|
||||
if_printf(ifp, "malloc of %u tx buffers failed\n",
|
||||
malo_txbuf);
|
||||
return ENOMEM;
|
||||
}
|
||||
@ -580,8 +605,7 @@ malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq)
|
||||
error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT,
|
||||
&bf->bf_dmamap);
|
||||
if (error != 0) {
|
||||
device_printf(sc->malo_dev,
|
||||
"unable to create dmamap for tx "
|
||||
if_printf(ifp, "unable to create dmamap for tx "
|
||||
"buffer %u, error %u\n", i, error);
|
||||
return error;
|
||||
}
|
||||
@ -980,19 +1004,33 @@ malo_tx_processq(struct malo_softc *sc, struct malo_txq *txq)
|
||||
if (status & MALO_TXD_STATUS_FAILED_AGING)
|
||||
sc->malo_stats.mst_tx_aging++;
|
||||
}
|
||||
/* XXX strip fw len in case header inspected */
|
||||
m_adj(bf->bf_m, sizeof(uint16_t));
|
||||
ieee80211_tx_complete(ni, bf->bf_m,
|
||||
(status & MALO_TXD_STATUS_OK) == 0);
|
||||
} else
|
||||
m_freem(bf->bf_m);
|
||||
|
||||
/*
|
||||
* Do any tx complete callback. Note this must
|
||||
* be done before releasing the node reference.
|
||||
* XXX no way to figure out if frame was ACK'd
|
||||
*/
|
||||
if (bf->bf_m->m_flags & M_TXCB) {
|
||||
/* XXX strip fw len in case header inspected */
|
||||
m_adj(bf->bf_m, sizeof(uint16_t));
|
||||
ieee80211_process_callback(ni, bf->bf_m,
|
||||
(status & MALO_TXD_STATUS_OK) == 0);
|
||||
}
|
||||
/*
|
||||
* Reclaim reference to node.
|
||||
*
|
||||
* NB: the node may be reclaimed here if, for example
|
||||
* this is a DEAUTH message that was sent and the
|
||||
* node was timed out due to inactivity.
|
||||
*/
|
||||
ieee80211_free_node(ni);
|
||||
}
|
||||
ds->status = htole32(MALO_TXD_STATUS_IDLE);
|
||||
ds->pktlen = htole32(0);
|
||||
|
||||
bus_dmamap_sync(sc->malo_dmat, bf->bf_dmamap,
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(sc->malo_dmat, bf->bf_dmamap);
|
||||
m_freem(bf->bf_m);
|
||||
bf->bf_m = NULL;
|
||||
bf->bf_node = NULL;
|
||||
|
||||
@ -1011,23 +1049,23 @@ static void
|
||||
malo_tx_proc(void *arg, int npending)
|
||||
{
|
||||
struct malo_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
int i, nreaped;
|
||||
|
||||
/*
|
||||
* Process each active queue.
|
||||
*/
|
||||
nreaped = 0;
|
||||
MALO_LOCK(sc);
|
||||
for (i = 0; i < MALO_NUM_TX_QUEUES; i++) {
|
||||
if (!STAILQ_EMPTY(&sc->malo_txq[i].active))
|
||||
nreaped += malo_tx_processq(sc, &sc->malo_txq[i]);
|
||||
}
|
||||
|
||||
if (nreaped != 0) {
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
sc->malo_timer = 0;
|
||||
malo_start(sc);
|
||||
malo_start(ifp);
|
||||
}
|
||||
MALO_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1041,7 +1079,8 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni,
|
||||
int error, ismcast, iswep;
|
||||
int copyhdrlen, hdrlen, pktlen;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211com *ic = &sc->malo_ic;
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct malo_txdesc *ds;
|
||||
struct malo_txrec *tr;
|
||||
@ -1186,7 +1225,7 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni,
|
||||
ds->txpriority = txq->qnum;
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->malo_dev, "bogus frame type 0x%x (%s)\n",
|
||||
if_printf(ifp, "bogus frame type 0x%x (%s)\n",
|
||||
wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
|
||||
/* XXX statistic */
|
||||
m_freem(m0);
|
||||
@ -1207,52 +1246,37 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni,
|
||||
STAILQ_INSERT_TAIL(&txq->active, bf, bf_list);
|
||||
MALO_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
sc->malo_timer = 5;
|
||||
MALO_TXQ_UNLOCK(txq);
|
||||
return 0;
|
||||
#undef IEEE80211_DIR_DSTODS
|
||||
}
|
||||
|
||||
static int
|
||||
malo_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct malo_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
MALO_LOCK(sc);
|
||||
if (!sc->malo_running) {
|
||||
MALO_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->malo_snd, m);
|
||||
if (error) {
|
||||
MALO_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
malo_start(sc);
|
||||
MALO_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
malo_start(struct malo_softc *sc)
|
||||
malo_start(struct ifnet *ifp)
|
||||
{
|
||||
struct malo_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct malo_txq *txq = &sc->malo_txq[0];
|
||||
struct malo_txbuf *bf = NULL;
|
||||
struct mbuf *m;
|
||||
int nqueued = 0;
|
||||
|
||||
MALO_LOCK_ASSERT(sc);
|
||||
|
||||
if (!sc->malo_running || sc->malo_invalid)
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->malo_invalid)
|
||||
return;
|
||||
|
||||
while ((m = mbufq_dequeue(&sc->malo_snd)) != NULL) {
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
bf = malo_getbuf(sc, txq);
|
||||
if (bf == NULL) {
|
||||
mbufq_prepend(&sc->malo_snd, m);
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
|
||||
/* XXX blocks other traffic */
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
sc->malo_stats.mst_tx_qstop++;
|
||||
break;
|
||||
}
|
||||
@ -1260,8 +1284,7 @@ malo_start(struct malo_softc *sc)
|
||||
* Pass the frame to the h/w for transmission.
|
||||
*/
|
||||
if (malo_tx_start(sc, ni, bf, m)) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
if (bf != NULL) {
|
||||
bf->bf_m = NULL;
|
||||
bf->bf_node = NULL;
|
||||
@ -1305,18 +1328,21 @@ malo_start(struct malo_softc *sc)
|
||||
static void
|
||||
malo_watchdog(void *arg)
|
||||
{
|
||||
struct malo_softc *sc = arg;
|
||||
struct malo_softc *sc;
|
||||
struct ifnet *ifp;
|
||||
|
||||
sc = arg;
|
||||
callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc);
|
||||
if (sc->malo_timer == 0 || --sc->malo_timer > 0)
|
||||
return;
|
||||
|
||||
if (sc->malo_running && !sc->malo_invalid) {
|
||||
device_printf(sc->malo_dev, "watchdog timeout\n");
|
||||
ifp = sc->malo_ifp;
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && !sc->malo_invalid) {
|
||||
if_printf(ifp, "watchdog timeout\n");
|
||||
|
||||
/* XXX no way to reset h/w. now */
|
||||
|
||||
counter_u64_add(sc->malo_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
sc->malo_stats.mst_watchdog++;
|
||||
}
|
||||
}
|
||||
@ -1325,7 +1351,8 @@ static int
|
||||
malo_hal_reset(struct malo_softc *sc)
|
||||
{
|
||||
static int first = 0;
|
||||
struct ieee80211com *ic = &sc->malo_ic;
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct malo_hal *mh = sc->malo_mh;
|
||||
|
||||
if (first == 0) {
|
||||
@ -1365,7 +1392,7 @@ malo_getrxmbuf(struct malo_softc *sc, struct malo_rxbuf *bf)
|
||||
mtod(m, caddr_t), MJUMPAGESIZE,
|
||||
malo_load_cb, &paddr, BUS_DMA_NOWAIT);
|
||||
if (error != 0) {
|
||||
device_printf(sc->malo_dev,
|
||||
if_printf(sc->malo_ifp,
|
||||
"%s: bus_dmamap_load failed, error %d\n", __func__, error);
|
||||
m_freem(m);
|
||||
return NULL;
|
||||
@ -1456,23 +1483,26 @@ malo_startrecv(struct malo_softc *sc)
|
||||
static void
|
||||
malo_init_locked(struct malo_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
struct malo_hal *mh = sc->malo_mh;
|
||||
int error;
|
||||
|
||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags 0x%x\n",
|
||||
__func__, ifp->if_flags);
|
||||
|
||||
MALO_LOCK_ASSERT(sc);
|
||||
|
||||
/*
|
||||
* Stop anything previously setup. This is safe whether this is
|
||||
* the first time through or not.
|
||||
*/
|
||||
malo_stop(sc);
|
||||
malo_stop_locked(ifp, 0);
|
||||
|
||||
/*
|
||||
* Push state to the firmware.
|
||||
*/
|
||||
if (!malo_hal_reset(sc)) {
|
||||
device_printf(sc->malo_dev,
|
||||
"%s: unable to reset hardware\n", __func__);
|
||||
if_printf(ifp, "%s: unable to reset hardware\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1481,8 +1511,7 @@ malo_init_locked(struct malo_softc *sc)
|
||||
*/
|
||||
error = malo_startrecv(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->malo_dev,
|
||||
"%s: unable to start recv logic, error %d\n",
|
||||
if_printf(ifp, "%s: unable to start recv logic, error %d\n",
|
||||
__func__, error);
|
||||
return;
|
||||
}
|
||||
@ -1499,7 +1528,7 @@ malo_init_locked(struct malo_softc *sc)
|
||||
| MALO_A2HRIC_BIT_RADAR_DETECT
|
||||
| MALO_A2HRIC_BIT_CHAN_SWITCH;
|
||||
|
||||
sc->malo_running = 1;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
malo_hal_intrset(mh, sc->malo_imask);
|
||||
callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc);
|
||||
}
|
||||
@ -1508,13 +1537,18 @@ static void
|
||||
malo_init(void *arg)
|
||||
{
|
||||
struct malo_softc *sc = (struct malo_softc *) arg;
|
||||
struct ieee80211com *ic = &sc->malo_ic;
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags 0x%x\n",
|
||||
__func__, ifp->if_flags);
|
||||
|
||||
MALO_LOCK(sc);
|
||||
malo_init_locked(sc);
|
||||
|
||||
MALO_UNLOCK(sc);
|
||||
|
||||
if (sc->malo_running)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic); /* start all vap's */
|
||||
}
|
||||
|
||||
@ -1524,8 +1558,9 @@ malo_init(void *arg)
|
||||
static void
|
||||
malo_setmcastfilter(struct malo_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->malo_ic;
|
||||
struct ieee80211vap *vap;
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifmultiaddr *ifma;
|
||||
uint8_t macs[IEEE80211_ADDR_LEN * MALO_HAL_MCAST_MAX];
|
||||
uint8_t *mp;
|
||||
int nmc;
|
||||
@ -1533,32 +1568,26 @@ malo_setmcastfilter(struct malo_softc *sc)
|
||||
mp = macs;
|
||||
nmc = 0;
|
||||
|
||||
if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 ||
|
||||
ic->ic_promisc > 0)
|
||||
if (ic->ic_opmode == IEEE80211_M_MONITOR ||
|
||||
(ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)))
|
||||
goto all;
|
||||
|
||||
if_maddr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
|
||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
|
||||
struct ifnet *ifp;
|
||||
struct ifmultiaddr *ifma;
|
||||
|
||||
ifp = vap->iv_ifp;
|
||||
if_maddr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
|
||||
if (nmc == MALO_HAL_MCAST_MAX) {
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
if_maddr_runlock(ifp);
|
||||
goto all;
|
||||
}
|
||||
IEEE80211_ADDR_COPY(mp,
|
||||
LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
|
||||
|
||||
mp += IEEE80211_ADDR_LEN, nmc++;
|
||||
if (nmc == MALO_HAL_MCAST_MAX) {
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
if_maddr_runlock(ifp);
|
||||
goto all;
|
||||
}
|
||||
if_maddr_runlock(ifp);
|
||||
IEEE80211_ADDR_COPY(mp,
|
||||
LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
|
||||
|
||||
mp += IEEE80211_ADDR_LEN, nmc++;
|
||||
}
|
||||
if_maddr_runlock(ifp);
|
||||
|
||||
malo_hal_setmcast(sc->malo_mh, nmc, macs);
|
||||
|
||||
@ -1573,7 +1602,8 @@ all:
|
||||
static int
|
||||
malo_mode_init(struct malo_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->malo_ic;
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct malo_hal *mh = sc->malo_mh;
|
||||
|
||||
/*
|
||||
@ -1582,7 +1612,7 @@ malo_mode_init(struct malo_softc *sc)
|
||||
* identify internal requests (from the bridge)
|
||||
* versus external requests such as for tcpdump.
|
||||
*/
|
||||
malo_hal_setpromisc(mh, ic->ic_promisc > 0 &&
|
||||
malo_hal_setpromisc(mh, (ifp->if_flags & IFF_PROMISC) &&
|
||||
ic->ic_opmode != IEEE80211_M_HOSTAP);
|
||||
malo_setmcastfilter(sc);
|
||||
|
||||
@ -1611,7 +1641,8 @@ malo_tx_draintxq(struct malo_softc *sc, struct malo_txq *txq)
|
||||
MALO_TXQ_UNLOCK(txq);
|
||||
#ifdef MALO_DEBUG
|
||||
if (sc->malo_debug & MALO_DEBUG_RESET) {
|
||||
struct ieee80211com *ic = &sc->malo_ic;
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
const struct malo_txrec *tr =
|
||||
mtod(bf->bf_m, const struct malo_txrec *);
|
||||
malo_printtxbuf(bf, txq->qnum, ix);
|
||||
@ -1639,17 +1670,18 @@ malo_tx_draintxq(struct malo_softc *sc, struct malo_txq *txq)
|
||||
}
|
||||
|
||||
static void
|
||||
malo_stop(struct malo_softc *sc)
|
||||
malo_stop_locked(struct ifnet *ifp, int disable)
|
||||
{
|
||||
struct malo_softc *sc = ifp->if_softc;
|
||||
struct malo_hal *mh = sc->malo_mh;
|
||||
int i;
|
||||
|
||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: invalid %u running %u\n",
|
||||
__func__, sc->malo_invalid, sc->malo_running);
|
||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n",
|
||||
__func__, sc->malo_invalid, ifp->if_flags);
|
||||
|
||||
MALO_LOCK_ASSERT(sc);
|
||||
|
||||
if (!sc->malo_running)
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -1661,10 +1693,10 @@ malo_stop(struct malo_softc *sc)
|
||||
* Note that some of this work is not possible if the hardware
|
||||
* is gone (invalid).
|
||||
*/
|
||||
sc->malo_running = 0;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
|
||||
callout_stop(&sc->malo_watchdog_timer);
|
||||
sc->malo_timer = 0;
|
||||
/* disable interrupt. */
|
||||
/* diable interrupt. */
|
||||
malo_hal_intrset(mh, 0);
|
||||
/* turn off the radio. */
|
||||
malo_hal_setradio(mh, 0, MHP_AUTO_PREAMBLE);
|
||||
@ -1674,38 +1706,57 @@ malo_stop(struct malo_softc *sc)
|
||||
malo_tx_draintxq(sc, &sc->malo_txq[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
malo_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
malo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct malo_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
#define MALO_IS_RUNNING(ifp) \
|
||||
((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
|
||||
struct malo_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error = 0, startall = 0;
|
||||
|
||||
MALO_LOCK(sc);
|
||||
if (ic->ic_nrunning > 0) {
|
||||
/*
|
||||
* Beware of being called during attach/detach
|
||||
* to reset promiscuous mode. In that case we
|
||||
* will still be marked UP but not RUNNING.
|
||||
* However trying to re-init the interface
|
||||
* is the wrong thing to do as we've already
|
||||
* torn down much of our state. There's
|
||||
* probably a better way to deal with this.
|
||||
*/
|
||||
if (!sc->malo_running && !sc->malo_invalid) {
|
||||
malo_init(sc);
|
||||
startall = 1;
|
||||
}
|
||||
/*
|
||||
* To avoid rescanning another access point,
|
||||
* do not call malo_init() here. Instead,
|
||||
* only reflect promisc mode settings.
|
||||
*/
|
||||
malo_mode_init(sc);
|
||||
} else if (sc->malo_running)
|
||||
malo_stop(sc);
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
if (MALO_IS_RUNNING(ifp)) {
|
||||
/*
|
||||
* To avoid rescanning another access point,
|
||||
* do not call malo_init() here. Instead,
|
||||
* only reflect promisc mode settings.
|
||||
*/
|
||||
malo_mode_init(sc);
|
||||
} else if (ifp->if_flags & IFF_UP) {
|
||||
/*
|
||||
* Beware of being called during attach/detach
|
||||
* to reset promiscuous mode. In that case we
|
||||
* will still be marked UP but not RUNNING.
|
||||
* However trying to re-init the interface
|
||||
* is the wrong thing to do as we've already
|
||||
* torn down much of our state. There's
|
||||
* probably a better way to deal with this.
|
||||
*/
|
||||
if (!sc->malo_invalid) {
|
||||
malo_init_locked(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else
|
||||
malo_stop_locked(ifp, 1);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
case SIOCSIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
||||
break;
|
||||
default:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
}
|
||||
MALO_UNLOCK(sc);
|
||||
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
return error;
|
||||
#undef MALO_IS_RUNNING
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1722,7 +1773,7 @@ malo_updateslot(struct ieee80211com *ic)
|
||||
int error;
|
||||
|
||||
/* NB: can be called early; suppress needless cmds */
|
||||
if (!sc->malo_running)
|
||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
DPRINTF(sc, MALO_DEBUG_RESET,
|
||||
@ -1744,7 +1795,7 @@ static int
|
||||
malo_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct malo_softc *sc = ic->ic_softc;
|
||||
struct malo_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct malo_hal *mh = sc->malo_mh;
|
||||
int error;
|
||||
|
||||
@ -1788,11 +1839,12 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct malo_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct malo_softc *sc = ifp->if_softc;
|
||||
struct malo_txbuf *bf;
|
||||
struct malo_txq *txq;
|
||||
|
||||
if (!sc->malo_running || sc->malo_invalid) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->malo_invalid) {
|
||||
ieee80211_free_node(ni);
|
||||
m_freem(m);
|
||||
return ENETDOWN;
|
||||
@ -1807,6 +1859,8 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
txq = &sc->malo_txq[0];
|
||||
bf = malo_getbuf(sc, txq);
|
||||
if (bf == NULL) {
|
||||
/* XXX blocks other traffic */
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
ieee80211_free_node(ni);
|
||||
m_freem(m);
|
||||
return ENOBUFS;
|
||||
@ -1816,6 +1870,7 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
* Pass the frame to the h/w for transmission.
|
||||
*/
|
||||
if (malo_tx_start(sc, ni, bf, m) != 0) {
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
bf->bf_m = NULL;
|
||||
bf->bf_node = NULL;
|
||||
MALO_TXQ_LOCK(txq);
|
||||
@ -1860,9 +1915,9 @@ malo_sysctlattach(struct malo_softc *sc)
|
||||
static void
|
||||
malo_announce(struct malo_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
|
||||
device_printf(sc->malo_dev,
|
||||
"versions [hw %d fw %d.%d.%d.%d] (regioncode %d)\n",
|
||||
if_printf(ifp, "versions [hw %d fw %d.%d.%d.%d] (regioncode %d)\n",
|
||||
sc->malo_hwspecs.hwversion,
|
||||
(sc->malo_hwspecs.fw_releasenum >> 24) & 0xff,
|
||||
(sc->malo_hwspecs.fw_releasenum >> 16) & 0xff,
|
||||
@ -1871,11 +1926,9 @@ malo_announce(struct malo_softc *sc)
|
||||
sc->malo_hwspecs.regioncode);
|
||||
|
||||
if (bootverbose || malo_rxbuf != MALO_RXBUF)
|
||||
device_printf(sc->malo_dev,
|
||||
"using %u rx buffers\n", malo_rxbuf);
|
||||
if_printf(ifp, "using %u rx buffers\n", malo_rxbuf);
|
||||
if (bootverbose || malo_txbuf != MALO_TXBUF)
|
||||
device_printf(sc->malo_dev,
|
||||
"using %u tx buffers\n", malo_txbuf);
|
||||
if_printf(ifp, "using %u tx buffers\n", malo_txbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1936,7 +1989,8 @@ malo_chan_set(struct malo_softc *sc, struct ieee80211_channel *chan)
|
||||
static void
|
||||
malo_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct malo_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct malo_softc *sc = ifp->if_softc;
|
||||
|
||||
DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__);
|
||||
}
|
||||
@ -1944,7 +1998,8 @@ malo_scan_start(struct ieee80211com *ic)
|
||||
static void
|
||||
malo_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct malo_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct malo_softc *sc = ifp->if_softc;
|
||||
|
||||
DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__);
|
||||
}
|
||||
@ -1952,7 +2007,8 @@ malo_scan_end(struct ieee80211com *ic)
|
||||
static void
|
||||
malo_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct malo_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct malo_softc *sc = ifp->if_softc;
|
||||
|
||||
(void) malo_chan_set(sc, ic->ic_curchan);
|
||||
}
|
||||
@ -1964,7 +2020,8 @@ malo_rx_proc(void *arg, int npending)
|
||||
((((const struct ieee80211_frame *)wh)->i_fc[1] & \
|
||||
IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
|
||||
struct malo_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->malo_ic;
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct malo_rxbuf *bf;
|
||||
struct malo_rxdesc *ds;
|
||||
struct mbuf *m, *mnew;
|
||||
@ -2021,7 +2078,7 @@ malo_rx_proc(void *arg, int npending)
|
||||
#endif
|
||||
status = ds->status;
|
||||
if (status & MALO_RXD_STATUS_DECRYPT_ERR_MASK) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto rx_next;
|
||||
}
|
||||
/*
|
||||
@ -2060,7 +2117,7 @@ malo_rx_proc(void *arg, int npending)
|
||||
/* XXX don't need mbuf, just dma buffer */
|
||||
mnew = malo_getrxmbuf(sc, bf);
|
||||
if (mnew == NULL) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto rx_next;
|
||||
}
|
||||
/*
|
||||
@ -2071,6 +2128,7 @@ malo_rx_proc(void *arg, int npending)
|
||||
bf->bf_m = mnew;
|
||||
m->m_data += off - hdrlen;
|
||||
m->m_pkthdr.len = m->m_len = pktlen;
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
|
||||
/*
|
||||
* Piece 802.11 header together.
|
||||
@ -2100,6 +2158,8 @@ malo_rx_proc(void *arg, int npending)
|
||||
len, ds->rate, rssi);
|
||||
}
|
||||
#endif
|
||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||
|
||||
/* dispatch */
|
||||
ni = ieee80211_find_rxnode(ic,
|
||||
(struct ieee80211_frame_min *)wh);
|
||||
@ -2117,11 +2177,22 @@ rx_next:
|
||||
malo_bar0_write4(sc, sc->malo_hwspecs.rxdesc_read, readptr);
|
||||
sc->malo_rxnext = bf;
|
||||
|
||||
if (mbufq_first(&sc->malo_snd) != NULL)
|
||||
malo_start(sc);
|
||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
|
||||
!IFQ_IS_EMPTY(&ifp->if_snd))
|
||||
malo_start(ifp);
|
||||
#undef IEEE80211_DIR_DSTODS
|
||||
}
|
||||
|
||||
static void
|
||||
malo_stop(struct ifnet *ifp, int disable)
|
||||
{
|
||||
struct malo_softc *sc = ifp->if_softc;
|
||||
|
||||
MALO_LOCK(sc);
|
||||
malo_stop_locked(ifp, disable);
|
||||
MALO_UNLOCK(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reclaim all tx queue resources.
|
||||
*/
|
||||
@ -2137,9 +2208,13 @@ malo_tx_cleanup(struct malo_softc *sc)
|
||||
int
|
||||
malo_detach(struct malo_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->malo_ic;
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
malo_stop(sc);
|
||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n",
|
||||
__func__, ifp->if_flags);
|
||||
|
||||
malo_stop(ifp, 1);
|
||||
|
||||
if (sc->malo_tq != NULL) {
|
||||
taskqueue_drain(sc->malo_tq, &sc->malo_rxtask);
|
||||
@ -2165,7 +2240,8 @@ malo_detach(struct malo_softc *sc)
|
||||
malo_dma_cleanup(sc);
|
||||
malo_tx_cleanup(sc);
|
||||
malo_hal_detach(sc->malo_mh);
|
||||
mbufq_drain(&sc->malo_snd);
|
||||
if_free(ifp);
|
||||
|
||||
MALO_LOCK_DESTROY(sc);
|
||||
|
||||
return 0;
|
||||
@ -2174,21 +2250,28 @@ malo_detach(struct malo_softc *sc)
|
||||
void
|
||||
malo_shutdown(struct malo_softc *sc)
|
||||
{
|
||||
|
||||
malo_stop(sc);
|
||||
malo_stop(sc->malo_ifp, 1);
|
||||
}
|
||||
|
||||
void
|
||||
malo_suspend(struct malo_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
|
||||
malo_stop(sc);
|
||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n",
|
||||
__func__, ifp->if_flags);
|
||||
|
||||
malo_stop(ifp, 1);
|
||||
}
|
||||
|
||||
void
|
||||
malo_resume(struct malo_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->malo_ifp;
|
||||
|
||||
if (sc->malo_ic.ic_nrunning > 0)
|
||||
DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n",
|
||||
__func__, ifp->if_flags);
|
||||
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
malo_init(sc);
|
||||
}
|
||||
|
@ -520,9 +520,8 @@ struct malo_vap {
|
||||
#define MALO_VAP(vap) ((struct malo_vap *)(vap))
|
||||
|
||||
struct malo_softc {
|
||||
struct ieee80211com malo_ic;
|
||||
struct mbufq malo_snd;
|
||||
device_t malo_dev;
|
||||
struct ifnet *malo_ifp; /* interface common */
|
||||
struct mtx malo_mtx; /* master lock (recursive) */
|
||||
struct taskqueue *malo_tq; /* private task queue */
|
||||
|
||||
@ -532,10 +531,9 @@ struct malo_softc {
|
||||
bus_space_handle_t malo_io1h; /* BAR 1 */
|
||||
bus_space_tag_t malo_io1t;
|
||||
|
||||
unsigned int malo_invalid: 1,/* disable hardware accesses */
|
||||
malo_recvsetup: 1, /* recv setup */
|
||||
malo_fixedrate: 1, /* use fixed tx rate */
|
||||
malo_running: 1;
|
||||
unsigned int malo_invalid : 1,/* disable hardware accesses */
|
||||
malo_recvsetup : 1, /* recv setup */
|
||||
malo_fixedrate: 1; /* use fixed tx rate */
|
||||
|
||||
struct malo_hal *malo_mh; /* h/w access layer */
|
||||
struct malo_hal_hwspec malo_hwspecs; /* h/w capabilities */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
|
@ -244,8 +244,7 @@ struct mwl_vap {
|
||||
#define MWL_VAP_CONST(vap) ((const struct mwl_vap *)(vap))
|
||||
|
||||
struct mwl_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp; /* interface common */
|
||||
struct mwl_stats sc_stats; /* interface statistics */
|
||||
int sc_debug;
|
||||
device_t sc_dev;
|
||||
@ -258,8 +257,7 @@ struct mwl_softc {
|
||||
struct taskqueue *sc_tq; /* private task queue */
|
||||
struct callout sc_watchdog;
|
||||
int sc_tx_timer;
|
||||
unsigned int sc_running : 1,
|
||||
sc_invalid : 1, /* disable hardware accesses */
|
||||
unsigned int sc_invalid : 1, /* disable hardware accesses */
|
||||
sc_recvsetup:1, /* recv setup */
|
||||
sc_csapending:1,/* 11h channel switch pending */
|
||||
sc_radarena : 1,/* radar detection enabled */
|
||||
|
@ -28,7 +28,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/rman.h>
|
||||
|
@ -127,10 +127,10 @@ static int rt2560_tx_mgt(struct rt2560_softc *, struct mbuf *,
|
||||
struct ieee80211_node *);
|
||||
static int rt2560_tx_data(struct rt2560_softc *, struct mbuf *,
|
||||
struct ieee80211_node *);
|
||||
static int rt2560_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void rt2560_start(struct rt2560_softc *);
|
||||
static void rt2560_start_locked(struct ifnet *);
|
||||
static void rt2560_start(struct ifnet *);
|
||||
static void rt2560_watchdog(void *);
|
||||
static void rt2560_parent(struct ieee80211com *);
|
||||
static int rt2560_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void rt2560_bbp_write(struct rt2560_softc *, uint8_t,
|
||||
uint8_t);
|
||||
static uint8_t rt2560_bbp_read(struct rt2560_softc *, uint8_t);
|
||||
@ -149,8 +149,7 @@ static void rt2560_set_basicrates(struct rt2560_softc *,
|
||||
const struct ieee80211_rateset *);
|
||||
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 *,
|
||||
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 ieee80211com *);
|
||||
static const char *rt2560_get_rf(int);
|
||||
@ -198,9 +197,11 @@ int
|
||||
rt2560_attach(device_t dev, int id)
|
||||
{
|
||||
struct rt2560_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
uint8_t bands;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
int error;
|
||||
uint8_t bands;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
sc->sc_dev = dev;
|
||||
|
||||
@ -208,7 +209,6 @@ rt2560_attach(device_t dev, int id)
|
||||
MTX_DEF | MTX_RECURSE);
|
||||
|
||||
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
/* retrieve RT2560 rev. no */
|
||||
sc->asic_rev = RAL_READ(sc, RT2560_CSR0);
|
||||
@ -252,9 +252,27 @@ rt2560_attach(device_t dev, int id)
|
||||
goto fail5;
|
||||
}
|
||||
|
||||
/* retrieve MAC address */
|
||||
rt2560_get_macaddr(sc, ic->ic_macaddr);
|
||||
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, macaddr);
|
||||
|
||||
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 = rt2560_init;
|
||||
ifp->if_ioctl = rt2560_ioctl;
|
||||
ifp->if_start = rt2560_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_name = device_get_nameunit(dev);
|
||||
ic->ic_opmode = IEEE80211_M_STA;
|
||||
@ -285,7 +303,7 @@ rt2560_attach(device_t dev, int id)
|
||||
setbit(&bands, IEEE80211_MODE_11A);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, macaddr);
|
||||
ic->ic_raw_xmit = rt2560_raw_xmit;
|
||||
ic->ic_updateslot = rt2560_update_slot;
|
||||
ic->ic_update_promisc = rt2560_update_promisc;
|
||||
@ -295,8 +313,6 @@ rt2560_attach(device_t dev, int id)
|
||||
|
||||
ic->ic_vap_create = rt2560_vap_create;
|
||||
ic->ic_vap_delete = rt2560_vap_delete;
|
||||
ic->ic_parent = rt2560_parent;
|
||||
ic->ic_transmit = rt2560_transmit;
|
||||
|
||||
ieee80211_radiotap_attach(ic,
|
||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
|
||||
@ -325,6 +341,7 @@ rt2560_attach(device_t dev, int id)
|
||||
|
||||
return 0;
|
||||
|
||||
fail6: rt2560_free_rx_ring(sc, &sc->rxq);
|
||||
fail5: rt2560_free_tx_ring(sc, &sc->bcnq);
|
||||
fail4: rt2560_free_tx_ring(sc, &sc->prioq);
|
||||
fail3: rt2560_free_tx_ring(sc, &sc->atimq);
|
||||
@ -338,12 +355,12 @@ int
|
||||
rt2560_detach(void *xsc)
|
||||
{
|
||||
struct rt2560_softc *sc = xsc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
rt2560_stop(sc);
|
||||
|
||||
ieee80211_ifdetach(ic);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
|
||||
rt2560_free_tx_ring(sc, &sc->txq);
|
||||
rt2560_free_tx_ring(sc, &sc->atimq);
|
||||
@ -351,6 +368,8 @@ rt2560_detach(void *xsc)
|
||||
rt2560_free_tx_ring(sc, &sc->bcnq);
|
||||
rt2560_free_rx_ring(sc, &sc->rxq);
|
||||
|
||||
if_free(ifp);
|
||||
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return 0;
|
||||
@ -362,7 +381,7 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct rt2560_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2560_vap *rvp;
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
@ -375,7 +394,7 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
case IEEE80211_M_MBSS:
|
||||
/* XXXRP: TBD */
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
|
||||
device_printf(sc->sc_dev, "only 1 vap supported\n");
|
||||
if_printf(ifp, "only 1 vap supported\n");
|
||||
return NULL;
|
||||
}
|
||||
if (opmode == IEEE80211_M_STA)
|
||||
@ -384,8 +403,7 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
case IEEE80211_M_WDS:
|
||||
if (TAILQ_EMPTY(&ic->ic_vaps) ||
|
||||
ic->ic_opmode != IEEE80211_M_HOSTAP) {
|
||||
device_printf(sc->sc_dev,
|
||||
"wds only supported in ap mode\n");
|
||||
if_printf(ifp, "wds only supported in ap mode\n");
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
@ -396,12 +414,15 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
flags &= ~IEEE80211_CLONE_BSSID;
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
|
||||
if_printf(ifp, "unknown opmode %d\n", opmode);
|
||||
return NULL;
|
||||
}
|
||||
rvp = malloc(sizeof(struct rt2560_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
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);
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
|
||||
|
||||
/* override state transition machine */
|
||||
rvp->ral_newstate = vap->iv_newstate;
|
||||
@ -410,8 +431,7 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
ieee80211_ratectl_init(vap);
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
||||
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
@ -431,8 +451,9 @@ void
|
||||
rt2560_resume(void *xsc)
|
||||
{
|
||||
struct rt2560_softc *sc = xsc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (sc->sc_ic.ic_nrunning > 0)
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
rt2560_init(sc);
|
||||
}
|
||||
|
||||
@ -742,7 +763,8 @@ static int
|
||||
rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct rt2560_vap *rvp = RT2560_VAP(vap);
|
||||
struct rt2560_softc *sc = vap->iv_ic->ic_softc;
|
||||
struct ifnet *ifp = vap->iv_ic->ic_ifp;
|
||||
struct rt2560_softc *sc = ifp->if_softc;
|
||||
int error;
|
||||
|
||||
if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) {
|
||||
@ -770,8 +792,7 @@ rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
vap->iv_opmode == IEEE80211_M_MBSS) {
|
||||
m = ieee80211_beacon_alloc(ni, &rvp->ral_bo);
|
||||
if (m == NULL) {
|
||||
device_printf(sc->sc_dev,
|
||||
"could not allocate beacon\n");
|
||||
if_printf(ifp, "could not allocate beacon\n");
|
||||
return ENOBUFS;
|
||||
}
|
||||
ieee80211_ref_node(ni);
|
||||
@ -905,13 +926,14 @@ rt2560_encryption_intr(struct rt2560_softc *sc)
|
||||
static void
|
||||
rt2560_tx_intr(struct rt2560_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct rt2560_tx_desc *desc;
|
||||
struct rt2560_tx_data *data;
|
||||
struct mbuf *m;
|
||||
uint32_t flags;
|
||||
int retrycnt;
|
||||
struct ieee80211vap *vap;
|
||||
struct ieee80211_node *ni;
|
||||
uint32_t flags;
|
||||
int retrycnt, status;
|
||||
|
||||
bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
|
||||
BUS_DMASYNC_POSTREAD);
|
||||
@ -939,7 +961,7 @@ rt2560_tx_intr(struct rt2560_softc *sc)
|
||||
ieee80211_ratectl_tx_complete(vap, ni,
|
||||
IEEE80211_RATECTL_TX_SUCCESS,
|
||||
&retrycnt, NULL);
|
||||
status = 0;
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
break;
|
||||
|
||||
case RT2560_TX_SUCCESS_RETRY:
|
||||
@ -951,7 +973,7 @@ rt2560_tx_intr(struct rt2560_softc *sc)
|
||||
ieee80211_ratectl_tx_complete(vap, ni,
|
||||
IEEE80211_RATECTL_TX_SUCCESS,
|
||||
&retrycnt, NULL);
|
||||
status = 0;
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
break;
|
||||
|
||||
case RT2560_TX_FAIL_RETRY:
|
||||
@ -963,7 +985,7 @@ rt2560_tx_intr(struct rt2560_softc *sc)
|
||||
ieee80211_ratectl_tx_complete(vap, ni,
|
||||
IEEE80211_RATECTL_TX_FAILURE,
|
||||
&retrycnt, NULL);
|
||||
status = 1;
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
break;
|
||||
|
||||
case RT2560_TX_FAIL_INVALID:
|
||||
@ -971,16 +993,16 @@ rt2560_tx_intr(struct rt2560_softc *sc)
|
||||
default:
|
||||
device_printf(sc->sc_dev, "sending data frame failed "
|
||||
"0x%08x\n", flags);
|
||||
status = 1;
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
|
||||
bus_dmamap_sync(sc->txq.data_dmat, data->map,
|
||||
BUS_DMASYNC_POSTWRITE);
|
||||
bus_dmamap_unload(sc->txq.data_dmat, data->map);
|
||||
|
||||
ieee80211_tx_complete(ni, m, status);
|
||||
data->ni = NULL;
|
||||
m_freem(m);
|
||||
data->m = NULL;
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
|
||||
/* descriptor is no longer valid */
|
||||
desc->flags &= ~htole32(RT2560_TX_VALID);
|
||||
@ -997,13 +1019,19 @@ rt2560_tx_intr(struct rt2560_softc *sc)
|
||||
if (sc->prioq.queued == 0 && sc->txq.queued == 0)
|
||||
sc->sc_tx_timer = 0;
|
||||
|
||||
if (sc->txq.queued < RT2560_TX_RING_COUNT - 1)
|
||||
rt2560_start(sc);
|
||||
if (sc->txq.queued < RT2560_TX_RING_COUNT - 1) {
|
||||
sc->sc_flags &= ~RT2560_F_DATA_OACTIVE;
|
||||
if ((sc->sc_flags &
|
||||
(RT2560_F_DATA_OACTIVE | RT2560_F_PRIO_OACTIVE)) == 0)
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
rt2560_start_locked(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rt2560_prio_intr(struct rt2560_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct rt2560_tx_desc *desc;
|
||||
struct rt2560_tx_data *data;
|
||||
struct ieee80211_node *ni;
|
||||
@ -1075,8 +1103,13 @@ rt2560_prio_intr(struct rt2560_softc *sc)
|
||||
if (sc->prioq.queued == 0 && sc->txq.queued == 0)
|
||||
sc->sc_tx_timer = 0;
|
||||
|
||||
if (sc->prioq.queued < RT2560_PRIO_RING_COUNT)
|
||||
rt2560_start(sc);
|
||||
if (sc->prioq.queued < RT2560_PRIO_RING_COUNT) {
|
||||
sc->sc_flags &= ~RT2560_F_PRIO_OACTIVE;
|
||||
if ((sc->sc_flags &
|
||||
(RT2560_F_DATA_OACTIVE | RT2560_F_PRIO_OACTIVE)) == 0)
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
rt2560_start_locked(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1086,7 +1119,8 @@ rt2560_prio_intr(struct rt2560_softc *sc)
|
||||
static void
|
||||
rt2560_decryption_intr(struct rt2560_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
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;
|
||||
@ -1112,13 +1146,13 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
|
||||
break;
|
||||
|
||||
if (data->drop) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if ((le32toh(desc->flags) & RT2560_RX_CIPHER_MASK) != 0 &&
|
||||
(le32toh(desc->flags) & RT2560_RX_ICV_ERROR)) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
@ -1131,7 +1165,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
|
||||
*/
|
||||
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (mnew == NULL) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
@ -1154,7 +1188,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
|
||||
panic("%s: could not load old rx mbuf",
|
||||
device_get_name(sc->sc_dev));
|
||||
}
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
@ -1167,6 +1201,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
|
||||
desc->physaddr = htole32(physaddr);
|
||||
|
||||
/* finalize mbuf */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len =
|
||||
(le32toh(desc->flags) >> 16) & 0xfff;
|
||||
|
||||
@ -1286,7 +1321,8 @@ rt2560_beacon_update(struct ieee80211vap *vap, 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;
|
||||
@ -1327,6 +1363,7 @@ void
|
||||
rt2560_intr(void *arg)
|
||||
{
|
||||
struct rt2560_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t r;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
@ -1335,7 +1372,7 @@ rt2560_intr(void *arg)
|
||||
RAL_WRITE(sc, RT2560_CSR8, 0xffffffff);
|
||||
|
||||
/* don't re-enable interrupts if we're shutting down */
|
||||
if (!(sc->sc_flags & RT2560_F_RUNNING)) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
RAL_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
@ -1403,7 +1440,8 @@ 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;
|
||||
|
||||
@ -1878,57 +1916,55 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rt2560_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct rt2560_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
if ((sc->sc_flags & RT2560_F_RUNNING) == 0) {
|
||||
RAL_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
RAL_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
rt2560_start(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
rt2560_start(struct rt2560_softc *sc)
|
||||
rt2560_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct ieee80211_node *ni;
|
||||
struct rt2560_softc *sc = ifp->if_softc;
|
||||
struct mbuf *m;
|
||||
struct ieee80211_node *ni;
|
||||
|
||||
RAL_LOCK_ASSERT(sc);
|
||||
|
||||
while (sc->txq.queued < RT2560_TX_RING_COUNT - 1 &&
|
||||
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
if (rt2560_tx_data(sc, m, ni) != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
for (;;) {
|
||||
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;
|
||||
}
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
if (rt2560_tx_data(sc, m, ni) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
sc->sc_tx_timer = 5;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rt2560_start(struct ifnet *ifp)
|
||||
{
|
||||
struct rt2560_softc *sc = ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
rt2560_start_locked(ifp);
|
||||
RAL_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
rt2560_watchdog(void *arg)
|
||||
{
|
||||
struct rt2560_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
RAL_LOCK_ASSERT(sc);
|
||||
|
||||
KASSERT(sc->sc_flags & RT2560_F_RUNNING, ("not running"));
|
||||
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
|
||||
|
||||
if (sc->sc_invalid) /* card ejected */
|
||||
return;
|
||||
@ -1937,33 +1973,51 @@ rt2560_watchdog(void *arg)
|
||||
rt2560_tx_intr(sc);
|
||||
|
||||
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
if_printf(ifp, "device timeout\n");
|
||||
rt2560_init_locked(sc);
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
/* NB: callout is reset in rt2560_init() */
|
||||
return;
|
||||
}
|
||||
callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
|
||||
}
|
||||
|
||||
static void
|
||||
rt2560_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
rt2560_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct rt2560_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
struct rt2560_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error = 0, startall = 0;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if ((sc->sc_flags & RT2560_F_RUNNING) == 0) {
|
||||
rt2560_init_locked(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
rt2560_update_promisc(ic);
|
||||
} else if (sc->sc_flags & RT2560_F_RUNNING)
|
||||
rt2560_stop_locked(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
RAL_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
rt2560_init_locked(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
rt2560_update_promisc(ic);
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
rt2560_stop_locked(sc);
|
||||
}
|
||||
RAL_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2047,7 +2101,8 @@ rt2560_rf_write(struct rt2560_softc *sc, uint8_t reg, uint32_t val)
|
||||
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;
|
||||
|
||||
@ -2146,7 +2201,8 @@ rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c)
|
||||
static void
|
||||
rt2560_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2560_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2560_softc *sc = ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
rt2560_set_chan(sc, ic->ic_curchan);
|
||||
@ -2182,7 +2238,8 @@ 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;
|
||||
@ -2223,7 +2280,8 @@ rt2560_enable_tsf(struct rt2560_softc *sc)
|
||||
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);
|
||||
@ -2302,7 +2360,8 @@ rt2560_set_basicrates(struct rt2560_softc *sc,
|
||||
const struct ieee80211_rateset *rs)
|
||||
{
|
||||
#define RV(r) ((r) & IEEE80211_RATE_VAL)
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t mask = 0;
|
||||
uint8_t rate;
|
||||
int i;
|
||||
@ -2347,7 +2406,7 @@ rt2560_set_bssid(struct rt2560_softc *sc, const uint8_t *bssid)
|
||||
}
|
||||
|
||||
static void
|
||||
rt2560_set_macaddr(struct rt2560_softc *sc, const uint8_t *addr)
|
||||
rt2560_set_macaddr(struct rt2560_softc *sc, uint8_t *addr)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
@ -2385,13 +2444,13 @@ rt2560_update_promisc(struct ieee80211com *ic)
|
||||
tmp = RAL_READ(sc, RT2560_RXCSR0);
|
||||
|
||||
tmp &= ~RT2560_DROP_NOT_TO_ME;
|
||||
if (ic->ic_promisc == 0)
|
||||
if (!(ic->ic_ifp->if_flags & IFF_PROMISC))
|
||||
tmp |= RT2560_DROP_NOT_TO_ME;
|
||||
|
||||
RAL_WRITE(sc, RT2560_RXCSR0, tmp);
|
||||
|
||||
DPRINTF(sc, "%s promiscuous mode\n",
|
||||
(ic->ic_promisc > 0) ? "entering" : "leaving");
|
||||
(ic->ic_ifp->if_flags & IFF_PROMISC) ? "entering" : "leaving");
|
||||
}
|
||||
|
||||
static const char *
|
||||
@ -2457,17 +2516,19 @@ rt2560_read_config(struct rt2560_softc *sc)
|
||||
static void
|
||||
rt2560_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2560_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2560_softc *sc = ifp->if_softc;
|
||||
|
||||
/* abort TSF synchronization */
|
||||
RAL_WRITE(sc, RT2560_CSR14, 0);
|
||||
rt2560_set_bssid(sc, ieee80211broadcastaddr);
|
||||
rt2560_set_bssid(sc, ifp->if_broadcastaddr);
|
||||
}
|
||||
|
||||
static void
|
||||
rt2560_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2560_softc *sc = ic->ic_softc;
|
||||
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);
|
||||
@ -2561,8 +2622,8 @@ static void
|
||||
rt2560_init_locked(struct rt2560_softc *sc)
|
||||
{
|
||||
#define N(a) (sizeof (a) / sizeof ((a)[0]))
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
int i;
|
||||
|
||||
@ -2593,7 +2654,7 @@ rt2560_init_locked(struct rt2560_softc *sc)
|
||||
for (i = 0; i < N(rt2560_def_mac); i++)
|
||||
RAL_WRITE(sc, rt2560_def_mac[i].reg, rt2560_def_mac[i].val);
|
||||
|
||||
rt2560_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
rt2560_set_macaddr(sc, IF_LLADDR(ifp));
|
||||
|
||||
/* set basic rate set (will be updated later) */
|
||||
RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153);
|
||||
@ -2623,7 +2684,7 @@ rt2560_init_locked(struct rt2560_softc *sc)
|
||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
|
||||
ic->ic_opmode != IEEE80211_M_MBSS)
|
||||
tmp |= RT2560_DROP_TODS;
|
||||
if (ic->ic_promisc == 0)
|
||||
if (!(ifp->if_flags & IFF_PROMISC))
|
||||
tmp |= RT2560_DROP_NOT_TO_ME;
|
||||
}
|
||||
RAL_WRITE(sc, RT2560_RXCSR0, tmp);
|
||||
@ -2638,7 +2699,8 @@ rt2560_init_locked(struct rt2560_softc *sc)
|
||||
/* enable interrupts */
|
||||
RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK);
|
||||
|
||||
sc->sc_flags |= RT2560_F_RUNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
|
||||
callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
|
||||
#undef N
|
||||
@ -2648,19 +2710,21 @@ static void
|
||||
rt2560_init(void *priv)
|
||||
{
|
||||
struct rt2560_softc *sc = priv;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
rt2560_init_locked(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
if (sc->sc_flags & RT2560_F_RUNNING)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic); /* start all vap's */
|
||||
}
|
||||
|
||||
static void
|
||||
rt2560_stop_locked(struct rt2560_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
volatile int *flags = &sc->sc_flags;
|
||||
|
||||
RAL_LOCK_ASSERT(sc);
|
||||
@ -2671,8 +2735,8 @@ rt2560_stop_locked(struct rt2560_softc *sc)
|
||||
callout_stop(&sc->watchdog_ch);
|
||||
sc->sc_tx_timer = 0;
|
||||
|
||||
if (sc->sc_flags & RT2560_F_RUNNING) {
|
||||
sc->sc_flags &= ~RT2560_F_RUNNING;
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
/* abort Tx */
|
||||
RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX);
|
||||
@ -2694,6 +2758,7 @@ rt2560_stop_locked(struct rt2560_softc *sc)
|
||||
rt2560_reset_tx_ring(sc, &sc->bcnq);
|
||||
rt2560_reset_rx_ring(sc, &sc->rxq);
|
||||
}
|
||||
sc->sc_flags &= ~(RT2560_F_PRIO_OACTIVE | RT2560_F_DATA_OACTIVE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2711,24 +2776,29 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct rt2560_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2560_softc *sc = ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!(sc->sc_flags & RT2560_F_RUNNING)) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
RAL_UNLOCK(sc);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return ENETDOWN;
|
||||
}
|
||||
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_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
|
||||
if (params == NULL) {
|
||||
/*
|
||||
* Legacy path; interpret frame contents to decide
|
||||
@ -2750,6 +2820,7 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
|
||||
return 0;
|
||||
bad:
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
RAL_UNLOCK(sc);
|
||||
return EIO; /* XXX */
|
||||
|
@ -105,13 +105,13 @@ struct rt2560_vap {
|
||||
#define RT2560_VAP(vap) ((struct rt2560_vap *)(vap))
|
||||
|
||||
struct rt2560_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mtx sc_mtx;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_st;
|
||||
bus_space_handle_t sc_sh;
|
||||
|
||||
struct mtx sc_mtx;
|
||||
|
||||
struct callout watchdog_ch;
|
||||
|
||||
int sc_tx_timer;
|
||||
@ -152,7 +152,8 @@ struct rt2560_softc {
|
||||
struct rt2560_tx_radiotap_header sc_txtap;
|
||||
int sc_txtap_len;
|
||||
#define RT2560_F_INPUT_RUNNING 0x1
|
||||
#define RT2560_F_RUNNING 0x2
|
||||
#define RT2560_F_PRIO_OACTIVE 0x2
|
||||
#define RT2560_F_DATA_OACTIVE 0x4
|
||||
int sc_flags;
|
||||
};
|
||||
|
||||
|
@ -121,12 +121,12 @@ static int rt2661_tx_data(struct rt2661_softc *, struct mbuf *,
|
||||
struct ieee80211_node *, int);
|
||||
static int rt2661_tx_mgt(struct rt2661_softc *, struct mbuf *,
|
||||
struct ieee80211_node *);
|
||||
static int rt2661_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void rt2661_start(struct rt2661_softc *);
|
||||
static void rt2661_start_locked(struct ifnet *);
|
||||
static void rt2661_start(struct ifnet *);
|
||||
static int rt2661_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static void rt2661_watchdog(void *);
|
||||
static void rt2661_parent(struct ieee80211com *);
|
||||
static int rt2661_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void rt2661_bbp_write(struct rt2661_softc *, uint8_t,
|
||||
uint8_t);
|
||||
static uint8_t rt2661_bbp_read(struct rt2661_softc *, uint8_t);
|
||||
@ -197,19 +197,27 @@ int
|
||||
rt2661_attach(device_t dev, int id)
|
||||
{
|
||||
struct rt2661_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
uint32_t val;
|
||||
int error, ac, ntries;
|
||||
uint8_t bands;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
sc->sc_id = id;
|
||||
sc->sc_dev = dev;
|
||||
|
||||
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_DEF | MTX_RECURSE);
|
||||
|
||||
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
/* wait for NIC to initialize */
|
||||
for (ntries = 0; ntries < 1000; ntries++) {
|
||||
@ -225,7 +233,7 @@ rt2661_attach(device_t dev, int id)
|
||||
}
|
||||
|
||||
/* retrieve RF rev. no and various other things from EEPROM */
|
||||
rt2661_read_eeprom(sc, ic->ic_macaddr);
|
||||
rt2661_read_eeprom(sc, macaddr);
|
||||
|
||||
device_printf(dev, "MAC/BBP RT%X, RF %s\n", val,
|
||||
rt2661_get_rf(sc->rf_rev));
|
||||
@ -255,6 +263,17 @@ rt2661_attach(device_t dev, int id)
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
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 = rt2661_init;
|
||||
ifp->if_ioctl = rt2661_ioctl;
|
||||
ifp->if_start = rt2661_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_name = device_get_nameunit(dev);
|
||||
ic->ic_opmode = IEEE80211_M_STA;
|
||||
@ -286,7 +305,7 @@ rt2661_attach(device_t dev, int id)
|
||||
setbit(&bands, IEEE80211_MODE_11A);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, macaddr);
|
||||
#if 0
|
||||
ic->ic_wme.wme_update = rt2661_wme_update;
|
||||
#endif
|
||||
@ -296,8 +315,7 @@ rt2661_attach(device_t dev, int id)
|
||||
ic->ic_updateslot = rt2661_update_slot;
|
||||
ic->ic_update_promisc = rt2661_update_promisc;
|
||||
ic->ic_raw_xmit = rt2661_raw_xmit;
|
||||
ic->ic_transmit = rt2661_transmit;
|
||||
ic->ic_parent = rt2661_parent;
|
||||
|
||||
ic->ic_vap_create = rt2661_vap_create;
|
||||
ic->ic_vap_delete = rt2661_vap_delete;
|
||||
|
||||
@ -321,6 +339,7 @@ fail3: rt2661_free_tx_ring(sc, &sc->mgtq);
|
||||
fail2: while (--ac >= 0)
|
||||
rt2661_free_tx_ring(sc, &sc->txq[ac]);
|
||||
fail1: mtx_destroy(&sc->sc_mtx);
|
||||
if_free(ifp);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -328,14 +347,14 @@ int
|
||||
rt2661_detach(void *xsc)
|
||||
{
|
||||
struct rt2661_softc *sc = xsc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
rt2661_stop_locked(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
ieee80211_ifdetach(ic);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
|
||||
rt2661_free_tx_ring(sc, &sc->txq[0]);
|
||||
rt2661_free_tx_ring(sc, &sc->txq[1]);
|
||||
@ -344,6 +363,8 @@ rt2661_detach(void *xsc)
|
||||
rt2661_free_tx_ring(sc, &sc->mgtq);
|
||||
rt2661_free_rx_ring(sc, &sc->rxq);
|
||||
|
||||
if_free(ifp);
|
||||
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return 0;
|
||||
@ -355,7 +376,7 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct rt2661_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2661_vap *rvp;
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
@ -368,7 +389,7 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
case IEEE80211_M_MBSS:
|
||||
/* XXXRP: TBD */
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
|
||||
device_printf(sc->sc_dev, "only 1 vap supported\n");
|
||||
if_printf(ifp, "only 1 vap supported\n");
|
||||
return NULL;
|
||||
}
|
||||
if (opmode == IEEE80211_M_STA)
|
||||
@ -377,8 +398,7 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
case IEEE80211_M_WDS:
|
||||
if (TAILQ_EMPTY(&ic->ic_vaps) ||
|
||||
ic->ic_opmode != IEEE80211_M_HOSTAP) {
|
||||
device_printf(sc->sc_dev,
|
||||
"wds only supported in ap mode\n");
|
||||
if_printf(ifp, "wds only supported in ap mode\n");
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
@ -389,12 +409,15 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
flags &= ~IEEE80211_CLONE_BSSID;
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
|
||||
if_printf(ifp, "unknown opmode %d\n", opmode);
|
||||
return NULL;
|
||||
}
|
||||
rvp = malloc(sizeof(struct rt2661_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
rvp = (struct rt2661_vap *) malloc(sizeof(struct rt2661_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);
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
|
||||
|
||||
/* override state transition machine */
|
||||
rvp->ral_newstate = vap->iv_newstate;
|
||||
@ -405,8 +428,7 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
ieee80211_ratectl_init(vap);
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
||||
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
@ -442,8 +464,9 @@ void
|
||||
rt2661_resume(void *xsc)
|
||||
{
|
||||
struct rt2661_softc *sc = xsc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (sc->sc_ic.ic_nrunning > 0)
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
rt2661_init(sc);
|
||||
}
|
||||
|
||||
@ -747,7 +770,7 @@ rt2661_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct rt2661_vap *rvp = RT2661_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct rt2661_softc *sc = ic->ic_softc;
|
||||
struct rt2661_softc *sc = ic->ic_ifp->if_softc;
|
||||
int error;
|
||||
|
||||
if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) {
|
||||
@ -846,10 +869,11 @@ rt2661_eeprom_read(struct rt2661_softc *sc, uint8_t addr)
|
||||
static void
|
||||
rt2661_tx_intr(struct rt2661_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct rt2661_tx_ring *txq;
|
||||
struct rt2661_tx_data *data;
|
||||
uint32_t val;
|
||||
int error, qid, retrycnt;
|
||||
int qid, retrycnt;
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
for (;;) {
|
||||
@ -887,7 +911,7 @@ rt2661_tx_intr(struct rt2661_softc *sc)
|
||||
ieee80211_ratectl_tx_complete(vap, ni,
|
||||
IEEE80211_RATECTL_TX_SUCCESS,
|
||||
&retrycnt, NULL);
|
||||
error = 0;
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
break;
|
||||
|
||||
case RT2661_TX_RETRY_FAIL:
|
||||
@ -899,14 +923,14 @@ rt2661_tx_intr(struct rt2661_softc *sc)
|
||||
ieee80211_ratectl_tx_complete(vap, ni,
|
||||
IEEE80211_RATECTL_TX_FAILURE,
|
||||
&retrycnt, NULL);
|
||||
error = 1;
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* other failure */
|
||||
device_printf(sc->sc_dev,
|
||||
"sending data frame failed 0x%08x\n", val);
|
||||
error = 1;
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
|
||||
DPRINTFN(sc, 15, "tx done q=%d idx=%u\n", qid, txq->stat);
|
||||
@ -915,12 +939,17 @@ rt2661_tx_intr(struct rt2661_softc *sc)
|
||||
if (++txq->stat >= txq->count) /* faster than % count */
|
||||
txq->stat = 0;
|
||||
|
||||
ieee80211_tx_complete(ni, m, error);
|
||||
if (m->m_flags & M_TXCB)
|
||||
ieee80211_process_callback(ni, m,
|
||||
RT2661_TX_RESULT(val) != RT2661_TX_SUCCESS);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
}
|
||||
|
||||
sc->sc_tx_timer = 0;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
||||
rt2661_start(sc);
|
||||
rt2661_start_locked(ifp);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -958,7 +987,8 @@ rt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2661_tx_ring *txq)
|
||||
static void
|
||||
rt2661_rx_intr(struct rt2661_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct rt2661_rx_desc *desc;
|
||||
struct rt2661_rx_data *data;
|
||||
bus_addr_t physaddr;
|
||||
@ -987,12 +1017,12 @@ rt2661_rx_intr(struct rt2661_softc *sc)
|
||||
*/
|
||||
DPRINTFN(sc, 5, "PHY or CRC error flags 0x%08x\n",
|
||||
le32toh(desc->flags));
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
if ((le32toh(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
@ -1005,7 +1035,7 @@ rt2661_rx_intr(struct rt2661_softc *sc)
|
||||
*/
|
||||
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (mnew == NULL) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
@ -1028,7 +1058,7 @@ rt2661_rx_intr(struct rt2661_softc *sc)
|
||||
panic("%s: could not load old rx mbuf",
|
||||
device_get_name(sc->sc_dev));
|
||||
}
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
@ -1041,6 +1071,7 @@ rt2661_rx_intr(struct rt2661_softc *sc)
|
||||
desc->physaddr = htole32(physaddr);
|
||||
|
||||
/* finalize mbuf */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len =
|
||||
(le32toh(desc->flags) >> 16) & 0xfff;
|
||||
|
||||
@ -1125,6 +1156,7 @@ void
|
||||
rt2661_intr(void *arg)
|
||||
{
|
||||
struct rt2661_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t r1, r2;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
@ -1134,7 +1166,7 @@ rt2661_intr(void *arg)
|
||||
RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
|
||||
|
||||
/* don't re-enable interrupts if we're shutting down */
|
||||
if (!(sc->sc_flags & RAL_RUNNING)) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
RAL_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
@ -1210,7 +1242,8 @@ rt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc,
|
||||
uint32_t flags, uint16_t xflags, int len, int rate,
|
||||
const bus_dma_segment_t *segs, int nsegs, int ac)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint16_t plcp_length;
|
||||
int i, remainder;
|
||||
|
||||
@ -1428,7 +1461,8 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
|
||||
struct ieee80211_node *ni, int ac)
|
||||
{
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct rt2661_tx_ring *txq = &sc->txq[ac];
|
||||
struct rt2661_tx_desc *desc;
|
||||
struct rt2661_tx_data *data;
|
||||
@ -1570,31 +1604,10 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rt2661_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct rt2661_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
if ((sc->sc_flags & RAL_RUNNING) == 0) {
|
||||
RAL_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
RAL_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
rt2661_start(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
rt2661_start(struct rt2661_softc *sc)
|
||||
rt2661_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct rt2661_softc *sc = ifp->if_softc;
|
||||
struct mbuf *m;
|
||||
struct ieee80211_node *ni;
|
||||
int ac;
|
||||
@ -1602,50 +1615,69 @@ rt2661_start(struct rt2661_softc *sc)
|
||||
RAL_LOCK_ASSERT(sc);
|
||||
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!(sc->sc_flags & RAL_RUNNING) || sc->sc_invalid)
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) || sc->sc_invalid)
|
||||
return;
|
||||
|
||||
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
|
||||
ac = M_WME_GETAC(m);
|
||||
if (sc->txq[ac].queued >= RT2661_TX_RING_COUNT - 1) {
|
||||
/* there is no place left in this ring */
|
||||
mbufq_prepend(&sc->sc_snd, m);
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
break;
|
||||
}
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
if (rt2661_tx_data(sc, m, ni, ac) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
sc->sc_tx_timer = 5;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rt2661_start(struct ifnet *ifp)
|
||||
{
|
||||
struct rt2661_softc *sc = ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
rt2661_start_locked(ifp);
|
||||
RAL_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
rt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct rt2661_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2661_softc *sc = ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!(sc->sc_flags & RAL_RUNNING)) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
RAL_UNLOCK(sc);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return ENETDOWN;
|
||||
}
|
||||
if (sc->mgtq.queued >= RT2661_MGT_RING_COUNT) {
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
RAL_UNLOCK(sc);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return ENOBUFS; /* XXX */
|
||||
}
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
|
||||
/*
|
||||
* Legacy path; interpret frame contents to decide
|
||||
* precisely how to send the frame.
|
||||
@ -1659,6 +1691,7 @@ rt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
|
||||
return 0;
|
||||
bad:
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
RAL_UNLOCK(sc);
|
||||
return EIO; /* XXX */
|
||||
@ -1668,42 +1701,61 @@ static void
|
||||
rt2661_watchdog(void *arg)
|
||||
{
|
||||
struct rt2661_softc *sc = (struct rt2661_softc *)arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
RAL_LOCK_ASSERT(sc);
|
||||
|
||||
KASSERT(sc->sc_flags & RAL_RUNNING, ("not running"));
|
||||
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
|
||||
|
||||
if (sc->sc_invalid) /* card ejected */
|
||||
return;
|
||||
|
||||
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
if_printf(ifp, "device timeout\n");
|
||||
rt2661_init_locked(sc);
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
/* NB: callout is reset in rt2661_init() */
|
||||
return;
|
||||
}
|
||||
callout_reset(&sc->watchdog_ch, hz, rt2661_watchdog, sc);
|
||||
}
|
||||
|
||||
static void
|
||||
rt2661_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
rt2661_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct rt2661_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
struct rt2661_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error = 0, startall = 0;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if ((sc->sc_flags & RAL_RUNNING) == 0) {
|
||||
rt2661_init_locked(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
rt2661_update_promisc(ic);
|
||||
} else if (sc->sc_flags & RAL_RUNNING)
|
||||
rt2661_stop_locked(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
RAL_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
rt2661_init_locked(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
rt2661_update_promisc(ic);
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
rt2661_stop_locked(sc);
|
||||
}
|
||||
RAL_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1827,7 +1879,8 @@ rt2661_select_antenna(struct rt2661_softc *sc)
|
||||
static void
|
||||
rt2661_enable_mrr(struct rt2661_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = RAL_READ(sc, RT2661_TXRX_CSR4);
|
||||
@ -1843,7 +1896,8 @@ rt2661_enable_mrr(struct rt2661_softc *sc)
|
||||
static void
|
||||
rt2661_set_txpreamble(struct rt2661_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = RAL_READ(sc, RT2661_TXRX_CSR4);
|
||||
@ -1860,7 +1914,8 @@ rt2661_set_basicrates(struct rt2661_softc *sc,
|
||||
const struct ieee80211_rateset *rs)
|
||||
{
|
||||
#define RV(r) ((r) & IEEE80211_RATE_VAL)
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t mask = 0;
|
||||
uint8_t rate;
|
||||
int i;
|
||||
@ -1929,7 +1984,8 @@ rt2661_select_band(struct rt2661_softc *sc, struct ieee80211_channel *c)
|
||||
static void
|
||||
rt2661_set_chan(struct rt2661_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
const struct rfprog *rfprog;
|
||||
uint8_t bbp3, bbp94 = RT2661_BBPR94_DEFAULT;
|
||||
int8_t power;
|
||||
@ -2032,13 +2088,13 @@ rt2661_update_promisc(struct ieee80211com *ic)
|
||||
tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
|
||||
|
||||
tmp &= ~RT2661_DROP_NOT_TO_ME;
|
||||
if (ic->ic_promisc == 0)
|
||||
if (!(ic->ic_ifp->if_flags & IFF_PROMISC))
|
||||
tmp |= RT2661_DROP_NOT_TO_ME;
|
||||
|
||||
RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
|
||||
|
||||
DPRINTF(sc, "%s promiscuous mode\n",
|
||||
(ic->ic_promisc > 0) ? "entering" : "leaving");
|
||||
(ic->ic_ifp->if_flags & IFF_PROMISC) ? "entering" : "leaving");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2047,7 +2103,7 @@ rt2661_update_promisc(struct ieee80211com *ic)
|
||||
static int
|
||||
rt2661_wme_update(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2661_softc *sc = ic->ic_softc;
|
||||
struct rt2661_softc *sc = ic->ic_ifp->if_softc;
|
||||
const struct wmeParams *wmep;
|
||||
|
||||
wmep = ic->ic_wme.wme_chanParams.cap_wmeParams;
|
||||
@ -2245,8 +2301,8 @@ static void
|
||||
rt2661_init_locked(struct rt2661_softc *sc)
|
||||
{
|
||||
#define N(a) (sizeof (a) / sizeof ((a)[0]))
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp, sta[3];
|
||||
int i, error, ntries;
|
||||
|
||||
@ -2255,7 +2311,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
|
||||
if ((sc->sc_flags & RAL_FW_LOADED) == 0) {
|
||||
error = rt2661_load_microcode(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
if_printf(ifp,
|
||||
"%s: could not load 8051 microcode, error %d\n",
|
||||
__func__, error);
|
||||
return;
|
||||
@ -2308,7 +2364,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
|
||||
for (i = 0; i < N(rt2661_def_mac); i++)
|
||||
RAL_WRITE(sc, rt2661_def_mac[i].reg, rt2661_def_mac[i].val);
|
||||
|
||||
rt2661_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
rt2661_set_macaddr(sc, IF_LLADDR(ifp));
|
||||
|
||||
/* set host ready */
|
||||
RAL_WRITE(sc, RT2661_MAC_CSR1, 3);
|
||||
@ -2347,7 +2403,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
|
||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
|
||||
ic->ic_opmode != IEEE80211_M_MBSS)
|
||||
tmp |= RT2661_DROP_TODS;
|
||||
if (ic->ic_promisc == 0)
|
||||
if (!(ifp->if_flags & IFF_PROMISC))
|
||||
tmp |= RT2661_DROP_NOT_TO_ME;
|
||||
}
|
||||
|
||||
@ -2369,7 +2425,8 @@ rt2661_init_locked(struct rt2661_softc *sc)
|
||||
/* kick Rx */
|
||||
RAL_WRITE(sc, RT2661_RX_CNTL_CSR, 1);
|
||||
|
||||
sc->sc_flags |= RAL_RUNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
|
||||
callout_reset(&sc->watchdog_ch, hz, rt2661_watchdog, sc);
|
||||
#undef N
|
||||
@ -2379,21 +2436,23 @@ static void
|
||||
rt2661_init(void *priv)
|
||||
{
|
||||
struct rt2661_softc *sc = priv;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
rt2661_init_locked(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
if (sc->sc_flags & RAL_RUNNING)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic); /* start all vap's */
|
||||
}
|
||||
|
||||
void
|
||||
rt2661_stop_locked(struct rt2661_softc *sc)
|
||||
{
|
||||
volatile int *flags = &sc->sc_flags;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t tmp;
|
||||
volatile int *flags = &sc->sc_flags;
|
||||
|
||||
while (*flags & RAL_INPUT_RUNNING)
|
||||
msleep(sc, &sc->sc_mtx, 0, "ralrunning", hz/10);
|
||||
@ -2401,8 +2460,8 @@ rt2661_stop_locked(struct rt2661_softc *sc)
|
||||
callout_stop(&sc->watchdog_ch);
|
||||
sc->sc_tx_timer = 0;
|
||||
|
||||
if (sc->sc_flags & RAL_RUNNING) {
|
||||
sc->sc_flags &= ~RAL_RUNNING;
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
/* abort Tx (for all 5 Tx rings) */
|
||||
RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 0x1f << 16);
|
||||
@ -2446,6 +2505,7 @@ rt2661_stop(void *priv)
|
||||
static int
|
||||
rt2661_load_microcode(struct rt2661_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
const struct firmware *fp;
|
||||
const char *imagename;
|
||||
int ntries, error;
|
||||
@ -2457,7 +2517,7 @@ rt2661_load_microcode(struct rt2661_softc *sc)
|
||||
case 0x0302: imagename = "rt2561fw"; break;
|
||||
case 0x0401: imagename = "rt2661fw"; break;
|
||||
default:
|
||||
device_printf(sc->sc_dev, "%s: unexpected pci device id 0x%x, "
|
||||
if_printf(ifp, "%s: unexpected pci device id 0x%x, "
|
||||
"don't know how to retrieve firmware\n",
|
||||
__func__, sc->sc_id);
|
||||
return EINVAL;
|
||||
@ -2466,8 +2526,7 @@ rt2661_load_microcode(struct rt2661_softc *sc)
|
||||
fp = firmware_get(imagename);
|
||||
RAL_LOCK(sc);
|
||||
if (fp == NULL) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: unable to retrieve firmware image %s\n",
|
||||
if_printf(ifp, "%s: unable to retrieve firmware image %s\n",
|
||||
__func__, imagename);
|
||||
return EINVAL;
|
||||
}
|
||||
@ -2498,8 +2557,8 @@ rt2661_load_microcode(struct rt2661_softc *sc)
|
||||
DELAY(100);
|
||||
}
|
||||
if (ntries == 500) {
|
||||
device_printf(sc->sc_dev,
|
||||
"%s: timeout waiting for MCU to initialize\n", __func__);
|
||||
if_printf(ifp, "%s: timeout waiting for MCU to initialize\n",
|
||||
__func__);
|
||||
error = EIO;
|
||||
} else
|
||||
error = 0;
|
||||
@ -2667,7 +2726,8 @@ rt2661_prepare_beacon(struct rt2661_softc *sc, struct ieee80211vap *vap)
|
||||
static void
|
||||
rt2661_enable_tsf_sync(struct rt2661_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);
|
||||
uint32_t tmp;
|
||||
|
||||
@ -2751,19 +2811,21 @@ rt2661_get_rssi(struct rt2661_softc *sc, uint8_t raw)
|
||||
static void
|
||||
rt2661_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2661_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2661_softc *sc = ifp->if_softc;
|
||||
uint32_t tmp;
|
||||
|
||||
/* abort TSF synchronization */
|
||||
tmp = RAL_READ(sc, RT2661_TXRX_CSR9);
|
||||
RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp & ~0xffffff);
|
||||
rt2661_set_bssid(sc, ieee80211broadcastaddr);
|
||||
rt2661_set_bssid(sc, ifp->if_broadcastaddr);
|
||||
}
|
||||
|
||||
static void
|
||||
rt2661_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2661_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2661_softc *sc = ifp->if_softc;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
|
||||
rt2661_enable_tsf_sync(sc);
|
||||
@ -2774,7 +2836,8 @@ rt2661_scan_end(struct ieee80211com *ic)
|
||||
static void
|
||||
rt2661_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2661_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2661_softc *sc = ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
rt2661_set_chan(sc, ic->ic_curchan);
|
||||
|
@ -97,13 +97,13 @@ struct rt2661_vap {
|
||||
#define RT2661_VAP(vap) ((struct rt2661_vap *)(vap))
|
||||
|
||||
struct rt2661_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mtx sc_mtx;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_st;
|
||||
bus_space_handle_t sc_sh;
|
||||
|
||||
struct mtx sc_mtx;
|
||||
|
||||
struct callout watchdog_ch;
|
||||
|
||||
int sc_tx_timer;
|
||||
@ -117,7 +117,6 @@ struct rt2661_softc {
|
||||
int sc_flags;
|
||||
#define RAL_FW_LOADED 0x1
|
||||
#define RAL_INPUT_RUNNING 0x2
|
||||
#define RAL_RUNNING 0x4
|
||||
int sc_id;
|
||||
struct ieee80211_channel *sc_curchan;
|
||||
|
||||
|
@ -122,10 +122,10 @@ static int rt2860_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
static int rt2860_tx_raw(struct rt2860_softc *, struct mbuf *,
|
||||
struct ieee80211_node *,
|
||||
const struct ieee80211_bpf_params *params);
|
||||
static int rt2860_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void rt2860_start(struct rt2860_softc *);
|
||||
static void rt2860_start(struct ifnet *);
|
||||
static void rt2860_start_locked(struct ifnet *);
|
||||
static void rt2860_watchdog(void *);
|
||||
static void rt2860_parent(struct ieee80211com *);
|
||||
static int rt2860_ioctl(struct ifnet *, u_long, caddr_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 void rt2860_rf_write(struct rt2860_softc *, uint8_t, uint32_t);
|
||||
@ -156,7 +156,7 @@ static void rt2860_set_bssid(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_updateslot(struct ieee80211com *);
|
||||
static void rt2860_updateprot(struct rt2860_softc *);
|
||||
static void rt2860_updateprot(struct ifnet *);
|
||||
static int rt2860_updateedca(struct ieee80211com *);
|
||||
#ifdef HW_CRYPTO
|
||||
static int rt2860_set_key(struct ieee80211com *, struct ieee80211_node *,
|
||||
@ -230,19 +230,27 @@ int
|
||||
rt2860_attach(device_t dev, int id)
|
||||
{
|
||||
struct rt2860_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
uint32_t tmp;
|
||||
int error, ntries, qid;
|
||||
uint8_t bands;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
sc->sc_dev = dev;
|
||||
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_DEF | MTX_RECURSE);
|
||||
|
||||
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
/* wait for NIC to initialize */
|
||||
for (ntries = 0; ntries < 100; ntries++) {
|
||||
@ -265,11 +273,11 @@ rt2860_attach(device_t dev, int id)
|
||||
sc->sc_flags |= RT2860_ADVANCED_PS;
|
||||
|
||||
/* retrieve RF rev. no and various other things from EEPROM */
|
||||
rt2860_read_eeprom(sc, ic->ic_macaddr);
|
||||
rt2860_read_eeprom(sc, macaddr);
|
||||
device_printf(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), "
|
||||
"RF %s (MIMO %dT%dR), address %6D\n",
|
||||
sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev),
|
||||
sc->ntxchains, sc->nrxchains, ic->ic_macaddr, ":");
|
||||
sc->ntxchains, sc->nrxchains, macaddr, ":");
|
||||
|
||||
/*
|
||||
* Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings.
|
||||
@ -296,6 +304,17 @@ rt2860_attach(device_t dev, int id)
|
||||
sc->mgtqid = (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) ?
|
||||
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_name = device_get_nameunit(dev);
|
||||
ic->ic_opmode = IEEE80211_M_STA;
|
||||
@ -326,7 +345,7 @@ rt2860_attach(device_t dev, int id)
|
||||
setbit(&bands, IEEE80211_MODE_11A);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, macaddr);
|
||||
|
||||
ic->ic_wme.wme_update = rt2860_updateedca;
|
||||
ic->ic_scan_start = rt2860_scan_start;
|
||||
@ -338,8 +357,7 @@ rt2860_attach(device_t dev, int id)
|
||||
sc->sc_node_free = ic->ic_node_free;
|
||||
ic->ic_node_free = rt2860_node_free;
|
||||
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_delete = rt2860_vap_delete;
|
||||
|
||||
@ -363,6 +381,7 @@ fail3: rt2860_free_rx_ring(sc, &sc->rxq);
|
||||
fail2: while (--qid >= 0)
|
||||
rt2860_free_tx_ring(sc, &sc->txq[qid]);
|
||||
fail1: mtx_destroy(&sc->sc_mtx);
|
||||
if_free(ifp);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -370,7 +389,8 @@ int
|
||||
rt2860_detach(void *xsc)
|
||||
{
|
||||
struct rt2860_softc *sc = xsc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
int qid;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
@ -378,12 +398,14 @@ rt2860_detach(void *xsc)
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
ieee80211_ifdetach(ic);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
|
||||
for (qid = 0; qid < 6; qid++)
|
||||
rt2860_free_tx_ring(sc, &sc->txq[qid]);
|
||||
rt2860_free_rx_ring(sc, &sc->rxq);
|
||||
rt2860_free_tx_pool(sc);
|
||||
|
||||
if_free(ifp);
|
||||
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return 0;
|
||||
@ -409,8 +431,9 @@ void
|
||||
rt2860_resume(void *xsc)
|
||||
{
|
||||
struct rt2860_softc *sc = xsc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (sc->sc_ic.ic_nrunning > 0)
|
||||
if (ifp->if_flags & IFF_UP)
|
||||
rt2860_init(sc);
|
||||
}
|
||||
|
||||
@ -420,7 +443,7 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2860_vap *rvp;
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
@ -433,7 +456,7 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
case IEEE80211_M_MBSS:
|
||||
/* XXXRP: TBD */
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
|
||||
device_printf(sc->sc_dev, "only 1 vap supported\n");
|
||||
if_printf(ifp, "only 1 vap supported\n");
|
||||
return NULL;
|
||||
}
|
||||
if (opmode == IEEE80211_M_STA)
|
||||
@ -442,8 +465,7 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
case IEEE80211_M_WDS:
|
||||
if (TAILQ_EMPTY(&ic->ic_vaps) ||
|
||||
ic->ic_opmode != IEEE80211_M_HOSTAP) {
|
||||
device_printf(sc->sc_dev,
|
||||
"wds only supported in ap mode\n");
|
||||
if_printf(ifp, "wds only supported in ap mode\n");
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
@ -454,12 +476,14 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
flags &= ~IEEE80211_CLONE_BSSID;
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
|
||||
if_printf(ifp, "unknown opmode %d\n", opmode);
|
||||
return NULL;
|
||||
}
|
||||
rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
rvp = malloc(sizeof(struct rt2860_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);
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
|
||||
|
||||
/* override state transition machine */
|
||||
rvp->ral_newstate = vap->iv_newstate;
|
||||
@ -473,8 +497,7 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
ieee80211_ratectl_init(vap);
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
||||
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
@ -806,7 +829,7 @@ rt2860_free_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring)
|
||||
static void
|
||||
rt2860_updatestats(struct rt2860_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
|
||||
/*
|
||||
* In IBSS or HostAP modes (when the hardware sends beacons), the
|
||||
@ -833,7 +856,7 @@ static void
|
||||
rt2860_newassoc(struct ieee80211_node *ni, int isnew)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
struct rt2860_softc *sc = ic->ic_ifp->if_softc;
|
||||
uint8_t wcid;
|
||||
|
||||
wcid = IEEE80211_AID(ni->ni_associd);
|
||||
@ -852,7 +875,7 @@ static void
|
||||
rt2860_node_free(struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
struct rt2860_softc *sc = ic->ic_ifp->if_softc;
|
||||
uint8_t wcid;
|
||||
|
||||
if (ni->ni_associd != 0) {
|
||||
@ -900,7 +923,7 @@ rt2860_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct rt2860_vap *rvp = RT2860_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
struct rt2860_softc *sc = ic->ic_ifp->if_softc;
|
||||
uint32_t tmp;
|
||||
int error;
|
||||
|
||||
@ -1078,6 +1101,7 @@ rt2860_intr_coherent(struct rt2860_softc *sc)
|
||||
static void
|
||||
rt2860_drain_stats_fifo(struct rt2860_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211_node *ni;
|
||||
uint32_t stat;
|
||||
int retrycnt;
|
||||
@ -1113,8 +1137,7 @@ rt2860_drain_stats_fifo(struct rt2860_softc *sc)
|
||||
} else {
|
||||
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
|
||||
IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL);
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1122,6 +1145,7 @@ rt2860_drain_stats_fifo(struct rt2860_softc *sc)
|
||||
static void
|
||||
rt2860_tx_intr(struct rt2860_softc *sc, int qid)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct rt2860_tx_ring *ring = &sc->txq[qid];
|
||||
uint32_t hw;
|
||||
|
||||
@ -1139,11 +1163,15 @@ rt2860_tx_intr(struct rt2860_softc *sc, int qid)
|
||||
ieee80211_process_callback(data->ni, data->m,
|
||||
0);
|
||||
}
|
||||
ieee80211_tx_complete(data->ni, data->m, 0);
|
||||
data->ni = NULL;
|
||||
m_freem(data->m);
|
||||
ieee80211_free_node(data->ni);
|
||||
data->m = NULL;
|
||||
data->ni = NULL;
|
||||
|
||||
SLIST_INSERT_HEAD(&sc->data_pool, data, next);
|
||||
ring->data[ring->next] = NULL;
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
}
|
||||
ring->queued--;
|
||||
ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT;
|
||||
@ -1152,7 +1180,8 @@ rt2860_tx_intr(struct rt2860_softc *sc, int qid)
|
||||
sc->sc_tx_timer = 0;
|
||||
if (ring->queued < RT2860_TX_RING_COUNT)
|
||||
sc->qfullmsk &= ~(1 << qid);
|
||||
rt2860_start(sc);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
rt2860_start_locked(ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1177,7 +1206,8 @@ static void
|
||||
rt2860_rx_intr(struct rt2860_softc *sc)
|
||||
{
|
||||
struct rt2860_rx_radiotap_header *tap;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m, *m1;
|
||||
@ -1204,7 +1234,7 @@ rt2860_rx_intr(struct rt2860_softc *sc)
|
||||
|
||||
if (__predict_false(rxd->flags &
|
||||
htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
@ -1213,14 +1243,14 @@ rt2860_rx_intr(struct rt2860_softc *sc)
|
||||
/* report MIC failures to net80211 for TKIP */
|
||||
ic->ic_stats.is_rx_locmicfail++;
|
||||
ieee80211_michael_mic_failure(ic, 0/* XXX */);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
#endif
|
||||
|
||||
m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (__predict_false(m1 == NULL)) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
@ -1244,7 +1274,7 @@ rt2860_rx_intr(struct rt2860_softc *sc)
|
||||
}
|
||||
/* physical address may have changed */
|
||||
rxd->sdp0 = htole32(physaddr);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto skip;
|
||||
}
|
||||
|
||||
@ -1259,6 +1289,7 @@ rt2860_rx_intr(struct rt2860_softc *sc)
|
||||
rxwi = mtod(m, struct rt2860_rxwi *);
|
||||
|
||||
/* finalize mbuf */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_data = (caddr_t)(rxwi + 1);
|
||||
m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff;
|
||||
|
||||
@ -1368,7 +1399,7 @@ rt2860_tbtt_intr(struct rt2860_softc *sc)
|
||||
#endif
|
||||
/* check if protection mode has changed */
|
||||
if ((sc->sc_ic_flags ^ ic->ic_flags) & IEEE80211_F_USEPROT) {
|
||||
rt2860_updateprot(sc);
|
||||
rt2860_updateprot(ic);
|
||||
sc->sc_ic_flags = ic->ic_flags;
|
||||
}
|
||||
#endif
|
||||
@ -1377,7 +1408,7 @@ rt2860_tbtt_intr(struct rt2860_softc *sc)
|
||||
static void
|
||||
rt2860_gp_intr(struct rt2860_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
|
||||
DPRINTFN(2, ("GP timeout state=%d\n", vap->iv_state));
|
||||
@ -1449,7 +1480,8 @@ rt2860_intr(void *arg)
|
||||
static int
|
||||
rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct rt2860_tx_ring *ring;
|
||||
struct rt2860_tx_data *data;
|
||||
@ -1693,13 +1725,14 @@ rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2860_softc *sc = ifp->if_softc;
|
||||
int error;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!(sc->sc_flags & RT2860_RUNNNING)) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
RAL_UNLOCK(sc);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
@ -1721,6 +1754,7 @@ rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
if (error != 0) {
|
||||
/* NB: m is reclaimed on tx failure */
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
sc->sc_tx_timer = 5;
|
||||
RAL_UNLOCK(sc);
|
||||
@ -1731,7 +1765,8 @@ static int
|
||||
rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m,
|
||||
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 ieee80211vap *vap = ni->ni_vap;
|
||||
struct rt2860_tx_ring *ring;
|
||||
struct rt2860_tx_data *data;
|
||||
@ -1938,46 +1973,41 @@ rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rt2860_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
static void
|
||||
rt2860_start(struct ifnet *ifp)
|
||||
{
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
struct rt2860_softc *sc = ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
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);
|
||||
rt2860_start_locked(ifp);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
rt2860_start(struct rt2860_softc *sc)
|
||||
rt2860_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct rt2860_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
RAL_LOCK_ASSERT(sc);
|
||||
|
||||
if ((sc->sc_flags & RT2860_RUNNNING) == 0)
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
|
||||
(ifp->if_drv_flags & IFF_DRV_OACTIVE))
|
||||
return;
|
||||
|
||||
while (!SLIST_EMPTY(&sc->data_pool) && sc->qfullmsk == 0 &&
|
||||
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
for (;;) {
|
||||
if (SLIST_EMPTY(&sc->data_pool) || sc->qfullmsk != 0) {
|
||||
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;
|
||||
if (rt2860_tx(sc, m, ni) != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
continue;
|
||||
}
|
||||
sc->sc_tx_timer = 5;
|
||||
@ -1988,42 +2018,61 @@ static void
|
||||
rt2860_watchdog(void *arg)
|
||||
{
|
||||
struct rt2860_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
RAL_LOCK_ASSERT(sc);
|
||||
|
||||
KASSERT(sc->sc_flags & RT2860_RUNNNING, ("not running"));
|
||||
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
|
||||
|
||||
if (sc->sc_invalid) /* card ejected */
|
||||
return;
|
||||
|
||||
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
if_printf(ifp, "device timeout\n");
|
||||
rt2860_stop_locked(sc);
|
||||
rt2860_init_locked(sc);
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return;
|
||||
}
|
||||
callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc);
|
||||
}
|
||||
|
||||
static void
|
||||
rt2860_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
rt2860_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
struct rt2860_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *)data;
|
||||
int error = 0, startall = 0;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
if (ic->ic_nrunning> 0) {
|
||||
if (!(sc->sc_flags & RT2860_RUNNNING)) {
|
||||
rt2860_init_locked(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
rt2860_update_promisc(ic);
|
||||
} else if (sc->sc_flags & RT2860_RUNNNING)
|
||||
rt2860_stop_locked(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
RAL_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
rt2860_init_locked(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
rt2860_update_promisc(ic);
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
rt2860_stop_locked(sc);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2246,7 +2295,8 @@ rt2860_enable_mrr(struct rt2860_softc *sc)
|
||||
static void
|
||||
rt2860_set_txpreamble(struct rt2860_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = RAL_READ(sc, RT2860_AUTO_RSP_CFG);
|
||||
@ -2261,7 +2311,8 @@ rt2860_set_basicrates(struct rt2860_softc *sc,
|
||||
const struct ieee80211_rateset *rs)
|
||||
{
|
||||
#define RV(r) ((r) & IEEE80211_RATE_VAL)
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t mask = 0;
|
||||
uint8_t rate;
|
||||
int i;
|
||||
@ -2282,7 +2333,8 @@ rt2860_set_basicrates(struct rt2860_softc *sc,
|
||||
static void
|
||||
rt2860_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2860_softc *sc = ifp->if_softc;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG);
|
||||
@ -2295,7 +2347,8 @@ rt2860_scan_start(struct ieee80211com *ic)
|
||||
static void
|
||||
rt2860_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2860_softc *sc = ifp->if_softc;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
|
||||
if (vap->iv_state == IEEE80211_S_RUN) {
|
||||
@ -2307,7 +2360,8 @@ rt2860_scan_end(struct ieee80211com *ic)
|
||||
static void
|
||||
rt2860_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rt2860_softc *sc = ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
rt2860_switch_chan(sc, ic->ic_curchan);
|
||||
@ -3059,9 +3113,10 @@ rt2860_updateslot(struct ieee80211com *ic)
|
||||
}
|
||||
|
||||
static void
|
||||
rt2860_updateprot(struct rt2860_softc *sc)
|
||||
rt2860_updateprot(struct ifnet *ifp)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct rt2860_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL;
|
||||
@ -3090,7 +3145,7 @@ rt2860_update_promisc(struct ieee80211com *ic)
|
||||
|
||||
tmp = RAL_READ(sc, RT2860_RX_FILTR_CFG);
|
||||
tmp &= ~RT2860_DROP_NOT_MYBSS;
|
||||
if (ic->ic_promisc == 0)
|
||||
if (!(ic->ic_ifp->if_flags & IFF_PROMISC))
|
||||
tmp |= RT2860_DROP_NOT_MYBSS;
|
||||
RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp);
|
||||
}
|
||||
@ -3098,7 +3153,7 @@ rt2860_update_promisc(struct ieee80211com *ic)
|
||||
static int
|
||||
rt2860_updateedca(struct ieee80211com *ic)
|
||||
{
|
||||
struct rt2860_softc *sc = ic->ic_softc;
|
||||
struct rt2860_softc *sc = ic->ic_ifp->if_softc;
|
||||
const struct wmeParams *wmep;
|
||||
int aci;
|
||||
|
||||
@ -3270,7 +3325,8 @@ rt2860_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
|
||||
static int8_t
|
||||
rt2860_rssi2dbm(struct rt2860_softc *sc, uint8_t rssi, uint8_t rxchain)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_channel *c = ic->ic_curchan;
|
||||
int delta;
|
||||
|
||||
@ -3745,7 +3801,8 @@ rt5390_bbp_init(struct rt2860_softc *sc)
|
||||
static int
|
||||
rt2860_txrx_enable(struct rt2860_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
int ntries;
|
||||
|
||||
@ -3791,21 +3848,22 @@ static void
|
||||
rt2860_init(void *arg)
|
||||
{
|
||||
struct rt2860_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
rt2860_init_locked(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
if (sc->sc_flags & RT2860_RUNNNING)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic);
|
||||
}
|
||||
|
||||
static void
|
||||
rt2860_init_locked(struct rt2860_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
uint8_t bbp1, bbp3;
|
||||
int i, qid, ridx, ntries, error;
|
||||
@ -3841,7 +3899,7 @@ rt2860_init_locked(struct rt2860_softc *sc)
|
||||
return;
|
||||
}
|
||||
|
||||
rt2860_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
rt2860_set_macaddr(sc, IF_LLADDR(ifp));
|
||||
|
||||
/* init Tx power for all Tx rates (from EEPROM) */
|
||||
for (ridx = 0; ridx < 5; ridx++) {
|
||||
@ -4038,7 +4096,7 @@ rt2860_init_locked(struct rt2860_softc *sc)
|
||||
RAL_WRITE(sc, RT2860_TX_RTS_CFG, tmp);
|
||||
|
||||
/* setup initial protection mode */
|
||||
rt2860_updateprot(sc);
|
||||
rt2860_updateprot(ifp);
|
||||
|
||||
/* turn radio LED on */
|
||||
rt2860_set_leds(sc, RT2860_LED_RADIO);
|
||||
@ -4057,7 +4115,8 @@ rt2860_init_locked(struct rt2860_softc *sc)
|
||||
if (sc->sc_flags & RT2860_ADVANCED_PS)
|
||||
rt2860_mcu_cmd(sc, RT2860_MCU_CMD_PSLEVEL, sc->pslevel, 0);
|
||||
|
||||
sc->sc_flags |= RT2860_RUNNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
|
||||
callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc);
|
||||
}
|
||||
@ -4075,15 +4134,16 @@ rt2860_stop(void *arg)
|
||||
static void
|
||||
rt2860_stop_locked(struct rt2860_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t tmp;
|
||||
int qid;
|
||||
|
||||
if (sc->sc_flags & RT2860_RUNNNING)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
rt2860_set_leds(sc, 0); /* turn all LEDs off */
|
||||
|
||||
callout_stop(&sc->watchdog_ch);
|
||||
sc->sc_tx_timer = 0;
|
||||
sc->sc_flags &= ~RT2860_RUNNNING;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
/* disable interrupts */
|
||||
RAL_WRITE(sc, RT2860_INT_MASK, 0);
|
||||
@ -4234,7 +4294,8 @@ rt3090_set_rx_antenna(struct rt2860_softc *sc, int aux)
|
||||
static void
|
||||
rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
u_int chan, group;
|
||||
|
||||
chan = ieee80211_chan2ieee(ic, c);
|
||||
@ -4303,7 +4364,8 @@ rt2860_setup_beacon(struct rt2860_softc *sc, struct ieee80211vap *vap)
|
||||
static void
|
||||
rt2860_enable_tsf_sync(struct rt2860_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);
|
||||
uint32_t tmp;
|
||||
|
||||
|
@ -115,13 +115,13 @@ struct rt2860_vap {
|
||||
#define RT2860_VAP(vap) ((struct rt2860_vap *)(vap))
|
||||
|
||||
struct rt2860_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct mtx sc_mtx;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
bus_space_tag_t sc_st;
|
||||
bus_space_handle_t sc_sh;
|
||||
|
||||
struct mtx sc_mtx;
|
||||
|
||||
struct callout watchdog_ch;
|
||||
|
||||
int sc_invalid;
|
||||
@ -139,7 +139,6 @@ struct rt2860_softc {
|
||||
#define RT2860_ENABLED (1 << 0)
|
||||
#define RT2860_ADVANCED_PS (1 << 1)
|
||||
#define RT2860_PCIE (1 << 2)
|
||||
#define RT2860_RUNNNING (1 << 3)
|
||||
|
||||
struct ieee80211_node *wcid2ni[RT2860_WCID_MAX];
|
||||
|
||||
|
@ -187,13 +187,15 @@ static struct mbuf *
|
||||
static void rsu_txeof(struct usb_xfer *, struct rsu_data *);
|
||||
static int rsu_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static void rsu_init(struct rsu_softc *);
|
||||
static void rsu_init(void *);
|
||||
static void rsu_init_locked(struct rsu_softc *);
|
||||
static int rsu_tx_start(struct rsu_softc *, struct ieee80211_node *,
|
||||
struct mbuf *, struct rsu_data *);
|
||||
static int rsu_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void rsu_start(struct rsu_softc *);
|
||||
static void rsu_parent(struct ieee80211com *);
|
||||
static void rsu_stop(struct rsu_softc *);
|
||||
static void rsu_start(struct ifnet *);
|
||||
static void rsu_start_locked(struct ifnet *);
|
||||
static int rsu_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void rsu_stop(struct ifnet *, int);
|
||||
static void rsu_stop_locked(struct ifnet *, int);
|
||||
static void rsu_ms_delay(struct rsu_softc *);
|
||||
|
||||
static device_method_t rsu_methods[] = {
|
||||
@ -283,7 +285,8 @@ rsu_attach(device_t self)
|
||||
{
|
||||
struct usb_attach_arg *uaa = device_get_ivars(self);
|
||||
struct rsu_softc *sc = device_get_softc(self);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
int error;
|
||||
uint8_t iface_index, bands;
|
||||
|
||||
@ -295,7 +298,6 @@ rsu_attach(device_t self)
|
||||
MTX_DEF);
|
||||
TIMEOUT_TASK_INIT(taskqueue_thread, &sc->calib_task, 0,
|
||||
rsu_calib_task, sc);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
/* Allocate Tx/Rx buffers. */
|
||||
error = rsu_alloc_rx_list(sc);
|
||||
@ -331,9 +333,28 @@ rsu_attach(device_t self)
|
||||
device_printf(self, "could not read ROM\n");
|
||||
goto fail_rom;
|
||||
}
|
||||
IEEE80211_ADDR_COPY(ic->ic_macaddr, &sc->rom[0x12]);
|
||||
IEEE80211_ADDR_COPY(sc->sc_bssid, &sc->rom[0x12]);
|
||||
device_printf(self, "MAC/BB RTL8712 cut %d\n", sc->cut);
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(self, "cannot allocate interface\n");
|
||||
goto fail_ifalloc;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "rsu", device_get_unit(self));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_init = rsu_init;
|
||||
ifp->if_ioctl = rsu_ioctl;
|
||||
ifp->if_start = rsu_start;
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
ifp->if_capabilities |= IFCAP_RXCSUM;
|
||||
ifp->if_capenable |= IFCAP_RXCSUM;
|
||||
ifp->if_hwassist = CSUM_TCP;
|
||||
|
||||
ic->ic_ifp = ifp;
|
||||
ic->ic_softc = sc;
|
||||
ic->ic_name = device_get_nameunit(self);
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */
|
||||
@ -366,7 +387,7 @@ rsu_attach(device_t self)
|
||||
setbit(&bands, IEEE80211_MODE_11G);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, sc->sc_bssid);
|
||||
ic->ic_raw_xmit = rsu_raw_xmit;
|
||||
ic->ic_scan_start = rsu_scan_start;
|
||||
ic->ic_scan_end = rsu_scan_end;
|
||||
@ -374,8 +395,6 @@ rsu_attach(device_t self)
|
||||
ic->ic_vap_create = rsu_vap_create;
|
||||
ic->ic_vap_delete = rsu_vap_delete;
|
||||
ic->ic_update_mcast = rsu_update_mcast;
|
||||
ic->ic_parent = rsu_parent;
|
||||
ic->ic_transmit = rsu_transmit;
|
||||
|
||||
ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr,
|
||||
sizeof(sc->sc_txtap), RSU_TX_RADIOTAP_PRESENT,
|
||||
@ -387,6 +406,7 @@ rsu_attach(device_t self)
|
||||
|
||||
return (0);
|
||||
|
||||
fail_ifalloc:
|
||||
fail_rom:
|
||||
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
|
||||
fail_usb:
|
||||
@ -398,11 +418,10 @@ static int
|
||||
rsu_detach(device_t self)
|
||||
{
|
||||
struct rsu_softc *sc = device_get_softc(self);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RSU_LOCK(sc);
|
||||
rsu_stop(sc);
|
||||
RSU_UNLOCK(sc);
|
||||
rsu_stop(ifp, 1);
|
||||
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
|
||||
ieee80211_ifdetach(ic);
|
||||
|
||||
@ -412,7 +431,7 @@ rsu_detach(device_t self)
|
||||
rsu_free_tx_list(sc);
|
||||
rsu_free_rx_list(sc);
|
||||
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
if_free(ifp);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -452,11 +471,14 @@ rsu_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
|
||||
return (NULL);
|
||||
|
||||
uvp = malloc(sizeof(struct rsu_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
uvp = (struct rsu_vap *) malloc(sizeof(struct rsu_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (uvp == NULL)
|
||||
return (NULL);
|
||||
vap = &uvp->vap;
|
||||
|
||||
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
|
||||
flags, bssid) != 0) {
|
||||
flags, bssid, mac) != 0) {
|
||||
/* out of memory */
|
||||
free(uvp, M_80211_VAP);
|
||||
return (NULL);
|
||||
@ -468,7 +490,7 @@ rsu_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
|
||||
return (vap);
|
||||
@ -486,8 +508,9 @@ rsu_vap_delete(struct ieee80211vap *vap)
|
||||
static void
|
||||
rsu_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct rsu_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rsu_softc *sc = ifp->if_softc;
|
||||
|
||||
/* Scanning is done by the firmware. */
|
||||
RSU_LOCK(sc);
|
||||
@ -653,8 +676,11 @@ rsu_getbuf(struct rsu_softc *sc)
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
|
||||
bf = _rsu_getbuf(sc);
|
||||
if (bf == NULL)
|
||||
if (bf == NULL) {
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
DPRINTF("stop queue\n");
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
}
|
||||
return (bf);
|
||||
}
|
||||
|
||||
@ -909,7 +935,7 @@ rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct rsu_vap *uvp = RSU_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct rsu_softc *sc = ic->ic_softc;
|
||||
struct rsu_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct ieee80211_rateset *rs;
|
||||
enum ieee80211_state ostate;
|
||||
@ -1007,27 +1033,29 @@ static int
|
||||
rsu_site_survey(struct rsu_softc *sc, struct ieee80211vap *vap)
|
||||
{
|
||||
struct r92s_fw_cmd_sitesurvey cmd;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->sc_scan_pass == 1)
|
||||
if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->scan_pass == 1)
|
||||
cmd.active = htole32(1);
|
||||
cmd.limit = htole32(48);
|
||||
if (sc->sc_scan_pass == 1 && vap->iv_des_nssid > 0) {
|
||||
if (sc->scan_pass == 1 && vap->iv_des_nssid > 0) {
|
||||
/* Do a directed scan for second pass. */
|
||||
cmd.ssidlen = htole32(vap->iv_des_ssid[0].len);
|
||||
memcpy(cmd.ssid, vap->iv_des_ssid[0].ssid,
|
||||
vap->iv_des_ssid[0].len);
|
||||
|
||||
}
|
||||
DPRINTF("sending site survey command, pass=%d\n", sc->sc_scan_pass);
|
||||
DPRINTF("sending site survey command, pass=%d\n", sc->scan_pass);
|
||||
return (rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY, &cmd, sizeof(cmd)));
|
||||
}
|
||||
|
||||
static int
|
||||
rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ndis_wlan_bssid_ex *bss;
|
||||
struct ndis_802_11_fixed_ies *fixed;
|
||||
@ -1105,7 +1133,8 @@ rsu_disconnect(struct rsu_softc *sc)
|
||||
static void
|
||||
rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_channel *c;
|
||||
struct ndis_wlan_bssid_ex *bss;
|
||||
@ -1136,7 +1165,7 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
|
||||
IEEE80211_FC0_SUBTYPE_BEACON;
|
||||
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
|
||||
USETW(wh->i_dur, 0);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr);
|
||||
IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr);
|
||||
*(uint16_t *)wh->i_seq = 0;
|
||||
@ -1144,6 +1173,7 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
|
||||
|
||||
/* Finalize mbuf. */
|
||||
m->m_pkthdr.len = m->m_len = pktlen;
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
/* Fix the channel. */
|
||||
c = ieee80211_find_channel_byieee(ic,
|
||||
le32toh(bss->config.dsconfig),
|
||||
@ -1161,7 +1191,8 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
|
||||
static void
|
||||
rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
|
||||
{
|
||||
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 ieee80211_node *ni = vap->iv_bss;
|
||||
struct r92s_event_join_bss *rsp;
|
||||
@ -1197,7 +1228,8 @@ rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
|
||||
static void
|
||||
rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
|
||||
{
|
||||
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);
|
||||
|
||||
DPRINTFN(4, "Rx event code=%d len=%d\n", code, len);
|
||||
@ -1208,18 +1240,18 @@ rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
|
||||
break;
|
||||
case R92S_EVT_SURVEY_DONE:
|
||||
DPRINTF("site survey pass %d done, found %d BSS\n",
|
||||
sc->sc_scan_pass, le32toh(*(uint32_t *)buf));
|
||||
sc->scan_pass, le32toh(*(uint32_t *)buf));
|
||||
if (vap->iv_state != IEEE80211_S_SCAN)
|
||||
break; /* Ignore if not scanning. */
|
||||
if (sc->sc_scan_pass == 0 && vap->iv_des_nssid != 0) {
|
||||
if (sc->scan_pass == 0 && vap->iv_des_nssid != 0) {
|
||||
/* Schedule a directed scan for hidden APs. */
|
||||
sc->sc_scan_pass = 1;
|
||||
sc->scan_pass = 1;
|
||||
RSU_UNLOCK(sc);
|
||||
ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
|
||||
RSU_LOCK(sc);
|
||||
break;
|
||||
}
|
||||
sc->sc_scan_pass = 0;
|
||||
sc->scan_pass = 0;
|
||||
break;
|
||||
case R92S_EVT_JOIN_BSS:
|
||||
if (vap->iv_state == IEEE80211_S_AUTH)
|
||||
@ -1242,7 +1274,7 @@ XXX and disrupts the WLAN traffic. Disable for now.
|
||||
DPRINTF("WPS PBC pushed.\n");
|
||||
break;
|
||||
case R92S_EVT_FWDBG:
|
||||
if (vap->iv_ifp->if_flags & IFF_DEBUG) {
|
||||
if (ifp->if_flags & IFF_DEBUG) {
|
||||
buf[60] = '\0';
|
||||
printf("FWDBG: %s\n", (char *)buf);
|
||||
}
|
||||
@ -1309,7 +1341,8 @@ rsu_get_rssi(struct rsu_softc *sc, int rate, void *physt)
|
||||
static struct mbuf *
|
||||
rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_frame *wh;
|
||||
struct r92s_rx_stat *stat;
|
||||
uint32_t rxdw0, rxdw3;
|
||||
@ -1322,11 +1355,11 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
|
||||
rxdw3 = le32toh(stat->rxdw3);
|
||||
|
||||
if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return NULL;
|
||||
}
|
||||
if (__predict_false(pktlen < sizeof(*wh) || pktlen > MCLBYTES)) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1344,9 +1377,11 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
|
||||
|
||||
m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (__predict_false(m == NULL)) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return NULL;
|
||||
}
|
||||
/* Finalize mbuf. */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
/* Hardware does Rx TCP checksum offload. */
|
||||
if (rxdw3 & R92S_RXDW3_TCPCHKVALID) {
|
||||
if (__predict_true(rxdw3 & R92S_RXDW3_TCPCHKRPT))
|
||||
@ -1444,7 +1479,6 @@ static struct mbuf *
|
||||
rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi)
|
||||
{
|
||||
struct rsu_softc *sc = data->sc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct r92s_rx_stat *stat;
|
||||
int len;
|
||||
|
||||
@ -1452,7 +1486,7 @@ rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi)
|
||||
|
||||
if (__predict_false(len < sizeof(*stat))) {
|
||||
DPRINTF("xfer too short %d\n", len);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1);
|
||||
return (NULL);
|
||||
}
|
||||
/* Determine if it is a firmware C2H event or an 802.11 frame. */
|
||||
@ -1469,7 +1503,8 @@ static void
|
||||
rsu_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct rsu_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m = NULL, *next;
|
||||
@ -1529,7 +1564,7 @@ tr_setup:
|
||||
}
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
break;
|
||||
@ -1537,16 +1572,35 @@ tr_setup:
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
rsu_txeof(struct usb_xfer *xfer, struct rsu_data *data)
|
||||
{
|
||||
struct rsu_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct mbuf *m;
|
||||
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
|
||||
/*
|
||||
* Do any tx complete callback. Note this must be done before releasing
|
||||
* the node reference.
|
||||
*/
|
||||
if (data->m) {
|
||||
/* XXX status? */
|
||||
ieee80211_tx_complete(data->ni, data->m, 0);
|
||||
m = data->m;
|
||||
if (m->m_flags & M_TXCB) {
|
||||
/* XXX status? */
|
||||
ieee80211_process_callback(data->ni, m, 0);
|
||||
}
|
||||
m_freem(m);
|
||||
data->m = NULL;
|
||||
}
|
||||
if (data->ni) {
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
}
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1554,7 +1608,7 @@ rsu_bulk_tx_callback_sub(struct usb_xfer *xfer, usb_error_t error,
|
||||
uint8_t which)
|
||||
{
|
||||
struct rsu_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct rsu_data *data;
|
||||
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
@ -1589,7 +1643,7 @@ tr_setup:
|
||||
rsu_txeof(xfer, data);
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
|
||||
}
|
||||
counter_u64_add(ic->ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
@ -1615,7 +1669,8 @@ static int
|
||||
rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
|
||||
struct mbuf *m0, struct rsu_data *data)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_key *k = NULL;
|
||||
@ -1717,75 +1772,82 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rsu_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
static void
|
||||
rsu_start(struct ifnet *ifp)
|
||||
{
|
||||
struct rsu_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
struct rsu_softc *sc = ifp->if_softc;
|
||||
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
RSU_LOCK(sc);
|
||||
if (!sc->sc_running) {
|
||||
RSU_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
RSU_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
rsu_start(sc);
|
||||
rsu_start_locked(ifp);
|
||||
RSU_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_start(struct rsu_softc *sc)
|
||||
rsu_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct rsu_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct rsu_data *bf;
|
||||
struct mbuf *m;
|
||||
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
|
||||
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
bf = rsu_getbuf(sc);
|
||||
if (bf == NULL) {
|
||||
mbufq_prepend(&sc->sc_snd, m);
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
|
||||
if (rsu_tx_start(sc, ni, m, bf) != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
bf = rsu_getbuf(sc);
|
||||
if (bf == NULL) {
|
||||
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
} else if (rsu_tx_start(sc, ni, m, bf) != 0) {
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
ieee80211_free_node(ni);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
rsu_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct rsu_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error = 0, startall = 0;
|
||||
|
||||
RSU_LOCK(sc);
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (!sc->sc_running) {
|
||||
rsu_init(sc);
|
||||
startall = 1;
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
rsu_init(ifp->if_softc);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
rsu_stop(ifp, 1);
|
||||
}
|
||||
} else if (sc->sc_running)
|
||||
rsu_stop(sc);
|
||||
RSU_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
||||
break;
|
||||
case SIOCGIFADDR:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2234,11 +2296,12 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct rsu_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rsu_softc *sc = ifp->if_softc;
|
||||
struct rsu_data *bf;
|
||||
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!sc->sc_running) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return (ENETDOWN);
|
||||
@ -2251,8 +2314,10 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
RSU_UNLOCK(sc);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
if (rsu_tx_start(sc, ni, m, bf) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
RSU_UNLOCK(sc);
|
||||
return (EIO);
|
||||
@ -2263,17 +2328,23 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_init(struct rsu_softc *sc)
|
||||
rsu_init(void *arg)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
struct rsu_softc *sc = arg;
|
||||
|
||||
RSU_LOCK(sc);
|
||||
rsu_init_locked(arg);
|
||||
RSU_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_init_locked(struct rsu_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct r92s_set_pwr_mode cmd;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
|
||||
/* Init host async commands ring. */
|
||||
sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
|
||||
|
||||
@ -2313,14 +2384,14 @@ rsu_init(struct rsu_softc *sc)
|
||||
rsu_read_1(sc, 0xfe5c) | 0x80);
|
||||
|
||||
/* Set MAC address. */
|
||||
IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
rsu_write_region_1(sc, R92S_MACID, macaddr, IEEE80211_ADDR_LEN);
|
||||
rsu_write_region_1(sc, R92S_MACID, IF_LLADDR(ifp),
|
||||
IEEE80211_ADDR_LEN);
|
||||
|
||||
/* It really takes 1.5 seconds for the firmware to boot: */
|
||||
usb_pause_mtx(&sc->sc_mtx, (3 * hz) / 2);
|
||||
|
||||
DPRINTF("setting MAC address to %s\n", ether_sprintf(macaddr));
|
||||
error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, macaddr,
|
||||
DPRINTF("setting MAC address to %s\n", ether_sprintf(IF_LLADDR(ifp)));
|
||||
error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp),
|
||||
IEEE80211_ADDR_LEN);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not set MAC address\n");
|
||||
@ -2356,11 +2427,12 @@ rsu_init(struct rsu_softc *sc)
|
||||
/* Set default channel. */
|
||||
ic->ic_bss->ni_chan = ic->ic_ibss_chan;
|
||||
#endif
|
||||
sc->sc_scan_pass = 0;
|
||||
sc->scan_pass = 0;
|
||||
usbd_transfer_start(sc->sc_xfer[RSU_BULK_RX]);
|
||||
|
||||
/* We're ready to go. */
|
||||
sc->sc_running = 1;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
return;
|
||||
fail:
|
||||
/* Need to stop all failed transfers, if any */
|
||||
@ -2369,11 +2441,22 @@ fail:
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_stop(struct rsu_softc *sc)
|
||||
rsu_stop(struct ifnet *ifp, int disable)
|
||||
{
|
||||
struct rsu_softc *sc = ifp->if_softc;
|
||||
|
||||
RSU_LOCK(sc);
|
||||
rsu_stop_locked(ifp, disable);
|
||||
RSU_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_stop_locked(struct ifnet *ifp, int disable __unused)
|
||||
{
|
||||
struct rsu_softc *sc = ifp->if_softc;
|
||||
int i;
|
||||
|
||||
sc->sc_running = 0;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
sc->sc_calibrating = 0;
|
||||
taskqueue_cancel_timeout(taskqueue_thread, &sc->calib_task, NULL);
|
||||
|
||||
|
@ -726,8 +726,7 @@ struct rsu_vap {
|
||||
#define RSU_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
|
||||
|
||||
struct rsu_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
struct usb_device *sc_udev;
|
||||
int (*sc_newstate)(struct ieee80211com *,
|
||||
@ -737,17 +736,17 @@ struct rsu_softc {
|
||||
const uint8_t *qid2idx;
|
||||
struct mtx sc_mtx;
|
||||
|
||||
u_int sc_running:1,
|
||||
sc_calibrating:1,
|
||||
sc_scan_pass:1;
|
||||
u_int cut;
|
||||
int scan_pass;
|
||||
struct rsu_host_cmd_ring cmdq;
|
||||
struct rsu_data sc_rx[RSU_RX_LIST_COUNT];
|
||||
struct rsu_data sc_tx[RSU_TX_LIST_COUNT];
|
||||
struct rsu_data *fwcmd_data;
|
||||
uint8_t cmd_seq;
|
||||
uint8_t rom[128];
|
||||
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
|
||||
struct usb_xfer *sc_xfer[RSU_N_TRANSFER];
|
||||
uint8_t sc_calibrating;
|
||||
|
||||
STAILQ_HEAD(, rsu_data) sc_rx_active;
|
||||
STAILQ_HEAD(, rsu_data) sc_rx_inactive;
|
||||
|
@ -175,9 +175,8 @@ static int rum_tx_raw(struct rum_softc *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static int rum_tx_data(struct rum_softc *, struct mbuf *,
|
||||
struct ieee80211_node *);
|
||||
static int rum_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void rum_start(struct rum_softc *);
|
||||
static void rum_parent(struct ieee80211com *);
|
||||
static void rum_start(struct ifnet *);
|
||||
static int rum_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void rum_eeprom_read(struct rum_softc *, uint16_t, void *,
|
||||
int);
|
||||
static uint32_t rum_read(struct rum_softc *, uint16_t);
|
||||
@ -199,7 +198,7 @@ static void rum_set_chan(struct rum_softc *,
|
||||
struct ieee80211_channel *);
|
||||
static void rum_enable_tsf_sync(struct rum_softc *);
|
||||
static void rum_enable_tsf(struct rum_softc *);
|
||||
static void rum_update_slot(struct rum_softc *);
|
||||
static void rum_update_slot(struct ifnet *);
|
||||
static void rum_set_bssid(struct rum_softc *, const uint8_t *);
|
||||
static void rum_set_macaddr(struct rum_softc *, const uint8_t *);
|
||||
static void rum_update_mcast(struct ieee80211com *);
|
||||
@ -208,7 +207,8 @@ static void rum_setpromisc(struct rum_softc *);
|
||||
static const char *rum_get_rf(int);
|
||||
static void rum_read_eeprom(struct rum_softc *);
|
||||
static int rum_bbp_init(struct rum_softc *);
|
||||
static void rum_init(struct rum_softc *);
|
||||
static void rum_init_locked(struct rum_softc *);
|
||||
static void rum_init(void *);
|
||||
static void rum_stop(struct rum_softc *);
|
||||
static void rum_load_microcode(struct rum_softc *, const uint8_t *,
|
||||
size_t);
|
||||
@ -425,7 +425,8 @@ rum_attach(device_t self)
|
||||
{
|
||||
struct usb_attach_arg *uaa = device_get_ivars(self);
|
||||
struct rum_softc *sc = device_get_softc(self);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
uint8_t iface_index, bands;
|
||||
uint32_t tmp;
|
||||
int error, ntries;
|
||||
@ -436,7 +437,6 @@ rum_attach(device_t self)
|
||||
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
iface_index = RT2573_IFACE_INDEX;
|
||||
error = usbd_transfer_setup(uaa->device, &iface_index,
|
||||
@ -470,6 +470,24 @@ rum_attach(device_t self)
|
||||
rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode));
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
||||
goto detach;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "rum", device_get_unit(sc->sc_dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_init = rum_init;
|
||||
ifp->if_ioctl = rum_ioctl;
|
||||
ifp->if_start = rum_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_name = device_get_nameunit(self);
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
@ -494,14 +512,13 @@ rum_attach(device_t self)
|
||||
setbit(&bands, IEEE80211_MODE_11A);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, sc->sc_bssid);
|
||||
ic->ic_update_promisc = rum_update_promisc;
|
||||
ic->ic_raw_xmit = rum_raw_xmit;
|
||||
ic->ic_scan_start = rum_scan_start;
|
||||
ic->ic_scan_end = rum_scan_end;
|
||||
ic->ic_set_channel = rum_set_channel;
|
||||
ic->ic_transmit = rum_transmit;
|
||||
ic->ic_parent = rum_parent;
|
||||
|
||||
ic->ic_vap_create = rum_vap_create;
|
||||
ic->ic_vap_delete = rum_vap_delete;
|
||||
ic->ic_update_mcast = rum_update_mcast;
|
||||
@ -526,6 +543,8 @@ static int
|
||||
rum_detach(device_t self)
|
||||
{
|
||||
struct rum_softc *sc = device_get_softc(self);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic;
|
||||
|
||||
/* Prevent further ioctls */
|
||||
RUM_LOCK(sc);
|
||||
@ -540,9 +559,11 @@ rum_detach(device_t self)
|
||||
rum_unsetup_tx_list(sc);
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
if (sc->sc_ic.ic_softc == sc)
|
||||
ieee80211_ifdetach(&sc->sc_ic);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
if (ifp) {
|
||||
ic = ifp->if_l2com;
|
||||
ieee80211_ifdetach(ic);
|
||||
if_free(ifp);
|
||||
}
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
return (0);
|
||||
}
|
||||
@ -574,18 +595,21 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct rum_softc *sc = ic->ic_softc;
|
||||
struct rum_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct rum_vap *rvp;
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
|
||||
return NULL;
|
||||
rvp = malloc(sizeof(struct rum_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
rvp = (struct rum_vap *) malloc(sizeof(struct rum_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (rvp == NULL)
|
||||
return NULL;
|
||||
vap = &rvp->vap;
|
||||
/* enable s/w bmiss handling for sta mode */
|
||||
|
||||
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
|
||||
/* out of memory */
|
||||
free(rvp, M_80211_VAP);
|
||||
return (NULL);
|
||||
@ -600,8 +624,7 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
ieee80211_ratectl_init(vap);
|
||||
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
}
|
||||
@ -625,8 +648,13 @@ rum_tx_free(struct rum_tx_data *data, int txerr)
|
||||
struct rum_softc *sc = data->sc;
|
||||
|
||||
if (data->m != NULL) {
|
||||
ieee80211_tx_complete(data->ni, data->m, txerr);
|
||||
if (data->m->m_flags & M_TXCB)
|
||||
ieee80211_process_callback(data->ni, data->m,
|
||||
txerr ? ETIMEDOUT : 0);
|
||||
m_freem(data->m);
|
||||
data->m = NULL;
|
||||
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
}
|
||||
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
|
||||
@ -683,7 +711,7 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct rum_vap *rvp = RUM_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct rum_softc *sc = ic->ic_softc;
|
||||
struct rum_softc *sc = ic->ic_ifp->if_softc;
|
||||
const struct ieee80211_txparam *tp;
|
||||
enum ieee80211_state ostate;
|
||||
struct ieee80211_node *ni;
|
||||
@ -717,12 +745,12 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
ieee80211_free_node(ni);
|
||||
return (-1);
|
||||
}
|
||||
rum_update_slot(sc);
|
||||
rum_update_slot(ic->ic_ifp);
|
||||
rum_enable_mrr(sc);
|
||||
rum_set_txpreamble(sc);
|
||||
rum_set_basicrates(sc);
|
||||
IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
|
||||
rum_set_bssid(sc, ic->ic_macaddr);
|
||||
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
|
||||
rum_set_bssid(sc, sc->sc_bssid);
|
||||
}
|
||||
|
||||
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
|
||||
@ -752,6 +780,7 @@ static void
|
||||
rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct rum_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211vap *vap;
|
||||
struct rum_tx_data *data;
|
||||
struct mbuf *m;
|
||||
@ -770,6 +799,9 @@ rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
rum_tx_free(data, 0);
|
||||
usbd_xfer_set_priv(xfer, NULL);
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case USB_ST_SETUP:
|
||||
tr_setup:
|
||||
@ -812,14 +844,16 @@ tr_setup:
|
||||
|
||||
usbd_transfer_submit(xfer);
|
||||
}
|
||||
rum_start(sc);
|
||||
RUM_UNLOCK(sc);
|
||||
rum_start(ifp);
|
||||
RUM_LOCK(sc);
|
||||
break;
|
||||
|
||||
default: /* Error */
|
||||
DPRINTFN(11, "transfer error, %s\n",
|
||||
usbd_errstr(error));
|
||||
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
data = usbd_xfer_get_priv(xfer);
|
||||
if (data != NULL) {
|
||||
rum_tx_free(data, error);
|
||||
@ -846,7 +880,8 @@ static void
|
||||
rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct rum_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m = NULL;
|
||||
struct usb_page_cache *pc;
|
||||
@ -864,7 +899,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) {
|
||||
DPRINTF("%s: xfer too short %d\n",
|
||||
device_get_nameunit(sc->sc_dev), len);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
|
||||
@ -881,20 +916,21 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
* filled RUM_TXRX_CSR2:
|
||||
*/
|
||||
DPRINTFN(5, "PHY or CRC error\n");
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
|
||||
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (m == NULL) {
|
||||
DPRINTF("could not allocate mbuf\n");
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
usbd_copy_out(pc, RT2573_RX_DESC_SIZE,
|
||||
mtod(m, uint8_t *), len);
|
||||
|
||||
/* finalize mbuf */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
|
||||
|
||||
if (ieee80211_radiotap_active(ic)) {
|
||||
@ -932,8 +968,10 @@ tr_setup:
|
||||
(void) ieee80211_input_all(ic, m, rssi,
|
||||
RT2573_NOISE_FLOOR);
|
||||
}
|
||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
|
||||
!IFQ_IS_EMPTY(&ifp->if_snd))
|
||||
rum_start(ifp);
|
||||
RUM_LOCK(sc);
|
||||
rum_start(sc);
|
||||
return;
|
||||
|
||||
default: /* Error */
|
||||
@ -973,7 +1011,8 @@ static void
|
||||
rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
|
||||
uint32_t flags, uint16_t xflags, int len, int rate)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint16_t plcp_length;
|
||||
int remainder;
|
||||
|
||||
@ -1070,7 +1109,8 @@ static int
|
||||
rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct rum_tx_data *data;
|
||||
struct ieee80211_frame *wh;
|
||||
const struct ieee80211_txparam *tp;
|
||||
@ -1181,7 +1221,8 @@ static int
|
||||
rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct rum_tx_data *data;
|
||||
struct ieee80211_frame *wh;
|
||||
const struct ieee80211_txparam *tp;
|
||||
@ -1258,73 +1299,80 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rum_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct rum_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
if (!sc->sc_running) {
|
||||
RUM_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
RUM_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
rum_start(sc);
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
rum_start(struct rum_softc *sc)
|
||||
rum_start(struct ifnet *ifp)
|
||||
{
|
||||
struct rum_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
RUM_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
if (!sc->sc_running)
|
||||
return;
|
||||
|
||||
while (sc->tx_nfree >= RUM_TX_MINFREE &&
|
||||
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
if (rum_tx_data(sc, m, ni) != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rum_parent(struct ieee80211com *ic)
|
||||
{
|
||||
struct rum_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
if (sc->sc_detached) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
RUM_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (!sc->sc_running) {
|
||||
rum_init(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
rum_setpromisc(sc);
|
||||
} else if (sc->sc_running)
|
||||
rum_stop(sc);
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
if (sc->tx_nfree < RUM_TX_MINFREE) {
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
break;
|
||||
}
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
if (rum_tx_data(sc, m, ni) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
RUM_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
}
|
||||
|
||||
static int
|
||||
rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct rum_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error;
|
||||
int startall = 0;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
error = sc->sc_detached ? ENXIO : 0;
|
||||
RUM_UNLOCK(sc);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
RUM_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
rum_init_locked(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
rum_setpromisc(sc);
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
rum_stop(sc);
|
||||
}
|
||||
RUM_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1524,7 +1572,8 @@ rum_select_antenna(struct rum_softc *sc)
|
||||
static void
|
||||
rum_enable_mrr(struct rum_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = rum_read(sc, RT2573_TXRX_CSR4);
|
||||
@ -1540,7 +1589,8 @@ rum_enable_mrr(struct rum_softc *sc)
|
||||
static void
|
||||
rum_set_txpreamble(struct rum_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = rum_read(sc, RT2573_TXRX_CSR4);
|
||||
@ -1555,7 +1605,8 @@ rum_set_txpreamble(struct rum_softc *sc)
|
||||
static void
|
||||
rum_set_basicrates(struct rum_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) {
|
||||
@ -1620,7 +1671,8 @@ rum_select_band(struct rum_softc *sc, struct ieee80211_channel *c)
|
||||
static void
|
||||
rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
const struct rfprog *rfprog;
|
||||
uint8_t bbp3, bbp94 = RT2573_BBPR94_DEFAULT;
|
||||
int8_t power;
|
||||
@ -1696,7 +1748,8 @@ rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
|
||||
static void
|
||||
rum_enable_tsf_sync(struct rum_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);
|
||||
uint32_t tmp;
|
||||
|
||||
@ -1731,9 +1784,10 @@ rum_enable_tsf(struct rum_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
rum_update_slot(struct rum_softc *sc)
|
||||
rum_update_slot(struct ifnet *ifp)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct rum_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint8_t slottime;
|
||||
uint32_t tmp;
|
||||
|
||||
@ -1773,17 +1827,18 @@ rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr)
|
||||
static void
|
||||
rum_setpromisc(struct rum_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = rum_read(sc, RT2573_TXRX_CSR0);
|
||||
|
||||
tmp &= ~RT2573_DROP_NOT_TO_ME;
|
||||
if (sc->sc_ic.ic_promisc == 0)
|
||||
if (!(ifp->if_flags & IFF_PROMISC))
|
||||
tmp |= RT2573_DROP_NOT_TO_ME;
|
||||
|
||||
rum_write(sc, RT2573_TXRX_CSR0, tmp);
|
||||
|
||||
DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc > 0 ?
|
||||
DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
|
||||
"entering" : "leaving");
|
||||
}
|
||||
|
||||
@ -1792,11 +1847,10 @@ rum_update_promisc(struct ieee80211com *ic)
|
||||
{
|
||||
struct rum_softc *sc = ic->ic_softc;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
if (!sc->sc_running) {
|
||||
RUM_UNLOCK(sc);
|
||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
RUM_LOCK(sc);
|
||||
rum_setpromisc(sc);
|
||||
RUM_UNLOCK(sc);
|
||||
}
|
||||
@ -1833,7 +1887,7 @@ rum_read_eeprom(struct rum_softc *sc)
|
||||
#endif
|
||||
|
||||
/* read MAC address */
|
||||
rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_ic.ic_macaddr, 6);
|
||||
rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_bssid, 6);
|
||||
|
||||
rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2);
|
||||
val = le16toh(val);
|
||||
@ -1940,10 +1994,10 @@ rum_bbp_init(struct rum_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
rum_init(struct rum_softc *sc)
|
||||
rum_init_locked(struct rum_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
usb_error_t error;
|
||||
int i, ntries;
|
||||
@ -1985,7 +2039,7 @@ rum_init(struct rum_softc *sc)
|
||||
/* clear STA registers */
|
||||
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
|
||||
|
||||
rum_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
rum_set_macaddr(sc, IF_LLADDR(ifp));
|
||||
|
||||
/* initialize ASIC */
|
||||
rum_write(sc, RT2573_MAC_CSR1, 4);
|
||||
@ -2004,12 +2058,13 @@ rum_init(struct rum_softc *sc)
|
||||
RT2573_DROP_ACKCTS;
|
||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP)
|
||||
tmp |= RT2573_DROP_TODS;
|
||||
if (ic->ic_promisc == 0)
|
||||
if (!(ifp->if_flags & IFF_PROMISC))
|
||||
tmp |= RT2573_DROP_NOT_TO_ME;
|
||||
}
|
||||
rum_write(sc, RT2573_TXRX_CSR0, tmp);
|
||||
|
||||
sc->sc_running = 1;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
usbd_xfer_set_stall(sc->sc_xfer[RUM_BULK_WR]);
|
||||
usbd_transfer_start(sc->sc_xfer[RUM_BULK_RD]);
|
||||
return;
|
||||
@ -2018,14 +2073,30 @@ fail: rum_stop(sc);
|
||||
#undef N
|
||||
}
|
||||
|
||||
static void
|
||||
rum_init(void *priv)
|
||||
{
|
||||
struct rum_softc *sc = priv;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
rum_init_locked(sc);
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic); /* start all vap's */
|
||||
}
|
||||
|
||||
static void
|
||||
rum_stop(struct rum_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t tmp;
|
||||
|
||||
RUM_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
sc->sc_running = 0;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
@ -2117,23 +2188,27 @@ static int
|
||||
rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct rum_softc *sc = ni->ni_ic->ic_softc;
|
||||
struct ifnet *ifp = ni->ni_ic->ic_ifp;
|
||||
struct rum_softc *sc = ifp->if_softc;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!sc->sc_running) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
RUM_UNLOCK(sc);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return ENETDOWN;
|
||||
}
|
||||
if (sc->tx_nfree < RUM_TX_MINFREE) {
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
RUM_UNLOCK(sc);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
|
||||
if (params == NULL) {
|
||||
/*
|
||||
* Legacy path; interpret frame contents to decide
|
||||
@ -2153,6 +2228,7 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
|
||||
return 0;
|
||||
bad:
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
RUM_UNLOCK(sc);
|
||||
ieee80211_free_node(ni);
|
||||
return EIO;
|
||||
@ -2186,7 +2262,8 @@ rum_ratectl_task(void *arg, int pending)
|
||||
struct rum_vap *rvp = arg;
|
||||
struct ieee80211vap *vap = &rvp->vap;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct rum_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rum_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
int ok, fail;
|
||||
int sum, retrycnt;
|
||||
@ -2206,8 +2283,7 @@ rum_ratectl_task(void *arg, int pending)
|
||||
(void) ieee80211_ratectl_rate(ni, NULL, 0);
|
||||
ieee80211_free_node(ni);
|
||||
|
||||
/* count TX retry-fail as Tx errors */
|
||||
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */
|
||||
|
||||
usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp);
|
||||
RUM_UNLOCK(sc);
|
||||
@ -2216,14 +2292,15 @@ rum_ratectl_task(void *arg, int pending)
|
||||
static void
|
||||
rum_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct rum_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct rum_softc *sc = ifp->if_softc;
|
||||
uint32_t tmp;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
/* abort TSF synchronization */
|
||||
tmp = rum_read(sc, RT2573_TXRX_CSR9);
|
||||
rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
|
||||
rum_set_bssid(sc, ieee80211broadcastaddr);
|
||||
rum_set_bssid(sc, ifp->if_broadcastaddr);
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
}
|
||||
@ -2231,11 +2308,11 @@ rum_scan_start(struct ieee80211com *ic)
|
||||
static void
|
||||
rum_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct rum_softc *sc = ic->ic_softc;
|
||||
struct rum_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
rum_enable_tsf_sync(sc);
|
||||
rum_set_bssid(sc, ic->ic_macaddr);
|
||||
rum_set_bssid(sc, sc->sc_bssid);
|
||||
RUM_UNLOCK(sc);
|
||||
|
||||
}
|
||||
@ -2243,7 +2320,7 @@ rum_scan_end(struct ieee80211com *ic)
|
||||
static void
|
||||
rum_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct rum_softc *sc = ic->ic_softc;
|
||||
struct rum_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
RUM_LOCK(sc);
|
||||
rum_set_chan(sc, ic->ic_curchan);
|
||||
@ -2253,7 +2330,8 @@ rum_set_channel(struct ieee80211com *ic)
|
||||
static int
|
||||
rum_get_rssi(struct rum_softc *sc, uint8_t raw)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
int lna, agc, rssi;
|
||||
|
||||
lna = (raw >> 5) & 0x3;
|
||||
|
@ -85,8 +85,7 @@ enum {
|
||||
};
|
||||
|
||||
struct rum_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
struct usb_device *sc_udev;
|
||||
|
||||
@ -106,8 +105,8 @@ struct rum_softc {
|
||||
uint32_t sta[6];
|
||||
uint32_t rf_regs[4];
|
||||
uint8_t txpow[44];
|
||||
u_int sc_detached:1,
|
||||
sc_running:1;
|
||||
uint8_t sc_bssid[6];
|
||||
uint8_t sc_detached;
|
||||
|
||||
struct {
|
||||
uint8_t val;
|
||||
|
@ -410,9 +410,8 @@ static int run_tx_param(struct run_softc *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static int run_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static int run_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void run_start(struct run_softc *);
|
||||
static void run_parent(struct ieee80211com *);
|
||||
static void run_start(struct ifnet *);
|
||||
static int run_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void run_iq_calib(struct run_softc *, u_int);
|
||||
static void run_set_agc(struct run_softc *, uint8_t);
|
||||
static void run_select_chan_group(struct run_softc *, int);
|
||||
@ -458,6 +457,7 @@ static void run_rt3593_rf_setup(struct run_softc *);
|
||||
static void run_rt5390_rf_setup(struct run_softc *);
|
||||
static int run_txrx_enable(struct run_softc *);
|
||||
static void run_adjust_freq_offset(struct run_softc *);
|
||||
static void run_init(void *);
|
||||
static void run_init_locked(struct run_softc *);
|
||||
static void run_stop(void *);
|
||||
static void run_delay(struct run_softc *, u_int);
|
||||
@ -702,7 +702,8 @@ run_attach(device_t self)
|
||||
{
|
||||
struct run_softc *sc = device_get_softc(self);
|
||||
struct usb_attach_arg *uaa = device_get_ivars(self);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
uint32_t ver;
|
||||
int ntries, error;
|
||||
uint8_t iface_index, bands;
|
||||
@ -715,7 +716,6 @@ run_attach(device_t self)
|
||||
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
iface_index = RT2860_IFACE_INDEX;
|
||||
|
||||
@ -754,10 +754,28 @@ run_attach(device_t self)
|
||||
device_printf(sc->sc_dev,
|
||||
"MAC/BBP RT%04X (rev 0x%04X), RF %s (MIMO %dT%dR), address %s\n",
|
||||
sc->mac_ver, sc->mac_rev, run_get_rf(sc->rf_rev),
|
||||
sc->ntxchains, sc->nrxchains, ether_sprintf(ic->ic_macaddr));
|
||||
sc->ntxchains, sc->nrxchains, ether_sprintf(sc->sc_bssid));
|
||||
|
||||
RUN_UNLOCK(sc);
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
||||
goto detach;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "run", device_get_unit(sc->sc_dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_init = run_init;
|
||||
ifp->if_ioctl = run_ioctl;
|
||||
ifp->if_start = run_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_name = device_get_nameunit(self);
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
@ -794,7 +812,7 @@ run_attach(device_t self)
|
||||
setbit(&bands, IEEE80211_MODE_11A);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, sc->sc_bssid);
|
||||
|
||||
ic->ic_scan_start = run_scan_start;
|
||||
ic->ic_scan_end = run_scan_end;
|
||||
@ -806,10 +824,9 @@ run_attach(device_t self)
|
||||
ic->ic_wme.wme_update = run_wme_update;
|
||||
ic->ic_raw_xmit = run_raw_xmit;
|
||||
ic->ic_update_promisc = run_update_promisc;
|
||||
|
||||
ic->ic_vap_create = run_vap_create;
|
||||
ic->ic_vap_delete = run_vap_delete;
|
||||
ic->ic_transmit = run_transmit;
|
||||
ic->ic_parent = run_parent;
|
||||
|
||||
ieee80211_radiotap_attach(ic,
|
||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
|
||||
@ -835,7 +852,8 @@ static int
|
||||
run_detach(device_t self)
|
||||
{
|
||||
struct run_softc *sc = device_get_softc(self);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic;
|
||||
int i;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
@ -854,15 +872,16 @@ run_detach(device_t self)
|
||||
run_unsetup_tx_list(sc, &sc->sc_epq[i]);
|
||||
RUN_UNLOCK(sc);
|
||||
|
||||
if (sc->sc_ic.ic_softc == sc) {
|
||||
if (ifp) {
|
||||
ic = ifp->if_l2com;
|
||||
/* drain tasks */
|
||||
usb_callout_drain(&sc->ratectl_ch);
|
||||
ieee80211_draintask(ic, &sc->cmdq_task);
|
||||
ieee80211_draintask(ic, &sc->ratectl_task);
|
||||
ieee80211_ifdetach(ic);
|
||||
if_free(ifp);
|
||||
}
|
||||
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -874,13 +893,14 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct run_softc *sc = ifp->if_softc;
|
||||
struct run_vap *rvp;
|
||||
struct ieee80211vap *vap;
|
||||
int i;
|
||||
|
||||
if (sc->rvp_cnt >= RUN_VAP_MAX) {
|
||||
device_printf(sc->sc_dev, "number of VAPs maxed out\n");
|
||||
if_printf(ifp, "number of VAPs maxed out\n");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -906,21 +926,23 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
break;
|
||||
}
|
||||
if (vap == NULL) {
|
||||
device_printf(sc->sc_dev,
|
||||
"wds only supported in ap mode\n");
|
||||
if_printf(ifp, "wds only supported in ap mode\n");
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
|
||||
if_printf(ifp, "unknown opmode %d\n", opmode);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
rvp = malloc(sizeof(struct run_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
rvp = (struct run_vap *) malloc(sizeof(struct run_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (rvp == NULL)
|
||||
return (NULL);
|
||||
vap = &rvp->vap;
|
||||
|
||||
if (ieee80211_vap_setup(ic, vap, name, unit, opmode, flags,
|
||||
bssid) != 0) {
|
||||
if (ieee80211_vap_setup(ic, vap, name, unit,
|
||||
opmode, flags, bssid, mac) != 0) {
|
||||
/* out of memory */
|
||||
free(rvp, M_80211_VAP);
|
||||
return (NULL);
|
||||
@ -947,8 +969,7 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status,
|
||||
mac);
|
||||
ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status);
|
||||
|
||||
/* make sure id is always unique */
|
||||
for (i = 0; i < RUN_VAP_MAX; i++) {
|
||||
@ -974,6 +995,7 @@ static void
|
||||
run_vap_delete(struct ieee80211vap *vap)
|
||||
{
|
||||
struct run_vap *rvp = RUN_VAP(vap);
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
struct run_softc *sc;
|
||||
uint8_t rvp_id;
|
||||
@ -982,7 +1004,9 @@ run_vap_delete(struct ieee80211vap *vap)
|
||||
return;
|
||||
|
||||
ic = vap->iv_ic;
|
||||
sc = ic->ic_softc;
|
||||
ifp = ic->ic_ifp;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
|
||||
@ -1716,7 +1740,6 @@ run_get_txpower(struct run_softc *sc)
|
||||
static int
|
||||
run_read_eeprom(struct run_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
int8_t delta_2ghz, delta_5ghz;
|
||||
uint32_t tmp;
|
||||
uint16_t val;
|
||||
@ -1737,14 +1760,14 @@ run_read_eeprom(struct run_softc *sc)
|
||||
|
||||
/* read MAC address */
|
||||
run_srom_read(sc, RT2860_EEPROM_MAC01, &val);
|
||||
ic->ic_macaddr[0] = val & 0xff;
|
||||
ic->ic_macaddr[1] = val >> 8;
|
||||
sc->sc_bssid[0] = val & 0xff;
|
||||
sc->sc_bssid[1] = val >> 8;
|
||||
run_srom_read(sc, RT2860_EEPROM_MAC23, &val);
|
||||
ic->ic_macaddr[2] = val & 0xff;
|
||||
ic->ic_macaddr[3] = val >> 8;
|
||||
sc->sc_bssid[2] = val & 0xff;
|
||||
sc->sc_bssid[3] = val >> 8;
|
||||
run_srom_read(sc, RT2860_EEPROM_MAC45, &val);
|
||||
ic->ic_macaddr[4] = val & 0xff;
|
||||
ic->ic_macaddr[5] = val >> 8;
|
||||
sc->sc_bssid[4] = val & 0xff;
|
||||
sc->sc_bssid[5] = val >> 8;
|
||||
|
||||
if (sc->mac_ver < 0x3593) {
|
||||
/* read vender BBP settings */
|
||||
@ -1979,7 +2002,7 @@ run_media_change(struct ifnet *ifp)
|
||||
struct ieee80211vap *vap = ifp->if_softc;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
const struct ieee80211_txparam *tp;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
uint8_t rate, ridx;
|
||||
int error;
|
||||
|
||||
@ -2010,7 +2033,7 @@ run_media_change(struct ifnet *ifp)
|
||||
|
||||
#if 0
|
||||
if ((ifp->if_flags & IFF_UP) &&
|
||||
(ifp->if_drv_flags & RUN_RUNNING)){
|
||||
(ifp->if_drv_flags & IFF_DRV_RUNNING)){
|
||||
run_init_locked(sc);
|
||||
}
|
||||
#endif
|
||||
@ -2025,7 +2048,7 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
const struct ieee80211_txparam *tp;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct run_vap *rvp = RUN_VAP(vap);
|
||||
enum ieee80211_state ostate;
|
||||
uint32_t sta[3];
|
||||
@ -2121,7 +2144,7 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
run_set_txpreamble(sc);
|
||||
run_set_basicrates(sc);
|
||||
ni = ieee80211_ref_node(vap->iv_bss);
|
||||
IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
|
||||
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
|
||||
run_set_bssid(sc, ni->ni_bssid);
|
||||
ieee80211_free_node(ni);
|
||||
run_enable_tsf_sync(sc);
|
||||
@ -2158,7 +2181,7 @@ static void
|
||||
run_wme_update_cb(void *arg)
|
||||
{
|
||||
struct ieee80211com *ic = arg;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ieee80211_wme_state *wmesp = &ic->ic_wme;
|
||||
int aci, error = 0;
|
||||
|
||||
@ -2211,7 +2234,7 @@ err:
|
||||
static int
|
||||
run_wme_update(struct ieee80211com *ic)
|
||||
{
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
/* sometime called wothout lock */
|
||||
if (mtx_owned(&ic->ic_comlock.mtx)) {
|
||||
@ -2254,7 +2277,7 @@ run_key_set_cb(void *arg)
|
||||
struct ieee80211vap *vap = cmdq->arg1;
|
||||
struct ieee80211_key *k = cmdq->k;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
uint32_t attr;
|
||||
uint16_t base, associd;
|
||||
@ -2376,7 +2399,7 @@ run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k,
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
uint32_t i;
|
||||
|
||||
i = RUN_CMDQ_GET(&sc->cmdq_store);
|
||||
@ -2444,7 +2467,7 @@ static int
|
||||
run_key_delete(struct ieee80211vap *vap, struct ieee80211_key *k)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ieee80211_key *k0;
|
||||
uint32_t i;
|
||||
|
||||
@ -2475,7 +2498,7 @@ run_ratectl_to(void *arg)
|
||||
struct run_softc *sc = arg;
|
||||
|
||||
/* do it in a process context, so it can go sleep */
|
||||
ieee80211_runtask(&sc->sc_ic, &sc->ratectl_task);
|
||||
ieee80211_runtask(sc->sc_ifp->if_l2com, &sc->ratectl_task);
|
||||
/* next timeout will be rescheduled in the callback task */
|
||||
}
|
||||
|
||||
@ -2484,7 +2507,7 @@ static void
|
||||
run_ratectl_cb(void *arg, int pending)
|
||||
{
|
||||
struct run_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
|
||||
if (vap == NULL)
|
||||
@ -2517,6 +2540,7 @@ static void
|
||||
run_drain_fifo(void *arg)
|
||||
{
|
||||
struct run_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t stat;
|
||||
uint16_t (*wstat)[3];
|
||||
uint8_t wcid, mcs, pid;
|
||||
@ -2553,7 +2577,7 @@ run_drain_fifo(void *arg)
|
||||
if (stat & RT2860_TXQ_OK)
|
||||
(*wstat)[RUN_SUCCESS]++;
|
||||
else
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
/*
|
||||
* Check if there were retries, ie if the Tx success rate is
|
||||
* different from the requested rate. Note that it works only
|
||||
@ -2576,6 +2600,8 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
|
||||
{
|
||||
struct run_softc *sc = arg;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct run_node *rn = (void *)ni;
|
||||
union run_stats sta[2];
|
||||
uint16_t (*wstat)[3];
|
||||
@ -2597,8 +2623,7 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
|
||||
goto fail;
|
||||
|
||||
/* count failed TX as errors */
|
||||
if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS,
|
||||
le16toh(sta[0].error.fail));
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, le16toh(sta[0].error.fail));
|
||||
|
||||
retrycnt = le16toh(sta[1].tx.retry);
|
||||
success = le16toh(sta[1].tx.success);
|
||||
@ -2636,7 +2661,7 @@ run_newassoc_cb(void *arg)
|
||||
{
|
||||
struct run_cmdq *cmdq = arg;
|
||||
struct ieee80211_node *ni = cmdq->arg1;
|
||||
struct run_softc *sc = ni->ni_vap->iv_ic->ic_softc;
|
||||
struct run_softc *sc = ni->ni_vap->iv_ic->ic_ifp->if_softc;
|
||||
uint8_t wcid = cmdq->wcid;
|
||||
|
||||
RUN_LOCK_ASSERT(sc, MA_OWNED);
|
||||
@ -2654,7 +2679,7 @@ run_newassoc(struct ieee80211_node *ni, int isnew)
|
||||
struct ieee80211_rateset *rs = &ni->ni_rates;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
uint8_t rate;
|
||||
uint8_t ridx;
|
||||
uint8_t wcid;
|
||||
@ -2744,7 +2769,8 @@ run_maxrssi_chain(struct run_softc *sc, const struct rt2860_rxwi *rxwi)
|
||||
static void
|
||||
run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_node *ni;
|
||||
struct rt2870_rxd *rxd;
|
||||
@ -2763,7 +2789,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
|
||||
rxwisize += sizeof(uint32_t);
|
||||
if (__predict_false(len > dmalen)) {
|
||||
m_freem(m);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
DPRINTF("bad RXWI length %u > %u\n", len, dmalen);
|
||||
return;
|
||||
}
|
||||
@ -2773,7 +2799,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
|
||||
|
||||
if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
|
||||
m_freem(m);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
DPRINTF("%s error.\n", (flags & RT2860_RX_CRCERR)?"CRC":"ICV");
|
||||
return;
|
||||
}
|
||||
@ -2802,7 +2828,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
|
||||
ieee80211_notify_michael_failure(ni->ni_vap, wh,
|
||||
rxwi->keyidx);
|
||||
m_freem(m);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
DPRINTF("MIC error. Someone is lying.\n");
|
||||
return;
|
||||
}
|
||||
@ -2811,6 +2837,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
|
||||
rssi = rxwi->rssi[ant];
|
||||
nf = run_rssi2dbm(sc, rssi, ant);
|
||||
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len = len;
|
||||
|
||||
if (ni != NULL) {
|
||||
@ -2863,7 +2890,7 @@ static void
|
||||
run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct run_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct mbuf *m = NULL;
|
||||
struct mbuf *m0;
|
||||
uint32_t dmalen;
|
||||
@ -2901,7 +2928,7 @@ tr_setup:
|
||||
}
|
||||
if (sc->rx_m == NULL) {
|
||||
DPRINTF("could not allocate mbuf - idle with stall\n");
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
usbd_xfer_set_stall(xfer);
|
||||
usbd_xfer_set_frames(xfer, 0);
|
||||
} else {
|
||||
@ -2921,9 +2948,12 @@ tr_setup:
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
/* try to clear stall first */
|
||||
usbd_xfer_set_stall(xfer);
|
||||
|
||||
if (error == USB_ERR_TIMEOUT)
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
|
||||
goto tr_setup;
|
||||
}
|
||||
if (sc->rx_m != NULL) {
|
||||
@ -2971,7 +3001,7 @@ tr_setup:
|
||||
m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (__predict_false(m0 == NULL)) {
|
||||
DPRINTF("could not allocate mbuf\n");
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
break;
|
||||
}
|
||||
m_copydata(m, 4 /* skip 32-bit DMA-len header */,
|
||||
@ -3018,7 +3048,8 @@ static void
|
||||
run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
|
||||
{
|
||||
struct run_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct run_tx_data *data;
|
||||
struct ieee80211vap *vap = NULL;
|
||||
struct usb_page_cache *pc;
|
||||
@ -3036,9 +3067,14 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
|
||||
"bytes @ index %d\n", actlen, index);
|
||||
|
||||
data = usbd_xfer_get_priv(xfer);
|
||||
|
||||
run_tx_free(pq, data, 0);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
||||
usbd_xfer_set_priv(xfer, NULL);
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case USB_ST_SETUP:
|
||||
tr_setup:
|
||||
@ -3055,7 +3091,11 @@ tr_setup:
|
||||
size + 3 + 8) > RUN_MAX_TXSZ) {
|
||||
DPRINTF("data overflow, %u bytes\n",
|
||||
m->m_pkthdr.len);
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
|
||||
run_tx_free(pq, data, 1);
|
||||
|
||||
goto tr_setup;
|
||||
}
|
||||
|
||||
@ -3092,8 +3132,12 @@ tr_setup:
|
||||
|
||||
usbd_xfer_set_frame_len(xfer, 0, size);
|
||||
usbd_xfer_set_priv(xfer, data);
|
||||
|
||||
usbd_transfer_submit(xfer);
|
||||
run_start(sc);
|
||||
|
||||
RUN_UNLOCK(sc);
|
||||
run_start(ifp);
|
||||
RUN_LOCK(sc);
|
||||
|
||||
break;
|
||||
|
||||
@ -3103,13 +3147,14 @@ tr_setup:
|
||||
|
||||
data = usbd_xfer_get_priv(xfer);
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
|
||||
if (data != NULL) {
|
||||
if(data->ni != NULL)
|
||||
vap = data->ni->ni_vap;
|
||||
run_tx_free(pq, data, error);
|
||||
usbd_xfer_set_priv(xfer, NULL);
|
||||
}
|
||||
|
||||
if (vap == NULL)
|
||||
vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
|
||||
@ -3175,7 +3220,7 @@ static void
|
||||
run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data)
|
||||
{
|
||||
struct mbuf *m = data->m;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211vap *vap = data->ni->ni_vap;
|
||||
struct ieee80211_frame *wh;
|
||||
struct rt2870_txd *txd;
|
||||
@ -3238,7 +3283,7 @@ run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data)
|
||||
static int
|
||||
run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_channel *chan;
|
||||
@ -3406,7 +3451,8 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
||||
static int
|
||||
run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct run_node *rn = (void *)ni;
|
||||
struct run_tx_data *data;
|
||||
struct ieee80211_frame *wh;
|
||||
@ -3437,9 +3483,11 @@ run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
|
||||
USETW(wh->i_dur, dur);
|
||||
}
|
||||
|
||||
if (sc->sc_epq[0].tx_nfree == 0)
|
||||
if (sc->sc_epq[0].tx_nfree == 0) {
|
||||
/* let caller free mbuf */
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
return (EIO);
|
||||
}
|
||||
data = STAILQ_FIRST(&sc->sc_epq[0].tx_fh);
|
||||
STAILQ_REMOVE_HEAD(&sc->sc_epq[0].tx_fh, next);
|
||||
sc->sc_epq[0].tx_nfree--;
|
||||
@ -3507,9 +3555,11 @@ run_sendprot(struct run_softc *sc,
|
||||
wflags = RT2860_TX_FRAG;
|
||||
|
||||
/* check that there are free slots before allocating the mbuf */
|
||||
if (sc->sc_epq[0].tx_nfree == 0)
|
||||
if (sc->sc_epq[0].tx_nfree == 0) {
|
||||
/* let caller free mbuf */
|
||||
sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
return (ENOBUFS);
|
||||
}
|
||||
|
||||
if (prot == IEEE80211_PROT_RTSCTS) {
|
||||
/* NB: CTS is the same size as an ACK */
|
||||
@ -3520,7 +3570,7 @@ run_sendprot(struct run_softc *sc,
|
||||
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
|
||||
}
|
||||
if (mprot == NULL) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
|
||||
if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
|
||||
DPRINTF("could not allocate mbuf\n");
|
||||
return (ENOBUFS);
|
||||
}
|
||||
@ -3602,6 +3652,7 @@ run_tx_param(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
|
||||
|
||||
if (sc->sc_epq[0].tx_nfree == 0) {
|
||||
/* let caller free mbuf */
|
||||
sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
DPRINTF("sending raw frame, but tx ring is full\n");
|
||||
return (EIO);
|
||||
}
|
||||
@ -3640,31 +3691,36 @@ static int
|
||||
run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct run_softc *sc = ni->ni_ic->ic_softc;
|
||||
struct ifnet *ifp = ni->ni_ic->ic_ifp;
|
||||
struct run_softc *sc = ifp->if_softc;
|
||||
int error = 0;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!(sc->sc_flags & RUN_RUNNING)) {
|
||||
error = ENETDOWN;
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
error = ENETDOWN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (params == NULL) {
|
||||
/* tx mgt packet */
|
||||
if ((error = run_tx_mgt(sc, m, ni)) != 0) {
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
DPRINTF("mgt tx failed\n");
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
/* tx raw packet with param */
|
||||
if ((error = run_tx_param(sc, m, ni, params)) != 0) {
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
DPRINTF("tx with param failed\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
|
||||
done:
|
||||
RUN_UNLOCK(sc);
|
||||
|
||||
@ -3677,71 +3733,83 @@ done:
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
run_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
if ((sc->sc_flags & RUN_RUNNING) == 0) {
|
||||
RUN_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
RUN_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
run_start(sc);
|
||||
RUN_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
run_start(struct run_softc *sc)
|
||||
run_start(struct ifnet *ifp)
|
||||
{
|
||||
struct run_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
RUN_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
if ((sc->sc_flags & RUN_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
||||
if (run_tx(sc, m, ni) != 0) {
|
||||
mbufq_prepend(&sc->sc_snd, m);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
run_parent(struct ieee80211com *ic)
|
||||
{
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
if (sc->sc_detached) {
|
||||
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
RUN_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (!(sc->sc_flags & RUN_RUNNING)) {
|
||||
startall = 1;
|
||||
run_init_locked(sc);
|
||||
} else
|
||||
run_update_promisc_locked(sc);
|
||||
} else if ((sc->sc_flags & RUN_RUNNING) && sc->rvp_cnt <= 1)
|
||||
run_stop(sc);
|
||||
for (;;) {
|
||||
/* send data frames */
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
|
||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
||||
if (run_tx(sc, m, ni) != 0) {
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RUN_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
}
|
||||
|
||||
static int
|
||||
run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct run_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int startall = 0;
|
||||
int error;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
error = sc->sc_detached ? ENXIO : 0;
|
||||
RUN_UNLOCK(sc);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
RUN_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)){
|
||||
startall = 1;
|
||||
run_init_locked(sc);
|
||||
} else
|
||||
run_update_promisc_locked(sc);
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
|
||||
(ic->ic_nrunning == 0 || sc->rvp_cnt <= 1)) {
|
||||
run_stop(sc);
|
||||
}
|
||||
}
|
||||
RUN_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4728,7 +4796,7 @@ run_set_rx_antenna(struct run_softc *sc, int aux)
|
||||
static int
|
||||
run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
u_int chan, group;
|
||||
|
||||
chan = ieee80211_chan2ieee(ic, c);
|
||||
@ -4773,7 +4841,7 @@ run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
|
||||
static void
|
||||
run_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
run_set_chan(sc, ic->ic_curchan);
|
||||
@ -4785,7 +4853,7 @@ run_set_channel(struct ieee80211com *ic)
|
||||
static void
|
||||
run_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
uint32_t tmp;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
@ -4795,7 +4863,7 @@ run_scan_start(struct ieee80211com *ic)
|
||||
run_write(sc, RT2860_BCN_TIME_CFG,
|
||||
tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
|
||||
RT2860_TBTT_TIMER_EN));
|
||||
run_set_bssid(sc, ieee80211broadcastaddr);
|
||||
run_set_bssid(sc, sc->sc_ifp->if_broadcastaddr);
|
||||
|
||||
RUN_UNLOCK(sc);
|
||||
|
||||
@ -4805,13 +4873,13 @@ run_scan_start(struct ieee80211com *ic)
|
||||
static void
|
||||
run_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
|
||||
run_enable_tsf_sync(sc);
|
||||
/* XXX keep local copy */
|
||||
run_set_bssid(sc, ic->ic_macaddr);
|
||||
run_set_bssid(sc, sc->sc_bssid);
|
||||
|
||||
RUN_UNLOCK(sc);
|
||||
|
||||
@ -4826,7 +4894,7 @@ static void
|
||||
run_update_beacon(struct ieee80211vap *vap, int item)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct run_vap *rvp = RUN_VAP(vap);
|
||||
int mcast = 0;
|
||||
uint32_t i;
|
||||
@ -4871,7 +4939,7 @@ run_update_beacon_cb(void *arg)
|
||||
struct ieee80211vap *vap = arg;
|
||||
struct run_vap *rvp = RUN_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct rt2860_txwi txwi;
|
||||
struct mbuf *m;
|
||||
uint16_t txwisize;
|
||||
@ -4919,7 +4987,7 @@ run_update_beacon_cb(void *arg)
|
||||
static void
|
||||
run_updateprot(struct ieee80211com *ic)
|
||||
{
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
uint32_t i;
|
||||
|
||||
i = RUN_CMDQ_GET(&sc->cmdq_store);
|
||||
@ -4933,7 +5001,7 @@ static void
|
||||
run_updateprot_cb(void *arg)
|
||||
{
|
||||
struct ieee80211com *ic = arg;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct run_softc *sc = ic->ic_ifp->if_softc;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL;
|
||||
@ -4957,7 +5025,7 @@ static void
|
||||
run_usb_timeout_cb(void *arg)
|
||||
{
|
||||
struct ieee80211vap *vap = arg;
|
||||
struct run_softc *sc = vap->iv_ic->ic_softc;
|
||||
struct run_softc *sc = vap->iv_ic->ic_ifp->if_softc;
|
||||
|
||||
RUN_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
@ -5003,12 +5071,12 @@ run_update_promisc_locked(struct run_softc *sc)
|
||||
run_read(sc, RT2860_RX_FILTR_CFG, &tmp);
|
||||
|
||||
tmp |= RT2860_DROP_UC_NOME;
|
||||
if (sc->sc_ic.ic_promisc > 0)
|
||||
if (sc->sc_ifp->if_flags & IFF_PROMISC)
|
||||
tmp &= ~RT2860_DROP_UC_NOME;
|
||||
|
||||
run_write(sc, RT2860_RX_FILTR_CFG, tmp);
|
||||
|
||||
DPRINTF("%s promiscuous mode\n", (sc->sc_ic.ic_promisc > 0) ?
|
||||
DPRINTF("%s promiscuous mode\n", (sc->sc_ifp->if_flags & IFF_PROMISC) ?
|
||||
"entering" : "leaving");
|
||||
}
|
||||
|
||||
@ -5017,7 +5085,7 @@ run_update_promisc(struct ieee80211com *ic)
|
||||
{
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
|
||||
if ((sc->sc_flags & RUN_RUNNING) == 0)
|
||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
@ -5028,7 +5096,7 @@ run_update_promisc(struct ieee80211com *ic)
|
||||
static void
|
||||
run_enable_tsf_sync(struct run_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
uint32_t tmp;
|
||||
|
||||
@ -5093,7 +5161,7 @@ run_enable_mrr(struct run_softc *sc)
|
||||
static void
|
||||
run_set_txpreamble(struct run_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
|
||||
run_read(sc, RT2860_AUTO_RSP_CFG, &tmp);
|
||||
@ -5107,7 +5175,7 @@ run_set_txpreamble(struct run_softc *sc)
|
||||
static void
|
||||
run_set_basicrates(struct run_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
|
||||
/* set basic rates mask */
|
||||
if (ic->ic_curmode == IEEE80211_MODE_11B)
|
||||
@ -5152,7 +5220,7 @@ run_updateslot(struct ieee80211com *ic)
|
||||
i = RUN_CMDQ_GET(&sc->cmdq_store);
|
||||
DPRINTF("cmdq_store=%d\n", i);
|
||||
sc->cmdq[i].func = run_updateslot_cb;
|
||||
sc->cmdq[i].arg0 = ic;
|
||||
sc->cmdq[i].arg0 = ic->ic_ifp;
|
||||
ieee80211_runtask(ic, &sc->cmdq_task);
|
||||
|
||||
return;
|
||||
@ -5162,8 +5230,9 @@ run_updateslot(struct ieee80211com *ic)
|
||||
static void
|
||||
run_updateslot_cb(void *arg)
|
||||
{
|
||||
struct ieee80211com *ic = arg;
|
||||
struct run_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = arg;
|
||||
struct run_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
|
||||
run_read(sc, RT2860_BKOFF_SLOT_CFG, &tmp);
|
||||
@ -5175,12 +5244,15 @@ run_updateslot_cb(void *arg)
|
||||
static void
|
||||
run_update_mcast(struct ieee80211com *ic)
|
||||
{
|
||||
|
||||
/* h/w filter supports getting everything or nothing */
|
||||
ic->ic_ifp->if_flags |= IFF_ALLMULTI;
|
||||
}
|
||||
|
||||
static int8_t
|
||||
run_rssi2dbm(struct run_softc *sc, uint8_t rssi, uint8_t rxchain)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211_channel *c = ic->ic_curchan;
|
||||
int delta;
|
||||
|
||||
@ -5830,7 +5902,7 @@ run_rt5390_rf_setup(struct run_softc *sc)
|
||||
static int
|
||||
run_txrx_enable(struct run_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
int error, ntries;
|
||||
|
||||
@ -5890,8 +5962,8 @@ run_adjust_freq_offset(struct run_softc *sc)
|
||||
static void
|
||||
run_init_locked(struct run_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t tmp;
|
||||
uint8_t bbp1, bbp3;
|
||||
int i;
|
||||
@ -5921,7 +5993,7 @@ run_init_locked(struct run_softc *sc)
|
||||
for (i = 0; i != RUN_EP_QUEUES; i++)
|
||||
run_setup_tx_list(sc, &sc->sc_epq[i]);
|
||||
|
||||
run_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
run_set_macaddr(sc, IF_LLADDR(ifp));
|
||||
|
||||
for (ntries = 0; ntries < 100; ntries++) {
|
||||
if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0)
|
||||
@ -6094,7 +6166,8 @@ run_init_locked(struct run_softc *sc)
|
||||
/* turn radio LED on */
|
||||
run_set_leds(sc, RT2860_LED_RADIO);
|
||||
|
||||
sc->sc_flags |= RUN_RUNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
sc->cmdq_run = RUN_CMDQ_GO;
|
||||
|
||||
for (i = 0; i != RUN_N_XFER; i++)
|
||||
@ -6111,20 +6184,36 @@ fail:
|
||||
run_stop(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
run_init(void *arg)
|
||||
{
|
||||
struct run_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RUN_LOCK(sc);
|
||||
run_init_locked(sc);
|
||||
RUN_UNLOCK(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic);
|
||||
}
|
||||
|
||||
static void
|
||||
run_stop(void *arg)
|
||||
{
|
||||
struct run_softc *sc = (struct run_softc *)arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t tmp;
|
||||
int i;
|
||||
int ntries;
|
||||
|
||||
RUN_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
if (sc->sc_flags & RUN_RUNNING)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
run_set_leds(sc, 0); /* turn all LEDs off */
|
||||
|
||||
sc->sc_flags &= ~RUN_RUNNING;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
sc->ratectl_run = RUN_RATECTL_OFF;
|
||||
sc->cmdq_run = sc->cmdq_key_set;
|
||||
|
@ -151,16 +151,13 @@ struct run_endpoint_queue {
|
||||
};
|
||||
|
||||
struct run_softc {
|
||||
struct mtx sc_mtx;
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
device_t sc_dev;
|
||||
struct usb_device *sc_udev;
|
||||
struct ifnet *sc_ifp;
|
||||
int sc_need_fwload;
|
||||
|
||||
int sc_flags;
|
||||
#define RUN_FLAG_FWLOAD_NEEDED 0x01
|
||||
#define RUN_RUNNING 0x02
|
||||
|
||||
uint16_t wcid_stats[RT2870_WCID_MAX + 1][3];
|
||||
#define RUN_TXCNT 0
|
||||
@ -206,6 +203,10 @@ struct run_softc {
|
||||
uint32_t txpow40mhz_2ghz[5];
|
||||
uint32_t txpow40mhz_5ghz[5];
|
||||
|
||||
uint8_t sc_bssid[6];
|
||||
|
||||
struct mtx sc_mtx;
|
||||
|
||||
struct run_endpoint_queue sc_epq[RUN_EP_QUEUES];
|
||||
|
||||
struct task ratectl_task;
|
||||
|
@ -279,11 +279,12 @@ static int uath_alloc_rx_data_list(struct uath_softc *);
|
||||
static int uath_alloc_tx_data_list(struct uath_softc *);
|
||||
static void uath_free_rx_data_list(struct uath_softc *);
|
||||
static void uath_free_tx_data_list(struct uath_softc *);
|
||||
static int uath_init(struct uath_softc *);
|
||||
static void uath_stop(struct uath_softc *);
|
||||
static void uath_parent(struct ieee80211com *);
|
||||
static int uath_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void uath_start(struct uath_softc *);
|
||||
static int uath_init_locked(void *);
|
||||
static void uath_init(void *);
|
||||
static void uath_stop_locked(struct ifnet *);
|
||||
static void uath_stop(struct ifnet *);
|
||||
static int uath_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void uath_start(struct ifnet *);
|
||||
static int uath_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static void uath_scan_start(struct ieee80211com *);
|
||||
@ -335,9 +336,11 @@ uath_attach(device_t dev)
|
||||
{
|
||||
struct uath_softc *sc = device_get_softc(dev);
|
||||
struct usb_attach_arg *uaa = device_get_ivars(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
uint8_t bands, iface_index = UATH_IFACE_INDEX; /* XXX */
|
||||
usb_error_t error;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
sc->sc_dev = dev;
|
||||
sc->sc_udev = uaa->device;
|
||||
@ -353,7 +356,6 @@ uath_attach(device_t dev)
|
||||
MTX_DEF);
|
||||
callout_init(&sc->stat_ch, 0);
|
||||
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
|
||||
uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
|
||||
@ -385,24 +387,31 @@ uath_attach(device_t dev)
|
||||
error = uath_host_available(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not initialize adapter\n");
|
||||
goto fail2;
|
||||
goto fail3;
|
||||
}
|
||||
error = uath_get_devcap(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"could not get device capabilities\n");
|
||||
goto fail2;
|
||||
goto fail3;
|
||||
}
|
||||
UATH_UNLOCK(sc);
|
||||
|
||||
/* Create device sysctl node. */
|
||||
uath_sysctl_node(sc);
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not allocate ifnet\n");
|
||||
error = ENXIO;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
UATH_LOCK(sc);
|
||||
error = uath_get_devstatus(sc, ic->ic_macaddr);
|
||||
error = uath_get_devstatus(sc, macaddr);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not get device status\n");
|
||||
goto fail2;
|
||||
goto fail4;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -411,15 +420,28 @@ uath_attach(device_t dev)
|
||||
error = uath_alloc_rx_data_list(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not allocate Rx data list\n");
|
||||
goto fail2;
|
||||
goto fail4;
|
||||
}
|
||||
error = uath_alloc_tx_data_list(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not allocate Tx data list\n");
|
||||
goto fail2;
|
||||
goto fail4;
|
||||
}
|
||||
UATH_UNLOCK(sc);
|
||||
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "uath", device_get_unit(sc->sc_dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_init = uath_init;
|
||||
ifp->if_ioctl = uath_ioctl;
|
||||
ifp->if_start = uath_start;
|
||||
/* XXX UATH_TX_DATA_LIST_COUNT */
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
|
||||
ic = ifp->if_l2com;
|
||||
ic->ic_ifp = ifp;
|
||||
ic->ic_softc = sc;
|
||||
ic->ic_name = device_get_nameunit(dev);
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
@ -447,17 +469,16 @@ uath_attach(device_t dev)
|
||||
/* XXX turbo */
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, macaddr);
|
||||
ic->ic_raw_xmit = uath_raw_xmit;
|
||||
ic->ic_scan_start = uath_scan_start;
|
||||
ic->ic_scan_end = uath_scan_end;
|
||||
ic->ic_set_channel = uath_set_channel;
|
||||
|
||||
ic->ic_vap_create = uath_vap_create;
|
||||
ic->ic_vap_delete = uath_vap_delete;
|
||||
ic->ic_update_mcast = uath_update_mcast;
|
||||
ic->ic_update_promisc = uath_update_promisc;
|
||||
ic->ic_transmit = uath_transmit;
|
||||
ic->ic_parent = uath_parent;
|
||||
|
||||
ieee80211_radiotap_attach(ic,
|
||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
|
||||
@ -470,8 +491,9 @@ uath_attach(device_t dev)
|
||||
|
||||
return (0);
|
||||
|
||||
fail2: UATH_UNLOCK(sc);
|
||||
uath_free_cmd_list(sc, sc->sc_cmd);
|
||||
fail4: if_free(ifp);
|
||||
fail3: UATH_UNLOCK(sc);
|
||||
fail2: uath_free_cmd_list(sc, sc->sc_cmd);
|
||||
fail1: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
|
||||
fail:
|
||||
return (error);
|
||||
@ -481,7 +503,8 @@ static int
|
||||
uath_detach(device_t dev)
|
||||
{
|
||||
struct uath_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
unsigned int x;
|
||||
|
||||
/*
|
||||
@ -502,10 +525,10 @@ uath_detach(device_t dev)
|
||||
STAILQ_INIT(&sc->sc_cmd_pending);
|
||||
STAILQ_INIT(&sc->sc_cmd_waiting);
|
||||
STAILQ_INIT(&sc->sc_cmd_inactive);
|
||||
|
||||
uath_stop(sc);
|
||||
UATH_UNLOCK(sc);
|
||||
|
||||
uath_stop(ifp);
|
||||
|
||||
callout_drain(&sc->stat_ch);
|
||||
callout_drain(&sc->watchdog_ch);
|
||||
|
||||
@ -524,7 +547,7 @@ uath_detach(device_t dev)
|
||||
usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
|
||||
|
||||
ieee80211_ifdetach(ic);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
if_free(ifp);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
return (0);
|
||||
}
|
||||
@ -1044,12 +1067,15 @@ uath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
|
||||
return (NULL);
|
||||
uvp = malloc(sizeof(struct uath_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
uvp = (struct uath_vap *) malloc(sizeof(struct uath_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (uvp == NULL)
|
||||
return (NULL);
|
||||
vap = &uvp->vap;
|
||||
/* enable s/w bmiss handling for sta mode */
|
||||
|
||||
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
|
||||
/* out of memory */
|
||||
free(uvp, M_80211_VAP);
|
||||
return (NULL);
|
||||
@ -1061,7 +1087,7 @@ uath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return (vap);
|
||||
}
|
||||
@ -1076,17 +1102,18 @@ uath_vap_delete(struct ieee80211vap *vap)
|
||||
}
|
||||
|
||||
static int
|
||||
uath_init(struct uath_softc *sc)
|
||||
uath_init_locked(void *arg)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct uath_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t val;
|
||||
int error;
|
||||
|
||||
UATH_ASSERT_LOCKED(sc);
|
||||
|
||||
if (sc->sc_flags & UATH_FLAG_INITDONE)
|
||||
uath_stop(sc);
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
uath_stop_locked(ifp);
|
||||
|
||||
/* reset variables */
|
||||
sc->sc_intrx_nextnum = sc->sc_msgid = 0;
|
||||
@ -1095,8 +1122,7 @@ uath_init(struct uath_softc *sc)
|
||||
uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof val, 0);
|
||||
|
||||
/* set MAC address */
|
||||
uath_config_multi(sc, CFG_MAC_ADDR,
|
||||
vap ? vap->iv_myaddr : ic->ic_macaddr, IEEE80211_ADDR_LEN);
|
||||
uath_config_multi(sc, CFG_MAC_ADDR, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
|
||||
|
||||
/* XXX honor net80211 state */
|
||||
uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001);
|
||||
@ -1145,6 +1171,8 @@ uath_init(struct uath_softc *sc)
|
||||
UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON,
|
||||
UATH_FILTER_OP_SET);
|
||||
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
sc->sc_flags |= UATH_FLAG_INITDONE;
|
||||
|
||||
callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
|
||||
@ -1152,16 +1180,28 @@ uath_init(struct uath_softc *sc)
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
uath_stop(sc);
|
||||
uath_stop_locked(ifp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
uath_stop(struct uath_softc *sc)
|
||||
uath_init(void *arg)
|
||||
{
|
||||
struct uath_softc *sc = arg;
|
||||
|
||||
UATH_LOCK(sc);
|
||||
(void)uath_init_locked(sc);
|
||||
UATH_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
uath_stop_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct uath_softc *sc = ifp->if_softc;
|
||||
|
||||
UATH_ASSERT_LOCKED(sc);
|
||||
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
sc->sc_flags &= ~UATH_FLAG_INITDONE;
|
||||
|
||||
callout_stop(&sc->stat_ch);
|
||||
@ -1177,6 +1217,16 @@ uath_stop(struct uath_softc *sc)
|
||||
uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
uath_stop(struct ifnet *ifp)
|
||||
{
|
||||
struct uath_softc *sc = ifp->if_softc;
|
||||
|
||||
UATH_LOCK(sc);
|
||||
uath_stop_locked(ifp);
|
||||
UATH_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val)
|
||||
{
|
||||
@ -1279,13 +1329,13 @@ static void
|
||||
uath_watchdog(void *arg)
|
||||
{
|
||||
struct uath_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (sc->sc_tx_timer > 0) {
|
||||
if (--sc->sc_tx_timer == 0) {
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
/*uath_init(sc); XXX needs a process context! */
|
||||
counter_u64_add(ic->ic_oerrors, 1);
|
||||
/*uath_init(ifp); XXX needs a process context! */
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return;
|
||||
}
|
||||
callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
|
||||
@ -1400,8 +1450,12 @@ uath_getbuf(struct uath_softc *sc)
|
||||
UATH_ASSERT_LOCKED(sc);
|
||||
|
||||
bf = _uath_getbuf(sc);
|
||||
if (bf == NULL)
|
||||
if (bf == NULL) {
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
DPRINTF(sc, UATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
}
|
||||
return (bf);
|
||||
}
|
||||
|
||||
@ -1420,7 +1474,8 @@ static int
|
||||
uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
#ifdef UATH_DEBUG
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
#endif
|
||||
struct uath_cmd_reset reset;
|
||||
|
||||
@ -1499,28 +1554,47 @@ uath_wme_init(struct uath_softc *sc)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
uath_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct uath_softc *sc = ic->ic_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
struct uath_softc *sc = ifp->if_softc;
|
||||
int error;
|
||||
int startall = 0;
|
||||
|
||||
UATH_LOCK(sc);
|
||||
if (sc->sc_flags & UATH_FLAG_INVALID) {
|
||||
UATH_UNLOCK(sc);
|
||||
return;
|
||||
error = (sc->sc_flags & UATH_FLAG_INVALID) ? ENXIO : 0;
|
||||
UATH_UNLOCK(sc);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
uath_init(ifp->if_softc);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
uath_stop(ifp);
|
||||
}
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
||||
break;
|
||||
case SIOCGIFADDR:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (!(sc->sc_flags & UATH_FLAG_INITDONE)) {
|
||||
uath_init(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else if (sc->sc_flags & UATH_FLAG_INITDONE)
|
||||
uath_stop(sc);
|
||||
UATH_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1689,49 +1763,31 @@ uath_freetx(struct mbuf *m)
|
||||
} while ((m = next) != NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
uath_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct uath_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
UATH_LOCK(sc);
|
||||
if ((sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
|
||||
UATH_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
UATH_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
uath_start(sc);
|
||||
UATH_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
uath_start(struct uath_softc *sc)
|
||||
uath_start(struct ifnet *ifp)
|
||||
{
|
||||
struct uath_data *bf;
|
||||
struct uath_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m, *next;
|
||||
uath_datahead frags;
|
||||
|
||||
UATH_ASSERT_LOCKED(sc);
|
||||
|
||||
if ((sc->sc_flags & UATH_FLAG_INITDONE) == 0 ||
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
|
||||
(sc->sc_flags & UATH_FLAG_INVALID))
|
||||
return;
|
||||
|
||||
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
UATH_LOCK(sc);
|
||||
for (;;) {
|
||||
bf = uath_getbuf(sc);
|
||||
if (bf == NULL) {
|
||||
mbufq_prepend(&sc->sc_snd, m);
|
||||
if (bf == NULL)
|
||||
break;
|
||||
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL) {
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
UATH_STAT_INC(sc, st_tx_inactive);
|
||||
break;
|
||||
}
|
||||
|
||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
|
||||
@ -1760,8 +1816,7 @@ uath_start(struct uath_softc *sc)
|
||||
next = m->m_nextpkt;
|
||||
if (uath_tx_start(sc, m, ni, bf) != 0) {
|
||||
bad:
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
reclaim:
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
UATH_STAT_INC(sc, st_tx_inactive);
|
||||
@ -1792,6 +1847,7 @@ uath_start(struct uath_softc *sc)
|
||||
|
||||
sc->sc_tx_timer = 5;
|
||||
}
|
||||
UATH_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1799,19 +1855,19 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct uath_data *bf;
|
||||
struct uath_softc *sc = ic->ic_softc;
|
||||
struct uath_softc *sc = ifp->if_softc;
|
||||
|
||||
UATH_LOCK(sc);
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
|
||||
!(sc->sc_flags & UATH_FLAG_INITDONE)) {
|
||||
!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
UATH_UNLOCK(sc);
|
||||
return (ENETDOWN);
|
||||
}
|
||||
|
||||
UATH_LOCK(sc);
|
||||
/* grab a TX buffer */
|
||||
bf = uath_getbuf(sc);
|
||||
if (bf == NULL) {
|
||||
@ -1824,6 +1880,7 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
sc->sc_seqnum = 0;
|
||||
if (uath_tx_start(sc, m, ni, bf) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
UATH_STAT_INC(sc, st_tx_inactive);
|
||||
UATH_UNLOCK(sc);
|
||||
@ -1850,11 +1907,12 @@ uath_scan_end(struct ieee80211com *ic)
|
||||
static void
|
||||
uath_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct uath_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct uath_softc *sc = ifp->if_softc;
|
||||
|
||||
UATH_LOCK(sc);
|
||||
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
|
||||
(sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
|
||||
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
UATH_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
@ -1875,7 +1933,7 @@ uath_update_mcast(struct ieee80211com *ic)
|
||||
|
||||
UATH_LOCK(sc);
|
||||
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
|
||||
(sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
|
||||
(ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
UATH_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
@ -1895,7 +1953,7 @@ uath_update_promisc(struct ieee80211com *ic)
|
||||
|
||||
UATH_LOCK(sc);
|
||||
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
|
||||
(sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
|
||||
(ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
UATH_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
@ -1912,7 +1970,7 @@ static int
|
||||
uath_create_connection(struct uath_softc *sc, uint32_t connid)
|
||||
{
|
||||
const struct ieee80211_rateset *rs;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ieee80211_node *ni;
|
||||
struct uath_cmd_create_connection create;
|
||||
@ -1963,7 +2021,7 @@ uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
|
||||
static int
|
||||
uath_write_associd(struct uath_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ieee80211_node *ni;
|
||||
struct uath_cmd_set_associd associd;
|
||||
@ -2017,7 +2075,7 @@ uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
int error;
|
||||
struct ieee80211_node *ni;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct uath_softc *sc = ic->ic_softc;
|
||||
struct uath_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct uath_vap *uvp = UATH_VAP(vap);
|
||||
|
||||
DPRINTF(sc, UATH_DEBUG_STATE,
|
||||
@ -2484,7 +2542,8 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
|
||||
struct uath_rx_desc **pdesc)
|
||||
{
|
||||
struct uath_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct uath_chunk *chunk;
|
||||
struct uath_rx_desc *desc;
|
||||
struct mbuf *m = data->m, *mnew, *mp;
|
||||
@ -2496,14 +2555,14 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
|
||||
if (actlen < (int)UATH_MIN_RXBUFSZ) {
|
||||
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
|
||||
"%s: wrong xfer size (len=%d)\n", __func__, actlen);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
chunk = (struct uath_chunk *)data->buf;
|
||||
if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
|
||||
device_printf(sc->sc_dev, "%s: strange response\n", __func__);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
UATH_RESET_INTRX(sc);
|
||||
return (NULL);
|
||||
}
|
||||
@ -2536,7 +2595,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
|
||||
if ((sc->sc_intrx_len + sizeof(struct uath_rx_desc) +
|
||||
chunklen) > UATH_MAX_INTRX_SIZE) {
|
||||
UATH_STAT_INC(sc, st_invalidlen);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
|
||||
if (sc->sc_intrx_head != NULL)
|
||||
m_freem(sc->sc_intrx_head);
|
||||
UATH_RESET_INTRX(sc);
|
||||
@ -2561,7 +2620,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
|
||||
if (mnew == NULL) {
|
||||
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
|
||||
"%s: can't get new mbuf, drop frame\n", __func__);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
if (sc->sc_intrx_head != NULL)
|
||||
m_freem(sc->sc_intrx_head);
|
||||
UATH_RESET_INTRX(sc);
|
||||
@ -2602,7 +2661,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
|
||||
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
|
||||
"%s: bad descriptor (len=%d)\n", __func__,
|
||||
be32toh(desc->len));
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
|
||||
UATH_STAT_INC(sc, st_toobigrxpkt);
|
||||
if (sc->sc_intrx_head != NULL)
|
||||
m_freem(sc->sc_intrx_head);
|
||||
@ -2614,11 +2673,13 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
|
||||
|
||||
/* finalize mbuf */
|
||||
if (sc->sc_intrx_head == NULL) {
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len =
|
||||
be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
|
||||
m->m_data += sizeof(struct uath_chunk);
|
||||
} else {
|
||||
mp = sc->sc_intrx_head;
|
||||
mp->m_pkthdr.rcvif = ifp;
|
||||
mp->m_flags |= M_PKTHDR;
|
||||
mp->m_pkthdr.len = sc->sc_intrx_len;
|
||||
m = mp;
|
||||
@ -2644,6 +2705,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
|
||||
tap->wr_antnoise = -95;
|
||||
}
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||
UATH_RESET_INTRX(sc);
|
||||
|
||||
return (m);
|
||||
@ -2653,7 +2715,8 @@ static void
|
||||
uath_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct uath_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m = NULL;
|
||||
@ -2713,8 +2776,10 @@ setup:
|
||||
m = NULL;
|
||||
desc = NULL;
|
||||
}
|
||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
|
||||
!IFQ_IS_EMPTY(&ifp->if_snd))
|
||||
uath_start(ifp);
|
||||
UATH_LOCK(sc);
|
||||
uath_start(sc);
|
||||
break;
|
||||
default:
|
||||
/* needs it to the inactive queue due to a error. */
|
||||
@ -2727,7 +2792,7 @@ setup:
|
||||
}
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto setup;
|
||||
}
|
||||
break;
|
||||
@ -2738,22 +2803,40 @@ static void
|
||||
uath_data_txeof(struct usb_xfer *xfer, struct uath_data *data)
|
||||
{
|
||||
struct uath_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct mbuf *m;
|
||||
|
||||
UATH_ASSERT_LOCKED(sc);
|
||||
|
||||
/*
|
||||
* Do any tx complete callback. Note this must be done before releasing
|
||||
* the node reference.
|
||||
*/
|
||||
if (data->m) {
|
||||
/* XXX status? */
|
||||
ieee80211_tx_complete(data->ni, data->m, 0);
|
||||
m = data->m;
|
||||
if (m->m_flags & M_TXCB &&
|
||||
(sc->sc_flags & UATH_FLAG_INVALID) == 0) {
|
||||
/* XXX status? */
|
||||
ieee80211_process_callback(data->ni, m, 0);
|
||||
}
|
||||
m_freem(m);
|
||||
data->m = NULL;
|
||||
}
|
||||
if (data->ni) {
|
||||
if ((sc->sc_flags & UATH_FLAG_INVALID) == 0)
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
}
|
||||
sc->sc_tx_timer = 0;
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
uath_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct uath_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct uath_data *data;
|
||||
|
||||
UATH_ASSERT_LOCKED(sc);
|
||||
@ -2785,18 +2868,19 @@ setup:
|
||||
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
|
||||
usbd_transfer_submit(xfer);
|
||||
|
||||
uath_start(sc);
|
||||
UATH_UNLOCK(sc);
|
||||
uath_start(ifp);
|
||||
UATH_LOCK(sc);
|
||||
break;
|
||||
default:
|
||||
data = STAILQ_FIRST(&sc->sc_tx_active);
|
||||
if (data == NULL)
|
||||
goto setup;
|
||||
if (data->ni != NULL) {
|
||||
if_inc_counter(data->ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if ((sc->sc_flags & UATH_FLAG_INVALID) == 0)
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
|
@ -183,8 +183,7 @@ struct uath_vap {
|
||||
#define UATH_VAP(vap) ((struct uath_vap *)(vap))
|
||||
|
||||
struct uath_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
struct usb_device *sc_udev;
|
||||
void *sc_cmd_dma_buf;
|
||||
|
@ -128,10 +128,10 @@ static void upgt_eeprom_parse_freq4(struct upgt_softc *, uint8_t *, int);
|
||||
static void upgt_eeprom_parse_freq6(struct upgt_softc *, uint8_t *, int);
|
||||
static uint32_t upgt_chksum_le(const uint32_t *, size_t);
|
||||
static void upgt_tx_done(struct upgt_softc *, uint8_t *);
|
||||
static void upgt_init(struct upgt_softc *);
|
||||
static void upgt_parent(struct ieee80211com *);
|
||||
static int upgt_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void upgt_start(struct upgt_softc *);
|
||||
static void upgt_init(void *);
|
||||
static void upgt_init_locked(struct upgt_softc *);
|
||||
static int upgt_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void upgt_start(struct ifnet *);
|
||||
static int upgt_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static void upgt_scan_start(struct ieee80211com *);
|
||||
@ -240,11 +240,12 @@ upgt_match(device_t dev)
|
||||
static int
|
||||
upgt_attach(device_t dev)
|
||||
{
|
||||
int error;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
struct upgt_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct usb_attach_arg *uaa = device_get_ivars(dev);
|
||||
uint8_t bands, iface_index = UPGT_IFACE_INDEX;
|
||||
int error;
|
||||
|
||||
sc->sc_dev = dev;
|
||||
sc->sc_udev = uaa->device;
|
||||
@ -257,7 +258,6 @@ upgt_attach(device_t dev)
|
||||
MTX_DEF);
|
||||
callout_init(&sc->sc_led_ch, 0);
|
||||
callout_init(&sc->sc_watchdog_ch, 0);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
|
||||
upgt_config, UPGT_N_XFERS, sc, &sc->sc_mtx);
|
||||
@ -280,20 +280,26 @@ upgt_attach(device_t dev)
|
||||
if (error)
|
||||
goto fail3;
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(dev, "can not if_alloc()\n");
|
||||
goto fail4;
|
||||
}
|
||||
|
||||
/* Initialize the device. */
|
||||
error = upgt_device_reset(sc);
|
||||
if (error)
|
||||
goto fail4;
|
||||
goto fail5;
|
||||
/* Verify the firmware. */
|
||||
error = upgt_fw_verify(sc);
|
||||
if (error)
|
||||
goto fail4;
|
||||
goto fail5;
|
||||
/* Calculate device memory space. */
|
||||
if (sc->sc_memaddr_frame_start == 0 || sc->sc_memaddr_frame_end == 0) {
|
||||
device_printf(dev,
|
||||
"could not find memory space addresses on FW\n");
|
||||
error = EIO;
|
||||
goto fail4;
|
||||
goto fail5;
|
||||
}
|
||||
sc->sc_memaddr_frame_end -= UPGT_MEMSIZE_RX + 1;
|
||||
sc->sc_memaddr_rx_start = sc->sc_memaddr_frame_end + 1;
|
||||
@ -310,19 +316,31 @@ upgt_attach(device_t dev)
|
||||
/* Load the firmware. */
|
||||
error = upgt_fw_load(sc);
|
||||
if (error)
|
||||
goto fail4;
|
||||
goto fail5;
|
||||
|
||||
/* Read the whole EEPROM content and parse it. */
|
||||
error = upgt_eeprom_read(sc);
|
||||
if (error)
|
||||
goto fail4;
|
||||
goto fail5;
|
||||
error = upgt_eeprom_parse(sc);
|
||||
if (error)
|
||||
goto fail4;
|
||||
goto fail5;
|
||||
|
||||
/* all works related with the device have done here. */
|
||||
upgt_abort_xfers(sc);
|
||||
|
||||
/* Setup the 802.11 device. */
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "upgt", device_get_unit(sc->sc_dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_init = upgt_init;
|
||||
ifp->if_ioctl = upgt_ioctl;
|
||||
ifp->if_start = upgt_start;
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
|
||||
ic = ifp->if_l2com;
|
||||
ic->ic_ifp = ifp;
|
||||
ic->ic_softc = sc;
|
||||
ic->ic_name = device_get_nameunit(dev);
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
@ -342,16 +360,15 @@ upgt_attach(device_t dev)
|
||||
setbit(&bands, IEEE80211_MODE_11G);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, sc->sc_myaddr);
|
||||
ic->ic_raw_xmit = upgt_raw_xmit;
|
||||
ic->ic_scan_start = upgt_scan_start;
|
||||
ic->ic_scan_end = upgt_scan_end;
|
||||
ic->ic_set_channel = upgt_set_channel;
|
||||
|
||||
ic->ic_vap_create = upgt_vap_create;
|
||||
ic->ic_vap_delete = upgt_vap_delete;
|
||||
ic->ic_update_mcast = upgt_update_mcast;
|
||||
ic->ic_transmit = upgt_transmit;
|
||||
ic->ic_parent = upgt_parent;
|
||||
|
||||
ieee80211_radiotap_attach(ic,
|
||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
|
||||
@ -366,6 +383,7 @@ upgt_attach(device_t dev)
|
||||
|
||||
return (0);
|
||||
|
||||
fail5: if_free(ifp);
|
||||
fail4: upgt_free_rx(sc);
|
||||
fail3: upgt_free_tx(sc);
|
||||
fail2: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
|
||||
@ -377,13 +395,30 @@ fail1: mtx_destroy(&sc->sc_mtx);
|
||||
static void
|
||||
upgt_txeof(struct usb_xfer *xfer, struct upgt_data *data)
|
||||
{
|
||||
struct upgt_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct mbuf *m;
|
||||
|
||||
UPGT_ASSERT_LOCKED(sc);
|
||||
|
||||
/*
|
||||
* Do any tx complete callback. Note this must be done before releasing
|
||||
* the node reference.
|
||||
*/
|
||||
if (data->m) {
|
||||
/* XXX status? */
|
||||
ieee80211_tx_complete(data->ni, data->m, 0);
|
||||
m = data->m;
|
||||
if (m->m_flags & M_TXCB) {
|
||||
/* XXX status? */
|
||||
ieee80211_process_callback(data->ni, m, 0);
|
||||
}
|
||||
m_freem(m);
|
||||
data->m = NULL;
|
||||
}
|
||||
if (data->ni) {
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
}
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -427,43 +462,77 @@ upgt_get_stats(struct upgt_softc *sc)
|
||||
upgt_bulk_tx(sc, data_cmd);
|
||||
}
|
||||
|
||||
static void
|
||||
upgt_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct upgt_softc *sc = ic->ic_softc;
|
||||
struct upgt_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error;
|
||||
int startall = 0;
|
||||
|
||||
UPGT_LOCK(sc);
|
||||
if (sc->sc_flags & UPGT_FLAG_DETACHED) {
|
||||
UPGT_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (sc->sc_flags & UPGT_FLAG_INITDONE) {
|
||||
if (ic->ic_allmulti > 0 || ic->ic_promisc > 0)
|
||||
upgt_set_multi(sc);
|
||||
} else {
|
||||
upgt_init(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else if (sc->sc_flags & UPGT_FLAG_INITDONE)
|
||||
upgt_stop(sc);
|
||||
error = (sc->sc_flags & UPGT_FLAG_DETACHED) ? ENXIO : 0;
|
||||
UPGT_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
if ((ifp->if_flags ^ sc->sc_if_flags) &
|
||||
(IFF_ALLMULTI | IFF_PROMISC))
|
||||
upgt_set_multi(sc);
|
||||
} else {
|
||||
upgt_init(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
upgt_stop(sc);
|
||||
}
|
||||
sc->sc_if_flags = ifp->if_flags;
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
upgt_stop_locked(struct upgt_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
UPGT_ASSERT_LOCKED(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
upgt_set_macfilter(sc, IEEE80211_S_INIT);
|
||||
upgt_abort_xfers_locked(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
upgt_stop(struct upgt_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
UPGT_ASSERT_LOCKED(sc);
|
||||
UPGT_LOCK(sc);
|
||||
upgt_stop_locked(sc);
|
||||
UPGT_UNLOCK(sc);
|
||||
|
||||
if (sc->sc_flags & UPGT_FLAG_INITDONE)
|
||||
upgt_set_macfilter(sc, IEEE80211_S_INIT);
|
||||
upgt_abort_xfers_locked(sc);
|
||||
/* device down */
|
||||
sc->sc_tx_timer = 0;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
sc->sc_flags &= ~UPGT_FLAG_INITDONE;
|
||||
}
|
||||
|
||||
@ -555,18 +624,36 @@ upgt_set_led_blink(void *arg)
|
||||
}
|
||||
|
||||
static void
|
||||
upgt_init(struct upgt_softc *sc)
|
||||
upgt_init(void *priv)
|
||||
{
|
||||
struct upgt_softc *sc = priv;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
UPGT_LOCK(sc);
|
||||
upgt_init_locked(sc);
|
||||
UPGT_UNLOCK(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic); /* start all vap's */
|
||||
}
|
||||
|
||||
static void
|
||||
upgt_init_locked(struct upgt_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
UPGT_ASSERT_LOCKED(sc);
|
||||
|
||||
if (sc->sc_flags & UPGT_FLAG_INITDONE)
|
||||
upgt_stop(sc);
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
upgt_stop_locked(sc);
|
||||
|
||||
usbd_transfer_start(sc->sc_xfer[UPGT_BULK_RX]);
|
||||
|
||||
(void)upgt_set_macfilter(sc, IEEE80211_S_SCAN);
|
||||
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
sc->sc_flags |= UPGT_FLAG_INITDONE;
|
||||
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc);
|
||||
@ -575,12 +662,14 @@ upgt_init(struct upgt_softc *sc)
|
||||
static int
|
||||
upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
|
||||
{
|
||||
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 ieee80211_node *ni;
|
||||
struct upgt_data *data_cmd;
|
||||
struct upgt_lmac_mem *mem;
|
||||
struct upgt_lmac_filter *filter;
|
||||
uint8_t broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
UPGT_ASSERT_LOCKED(sc);
|
||||
|
||||
@ -620,11 +709,10 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
|
||||
case IEEE80211_S_SCAN:
|
||||
DPRINTF(sc, UPGT_DEBUG_STATE,
|
||||
"set MAC filter to SCAN (bssid %s)\n",
|
||||
ether_sprintf(ieee80211broadcastaddr));
|
||||
ether_sprintf(broadcast));
|
||||
filter->type = htole16(UPGT_FILTER_TYPE_NONE);
|
||||
IEEE80211_ADDR_COPY(filter->dst,
|
||||
vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
IEEE80211_ADDR_COPY(filter->src, ieee80211broadcastaddr);
|
||||
IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
|
||||
IEEE80211_ADDR_COPY(filter->src, broadcast);
|
||||
filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1);
|
||||
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
|
||||
filter->unknown2 = htole16(UPGT_FILTER_UNKNOWN2);
|
||||
@ -636,8 +724,7 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
|
||||
/* XXX monitor mode isn't tested yet. */
|
||||
if (vap->iv_opmode == IEEE80211_M_MONITOR) {
|
||||
filter->type = htole16(UPGT_FILTER_TYPE_MONITOR);
|
||||
IEEE80211_ADDR_COPY(filter->dst,
|
||||
vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
|
||||
IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid);
|
||||
filter->unknown1 = htole16(UPGT_FILTER_MONITOR_UNKNOWN1);
|
||||
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
|
||||
@ -649,8 +736,7 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
|
||||
"set MAC filter to RUN (bssid %s)\n",
|
||||
ether_sprintf(ni->ni_bssid));
|
||||
filter->type = htole16(UPGT_FILTER_TYPE_STA);
|
||||
IEEE80211_ADDR_COPY(filter->dst,
|
||||
vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
|
||||
IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid);
|
||||
filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1);
|
||||
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
|
||||
@ -679,7 +765,8 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
|
||||
static void
|
||||
upgt_setup_rates(struct ieee80211vap *vap, struct ieee80211com *ic)
|
||||
{
|
||||
struct upgt_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct upgt_softc *sc = ifp->if_softc;
|
||||
const struct ieee80211_txparam *tp;
|
||||
|
||||
/*
|
||||
@ -726,48 +813,39 @@ upgt_setup_rates(struct ieee80211vap *vap, struct ieee80211com *ic)
|
||||
static void
|
||||
upgt_set_multi(void *arg)
|
||||
{
|
||||
struct upgt_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
/* XXX don't know how to set a device. Lack of docs. */
|
||||
}
|
||||
if (!(ifp->if_flags & IFF_UP))
|
||||
return;
|
||||
|
||||
static int
|
||||
upgt_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct upgt_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
UPGT_LOCK(sc);
|
||||
if ((sc->sc_flags & UPGT_FLAG_INITDONE) == 0) {
|
||||
UPGT_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
UPGT_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
upgt_start(sc);
|
||||
UPGT_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
/*
|
||||
* XXX don't know how to set a device. Lack of docs. Just try to set
|
||||
* IFF_ALLMULTI flag here.
|
||||
*/
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
}
|
||||
|
||||
static void
|
||||
upgt_start(struct upgt_softc *sc)
|
||||
upgt_start(struct ifnet *ifp)
|
||||
{
|
||||
struct upgt_softc *sc = ifp->if_softc;
|
||||
struct upgt_data *data_tx;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
UPGT_ASSERT_LOCKED(sc);
|
||||
|
||||
if ((sc->sc_flags & UPGT_FLAG_INITDONE) == 0)
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
UPGT_LOCK(sc);
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
|
||||
data_tx = upgt_gettxbuf(sc);
|
||||
if (data_tx == NULL) {
|
||||
mbufq_prepend(&sc->sc_snd, m);
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -775,15 +853,15 @@ upgt_start(struct upgt_softc *sc)
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
|
||||
if (upgt_tx_start(sc, m, ni, data_tx) != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next);
|
||||
UPGT_STAT_INC(sc, st_tx_inactive);
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
continue;
|
||||
}
|
||||
sc->sc_tx_timer = 5;
|
||||
}
|
||||
UPGT_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -791,18 +869,18 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct upgt_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct upgt_softc *sc = ifp->if_softc;
|
||||
struct upgt_data *data_tx = NULL;
|
||||
|
||||
UPGT_LOCK(sc);
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!(sc->sc_flags & UPGT_FLAG_INITDONE)) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
UPGT_UNLOCK(sc);
|
||||
return ENETDOWN;
|
||||
}
|
||||
|
||||
UPGT_LOCK(sc);
|
||||
data_tx = upgt_gettxbuf(sc);
|
||||
if (data_tx == NULL) {
|
||||
ieee80211_free_node(ni);
|
||||
@ -815,6 +893,7 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next);
|
||||
UPGT_STAT_INC(sc, st_tx_inactive);
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
UPGT_UNLOCK(sc);
|
||||
return (EIO);
|
||||
}
|
||||
@ -828,13 +907,13 @@ static void
|
||||
upgt_watchdog(void *arg)
|
||||
{
|
||||
struct upgt_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (sc->sc_tx_timer > 0) {
|
||||
if (--sc->sc_tx_timer == 0) {
|
||||
device_printf(sc->sc_dev, "watchdog timeout\n");
|
||||
/* upgt_init(sc); XXX needs a process context ? */
|
||||
counter_u64_add(ic->ic_oerrors, 1);
|
||||
/* upgt_init(ifp); XXX needs a process context ? */
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return;
|
||||
}
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc);
|
||||
@ -871,7 +950,7 @@ upgt_scan_end(struct ieee80211com *ic)
|
||||
static void
|
||||
upgt_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct upgt_softc *sc = ic->ic_softc;
|
||||
struct upgt_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
UPGT_LOCK(sc);
|
||||
upgt_set_chan(sc, ic->ic_curchan);
|
||||
@ -881,7 +960,8 @@ upgt_set_channel(struct ieee80211com *ic)
|
||||
static void
|
||||
upgt_set_chan(struct upgt_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct upgt_data *data_cmd;
|
||||
struct upgt_lmac_mem *mem;
|
||||
struct upgt_lmac_channel *chan;
|
||||
@ -964,7 +1044,7 @@ upgt_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
/* enable s/w bmiss handling for sta mode */
|
||||
|
||||
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
|
||||
/* out of memory */
|
||||
free(uvp, M_80211_VAP);
|
||||
return (NULL);
|
||||
@ -979,7 +1059,7 @@ upgt_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
}
|
||||
@ -989,7 +1069,7 @@ upgt_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct upgt_vap *uvp = UPGT_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct upgt_softc *sc = ic->ic_softc;
|
||||
struct upgt_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
/* do it in a process context */
|
||||
sc->sc_state = nstate;
|
||||
@ -1045,7 +1125,6 @@ upgt_update_mcast(struct ieee80211com *ic)
|
||||
static int
|
||||
upgt_eeprom_parse(struct upgt_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct upgt_eeprom_header *eeprom_header;
|
||||
struct upgt_eeprom_option *eeprom_option;
|
||||
uint16_t option_len;
|
||||
@ -1090,8 +1169,7 @@ upgt_eeprom_parse(struct upgt_softc *sc)
|
||||
DPRINTF(sc, UPGT_DEBUG_FW,
|
||||
"EEPROM mac len=%d\n", option_len);
|
||||
|
||||
IEEE80211_ADDR_COPY(ic->ic_macaddr,
|
||||
eeprom_option->data);
|
||||
IEEE80211_ADDR_COPY(sc->sc_myaddr, eeprom_option->data);
|
||||
break;
|
||||
case UPGT_EEPROM_TYPE_HWRX:
|
||||
DPRINTF(sc, UPGT_DEBUG_FW,
|
||||
@ -1440,7 +1518,8 @@ upgt_chksum_le(const uint32_t *buf, size_t size)
|
||||
static struct mbuf *
|
||||
upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct upgt_lmac_rx_desc *rxdesc;
|
||||
struct mbuf *m;
|
||||
|
||||
@ -1448,7 +1527,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
|
||||
* don't pass packets to the ieee80211 framework if the driver isn't
|
||||
* RUNNING.
|
||||
*/
|
||||
if (!(sc->sc_flags & UPGT_FLAG_INITDONE))
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
|
||||
return (NULL);
|
||||
|
||||
/* access RX packet descriptor */
|
||||
@ -1466,6 +1545,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
|
||||
memcpy(mtod(m, char *), rxdesc->data, pkglen);
|
||||
/* trim FCS */
|
||||
m->m_len = m->m_pkthdr.len = pkglen - IEEE80211_CRC_LEN;
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
|
||||
if (ieee80211_radiotap_active(ic)) {
|
||||
struct upgt_rx_radiotap_header *tap = &sc->sc_rxtap;
|
||||
@ -1474,6 +1554,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
|
||||
tap->wr_rate = upgt_rx_rate(sc, rxdesc->rate);
|
||||
tap->wr_antsignal = rxdesc->rssi;
|
||||
}
|
||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||
|
||||
DPRINTF(sc, UPGT_DEBUG_RX_PROC, "%s: RX done\n", __func__);
|
||||
*rssi = rxdesc->rssi;
|
||||
@ -1483,7 +1564,8 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
|
||||
static uint8_t
|
||||
upgt_rx_rate(struct upgt_softc *sc, const int rate)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
static const uint8_t cck_upgt2rate[4] = { 2, 4, 11, 22 };
|
||||
static const uint8_t ofdm_upgt2rate[12] =
|
||||
{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
|
||||
@ -1502,6 +1584,7 @@ upgt_rx_rate(struct upgt_softc *sc, const int rate)
|
||||
static void
|
||||
upgt_tx_done(struct upgt_softc *sc, uint8_t *data)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct upgt_lmac_tx_done_desc *desc;
|
||||
int i, freed = 0;
|
||||
|
||||
@ -1530,9 +1613,10 @@ upgt_tx_done(struct upgt_softc *sc, uint8_t *data)
|
||||
}
|
||||
|
||||
if (freed != 0) {
|
||||
UPGT_UNLOCK(sc);
|
||||
sc->sc_tx_timer = 0;
|
||||
upgt_start(sc);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
UPGT_UNLOCK(sc);
|
||||
upgt_start(ifp);
|
||||
UPGT_LOCK(sc);
|
||||
}
|
||||
}
|
||||
@ -1938,7 +2022,8 @@ static int
|
||||
upgt_detach(device_t dev)
|
||||
{
|
||||
struct upgt_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
unsigned int x;
|
||||
|
||||
/*
|
||||
@ -1954,9 +2039,9 @@ upgt_detach(device_t dev)
|
||||
|
||||
STAILQ_INIT(&sc->sc_rx_active);
|
||||
STAILQ_INIT(&sc->sc_rx_inactive);
|
||||
UPGT_UNLOCK(sc);
|
||||
|
||||
upgt_stop(sc);
|
||||
UPGT_UNLOCK(sc);
|
||||
|
||||
callout_drain(&sc->sc_led_ch);
|
||||
callout_drain(&sc->sc_watchdog_ch);
|
||||
@ -1975,7 +2060,7 @@ upgt_detach(device_t dev)
|
||||
usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
|
||||
|
||||
ieee80211_ifdetach(ic);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
if_free(ifp);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -2083,8 +2168,12 @@ upgt_getbuf(struct upgt_softc *sc)
|
||||
UPGT_ASSERT_LOCKED(sc);
|
||||
|
||||
bf = _upgt_getbuf(sc);
|
||||
if (bf == NULL)
|
||||
if (bf == NULL) {
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: stop queue\n", __func__);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
}
|
||||
|
||||
return (bf);
|
||||
}
|
||||
@ -2102,10 +2191,14 @@ upgt_gettxbuf(struct upgt_softc *sc)
|
||||
|
||||
bf->addr = upgt_mem_alloc(sc);
|
||||
if (bf->addr == 0) {
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: no free prism memory!\n",
|
||||
__func__);
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
UPGT_STAT_INC(sc, st_tx_inactive);
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_OACTIVE))
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
return (NULL);
|
||||
}
|
||||
return (bf);
|
||||
@ -2119,6 +2212,7 @@ upgt_tx_start(struct upgt_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
|
||||
int error = 0, len;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_key *k;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct upgt_lmac_mem *mem;
|
||||
struct upgt_lmac_tx_desc *txdesc;
|
||||
|
||||
@ -2201,7 +2295,7 @@ done:
|
||||
* will stall. It's strange, but it works, so we keep reading
|
||||
* the statistics here. *shrug*
|
||||
*/
|
||||
if (!(vap->iv_ifp->if_get_counter(vap->iv_ifp, IFCOUNTER_OPACKETS) %
|
||||
if (!(ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS) %
|
||||
UPGT_TX_STAT_INTERVAL))
|
||||
upgt_get_stats(sc);
|
||||
|
||||
@ -2212,7 +2306,8 @@ static void
|
||||
upgt_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct upgt_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m = NULL;
|
||||
@ -2260,8 +2355,10 @@ setup:
|
||||
(void) ieee80211_input_all(ic, m, rssi, nf);
|
||||
m = NULL;
|
||||
}
|
||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
|
||||
!IFQ_IS_EMPTY(&ifp->if_snd))
|
||||
upgt_start(ifp);
|
||||
UPGT_LOCK(sc);
|
||||
upgt_start(sc);
|
||||
break;
|
||||
default:
|
||||
/* needs it to the inactive queue due to a error. */
|
||||
@ -2272,7 +2369,7 @@ setup:
|
||||
}
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto setup;
|
||||
}
|
||||
break;
|
||||
@ -2283,6 +2380,7 @@ static void
|
||||
upgt_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct upgt_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct upgt_data *data;
|
||||
|
||||
UPGT_ASSERT_LOCKED(sc);
|
||||
@ -2312,17 +2410,18 @@ setup:
|
||||
|
||||
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
|
||||
usbd_transfer_submit(xfer);
|
||||
upgt_start(sc);
|
||||
UPGT_UNLOCK(sc);
|
||||
upgt_start(ifp);
|
||||
UPGT_LOCK(sc);
|
||||
break;
|
||||
default:
|
||||
data = STAILQ_FIRST(&sc->sc_tx_active);
|
||||
if (data == NULL)
|
||||
goto setup;
|
||||
if (data->ni != NULL) {
|
||||
if_inc_counter(data->ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
|
@ -418,9 +418,8 @@ struct upgt_vap {
|
||||
#define UPGT_VAP(vap) ((struct upgt_vap *)(vap))
|
||||
|
||||
struct upgt_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
device_t sc_dev;
|
||||
struct ifnet *sc_ifp;
|
||||
struct usb_device *sc_udev;
|
||||
void *sc_rx_dma_buf;
|
||||
void *sc_tx_dma_buf;
|
||||
@ -430,8 +429,11 @@ struct upgt_softc {
|
||||
#define UPGT_FLAG_FWLOADED (1 << 0)
|
||||
#define UPGT_FLAG_INITDONE (1 << 1)
|
||||
#define UPGT_FLAG_DETACHED (1 << 2)
|
||||
int sc_if_flags;
|
||||
int sc_debug;
|
||||
|
||||
uint8_t sc_myaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
enum ieee80211_state sc_state;
|
||||
int sc_arg;
|
||||
int sc_led_blink;
|
||||
|
@ -149,9 +149,8 @@ static int ural_tx_mgt(struct ural_softc *, struct mbuf *,
|
||||
struct ieee80211_node *);
|
||||
static int ural_tx_data(struct ural_softc *, struct mbuf *,
|
||||
struct ieee80211_node *);
|
||||
static int ural_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void ural_start(struct ural_softc *);
|
||||
static void ural_parent(struct ieee80211com *);
|
||||
static void ural_start(struct ifnet *);
|
||||
static int ural_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void ural_set_testmode(struct ural_softc *);
|
||||
static void ural_eeprom_read(struct ural_softc *, uint16_t, void *,
|
||||
int);
|
||||
@ -172,12 +171,12 @@ static void ural_set_chan(struct ural_softc *,
|
||||
static void ural_disable_rf_tune(struct ural_softc *);
|
||||
static void ural_enable_tsf_sync(struct ural_softc *);
|
||||
static void ural_enable_tsf(struct ural_softc *);
|
||||
static void ural_update_slot(struct ural_softc *);
|
||||
static void ural_update_slot(struct ifnet *);
|
||||
static void ural_set_txpreamble(struct ural_softc *);
|
||||
static void ural_set_basicrates(struct ural_softc *,
|
||||
const struct ieee80211_channel *);
|
||||
static void ural_set_bssid(struct ural_softc *, const uint8_t *);
|
||||
static void ural_set_macaddr(struct ural_softc *, const uint8_t *);
|
||||
static void ural_set_macaddr(struct ural_softc *, uint8_t *);
|
||||
static void ural_update_promisc(struct ieee80211com *);
|
||||
static void ural_setpromisc(struct ural_softc *);
|
||||
static const char *ural_get_rf(int);
|
||||
@ -185,7 +184,8 @@ static void ural_read_eeprom(struct ural_softc *);
|
||||
static int ural_bbp_init(struct ural_softc *);
|
||||
static void ural_set_txantenna(struct ural_softc *, int);
|
||||
static void ural_set_rxantenna(struct ural_softc *, int);
|
||||
static void ural_init(struct ural_softc *);
|
||||
static void ural_init_locked(struct ural_softc *);
|
||||
static void ural_init(void *);
|
||||
static void ural_stop(struct ural_softc *);
|
||||
static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
@ -422,7 +422,8 @@ ural_attach(device_t self)
|
||||
{
|
||||
struct usb_attach_arg *uaa = device_get_ivars(self);
|
||||
struct ural_softc *sc = device_get_softc(self);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
uint8_t iface_index, bands;
|
||||
int error;
|
||||
|
||||
@ -432,7 +433,6 @@ ural_attach(device_t self)
|
||||
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
iface_index = RAL_IFACE_INDEX;
|
||||
error = usbd_transfer_setup(uaa->device,
|
||||
@ -455,6 +455,24 @@ ural_attach(device_t self)
|
||||
device_printf(self, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
|
||||
sc->asic_rev, ural_get_rf(sc->rf_rev));
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
||||
goto detach;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "ural", device_get_unit(sc->sc_dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_init = ural_init;
|
||||
ifp->if_ioctl = ural_ioctl;
|
||||
ifp->if_start = ural_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_name = device_get_nameunit(self);
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
@ -479,14 +497,13 @@ ural_attach(device_t self)
|
||||
setbit(&bands, IEEE80211_MODE_11A);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, sc->sc_bssid);
|
||||
ic->ic_update_promisc = ural_update_promisc;
|
||||
ic->ic_raw_xmit = ural_raw_xmit;
|
||||
ic->ic_scan_start = ural_scan_start;
|
||||
ic->ic_scan_end = ural_scan_end;
|
||||
ic->ic_set_channel = ural_set_channel;
|
||||
ic->ic_parent = ural_parent;
|
||||
ic->ic_transmit = ural_transmit;
|
||||
|
||||
ic->ic_vap_create = ural_vap_create;
|
||||
ic->ic_vap_delete = ural_vap_delete;
|
||||
|
||||
@ -510,7 +527,8 @@ static int
|
||||
ural_detach(device_t self)
|
||||
{
|
||||
struct ural_softc *sc = device_get_softc(self);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic;
|
||||
|
||||
/* prevent further ioctls */
|
||||
RAL_LOCK(sc);
|
||||
@ -525,9 +543,11 @@ ural_detach(device_t self)
|
||||
ural_unsetup_tx_list(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
if (ic->ic_softc == sc)
|
||||
if (ifp) {
|
||||
ic = ifp->if_l2com;
|
||||
ieee80211_ifdetach(ic);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
if_free(ifp);
|
||||
}
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -560,7 +580,7 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct ural_softc *sc = ic->ic_softc;
|
||||
struct ural_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ural_vap *uvp;
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
@ -574,7 +594,7 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
/* enable s/w bmiss handling for sta mode */
|
||||
|
||||
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
|
||||
/* out of memory */
|
||||
free(uvp, M_80211_VAP);
|
||||
return (NULL);
|
||||
@ -590,8 +610,7 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
}
|
||||
@ -615,8 +634,13 @@ ural_tx_free(struct ural_tx_data *data, int txerr)
|
||||
struct ural_softc *sc = data->sc;
|
||||
|
||||
if (data->m != NULL) {
|
||||
ieee80211_tx_complete(data->ni, data->m, txerr);
|
||||
if (data->m->m_flags & M_TXCB)
|
||||
ieee80211_process_callback(data->ni, data->m,
|
||||
txerr ? ETIMEDOUT : 0);
|
||||
m_freem(data->m);
|
||||
data->m = NULL;
|
||||
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
}
|
||||
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
|
||||
@ -673,7 +697,7 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct ural_vap *uvp = URAL_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ural_softc *sc = ic->ic_softc;
|
||||
struct ural_softc *sc = ic->ic_ifp->if_softc;
|
||||
const struct ieee80211_txparam *tp;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
@ -707,11 +731,11 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
ieee80211_free_node(ni);
|
||||
return (-1);
|
||||
}
|
||||
ural_update_slot(sc);
|
||||
ural_update_slot(ic->ic_ifp);
|
||||
ural_set_txpreamble(sc);
|
||||
ural_set_basicrates(sc, ic->ic_bsschan);
|
||||
IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
|
||||
ural_set_bssid(sc, ic->ic_macaddr);
|
||||
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
|
||||
ural_set_bssid(sc, sc->sc_bssid);
|
||||
}
|
||||
|
||||
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
|
||||
@ -765,6 +789,7 @@ static void
|
||||
ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct ural_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211vap *vap;
|
||||
struct ural_tx_data *data;
|
||||
struct mbuf *m;
|
||||
@ -782,6 +807,9 @@ ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
ural_tx_free(data, 0);
|
||||
usbd_xfer_set_priv(xfer, NULL);
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case USB_ST_SETUP:
|
||||
tr_setup:
|
||||
@ -824,13 +852,16 @@ tr_setup:
|
||||
|
||||
usbd_transfer_submit(xfer);
|
||||
}
|
||||
ural_start(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
ural_start(ifp);
|
||||
RAL_LOCK(sc);
|
||||
break;
|
||||
|
||||
default: /* Error */
|
||||
DPRINTFN(11, "transfer error, %s\n",
|
||||
usbd_errstr(error));
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
data = usbd_xfer_get_priv(xfer);
|
||||
if (data != NULL) {
|
||||
ural_tx_free(data, error);
|
||||
@ -852,7 +883,8 @@ static void
|
||||
ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct ural_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m = NULL;
|
||||
struct usb_page_cache *pc;
|
||||
@ -870,7 +902,7 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
if (len < (int)(RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN)) {
|
||||
DPRINTF("%s: xfer too short %d\n",
|
||||
device_get_nameunit(sc->sc_dev), len);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
|
||||
@ -889,19 +921,20 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
* filled RAL_TXRX_CSR2:
|
||||
*/
|
||||
DPRINTFN(5, "PHY or CRC error\n");
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
|
||||
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (m == NULL) {
|
||||
DPRINTF("could not allocate mbuf\n");
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
usbd_copy_out(pc, 0, mtod(m, uint8_t *), len);
|
||||
|
||||
/* finalize mbuf */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
|
||||
|
||||
if (ieee80211_radiotap_active(ic)) {
|
||||
@ -940,8 +973,10 @@ tr_setup:
|
||||
} else
|
||||
(void) ieee80211_input_all(ic, m, rssi, nf);
|
||||
}
|
||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
|
||||
!IFQ_IS_EMPTY(&ifp->if_snd))
|
||||
ural_start(ifp);
|
||||
RAL_LOCK(sc);
|
||||
ural_start(sc);
|
||||
return;
|
||||
|
||||
default: /* Error */
|
||||
@ -981,7 +1016,8 @@ static void
|
||||
ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc,
|
||||
uint32_t flags, int len, int rate)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint16_t plcp_length;
|
||||
int remainder;
|
||||
|
||||
@ -1030,10 +1066,12 @@ ural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
const struct ieee80211_txparam *tp;
|
||||
struct ural_tx_data *data;
|
||||
|
||||
if (sc->tx_nfree == 0) {
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
m_freem(m0);
|
||||
ieee80211_free_node(ni);
|
||||
return (EIO);
|
||||
@ -1310,73 +1348,78 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ural_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct ural_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
if (!sc->sc_running) {
|
||||
RAL_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
RAL_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
ural_start(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ural_start(struct ural_softc *sc)
|
||||
ural_start(struct ifnet *ifp)
|
||||
{
|
||||
struct ural_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
RAL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
if (sc->sc_running == 0)
|
||||
return;
|
||||
|
||||
while (sc->tx_nfree >= RAL_TX_MINFREE &&
|
||||
(m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
if (ural_tx_data(sc, m, ni) != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ural_parent(struct ieee80211com *ic)
|
||||
{
|
||||
struct ural_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
if (sc->sc_detached) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
RAL_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (sc->sc_running == 0) {
|
||||
ural_init(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
ural_setpromisc(sc);
|
||||
} else if (sc->sc_running)
|
||||
ural_stop(sc);
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
if (sc->tx_nfree < RAL_TX_MINFREE) {
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
break;
|
||||
}
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
if (ural_tx_data(sc, m, ni) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
RAL_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
}
|
||||
|
||||
static int
|
||||
ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct ural_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error;
|
||||
int startall = 0;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
error = sc->sc_detached ? ENXIO : 0;
|
||||
RAL_UNLOCK(sc);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
RAL_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
ural_init_locked(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
ural_setpromisc(sc);
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ural_stop(sc);
|
||||
}
|
||||
RAL_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
case SIOCSIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
||||
break;
|
||||
default:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1571,22 +1614,23 @@ ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val)
|
||||
static void
|
||||
ural_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct ural_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ural_softc *sc = ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
ural_write(sc, RAL_TXRX_CSR19, 0);
|
||||
ural_set_bssid(sc, ieee80211broadcastaddr);
|
||||
ural_set_bssid(sc, ifp->if_broadcastaddr);
|
||||
RAL_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
ural_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct ural_softc *sc = ic->ic_softc;
|
||||
struct ural_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
ural_enable_tsf_sync(sc);
|
||||
ural_set_bssid(sc, ic->ic_macaddr);
|
||||
ural_set_bssid(sc, sc->sc_bssid);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
}
|
||||
@ -1594,7 +1638,7 @@ ural_scan_end(struct ieee80211com *ic)
|
||||
static void
|
||||
ural_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct ural_softc *sc = ic->ic_softc;
|
||||
struct ural_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
ural_set_chan(sc, ic->ic_curchan);
|
||||
@ -1604,7 +1648,8 @@ ural_set_channel(struct ieee80211com *ic)
|
||||
static void
|
||||
ural_set_chan(struct ural_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;
|
||||
int i, chan;
|
||||
|
||||
@ -1735,7 +1780,8 @@ ural_disable_rf_tune(struct ural_softc *sc)
|
||||
static void
|
||||
ural_enable_tsf_sync(struct ural_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, tmp;
|
||||
|
||||
@ -1771,9 +1817,10 @@ ural_enable_tsf(struct ural_softc *sc)
|
||||
|
||||
#define RAL_RXTX_TURNAROUND 5 /* us */
|
||||
static void
|
||||
ural_update_slot(struct ural_softc *sc)
|
||||
ural_update_slot(struct ifnet *ifp)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ural_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint16_t slottime, sifs, eifs;
|
||||
|
||||
slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
|
||||
@ -1798,7 +1845,8 @@ ural_update_slot(struct ural_softc *sc)
|
||||
static void
|
||||
ural_set_txpreamble(struct ural_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint16_t tmp;
|
||||
|
||||
tmp = ural_read(sc, RAL_TXRX_CSR10);
|
||||
@ -1845,7 +1893,7 @@ ural_set_bssid(struct ural_softc *sc, const uint8_t *bssid)
|
||||
}
|
||||
|
||||
static void
|
||||
ural_set_macaddr(struct ural_softc *sc, const uint8_t *addr)
|
||||
ural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
|
||||
{
|
||||
uint16_t tmp;
|
||||
|
||||
@ -1864,17 +1912,18 @@ ural_set_macaddr(struct ural_softc *sc, const uint8_t *addr)
|
||||
static void
|
||||
ural_setpromisc(struct ural_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = ural_read(sc, RAL_TXRX_CSR2);
|
||||
|
||||
tmp &= ~RAL_DROP_NOT_TO_ME;
|
||||
if (sc->sc_ic.ic_promisc == 0)
|
||||
if (!(ifp->if_flags & IFF_PROMISC))
|
||||
tmp |= RAL_DROP_NOT_TO_ME;
|
||||
|
||||
ural_write(sc, RAL_TXRX_CSR2, tmp);
|
||||
|
||||
DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc ?
|
||||
DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
|
||||
"entering" : "leaving");
|
||||
}
|
||||
|
||||
@ -1883,9 +1932,11 @@ ural_update_promisc(struct ieee80211com *ic)
|
||||
{
|
||||
struct ural_softc *sc = ic->ic_softc;
|
||||
|
||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
if (sc->sc_running)
|
||||
ural_setpromisc(sc);
|
||||
ural_setpromisc(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
}
|
||||
|
||||
@ -1907,7 +1958,6 @@ ural_get_rf(int rev)
|
||||
static void
|
||||
ural_read_eeprom(struct ural_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
uint16_t val;
|
||||
|
||||
ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2);
|
||||
@ -1920,7 +1970,7 @@ ural_read_eeprom(struct ural_softc *sc)
|
||||
sc->nb_ant = val & 0x3;
|
||||
|
||||
/* read MAC address */
|
||||
ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_macaddr, 6);
|
||||
ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6);
|
||||
|
||||
/* read default values for BBP registers */
|
||||
ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16);
|
||||
@ -2014,11 +2064,11 @@ ural_set_rxantenna(struct ural_softc *sc, int antenna)
|
||||
}
|
||||
|
||||
static void
|
||||
ural_init(struct ural_softc *sc)
|
||||
ural_init_locked(struct ural_softc *sc)
|
||||
{
|
||||
#define N(a) ((int)(sizeof (a) / sizeof ((a)[0])))
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint16_t tmp;
|
||||
int i, ntries;
|
||||
|
||||
@ -2065,7 +2115,7 @@ ural_init(struct ural_softc *sc)
|
||||
ural_set_txantenna(sc, sc->tx_ant);
|
||||
ural_set_rxantenna(sc, sc->rx_ant);
|
||||
|
||||
ural_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
ural_set_macaddr(sc, IF_LLADDR(ifp));
|
||||
|
||||
/*
|
||||
* Allocate Tx and Rx xfer queues.
|
||||
@ -2078,12 +2128,13 @@ ural_init(struct ural_softc *sc)
|
||||
tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION;
|
||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP)
|
||||
tmp |= RAL_DROP_TODS;
|
||||
if (ic->ic_promisc == 0)
|
||||
if (!(ifp->if_flags & IFF_PROMISC))
|
||||
tmp |= RAL_DROP_NOT_TO_ME;
|
||||
}
|
||||
ural_write(sc, RAL_TXRX_CSR2, tmp);
|
||||
|
||||
sc->sc_running = 1;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
usbd_xfer_set_stall(sc->sc_xfer[URAL_BULK_WR]);
|
||||
usbd_transfer_start(sc->sc_xfer[URAL_BULK_RD]);
|
||||
return;
|
||||
@ -2092,13 +2143,29 @@ fail: ural_stop(sc);
|
||||
#undef N
|
||||
}
|
||||
|
||||
static void
|
||||
ural_init(void *priv)
|
||||
{
|
||||
struct ural_softc *sc = priv;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
ural_init_locked(sc);
|
||||
RAL_UNLOCK(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic); /* start all vap's */
|
||||
}
|
||||
|
||||
static void
|
||||
ural_stop(struct ural_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
RAL_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
sc->sc_running = 0;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
/*
|
||||
* Drain all the transfers, if not already drained:
|
||||
@ -2126,23 +2193,27 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ural_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ural_softc *sc = ifp->if_softc;
|
||||
|
||||
RAL_LOCK(sc);
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!sc->sc_running) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
RAL_UNLOCK(sc);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return ENETDOWN;
|
||||
}
|
||||
if (sc->tx_nfree < RAL_TX_MINFREE) {
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
RAL_UNLOCK(sc);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
|
||||
if (params == NULL) {
|
||||
/*
|
||||
* Legacy path; interpret frame contents to decide
|
||||
@ -2161,6 +2232,7 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
RAL_UNLOCK(sc);
|
||||
return 0;
|
||||
bad:
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
RAL_UNLOCK(sc);
|
||||
ieee80211_free_node(ni);
|
||||
return EIO; /* XXX */
|
||||
@ -2194,7 +2266,8 @@ ural_ratectl_task(void *arg, int pending)
|
||||
struct ural_vap *uvp = arg;
|
||||
struct ieee80211vap *vap = &uvp->vap;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ural_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ural_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
int ok, fail;
|
||||
int sum, retrycnt;
|
||||
@ -2213,8 +2286,7 @@ ural_ratectl_task(void *arg, int pending)
|
||||
ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt);
|
||||
(void) ieee80211_ratectl_rate(ni, NULL, 0);
|
||||
|
||||
/* count TX retry-fail as Tx errors */
|
||||
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */
|
||||
|
||||
usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp);
|
||||
RAL_UNLOCK(sc);
|
||||
|
@ -89,8 +89,7 @@ enum {
|
||||
};
|
||||
|
||||
struct ural_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
struct usb_device *sc_udev;
|
||||
|
||||
@ -110,8 +109,8 @@ struct ural_softc {
|
||||
uint16_t sta[11];
|
||||
uint32_t rf_regs[4];
|
||||
uint8_t txpow[14];
|
||||
u_int sc_detached:1,
|
||||
sc_running:1;
|
||||
uint8_t sc_bssid[6];
|
||||
uint8_t sc_detached;
|
||||
|
||||
struct {
|
||||
uint8_t val;
|
||||
|
@ -651,11 +651,11 @@ static struct ieee80211vap *urtw_vap_create(struct ieee80211com *,
|
||||
int, const uint8_t [IEEE80211_ADDR_LEN],
|
||||
const uint8_t [IEEE80211_ADDR_LEN]);
|
||||
static void urtw_vap_delete(struct ieee80211vap *);
|
||||
static void urtw_init(struct urtw_softc *);
|
||||
static void urtw_stop(struct urtw_softc *);
|
||||
static void urtw_parent(struct ieee80211com *);
|
||||
static int urtw_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void urtw_start(struct urtw_softc *);
|
||||
static void urtw_init(void *);
|
||||
static void urtw_stop(struct ifnet *);
|
||||
static void urtw_stop_locked(struct ifnet *);
|
||||
static int urtw_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void urtw_start(struct ifnet *);
|
||||
static int urtw_alloc_rx_data_list(struct urtw_softc *);
|
||||
static int urtw_alloc_tx_data_list(struct urtw_softc *);
|
||||
static int urtw_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
@ -784,7 +784,8 @@ urtw_attach(device_t dev)
|
||||
int ret = ENXIO;
|
||||
struct urtw_softc *sc = device_get_softc(dev);
|
||||
struct usb_attach_arg *uaa = device_get_ivars(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
uint8_t bands, iface_index = URTW_IFACE_INDEX; /* XXX */
|
||||
uint16_t n_setup;
|
||||
uint32_t data;
|
||||
@ -806,7 +807,6 @@ urtw_attach(device_t dev)
|
||||
TASK_INIT(&sc->sc_led_task, 0, urtw_ledtask, sc);
|
||||
TASK_INIT(&sc->sc_updateslot_task, 0, urtw_updateslottask, sc);
|
||||
callout_init(&sc->sc_watchdog_ch, 0);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
if (sc->sc_flags & URTW_RTL8187B) {
|
||||
setup_start = urtw_8187b_usbconfig;
|
||||
@ -861,6 +861,26 @@ urtw_attach(device_t dev)
|
||||
sc->sc_currate = 3;
|
||||
sc->sc_preamble_mode = urtw_preamble_mode;
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not allocate ifnet\n");
|
||||
ret = ENOMEM;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "urtw", device_get_unit(sc->sc_dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_init = urtw_init;
|
||||
ifp->if_ioctl = urtw_ioctl;
|
||||
ifp->if_start = urtw_start;
|
||||
/* XXX URTW_TX_DATA_LIST_COUNT */
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
|
||||
ic = ifp->if_l2com;
|
||||
ic->ic_ifp = ifp;
|
||||
ic->ic_softc = sc;
|
||||
ic->ic_name = device_get_nameunit(dev);
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
@ -881,7 +901,7 @@ urtw_attach(device_t dev)
|
||||
setbit(&bands, IEEE80211_MODE_11G);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, sc->sc_bssid);
|
||||
ic->ic_raw_xmit = urtw_raw_xmit;
|
||||
ic->ic_scan_start = urtw_scan_start;
|
||||
ic->ic_scan_end = urtw_scan_end;
|
||||
@ -890,8 +910,6 @@ urtw_attach(device_t dev)
|
||||
ic->ic_vap_create = urtw_vap_create;
|
||||
ic->ic_vap_delete = urtw_vap_delete;
|
||||
ic->ic_update_mcast = urtw_update_mcast;
|
||||
ic->ic_parent = urtw_parent;
|
||||
ic->ic_transmit = urtw_transmit;
|
||||
|
||||
ieee80211_radiotap_attach(ic,
|
||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
|
||||
@ -905,9 +923,8 @@ urtw_attach(device_t dev)
|
||||
ieee80211_announce(ic);
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
URTW_UNLOCK(sc);
|
||||
usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
|
||||
fail: URTW_UNLOCK(sc);
|
||||
fail1: usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
|
||||
URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
|
||||
fail0:
|
||||
return (ret);
|
||||
@ -917,16 +934,18 @@ static int
|
||||
urtw_detach(device_t dev)
|
||||
{
|
||||
struct urtw_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
unsigned int x;
|
||||
unsigned int n_xfers;
|
||||
|
||||
/* Prevent further ioctls */
|
||||
URTW_LOCK(sc);
|
||||
sc->sc_flags |= URTW_DETACHED;
|
||||
urtw_stop(sc);
|
||||
URTW_UNLOCK(sc);
|
||||
|
||||
urtw_stop(ifp);
|
||||
|
||||
ieee80211_draintask(ic, &sc->sc_updateslot_task);
|
||||
ieee80211_draintask(ic, &sc->sc_led_task);
|
||||
|
||||
@ -960,7 +979,7 @@ urtw_detach(device_t dev)
|
||||
usbd_transfer_unsetup(sc->sc_xfer, n_xfers);
|
||||
|
||||
ieee80211_ifdetach(ic);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
if_free(ifp);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
return (0);
|
||||
}
|
||||
@ -1013,12 +1032,15 @@ urtw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
|
||||
return (NULL);
|
||||
uvp = malloc(sizeof(struct urtw_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
uvp = (struct urtw_vap *) malloc(sizeof(struct urtw_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (uvp == NULL)
|
||||
return (NULL);
|
||||
vap = &uvp->vap;
|
||||
/* enable s/w bmiss handling for sta mode */
|
||||
|
||||
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
|
||||
/* out of memory */
|
||||
free(uvp, M_80211_VAP);
|
||||
return (NULL);
|
||||
@ -1030,7 +1052,7 @@ urtw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return (vap);
|
||||
}
|
||||
@ -1045,15 +1067,15 @@ urtw_vap_delete(struct ieee80211vap *vap)
|
||||
}
|
||||
|
||||
static void
|
||||
urtw_init(struct urtw_softc *sc)
|
||||
urtw_init_locked(void *arg)
|
||||
{
|
||||
usb_error_t error;
|
||||
int ret;
|
||||
struct urtw_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
usb_error_t error;
|
||||
|
||||
URTW_ASSERT_LOCKED(sc);
|
||||
|
||||
if (sc->sc_flags & URTW_RUNNING)
|
||||
urtw_stop(sc);
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
urtw_stop_locked(ifp);
|
||||
|
||||
error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) :
|
||||
urtw_adapter_start(sc);
|
||||
@ -1083,13 +1105,24 @@ urtw_init(struct urtw_softc *sc)
|
||||
if (sc->sc_flags & URTW_RTL8187B)
|
||||
usbd_transfer_start(sc->sc_xfer[URTW_8187B_BULK_TX_STATUS]);
|
||||
|
||||
sc->sc_flags |= URTW_RUNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
|
||||
fail:
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
urtw_init(void *arg)
|
||||
{
|
||||
struct urtw_softc *sc = arg;
|
||||
|
||||
URTW_LOCK(sc);
|
||||
urtw_init_locked(arg);
|
||||
URTW_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static usb_error_t
|
||||
urtw_adapter_start_b(struct urtw_softc *sc)
|
||||
{
|
||||
@ -1182,7 +1215,6 @@ fail:
|
||||
static usb_error_t
|
||||
urtw_adapter_start(struct urtw_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
usb_error_t error;
|
||||
|
||||
error = urtw_reset(sc);
|
||||
@ -1202,8 +1234,8 @@ urtw_adapter_start(struct urtw_softc *sc)
|
||||
if (error)
|
||||
goto fail;
|
||||
/* applying MAC address again. */
|
||||
urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
|
||||
urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
|
||||
urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]);
|
||||
urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff);
|
||||
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
|
||||
if (error)
|
||||
goto fail;
|
||||
@ -1306,14 +1338,13 @@ urtw_do_request(struct urtw_softc *sc,
|
||||
}
|
||||
|
||||
static void
|
||||
urtw_stop(struct urtw_softc *sc)
|
||||
urtw_stop_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct urtw_softc *sc = ifp->if_softc;
|
||||
uint8_t data8;
|
||||
usb_error_t error;
|
||||
|
||||
URTW_ASSERT_LOCKED(sc);
|
||||
|
||||
sc->sc_flags &= ~URTW_RUNNING;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
error = urtw_intr_disable(sc);
|
||||
if (error)
|
||||
@ -1345,6 +1376,16 @@ fail:
|
||||
urtw_abort_xfers(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
urtw_stop(struct ifnet *ifp)
|
||||
{
|
||||
struct urtw_softc *sc = ifp->if_softc;
|
||||
|
||||
URTW_LOCK(sc);
|
||||
urtw_stop_locked(ifp);
|
||||
URTW_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
urtw_abort_xfers(struct urtw_softc *sc)
|
||||
{
|
||||
@ -1360,71 +1401,72 @@ urtw_abort_xfers(struct urtw_softc *sc)
|
||||
usbd_transfer_stop(sc->sc_xfer[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
urtw_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct urtw_softc *sc = ic->ic_softc;
|
||||
struct urtw_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error;
|
||||
int startall = 0;
|
||||
|
||||
URTW_LOCK(sc);
|
||||
if (sc->sc_flags & URTW_DETACHED) {
|
||||
URTW_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (sc->sc_flags & URTW_RUNNING) {
|
||||
if (ic->ic_promisc > 0 || ic->ic_allmulti > 0)
|
||||
urtw_set_multi(sc);
|
||||
} else {
|
||||
urtw_init(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else if (sc->sc_flags & URTW_RUNNING)
|
||||
urtw_stop(sc);
|
||||
error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0;
|
||||
URTW_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
}
|
||||
|
||||
static int
|
||||
urtw_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct urtw_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
URTW_LOCK(sc);
|
||||
if ((sc->sc_flags & URTW_RUNNING) == 0) {
|
||||
URTW_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
URTW_UNLOCK(sc);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
urtw_start(sc);
|
||||
URTW_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
if ((ifp->if_flags ^ sc->sc_if_flags) &
|
||||
(IFF_ALLMULTI | IFF_PROMISC))
|
||||
urtw_set_multi(sc);
|
||||
} else {
|
||||
urtw_init(ifp->if_softc);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
urtw_stop(ifp);
|
||||
}
|
||||
sc->sc_if_flags = ifp->if_flags;
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
urtw_start(struct urtw_softc *sc)
|
||||
urtw_start(struct ifnet *ifp)
|
||||
{
|
||||
struct urtw_data *bf;
|
||||
struct urtw_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
URTW_ASSERT_LOCKED(sc);
|
||||
|
||||
if ((sc->sc_flags & URTW_RUNNING) == 0)
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
URTW_LOCK(sc);
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
bf = urtw_getbuf(sc);
|
||||
if (bf == NULL) {
|
||||
mbufq_prepend(&sc->sc_snd, m);
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1432,8 +1474,7 @@ urtw_start(struct urtw_softc *sc)
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
|
||||
if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_NORMAL) != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
ieee80211_free_node(ni);
|
||||
break;
|
||||
@ -1442,6 +1483,7 @@ urtw_start(struct urtw_softc *sc)
|
||||
sc->sc_txtimer = 5;
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
|
||||
}
|
||||
URTW_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1523,11 +1565,12 @@ urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct urtw_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct urtw_data *bf;
|
||||
struct urtw_softc *sc = ifp->if_softc;
|
||||
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!(sc->sc_flags & URTW_RUNNING)) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return ENETDOWN;
|
||||
@ -1541,8 +1584,10 @@ urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
return (ENOBUFS); /* XXX */
|
||||
}
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_LOW) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
URTW_UNLOCK(sc);
|
||||
return (EIO);
|
||||
@ -1570,7 +1615,8 @@ urtw_scan_end(struct ieee80211com *ic)
|
||||
static void
|
||||
urtw_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct urtw_softc *sc = ic->ic_softc;
|
||||
struct urtw_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t data, orig;
|
||||
usb_error_t error;
|
||||
|
||||
@ -1580,7 +1626,7 @@ urtw_set_channel(struct ieee80211com *ic)
|
||||
* initialization would be failed if setting a channel is called before
|
||||
* the init have done.
|
||||
*/
|
||||
if (!(sc->sc_flags & URTW_RUNNING))
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
|
||||
return;
|
||||
|
||||
if (sc->sc_curchan != NULL && sc->sc_curchan == ic->ic_curchan)
|
||||
@ -1627,10 +1673,11 @@ static int
|
||||
urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0,
|
||||
struct urtw_data *data, int prior)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *);
|
||||
struct ieee80211_key *k;
|
||||
const struct ieee80211_txparam *tp;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct usb_xfer *rtl8187b_pipes[URTW_8187B_TXPIPE_MAX] = {
|
||||
sc->sc_xfer[URTW_8187B_BULK_TX_BE],
|
||||
@ -1815,7 +1862,7 @@ static int
|
||||
urtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct urtw_softc *sc = ic->ic_softc;
|
||||
struct urtw_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct urtw_vap *uvp = URTW_VAP(vap);
|
||||
struct ieee80211_node *ni;
|
||||
usb_error_t error = 0;
|
||||
@ -1868,11 +1915,12 @@ static void
|
||||
urtw_watchdog(void *arg)
|
||||
{
|
||||
struct urtw_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (sc->sc_txtimer > 0) {
|
||||
if (--sc->sc_txtimer == 0) {
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return;
|
||||
}
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
|
||||
@ -1882,7 +1930,17 @@ urtw_watchdog(void *arg)
|
||||
static void
|
||||
urtw_set_multi(void *arg)
|
||||
{
|
||||
/* XXX don't know how to set a device. Lack of docs. */
|
||||
struct urtw_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (!(ifp->if_flags & IFF_UP))
|
||||
return;
|
||||
|
||||
/*
|
||||
* XXX don't know how to set a device. Lack of docs. Just try to set
|
||||
* IFF_ALLMULTI flag here.
|
||||
*/
|
||||
ifp->if_flags |= IFF_ALLMULTI;
|
||||
}
|
||||
|
||||
static usb_error_t
|
||||
@ -1944,7 +2002,8 @@ urtw_rtl2rate(uint32_t rate)
|
||||
static usb_error_t
|
||||
urtw_update_msr(struct urtw_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint8_t data;
|
||||
usb_error_t error;
|
||||
|
||||
@ -2085,25 +2144,24 @@ urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data)
|
||||
static usb_error_t
|
||||
urtw_get_macaddr(struct urtw_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
uint32_t data;
|
||||
usb_error_t error;
|
||||
|
||||
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
ic->ic_macaddr[0] = data & 0xff;
|
||||
ic->ic_macaddr[1] = (data & 0xff00) >> 8;
|
||||
sc->sc_bssid[0] = data & 0xff;
|
||||
sc->sc_bssid[1] = (data & 0xff00) >> 8;
|
||||
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
ic->ic_macaddr[2] = data & 0xff;
|
||||
ic->ic_macaddr[3] = (data & 0xff00) >> 8;
|
||||
sc->sc_bssid[2] = data & 0xff;
|
||||
sc->sc_bssid[3] = (data & 0xff00) >> 8;
|
||||
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
ic->ic_macaddr[4] = data & 0xff;
|
||||
ic->ic_macaddr[5] = (data & 0xff00) >> 8;
|
||||
sc->sc_bssid[4] = data & 0xff;
|
||||
sc->sc_bssid[5] = (data & 0xff00) >> 8;
|
||||
fail:
|
||||
return (error);
|
||||
}
|
||||
@ -3175,7 +3233,7 @@ fail:
|
||||
static usb_error_t
|
||||
urtw_8225v2b_rf_init(struct urtw_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
#define N(a) ((int)(sizeof(a) / sizeof((a)[0])))
|
||||
int i;
|
||||
uint8_t data8;
|
||||
usb_error_t error;
|
||||
@ -3223,8 +3281,8 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
|
||||
urtw_write8_m(sc, URTW_CONFIG1, data8);
|
||||
|
||||
/* applying MAC address again. */
|
||||
urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
|
||||
urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
|
||||
urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]);
|
||||
urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff);
|
||||
|
||||
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
|
||||
if (error)
|
||||
@ -3235,7 +3293,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
|
||||
/*
|
||||
* MAC configuration
|
||||
*/
|
||||
for (i = 0; i < nitems(urtw_8225v2b_rf_part1); i++)
|
||||
for (i = 0; i < N(urtw_8225v2b_rf_part1); i++)
|
||||
urtw_write8_m(sc, urtw_8225v2b_rf_part1[i].reg,
|
||||
urtw_8225v2b_rf_part1[i].val);
|
||||
urtw_write16_m(sc, URTW_TID_AC_MAP, 0xfa50);
|
||||
@ -3268,7 +3326,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
|
||||
urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1fff);
|
||||
usb_pause_mtx(&sc->sc_mtx, 1100);
|
||||
|
||||
for (i = 0; i < nitems(urtw_8225v2b_rf_part0); i++) {
|
||||
for (i = 0; i < N(urtw_8225v2b_rf_part0); i++) {
|
||||
urtw_8225_write(sc, urtw_8225v2b_rf_part0[i].reg,
|
||||
urtw_8225v2b_rf_part0[i].val);
|
||||
usb_pause_mtx(&sc->sc_mtx, 1);
|
||||
@ -3314,7 +3372,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
|
||||
}
|
||||
urtw_8187_write_phy_ofdm(sc, 0x80, 0x10);
|
||||
|
||||
for (i = 0; i < nitems(urtw_8225v2b_rf_part2); i++)
|
||||
for (i = 0; i < N(urtw_8225v2b_rf_part2); i++)
|
||||
urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val);
|
||||
|
||||
urtw_write32_m(sc, URTW_8187B_AC_VO, (7 << 12) | (3 << 8) | 0x1c);
|
||||
@ -3729,7 +3787,8 @@ static void
|
||||
urtw_led_ch(void *arg)
|
||||
{
|
||||
struct urtw_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
ieee80211_runtask(ic, &sc->sc_led_task);
|
||||
}
|
||||
@ -3876,7 +3935,8 @@ fail:
|
||||
static usb_error_t
|
||||
urtw_rx_setconf(struct urtw_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t data;
|
||||
usb_error_t error;
|
||||
|
||||
@ -3901,7 +3961,7 @@ urtw_rx_setconf(struct urtw_softc *sc)
|
||||
data = data | URTW_RX_FILTER_CRCERR;
|
||||
|
||||
if (ic->ic_opmode == IEEE80211_M_MONITOR ||
|
||||
ic->ic_promisc > 0 || ic->ic_allmulti > 0) {
|
||||
(ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
|
||||
data = data | URTW_RX_FILTER_ALLMAC;
|
||||
} else {
|
||||
data = data | URTW_RX_FILTER_NICMAC;
|
||||
@ -3928,13 +3988,14 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
|
||||
struct ieee80211_frame *wh;
|
||||
struct mbuf *m, *mnew;
|
||||
struct urtw_softc *sc = data->sc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint8_t noise = 0, rate;
|
||||
|
||||
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
|
||||
|
||||
if (actlen < (int)URTW_MIN_RXBUFSZ) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -3945,7 +4006,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
|
||||
(actlen - (sizeof(struct urtw_8187b_rxhdr))));
|
||||
flen = le32toh(rx->flag) & 0xfff;
|
||||
if (flen > actlen) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return (NULL);
|
||||
}
|
||||
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
|
||||
@ -3959,7 +4020,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
|
||||
(actlen - (sizeof(struct urtw_8187l_rxhdr))));
|
||||
flen = le32toh(rx->flag) & 0xfff;
|
||||
if (flen > actlen) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -3971,7 +4032,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
|
||||
|
||||
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
if (mnew == NULL) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -3980,6 +4041,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
|
||||
data->buf = mtod(mnew, uint8_t *);
|
||||
|
||||
/* finalize mbuf */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len = flen - IEEE80211_CRC_LEN;
|
||||
|
||||
if (ieee80211_radiotap_active(ic)) {
|
||||
@ -4005,7 +4067,8 @@ static void
|
||||
urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct urtw_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m = NULL;
|
||||
@ -4066,7 +4129,7 @@ setup:
|
||||
}
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto setup;
|
||||
}
|
||||
break;
|
||||
@ -4080,7 +4143,7 @@ static void
|
||||
urtw_txstatus_eof(struct usb_xfer *xfer)
|
||||
{
|
||||
struct urtw_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int actlen, type, pktretry, seq;
|
||||
uint64_t val;
|
||||
|
||||
@ -4095,7 +4158,7 @@ urtw_txstatus_eof(struct usb_xfer *xfer)
|
||||
pktretry = val & 0xff;
|
||||
seq = (val >> 16) & 0xff;
|
||||
if (pktretry == URTW_TX_MAXRETRY)
|
||||
counter_u64_add(ic->ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
DPRINTF(sc, URTW_DEBUG_TXSTATUS, "pktretry %d seq %#x\n",
|
||||
pktretry, seq);
|
||||
}
|
||||
@ -4105,7 +4168,7 @@ static void
|
||||
urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct urtw_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0);
|
||||
|
||||
URTW_ASSERT_LOCKED(sc);
|
||||
@ -4123,7 +4186,7 @@ setup:
|
||||
default:
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto setup;
|
||||
}
|
||||
break;
|
||||
@ -4134,22 +4197,38 @@ static void
|
||||
urtw_txeof(struct usb_xfer *xfer, struct urtw_data *data)
|
||||
{
|
||||
struct urtw_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct mbuf *m;
|
||||
|
||||
URTW_ASSERT_LOCKED(sc);
|
||||
|
||||
/*
|
||||
* Do any tx complete callback. Note this must be done before releasing
|
||||
* the node reference.
|
||||
*/
|
||||
if (data->m) {
|
||||
/* XXX status? */
|
||||
ieee80211_tx_complete(data->ni, data->m, 0);
|
||||
m = data->m;
|
||||
if (m->m_flags & M_TXCB) {
|
||||
/* XXX status? */
|
||||
ieee80211_process_callback(data->ni, m, 0);
|
||||
}
|
||||
m_freem(m);
|
||||
data->m = NULL;
|
||||
}
|
||||
if (data->ni) {
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
}
|
||||
sc->sc_txtimer = 0;
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
urtw_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct urtw_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct urtw_data *data;
|
||||
|
||||
URTW_ASSERT_LOCKED(sc);
|
||||
@ -4177,17 +4256,18 @@ setup:
|
||||
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
|
||||
usbd_transfer_submit(xfer);
|
||||
|
||||
urtw_start(sc);
|
||||
URTW_UNLOCK(sc);
|
||||
urtw_start(ifp);
|
||||
URTW_LOCK(sc);
|
||||
break;
|
||||
default:
|
||||
data = STAILQ_FIRST(&sc->sc_tx_active);
|
||||
if (data == NULL)
|
||||
goto setup;
|
||||
if (data->ni != NULL) {
|
||||
if_inc_counter(data->ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
@ -4221,8 +4301,12 @@ urtw_getbuf(struct urtw_softc *sc)
|
||||
URTW_ASSERT_LOCKED(sc);
|
||||
|
||||
bf = _urtw_getbuf(sc);
|
||||
if (bf == NULL)
|
||||
if (bf == NULL) {
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
DPRINTF(sc, URTW_DEBUG_XMIT, "%s: stop queue\n", __func__);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
}
|
||||
return (bf);
|
||||
}
|
||||
|
||||
@ -4294,14 +4378,14 @@ static void
|
||||
urtw_updateslottask(void *arg, int pending)
|
||||
{
|
||||
struct urtw_softc *sc = arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
int error;
|
||||
|
||||
URTW_LOCK(sc);
|
||||
if ((sc->sc_flags & URTW_RUNNING) == 0) {
|
||||
URTW_UNLOCK(sc);
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
URTW_LOCK(sc);
|
||||
if (sc->sc_flags & URTW_RTL8187B) {
|
||||
urtw_write8_m(sc, URTW_SIFS, 0x22);
|
||||
if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan))
|
||||
|
@ -169,8 +169,8 @@ static device_detach_t urtwn_detach;
|
||||
static usb_callback_t urtwn_bulk_tx_callback;
|
||||
static usb_callback_t urtwn_bulk_rx_callback;
|
||||
|
||||
static usb_error_t urtwn_do_request(struct urtwn_softc *,
|
||||
struct usb_device_request *, void *);
|
||||
static usb_error_t urtwn_do_request(struct urtwn_softc *sc,
|
||||
struct usb_device_request *req, void *data);
|
||||
static struct ieee80211vap *urtwn_vap_create(struct ieee80211com *,
|
||||
const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
|
||||
const uint8_t [IEEE80211_ADDR_LEN],
|
||||
@ -228,9 +228,10 @@ static int8_t urtwn_r88e_get_rssi(struct urtwn_softc *, int, void *);
|
||||
static int urtwn_tx_start(struct urtwn_softc *,
|
||||
struct ieee80211_node *, struct mbuf *,
|
||||
struct urtwn_data *);
|
||||
static int urtwn_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void urtwn_start(struct urtwn_softc *);
|
||||
static void urtwn_parent(struct ieee80211com *);
|
||||
static void urtwn_start(struct ifnet *);
|
||||
static void urtwn_start_locked(struct ifnet *,
|
||||
struct urtwn_softc *);
|
||||
static int urtwn_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static int urtwn_r92c_power_on(struct urtwn_softc *);
|
||||
static int urtwn_r88e_power_on(struct urtwn_softc *);
|
||||
static int urtwn_llt_init(struct urtwn_softc *);
|
||||
@ -268,8 +269,10 @@ static void urtwn_set_chan(struct urtwn_softc *,
|
||||
static void urtwn_update_mcast(struct ieee80211com *);
|
||||
static void urtwn_iq_calib(struct urtwn_softc *);
|
||||
static void urtwn_lc_calib(struct urtwn_softc *);
|
||||
static void urtwn_init(struct urtwn_softc *);
|
||||
static void urtwn_stop(struct urtwn_softc *);
|
||||
static void urtwn_init(void *);
|
||||
static void urtwn_init_locked(void *);
|
||||
static void urtwn_stop(struct ifnet *);
|
||||
static void urtwn_stop_locked(struct ifnet *);
|
||||
static void urtwn_abort_xfers(struct urtwn_softc *);
|
||||
static int urtwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
@ -365,7 +368,8 @@ urtwn_attach(device_t self)
|
||||
{
|
||||
struct usb_attach_arg *uaa = device_get_ivars(self);
|
||||
struct urtwn_softc *sc = device_get_softc(self);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
uint8_t iface_index, bands;
|
||||
int error;
|
||||
|
||||
@ -378,7 +382,6 @@ urtwn_attach(device_t self)
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
callout_init(&sc->sc_watchdog_ch, 0);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
iface_index = URTWN_IFACE_INDEX;
|
||||
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
|
||||
@ -421,6 +424,24 @@ urtwn_attach(device_t self)
|
||||
|
||||
URTWN_UNLOCK(sc);
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
||||
goto detach;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "urtwn", device_get_unit(sc->sc_dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_init = urtwn_init;
|
||||
ifp->if_ioctl = urtwn_ioctl;
|
||||
ifp->if_start = urtwn_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_name = device_get_nameunit(self);
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
@ -441,13 +462,12 @@ urtwn_attach(device_t self)
|
||||
setbit(&bands, IEEE80211_MODE_11G);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, sc->sc_bssid);
|
||||
ic->ic_raw_xmit = urtwn_raw_xmit;
|
||||
ic->ic_scan_start = urtwn_scan_start;
|
||||
ic->ic_scan_end = urtwn_scan_end;
|
||||
ic->ic_set_channel = urtwn_set_channel;
|
||||
ic->ic_transmit = urtwn_transmit;
|
||||
ic->ic_parent = urtwn_parent;
|
||||
|
||||
ic->ic_vap_create = urtwn_vap_create;
|
||||
ic->ic_vap_delete = urtwn_vap_delete;
|
||||
ic->ic_update_mcast = urtwn_update_mcast;
|
||||
@ -471,15 +491,17 @@ static int
|
||||
urtwn_detach(device_t self)
|
||||
{
|
||||
struct urtwn_softc *sc = device_get_softc(self);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
unsigned int x;
|
||||
|
||||
/* Prevent further ioctls. */
|
||||
URTWN_LOCK(sc);
|
||||
sc->sc_flags |= URTWN_DETACHED;
|
||||
urtwn_stop(sc);
|
||||
URTWN_UNLOCK(sc);
|
||||
|
||||
urtwn_stop(ifp);
|
||||
|
||||
callout_drain(&sc->sc_watchdog_ch);
|
||||
|
||||
/* Prevent further allocations from RX/TX data lists. */
|
||||
@ -505,7 +527,8 @@ urtwn_detach(device_t self)
|
||||
/* stop all USB transfers */
|
||||
usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER);
|
||||
ieee80211_ifdetach(ic);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
|
||||
if_free(ifp);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -576,12 +599,15 @@ urtwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
|
||||
return (NULL);
|
||||
|
||||
uvp = malloc(sizeof(struct urtwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
uvp = (struct urtwn_vap *) malloc(sizeof(struct urtwn_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (uvp == NULL)
|
||||
return (NULL);
|
||||
vap = &uvp->vap;
|
||||
/* enable s/w bmiss handling for sta mode */
|
||||
|
||||
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
|
||||
/* out of memory */
|
||||
free(uvp, M_80211_VAP);
|
||||
return (NULL);
|
||||
@ -593,7 +619,7 @@ urtwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return (vap);
|
||||
}
|
||||
@ -610,7 +636,8 @@ urtwn_vap_delete(struct ieee80211vap *vap)
|
||||
static struct mbuf *
|
||||
urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_frame *wh;
|
||||
struct mbuf *m;
|
||||
struct r92c_rx_stat *stat;
|
||||
@ -623,7 +650,7 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
|
||||
* don't pass packets to the ieee80211 framework if the driver isn't
|
||||
* RUNNING.
|
||||
*/
|
||||
if (!(sc->sc_flags & URTWN_RUNNING))
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
|
||||
return (NULL);
|
||||
|
||||
stat = (struct r92c_rx_stat *)buf;
|
||||
@ -635,11 +662,11 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
|
||||
* This should not happen since we setup our Rx filter
|
||||
* to not receive these frames.
|
||||
*/
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return (NULL);
|
||||
}
|
||||
if (pktlen < sizeof(*wh) || pktlen > MCLBYTES) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -668,6 +695,7 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
|
||||
}
|
||||
|
||||
/* Finalize mbuf. */
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
wh = (struct ieee80211_frame *)((uint8_t *)&stat[1] + infosz);
|
||||
memcpy(mtod(m, uint8_t *), wh, pktlen);
|
||||
m->m_pkthdr.len = m->m_len = pktlen;
|
||||
@ -713,7 +741,7 @@ urtwn_rxeof(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi,
|
||||
int8_t *nf)
|
||||
{
|
||||
struct urtwn_softc *sc = data->sc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct r92c_rx_stat *stat;
|
||||
struct mbuf *m, *m0 = NULL, *prevm = NULL;
|
||||
uint32_t rxdw0;
|
||||
@ -723,7 +751,7 @@ urtwn_rxeof(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi,
|
||||
usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
|
||||
|
||||
if (len < sizeof(*stat)) {
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -774,7 +802,8 @@ static void
|
||||
urtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m = NULL, *next;
|
||||
@ -837,7 +866,7 @@ tr_setup:
|
||||
}
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
goto tr_setup;
|
||||
}
|
||||
break;
|
||||
@ -848,19 +877,38 @@ static void
|
||||
urtwn_txeof(struct usb_xfer *xfer, struct urtwn_data *data)
|
||||
{
|
||||
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct mbuf *m;
|
||||
|
||||
URTWN_ASSERT_LOCKED(sc);
|
||||
/* XXX status? */
|
||||
ieee80211_tx_complete(data->ni, data->m, 0);
|
||||
data->ni = NULL;
|
||||
data->m = NULL;
|
||||
|
||||
/*
|
||||
* Do any tx complete callback. Note this must be done before releasing
|
||||
* the node reference.
|
||||
*/
|
||||
if (data->m) {
|
||||
m = data->m;
|
||||
if (m->m_flags & M_TXCB) {
|
||||
/* XXX status? */
|
||||
ieee80211_process_callback(data->ni, m, 0);
|
||||
}
|
||||
m_freem(m);
|
||||
data->m = NULL;
|
||||
}
|
||||
if (data->ni) {
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
}
|
||||
sc->sc_txtimer = 0;
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
urtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct urtwn_data *data;
|
||||
|
||||
URTWN_ASSERT_LOCKED(sc);
|
||||
@ -885,17 +933,16 @@ tr_setup:
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next);
|
||||
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
|
||||
usbd_transfer_submit(xfer);
|
||||
urtwn_start(sc);
|
||||
urtwn_start_locked(ifp, sc);
|
||||
break;
|
||||
default:
|
||||
data = STAILQ_FIRST(&sc->sc_tx_active);
|
||||
if (data == NULL)
|
||||
goto tr_setup;
|
||||
if (data->ni != NULL) {
|
||||
if_inc_counter(data->ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
}
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
@ -928,8 +975,11 @@ urtwn_getbuf(struct urtwn_softc *sc)
|
||||
URTWN_ASSERT_LOCKED(sc);
|
||||
|
||||
bf = _urtwn_getbuf(sc);
|
||||
if (bf == NULL)
|
||||
if (bf == NULL) {
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
DPRINTF("%s: stop queue\n", __func__);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
}
|
||||
return (bf);
|
||||
}
|
||||
|
||||
@ -1252,7 +1302,7 @@ urtwn_read_rom(struct urtwn_softc *sc)
|
||||
|
||||
sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY);
|
||||
DPRINTF("regulatory type=%d\n", sc->regulatory);
|
||||
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
|
||||
IEEE80211_ADDR_COPY(sc->sc_bssid, rom->macaddr);
|
||||
|
||||
sc->sc_rf_write = urtwn_r92c_rf_write;
|
||||
sc->sc_power_on = urtwn_r92c_power_on;
|
||||
@ -1313,7 +1363,7 @@ urtwn_r88e_read_rom(struct urtwn_softc *sc)
|
||||
if (sc->ofdm_tx_pwr_diff & 0x08)
|
||||
sc->ofdm_tx_pwr_diff |= 0xf0;
|
||||
sc->regulatory = MS(sc->r88e_rom[0xc1], R92C_ROM_RF1_REGULATORY);
|
||||
IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, &sc->r88e_rom[0xd7]);
|
||||
IEEE80211_ADDR_COPY(sc->sc_bssid, &sc->r88e_rom[0xd7]);
|
||||
|
||||
sc->sc_rf_write = urtwn_r88e_rf_write;
|
||||
sc->sc_power_on = urtwn_r88e_power_on;
|
||||
@ -1328,7 +1378,7 @@ urtwn_ra_init(struct urtwn_softc *sc)
|
||||
{
|
||||
static const uint8_t map[] =
|
||||
{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ieee80211_node *ni;
|
||||
struct ieee80211_rateset *rs;
|
||||
@ -1405,7 +1455,8 @@ urtwn_ra_init(struct urtwn_softc *sc)
|
||||
void
|
||||
urtwn_tsf_sync_enable(struct urtwn_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 ieee80211_node *ni = vap->iv_bss;
|
||||
|
||||
@ -1462,7 +1513,7 @@ urtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct urtwn_vap *uvp = URTWN_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct urtwn_softc *sc = ic->ic_softc;
|
||||
struct urtwn_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
enum ieee80211_state ostate;
|
||||
uint32_t reg;
|
||||
@ -1618,11 +1669,12 @@ static void
|
||||
urtwn_watchdog(void *arg)
|
||||
{
|
||||
struct urtwn_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (sc->sc_txtimer > 0) {
|
||||
if (--sc->sc_txtimer == 0) {
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return;
|
||||
}
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
|
||||
@ -1748,9 +1800,10 @@ static int
|
||||
urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
|
||||
struct mbuf *m0, struct urtwn_data *data)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_key *k;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct usb_xfer *xfer;
|
||||
struct r92c_tx_desc *txd;
|
||||
@ -1889,78 +1942,89 @@ urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
urtwn_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
static void
|
||||
urtwn_start(struct ifnet *ifp)
|
||||
{
|
||||
struct urtwn_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
struct urtwn_softc *sc = ifp->if_softc;
|
||||
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
URTWN_LOCK(sc);
|
||||
if ((sc->sc_flags & URTWN_RUNNING) == 0) {
|
||||
URTWN_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
URTWN_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
urtwn_start(sc);
|
||||
urtwn_start_locked(ifp, sc);
|
||||
URTWN_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
urtwn_start(struct urtwn_softc *sc)
|
||||
urtwn_start_locked(struct ifnet *ifp, struct urtwn_softc *sc)
|
||||
{
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
struct urtwn_data *bf;
|
||||
|
||||
URTWN_ASSERT_LOCKED(sc);
|
||||
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
bf = urtwn_getbuf(sc);
|
||||
if (bf == NULL) {
|
||||
mbufq_prepend(&sc->sc_snd, m);
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
break;
|
||||
}
|
||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
|
||||
if (urtwn_tx_start(sc, ni, m, bf) != 0) {
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
ieee80211_free_node(ni);
|
||||
break;
|
||||
}
|
||||
|
||||
sc->sc_txtimer = 5;
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
urtwn_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
urtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct urtwn_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
struct urtwn_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error = 0, startall = 0;
|
||||
|
||||
URTWN_LOCK(sc);
|
||||
if (sc->sc_flags & URTWN_DETACHED) {
|
||||
URTWN_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if ((sc->sc_flags & URTWN_RUNNING) == 0) {
|
||||
urtwn_init(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else if (sc->sc_flags & URTWN_RUNNING)
|
||||
urtwn_stop(sc);
|
||||
error = (sc->sc_flags & URTWN_DETACHED) ? ENXIO : 0;
|
||||
URTWN_UNLOCK(sc);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
urtwn_init(ifp->if_softc);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
urtwn_stop(ifp);
|
||||
}
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
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);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2874,7 +2938,7 @@ urtwn_get_txpower(struct urtwn_softc *sc, int chain,
|
||||
struct ieee80211_channel *c, struct ieee80211_channel *extc,
|
||||
uint16_t power[URTWN_RIDX_COUNT])
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct r92c_rom *rom = &sc->rom;
|
||||
uint16_t cckpow, ofdmpow, htpow, diff, max;
|
||||
const struct urtwn_txpwr *base;
|
||||
@ -2973,7 +3037,7 @@ urtwn_r88e_get_txpower(struct urtwn_softc *sc, int chain,
|
||||
struct ieee80211_channel *c, struct ieee80211_channel *extc,
|
||||
uint16_t power[URTWN_RIDX_COUNT])
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
uint16_t cckpow, ofdmpow, bw20pow, htpow;
|
||||
const struct urtwn_r88e_txpwr *base;
|
||||
int ridx, chan, group;
|
||||
@ -3070,7 +3134,7 @@ urtwn_scan_end(struct ieee80211com *ic)
|
||||
static void
|
||||
urtwn_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct urtwn_softc *sc = ic->ic_softc;
|
||||
struct urtwn_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
|
||||
URTWN_LOCK(sc);
|
||||
@ -3092,7 +3156,7 @@ static void
|
||||
urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c,
|
||||
struct ieee80211_channel *extc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
uint32_t reg;
|
||||
u_int chan;
|
||||
int i;
|
||||
@ -3223,18 +3287,17 @@ urtwn_lc_calib(struct urtwn_softc *sc)
|
||||
}
|
||||
|
||||
static void
|
||||
urtwn_init(struct urtwn_softc *sc)
|
||||
urtwn_init_locked(void *arg)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
struct urtwn_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
uint32_t reg;
|
||||
int error;
|
||||
|
||||
URTWN_ASSERT_LOCKED(sc);
|
||||
|
||||
if (sc->sc_flags & URTWN_RUNNING)
|
||||
urtwn_stop(sc);
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
urtwn_stop_locked(ifp);
|
||||
|
||||
/* Init firmware commands ring. */
|
||||
sc->fwcur = 0;
|
||||
@ -3277,8 +3340,8 @@ urtwn_init(struct urtwn_softc *sc)
|
||||
}
|
||||
|
||||
/* Set MAC address. */
|
||||
IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
urtwn_write_region_1(sc, R92C_MACID, macaddr, IEEE80211_ADDR_LEN);
|
||||
urtwn_write_region_1(sc, R92C_MACID, IF_LLADDR(ifp),
|
||||
IEEE80211_ADDR_LEN);
|
||||
|
||||
/* Set initial network type. */
|
||||
reg = urtwn_read_4(sc, R92C_CR);
|
||||
@ -3402,7 +3465,8 @@ urtwn_init(struct urtwn_softc *sc)
|
||||
|
||||
usbd_transfer_start(sc->sc_xfer[URTWN_BULK_RX]);
|
||||
|
||||
sc->sc_flags |= URTWN_RUNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
|
||||
fail:
|
||||
@ -3410,15 +3474,38 @@ fail:
|
||||
}
|
||||
|
||||
static void
|
||||
urtwn_stop(struct urtwn_softc *sc)
|
||||
urtwn_init(void *arg)
|
||||
{
|
||||
struct urtwn_softc *sc = arg;
|
||||
|
||||
URTWN_LOCK(sc);
|
||||
urtwn_init_locked(arg);
|
||||
URTWN_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
urtwn_stop_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct urtwn_softc *sc = ifp->if_softc;
|
||||
|
||||
URTWN_ASSERT_LOCKED(sc);
|
||||
sc->sc_flags &= ~URTWN_RUNNING;
|
||||
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
callout_stop(&sc->sc_watchdog_ch);
|
||||
urtwn_abort_xfers(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
urtwn_stop(struct ifnet *ifp)
|
||||
{
|
||||
struct urtwn_softc *sc = ifp->if_softc;
|
||||
|
||||
URTWN_LOCK(sc);
|
||||
urtwn_stop_locked(ifp);
|
||||
URTWN_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
urtwn_abort_xfers(struct urtwn_softc *sc)
|
||||
{
|
||||
@ -3436,11 +3523,12 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct urtwn_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct urtwn_softc *sc = ifp->if_softc;
|
||||
struct urtwn_data *bf;
|
||||
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!(sc->sc_flags & URTWN_RUNNING)) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return (ENETDOWN);
|
||||
@ -3454,8 +3542,10 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
return (ENOBUFS);
|
||||
}
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
if (urtwn_tx_start(sc, ni, m, bf) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
URTWN_UNLOCK(sc);
|
||||
return (EIO);
|
||||
|
@ -1172,8 +1172,7 @@ enum {
|
||||
#define URTWN_EP_QUEUES URTWN_BULK_RX
|
||||
|
||||
struct urtwn_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
struct usb_device *sc_udev;
|
||||
|
||||
@ -1181,7 +1180,6 @@ struct urtwn_softc {
|
||||
u_int sc_flags;
|
||||
#define URTWN_FLAG_CCK_HIPWR 0x01
|
||||
#define URTWN_DETACHED 0x02
|
||||
#define URTWN_RUNNING 0x04
|
||||
|
||||
u_int chip;
|
||||
#define URTWN_CHIP_92C 0x01
|
||||
@ -1226,6 +1224,7 @@ struct urtwn_softc {
|
||||
uint8_t ht40_tx_pwr[5];
|
||||
int8_t bw20_tx_pwr_diff;
|
||||
int8_t ofdm_tx_pwr_diff;
|
||||
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
|
||||
|
||||
struct callout sc_watchdog_ch;
|
||||
struct mtx sc_mtx;
|
||||
|
@ -93,14 +93,14 @@ struct urtw_vap {
|
||||
#define URTW_VAP(vap) ((struct urtw_vap *)(vap))
|
||||
|
||||
struct urtw_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
struct usb_device *sc_udev;
|
||||
struct mtx sc_mtx;
|
||||
void *sc_tx_dma_buf;
|
||||
|
||||
int sc_debug;
|
||||
int sc_if_flags;
|
||||
int sc_flags;
|
||||
#define URTW_INIT_ONCE (1 << 1)
|
||||
#define URTW_RTL8187B (1 << 2)
|
||||
@ -108,13 +108,13 @@ struct urtw_softc {
|
||||
#define URTW_RTL8187B_REV_D (1 << 4)
|
||||
#define URTW_RTL8187B_REV_E (1 << 5)
|
||||
#define URTW_DETACHED (1 << 6)
|
||||
#define URTW_RUNNING (1 << 7)
|
||||
enum ieee80211_state sc_state;
|
||||
|
||||
int sc_epromtype;
|
||||
#define URTW_EEPROM_93C46 0
|
||||
#define URTW_EEPROM_93C56 1
|
||||
uint8_t sc_crcmon;
|
||||
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
|
||||
|
||||
struct ieee80211_channel *sc_curchan;
|
||||
|
||||
|
@ -154,12 +154,12 @@ static int zyd_set_beacon_interval(struct zyd_softc *, int);
|
||||
static void zyd_rx_data(struct usb_xfer *, int, uint16_t);
|
||||
static int zyd_tx_start(struct zyd_softc *, struct mbuf *,
|
||||
struct ieee80211_node *);
|
||||
static int zyd_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void zyd_start(struct zyd_softc *);
|
||||
static void zyd_start(struct ifnet *);
|
||||
static int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static void zyd_parent(struct ieee80211com *);
|
||||
static int zyd_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void zyd_init_locked(struct zyd_softc *);
|
||||
static void zyd_init(void *);
|
||||
static void zyd_stop(struct zyd_softc *);
|
||||
static int zyd_loadfirmware(struct zyd_softc *);
|
||||
static void zyd_scan_start(struct ieee80211com *);
|
||||
@ -333,7 +333,8 @@ zyd_attach(device_t dev)
|
||||
{
|
||||
struct usb_attach_arg *uaa = device_get_ivars(dev);
|
||||
struct zyd_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
uint8_t iface_index, bands;
|
||||
int error;
|
||||
|
||||
@ -352,7 +353,6 @@ zyd_attach(device_t dev)
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
|
||||
MTX_NETWORK_LOCK, MTX_DEF);
|
||||
STAILQ_INIT(&sc->sc_rqh);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
iface_index = ZYD_IFACE_INDEX;
|
||||
error = usbd_transfer_setup(uaa->device,
|
||||
@ -372,6 +372,22 @@ zyd_attach(device_t dev)
|
||||
}
|
||||
ZYD_UNLOCK(sc);
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(sc->sc_dev, "can not if_alloc()\n");
|
||||
goto detach;
|
||||
}
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, "zyd", device_get_unit(sc->sc_dev));
|
||||
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
|
||||
ifp->if_init = zyd_init;
|
||||
ifp->if_ioctl = zyd_ioctl;
|
||||
ifp->if_start = zyd_start;
|
||||
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
|
||||
IFQ_SET_READY(&ifp->if_snd);
|
||||
|
||||
ic = ifp->if_l2com;
|
||||
ic->ic_ifp = ifp;
|
||||
ic->ic_softc = sc;
|
||||
ic->ic_name = device_get_nameunit(dev);
|
||||
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
|
||||
@ -392,17 +408,16 @@ zyd_attach(device_t dev)
|
||||
setbit(&bands, IEEE80211_MODE_11G);
|
||||
ieee80211_init_channels(ic, NULL, &bands);
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, sc->sc_bssid);
|
||||
ic->ic_raw_xmit = zyd_raw_xmit;
|
||||
ic->ic_scan_start = zyd_scan_start;
|
||||
ic->ic_scan_end = zyd_scan_end;
|
||||
ic->ic_set_channel = zyd_set_channel;
|
||||
|
||||
ic->ic_vap_create = zyd_vap_create;
|
||||
ic->ic_vap_delete = zyd_vap_delete;
|
||||
ic->ic_update_mcast = zyd_update_mcast;
|
||||
ic->ic_update_promisc = zyd_update_mcast;
|
||||
ic->ic_parent = zyd_parent;
|
||||
ic->ic_transmit = zyd_transmit;
|
||||
|
||||
ieee80211_radiotap_attach(ic,
|
||||
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
|
||||
@ -424,7 +439,8 @@ static int
|
||||
zyd_detach(device_t dev)
|
||||
{
|
||||
struct zyd_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic;
|
||||
unsigned int x;
|
||||
|
||||
/*
|
||||
@ -449,9 +465,11 @@ zyd_detach(device_t dev)
|
||||
/* free USB transfers and some data buffers */
|
||||
usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
|
||||
|
||||
if (ic->ic_softc == sc)
|
||||
if (ifp) {
|
||||
ic = ifp->if_l2com;
|
||||
ieee80211_ifdetach(ic);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
if_free(ifp);
|
||||
}
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -468,12 +486,15 @@ zyd_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
|
||||
return (NULL);
|
||||
zvp = malloc(sizeof(struct zyd_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
zvp = (struct zyd_vap *) malloc(sizeof(struct zyd_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (zvp == NULL)
|
||||
return (NULL);
|
||||
vap = &zvp->vap;
|
||||
|
||||
/* enable s/w bmiss handling for sta mode */
|
||||
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
|
||||
/* out of memory */
|
||||
free(zvp, M_80211_VAP);
|
||||
return (NULL);
|
||||
@ -488,7 +509,7 @@ zyd_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change,
|
||||
ieee80211_media_status, mac);
|
||||
ieee80211_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return (vap);
|
||||
}
|
||||
@ -509,8 +530,13 @@ zyd_tx_free(struct zyd_tx_data *data, int txerr)
|
||||
struct zyd_softc *sc = data->sc;
|
||||
|
||||
if (data->m != NULL) {
|
||||
ieee80211_tx_complete(data->ni, data->m, txerr);
|
||||
if (data->m->m_flags & M_TXCB)
|
||||
ieee80211_process_callback(data->ni, data->m,
|
||||
txerr ? ETIMEDOUT : 0);
|
||||
m_freem(data->m);
|
||||
data->m = NULL;
|
||||
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
}
|
||||
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
|
||||
@ -567,7 +593,7 @@ zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct zyd_vap *zvp = ZYD_VAP(vap);
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct zyd_softc *sc = ic->ic_softc;
|
||||
struct zyd_softc *sc = ic->ic_ifp->if_softc;
|
||||
int error;
|
||||
|
||||
DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__,
|
||||
@ -592,8 +618,8 @@ zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
/* make data LED blink upon Tx */
|
||||
zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1);
|
||||
|
||||
IEEE80211_ADDR_COPY(ic->ic_macaddr, vap->iv_bss->ni_bssid);
|
||||
zyd_set_bssid(sc, ic->ic_macaddr);
|
||||
IEEE80211_ADDR_COPY(sc->sc_bssid, vap->iv_bss->ni_bssid);
|
||||
zyd_set_bssid(sc, sc->sc_bssid);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -611,7 +637,8 @@ static void
|
||||
zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct zyd_softc *sc = usbd_xfer_softc(xfer);
|
||||
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 ieee80211_node *ni;
|
||||
struct zyd_cmd *cmd = &sc->sc_ibuf;
|
||||
@ -654,9 +681,7 @@ zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
ieee80211_free_node(ni);
|
||||
}
|
||||
if (le16toh(retry->count) & 0x100)
|
||||
/* too many retries */
|
||||
if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS,
|
||||
1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); /* too many retries */
|
||||
break;
|
||||
}
|
||||
case ZYD_NOTIF_IORD:
|
||||
@ -1218,7 +1243,8 @@ zyd_al2230_bandedge6(struct zyd_rf *rf, struct ieee80211_channel *c)
|
||||
#define N(a) ((int)(sizeof(a) / sizeof((a)[0])))
|
||||
int error = 0, i;
|
||||
struct zyd_softc *sc = rf->rf_sc;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6;
|
||||
int chan = ieee80211_chan2ieee(ic, c);
|
||||
|
||||
@ -1906,7 +1932,7 @@ zyd_get_macaddr(struct zyd_softc *sc)
|
||||
USETW(req.wIndex, 0);
|
||||
USETW(req.wLength, IEEE80211_ADDR_LEN);
|
||||
|
||||
error = zyd_do_request(sc, &req, sc->sc_ic.ic_macaddr);
|
||||
error = zyd_do_request(sc, &req, sc->sc_bssid);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not read EEPROM: %s\n",
|
||||
usbd_errstr(error));
|
||||
@ -1978,41 +2004,36 @@ fail:
|
||||
static void
|
||||
zyd_set_multi(struct zyd_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
uint32_t low, high;
|
||||
int error;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifmultiaddr *ifma;
|
||||
uint32_t low, high;
|
||||
uint8_t v;
|
||||
|
||||
if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0)
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
low = 0x00000000;
|
||||
high = 0x80000000;
|
||||
|
||||
if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 ||
|
||||
ic->ic_promisc > 0) {
|
||||
if (ic->ic_opmode == IEEE80211_M_MONITOR ||
|
||||
(ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
|
||||
low = 0xffffffff;
|
||||
high = 0xffffffff;
|
||||
} else {
|
||||
struct ieee80211vap *vap;
|
||||
struct ifnet *ifp;
|
||||
struct ifmultiaddr *ifma;
|
||||
uint8_t v;
|
||||
|
||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
|
||||
ifp = vap->iv_ifp;
|
||||
if_maddr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
v = ((uint8_t *)LLADDR((struct sockaddr_dl *)
|
||||
ifma->ifma_addr))[5] >> 2;
|
||||
if (v < 32)
|
||||
low |= 1 << v;
|
||||
else
|
||||
high |= 1 << (v - 32);
|
||||
}
|
||||
if_maddr_runlock(ifp);
|
||||
if_maddr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
v = ((uint8_t *)LLADDR((struct sockaddr_dl *)
|
||||
ifma->ifma_addr))[5] >> 2;
|
||||
if (v < 32)
|
||||
low |= 1 << v;
|
||||
else
|
||||
high |= 1 << (v - 32);
|
||||
}
|
||||
if_maddr_runlock(ifp);
|
||||
}
|
||||
|
||||
/* reprogram multicast global hash table */
|
||||
@ -2029,6 +2050,9 @@ zyd_update_mcast(struct ieee80211com *ic)
|
||||
{
|
||||
struct zyd_softc *sc = ic->ic_softc;
|
||||
|
||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return;
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
zyd_set_multi(sc);
|
||||
ZYD_UNLOCK(sc);
|
||||
@ -2037,7 +2061,8 @@ zyd_update_mcast(struct ieee80211com *ic)
|
||||
static int
|
||||
zyd_set_rxfilter(struct zyd_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
uint32_t rxfilter;
|
||||
|
||||
switch (ic->ic_opmode) {
|
||||
@ -2062,7 +2087,8 @@ static void
|
||||
zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c)
|
||||
{
|
||||
int error;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct zyd_rf *rf = &sc->sc_rf;
|
||||
uint32_t tmp;
|
||||
int chan;
|
||||
@ -2153,7 +2179,8 @@ static void
|
||||
zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
|
||||
{
|
||||
struct zyd_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct zyd_plcphdr plcp;
|
||||
struct zyd_rx_stat stat;
|
||||
struct usb_page_cache *pc;
|
||||
@ -2163,7 +2190,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
|
||||
if (len < ZYD_MIN_FRAGSZ) {
|
||||
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too short (length=%d)\n",
|
||||
device_get_nameunit(sc->sc_dev), len);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
pc = usbd_xfer_get_frame(xfer, 0);
|
||||
@ -2174,7 +2201,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
|
||||
DPRINTF(sc, ZYD_DEBUG_RECV,
|
||||
"%s: RX status indicated error (%x)\n",
|
||||
device_get_nameunit(sc->sc_dev), stat.flags);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2186,7 +2213,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
|
||||
if (rlen > (int)MCLBYTES) {
|
||||
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too long (length=%d)\n",
|
||||
device_get_nameunit(sc->sc_dev), rlen);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
} else if (rlen > (int)MHLEN)
|
||||
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
@ -2195,9 +2222,10 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
|
||||
if (m == NULL) {
|
||||
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: could not allocate rx mbuf\n",
|
||||
device_get_nameunit(sc->sc_dev));
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
return;
|
||||
}
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
m->m_pkthdr.len = m->m_len = rlen;
|
||||
usbd_copy_out(pc, offset + sizeof(plcp), mtod(m, uint8_t *), rlen);
|
||||
|
||||
@ -2227,7 +2255,8 @@ static void
|
||||
zyd_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct zyd_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_node *ni;
|
||||
struct zyd_rx_desc desc;
|
||||
struct mbuf *m;
|
||||
@ -2299,8 +2328,10 @@ tr_setup:
|
||||
} else
|
||||
(void)ieee80211_input_all(ic, m, rssi, nf);
|
||||
}
|
||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
|
||||
!IFQ_IS_EMPTY(&ifp->if_snd))
|
||||
zyd_start(ifp);
|
||||
ZYD_LOCK(sc);
|
||||
zyd_start(sc);
|
||||
break;
|
||||
|
||||
default: /* Error */
|
||||
@ -2355,6 +2386,7 @@ static void
|
||||
zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
struct zyd_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211vap *vap;
|
||||
struct zyd_tx_data *data;
|
||||
struct mbuf *m;
|
||||
@ -2373,6 +2405,9 @@ zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
zyd_tx_free(data, 0);
|
||||
usbd_xfer_set_priv(xfer, NULL);
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case USB_ST_SETUP:
|
||||
tr_setup:
|
||||
@ -2405,14 +2440,16 @@ tr_setup:
|
||||
usbd_xfer_set_priv(xfer, data);
|
||||
usbd_transfer_submit(xfer);
|
||||
}
|
||||
zyd_start(sc);
|
||||
ZYD_UNLOCK(sc);
|
||||
zyd_start(ifp);
|
||||
ZYD_LOCK(sc);
|
||||
break;
|
||||
|
||||
default: /* Error */
|
||||
DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n",
|
||||
usbd_errstr(error));
|
||||
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
data = usbd_xfer_get_priv(xfer);
|
||||
usbd_xfer_set_priv(xfer, NULL);
|
||||
if (data != NULL)
|
||||
@ -2553,45 +2590,31 @@ zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
zyd_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct zyd_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0) {
|
||||
ZYD_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
ZYD_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
zyd_start(sc);
|
||||
ZYD_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_start(struct zyd_softc *sc)
|
||||
zyd_start(struct ifnet *ifp)
|
||||
{
|
||||
struct zyd_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
ZYD_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
while (sc->tx_nfree > 0 && (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
ZYD_LOCK(sc);
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
if (sc->tx_nfree == 0) {
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
break;
|
||||
}
|
||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
||||
if (zyd_tx_start(sc, m, ni) != 0) {
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ZYD_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2599,17 +2622,19 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct zyd_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct zyd_softc *sc = ifp->if_softc;
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
/* prevent management frames from being sent if we're not ready */
|
||||
if (!(sc->sc_flags & ZYD_FLAG_RUNNING)) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
ZYD_UNLOCK(sc);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
return (ENETDOWN);
|
||||
}
|
||||
if (sc->tx_nfree == 0) {
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
ZYD_UNLOCK(sc);
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
@ -2623,6 +2648,7 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
*/
|
||||
if (zyd_tx_start(sc, m, ni) != 0) {
|
||||
ZYD_UNLOCK(sc);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
ieee80211_free_node(ni);
|
||||
return (EIO);
|
||||
}
|
||||
@ -2630,35 +2656,56 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct zyd_softc *sc = ic->ic_softc;
|
||||
struct zyd_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error;
|
||||
int startall = 0;
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
if (sc->sc_flags & ZYD_FLAG_DETACHED) {
|
||||
ZYD_UNLOCK(sc);
|
||||
return;
|
||||
}
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0) {
|
||||
zyd_init_locked(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
zyd_set_multi(sc);
|
||||
} else if (sc->sc_flags & ZYD_FLAG_RUNNING)
|
||||
zyd_stop(sc);
|
||||
error = (sc->sc_flags & ZYD_FLAG_DETACHED) ? ENXIO : 0;
|
||||
ZYD_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
ZYD_LOCK(sc);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
zyd_init_locked(sc);
|
||||
startall = 1;
|
||||
} else
|
||||
zyd_set_multi(sc);
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
zyd_stop(sc);
|
||||
}
|
||||
ZYD_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_init_locked(struct zyd_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct usb_config_descriptor *cd;
|
||||
int error;
|
||||
uint32_t val;
|
||||
@ -2710,12 +2757,12 @@ zyd_init_locked(struct zyd_softc *sc)
|
||||
sc->sc_flags |= ZYD_FLAG_INITONCE;
|
||||
}
|
||||
|
||||
if (sc->sc_flags & ZYD_FLAG_RUNNING)
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
zyd_stop(sc);
|
||||
|
||||
DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %6D\n",
|
||||
vap ? vap->iv_myaddr : ic->ic_macaddr, ":");
|
||||
error = zyd_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
||||
IF_LLADDR(ifp), ":");
|
||||
error = zyd_set_macaddr(sc, IF_LLADDR(ifp));
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
@ -2751,7 +2798,8 @@ zyd_init_locked(struct zyd_softc *sc)
|
||||
/* enable interrupts */
|
||||
zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK);
|
||||
|
||||
sc->sc_flags |= ZYD_FLAG_RUNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
usbd_xfer_set_stall(sc->sc_xfer[ZYD_BULK_WR]);
|
||||
usbd_transfer_start(sc->sc_xfer[ZYD_BULK_RD]);
|
||||
usbd_transfer_start(sc->sc_xfer[ZYD_INTR_RD]);
|
||||
@ -2762,14 +2810,30 @@ fail: zyd_stop(sc);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_init(void *priv)
|
||||
{
|
||||
struct zyd_softc *sc = priv;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
zyd_init_locked(sc);
|
||||
ZYD_UNLOCK(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic); /* start all vap's */
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_stop(struct zyd_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int error;
|
||||
|
||||
ZYD_LOCK_ASSERT(sc, MA_OWNED);
|
||||
|
||||
sc->sc_flags &= ~ZYD_FLAG_RUNNING;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
|
||||
/*
|
||||
* Drain all the transfers, if not already drained:
|
||||
@ -2861,29 +2925,30 @@ zyd_loadfirmware(struct zyd_softc *sc)
|
||||
static void
|
||||
zyd_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct zyd_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct zyd_softc *sc = ifp->if_softc;
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
/* want broadcast address while scanning */
|
||||
zyd_set_bssid(sc, ieee80211broadcastaddr);
|
||||
zyd_set_bssid(sc, ifp->if_broadcastaddr);
|
||||
ZYD_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct zyd_softc *sc = ic->ic_softc;
|
||||
struct zyd_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
/* restore previous bssid */
|
||||
zyd_set_bssid(sc, ic->ic_macaddr);
|
||||
zyd_set_bssid(sc, sc->sc_bssid);
|
||||
ZYD_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
zyd_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct zyd_softc *sc = ic->ic_softc;
|
||||
struct zyd_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
ZYD_LOCK(sc);
|
||||
zyd_set_chan(sc, ic->ic_curchan);
|
||||
|
@ -1249,8 +1249,7 @@ enum {
|
||||
};
|
||||
|
||||
struct zyd_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
struct usb_device *sc_udev;
|
||||
|
||||
@ -1261,13 +1260,13 @@ struct zyd_softc {
|
||||
#define ZYD_FLAG_INITONCE (1 << 1)
|
||||
#define ZYD_FLAG_INITDONE (1 << 2)
|
||||
#define ZYD_FLAG_DETACHED (1 << 3)
|
||||
#define ZYD_FLAG_RUNNING (1 << 4)
|
||||
|
||||
struct zyd_rf sc_rf;
|
||||
|
||||
STAILQ_HEAD(, zyd_rq) sc_rtx;
|
||||
STAILQ_HEAD(, zyd_rq) sc_rqh;
|
||||
|
||||
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
|
||||
uint16_t sc_fwbase;
|
||||
uint8_t sc_regdomain;
|
||||
uint8_t sc_macrev;
|
||||
|
@ -116,9 +116,11 @@ static struct ieee80211vap *wi_vap_create(struct ieee80211com *,
|
||||
const uint8_t [IEEE80211_ADDR_LEN],
|
||||
const uint8_t [IEEE80211_ADDR_LEN]);
|
||||
static void wi_vap_delete(struct ieee80211vap *vap);
|
||||
static int wi_transmit(struct ieee80211com *, struct mbuf *);
|
||||
static void wi_start(struct wi_softc *);
|
||||
static int wi_start_tx(struct wi_softc *, struct wi_frame *, struct mbuf *);
|
||||
static void wi_stop_locked(struct wi_softc *sc, int disable);
|
||||
static void wi_start_locked(struct ifnet *);
|
||||
static void wi_start(struct ifnet *);
|
||||
static int wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr,
|
||||
struct mbuf *m0);
|
||||
static int wi_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static int wi_newstate_sta(struct ieee80211vap *, enum ieee80211_state, int);
|
||||
@ -129,8 +131,10 @@ static void wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
|
||||
int rssi, int nf);
|
||||
static int wi_reset(struct wi_softc *);
|
||||
static void wi_watchdog(void *);
|
||||
static void wi_parent(struct ieee80211com *);
|
||||
static int wi_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void wi_media_status(struct ifnet *, struct ifmediareq *);
|
||||
static uint64_t wi_get_counter(struct ifnet *, ift_counter);
|
||||
|
||||
static void wi_rx_intr(struct wi_softc *);
|
||||
static void wi_tx_intr(struct wi_softc *);
|
||||
static void wi_tx_ex_intr(struct wi_softc *);
|
||||
@ -149,10 +153,10 @@ static int wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
|
||||
static int wi_cmd(struct wi_softc *, int, int, int, int);
|
||||
static int wi_seek_bap(struct wi_softc *, int, int);
|
||||
static int wi_read_bap(struct wi_softc *, int, int, void *, int);
|
||||
static int wi_write_bap(struct wi_softc *, int, int, const void *, int);
|
||||
static int wi_write_bap(struct wi_softc *, int, int, void *, int);
|
||||
static int wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int);
|
||||
static int wi_read_rid(struct wi_softc *, int, void *, int *);
|
||||
static int wi_write_rid(struct wi_softc *, int, const void *, int);
|
||||
static int wi_write_rid(struct wi_softc *, int, void *, int);
|
||||
static int wi_write_appie(struct wi_softc *, int, const struct ieee80211_appie *);
|
||||
|
||||
static void wi_scan_start(struct ieee80211com *);
|
||||
@ -233,7 +237,8 @@ int
|
||||
wi_attach(device_t dev)
|
||||
{
|
||||
struct wi_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
int i, nrates, buflen;
|
||||
u_int16_t val;
|
||||
u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE];
|
||||
@ -244,6 +249,15 @@ wi_attach(device_t dev)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
int error;
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
|
||||
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
device_printf(dev, "can not if_alloc\n");
|
||||
wi_free(dev);
|
||||
return ENOSPC;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
|
||||
sc->sc_firmware_type = WI_NOTYPE;
|
||||
sc->wi_cmd_count = 500;
|
||||
@ -295,7 +309,6 @@ wi_attach(device_t dev)
|
||||
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
|
||||
MTX_DEF | MTX_RECURSE);
|
||||
callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
|
||||
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
||||
|
||||
/*
|
||||
* Read the station address.
|
||||
@ -304,13 +317,12 @@ wi_attach(device_t dev)
|
||||
* the probe to fail.
|
||||
*/
|
||||
buflen = IEEE80211_ADDR_LEN;
|
||||
error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr, &buflen);
|
||||
error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
|
||||
if (error != 0) {
|
||||
buflen = IEEE80211_ADDR_LEN;
|
||||
error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr,
|
||||
&buflen);
|
||||
error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
|
||||
}
|
||||
if (error || IEEE80211_ADDR_EQ(&ic->ic_macaddr, empty_macaddr)) {
|
||||
if (error || IEEE80211_ADDR_EQ(macaddr, empty_macaddr)) {
|
||||
if (error != 0)
|
||||
device_printf(dev, "mac read failed %d\n", error);
|
||||
else {
|
||||
@ -321,6 +333,18 @@ wi_attach(device_t dev)
|
||||
return (error);
|
||||
}
|
||||
|
||||
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_ioctl = wi_ioctl;
|
||||
ifp->if_start = wi_start;
|
||||
ifp->if_init = wi_init;
|
||||
ifp->if_get_counter = wi_get_counter;
|
||||
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_name = device_get_nameunit(dev);
|
||||
ic->ic_phytype = IEEE80211_T_DS;
|
||||
@ -434,17 +458,16 @@ wi_attach(device_t dev)
|
||||
|
||||
sc->sc_portnum = WI_DEFAULT_PORT;
|
||||
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, macaddr);
|
||||
ic->ic_raw_xmit = wi_raw_xmit;
|
||||
ic->ic_scan_start = wi_scan_start;
|
||||
ic->ic_scan_end = wi_scan_end;
|
||||
ic->ic_set_channel = wi_set_channel;
|
||||
|
||||
ic->ic_vap_create = wi_vap_create;
|
||||
ic->ic_vap_delete = wi_vap_delete;
|
||||
ic->ic_update_mcast = wi_update_mcast;
|
||||
ic->ic_update_promisc = wi_update_promisc;
|
||||
ic->ic_transmit = wi_transmit;
|
||||
ic->ic_parent = wi_parent;
|
||||
|
||||
ieee80211_radiotap_attach(ic,
|
||||
&sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
|
||||
@ -460,6 +483,7 @@ wi_attach(device_t dev)
|
||||
if (error) {
|
||||
device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
|
||||
ieee80211_ifdetach(ic);
|
||||
if_free(sc->sc_ifp);
|
||||
wi_free(dev);
|
||||
return error;
|
||||
}
|
||||
@ -471,20 +495,21 @@ int
|
||||
wi_detach(device_t dev)
|
||||
{
|
||||
struct wi_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
WI_LOCK(sc);
|
||||
|
||||
/* check if device was removed */
|
||||
sc->wi_gone |= !bus_child_present(dev);
|
||||
|
||||
wi_stop(sc, 0);
|
||||
wi_stop_locked(sc, 0);
|
||||
WI_UNLOCK(sc);
|
||||
ieee80211_ifdetach(ic);
|
||||
|
||||
bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
|
||||
if_free(sc->sc_ifp);
|
||||
wi_free(dev);
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
return (0);
|
||||
}
|
||||
@ -495,16 +520,19 @@ wi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct wi_softc *sc = ic->ic_softc;
|
||||
struct wi_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct wi_vap *wvp;
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
|
||||
return NULL;
|
||||
wvp = malloc(sizeof(struct wi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
wvp = (struct wi_vap *) malloc(sizeof(struct wi_vap),
|
||||
M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (wvp == NULL)
|
||||
return NULL;
|
||||
|
||||
vap = &wvp->wv_vap;
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
|
||||
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
|
||||
|
||||
vap->iv_max_aid = WI_MAX_AID;
|
||||
|
||||
@ -538,7 +566,7 @@ wi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
||||
}
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status, mac);
|
||||
ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status);
|
||||
ic->ic_opmode = opmode;
|
||||
return vap;
|
||||
}
|
||||
@ -557,9 +585,7 @@ wi_shutdown(device_t dev)
|
||||
{
|
||||
struct wi_softc *sc = device_get_softc(dev);
|
||||
|
||||
WI_LOCK(sc);
|
||||
wi_stop(sc, 1);
|
||||
WI_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -567,12 +593,12 @@ void
|
||||
wi_intr(void *arg)
|
||||
{
|
||||
struct wi_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
u_int16_t status;
|
||||
|
||||
WI_LOCK(sc);
|
||||
|
||||
if (sc->wi_gone || !sc->sc_enabled ||
|
||||
(sc->sc_flags & WI_FLAGS_RUNNING) == 0) {
|
||||
if (sc->wi_gone || !sc->sc_enabled || (ifp->if_flags & IFF_UP) == 0) {
|
||||
CSR_WRITE_2(sc, WI_INT_EN, 0);
|
||||
CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
|
||||
WI_UNLOCK(sc);
|
||||
@ -591,8 +617,9 @@ wi_intr(void *arg)
|
||||
wi_tx_ex_intr(sc);
|
||||
if (status & WI_EV_INFO)
|
||||
wi_info_intr(sc);
|
||||
if (mbufq_first(&sc->sc_snd) != NULL)
|
||||
wi_start(sc);
|
||||
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
|
||||
!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
|
||||
wi_start_locked(ifp);
|
||||
|
||||
/* Re-enable interrupts. */
|
||||
CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
|
||||
@ -615,7 +642,7 @@ wi_enable(struct wi_softc *sc)
|
||||
|
||||
static int
|
||||
wi_setup_locked(struct wi_softc *sc, int porttype, int mode,
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -649,25 +676,26 @@ wi_setup_locked(struct wi_softc *sc, int porttype, int mode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
wi_init(struct wi_softc *sc)
|
||||
static void
|
||||
wi_init_locked(struct wi_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int wasenabled;
|
||||
|
||||
WI_LOCK_ASSERT(sc);
|
||||
|
||||
wasenabled = sc->sc_enabled;
|
||||
if (wasenabled)
|
||||
wi_stop(sc, 1);
|
||||
wi_stop_locked(sc, 1);
|
||||
|
||||
if (wi_setup_locked(sc, sc->sc_porttype, 3,
|
||||
sc->sc_ic.ic_macaddr) != 0) {
|
||||
device_printf(sc->sc_dev, "interface not running\n");
|
||||
wi_stop(sc, 1);
|
||||
if (wi_setup_locked(sc, sc->sc_porttype, 3, IF_LLADDR(ifp)) != 0) {
|
||||
if_printf(ifp, "interface not running\n");
|
||||
wi_stop_locked(sc, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
sc->sc_flags |= WI_FLAGS_RUNNING;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
||||
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
|
||||
|
||||
@ -675,8 +703,24 @@ wi_init(struct wi_softc *sc)
|
||||
}
|
||||
|
||||
void
|
||||
wi_stop(struct wi_softc *sc, int disable)
|
||||
wi_init(void *arg)
|
||||
{
|
||||
struct wi_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
WI_LOCK(sc);
|
||||
wi_init_locked(sc);
|
||||
WI_UNLOCK(sc);
|
||||
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
ieee80211_start_all(ic); /* start all vap's */
|
||||
}
|
||||
|
||||
static void
|
||||
wi_stop_locked(struct wi_softc *sc, int disable)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
WI_LOCK_ASSERT(sc);
|
||||
|
||||
@ -692,13 +736,22 @@ wi_stop(struct wi_softc *sc, int disable)
|
||||
sc->sc_tx_timer = 0;
|
||||
sc->sc_false_syns = 0;
|
||||
|
||||
sc->sc_flags &= ~WI_FLAGS_RUNNING;
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE | IFF_DRV_RUNNING);
|
||||
}
|
||||
|
||||
void
|
||||
wi_stop(struct wi_softc *sc, int disable)
|
||||
{
|
||||
WI_LOCK(sc);
|
||||
wi_stop_locked(sc, disable);
|
||||
WI_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static void
|
||||
wi_set_channel(struct ieee80211com *ic)
|
||||
{
|
||||
struct wi_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
|
||||
DPRINTF(("%s: channel %d, %sscanning\n", __func__,
|
||||
ieee80211_chan2ieee(ic, ic->ic_curchan),
|
||||
@ -713,7 +766,8 @@ wi_set_channel(struct ieee80211com *ic)
|
||||
static void
|
||||
wi_scan_start(struct ieee80211com *ic)
|
||||
{
|
||||
struct wi_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_scan_state *ss = ic->ic_scan;
|
||||
|
||||
DPRINTF(("%s\n", __func__));
|
||||
@ -736,7 +790,8 @@ wi_scan_start(struct ieee80211com *ic)
|
||||
static void
|
||||
wi_scan_end(struct ieee80211com *ic)
|
||||
{
|
||||
struct wi_softc *sc = ic->ic_softc;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
|
||||
DPRINTF(("%s: restore port type %d\n", __func__, sc->sc_porttype));
|
||||
|
||||
@ -769,8 +824,9 @@ static int
|
||||
wi_newstate_sta(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ieee80211_node *bss;
|
||||
struct wi_softc *sc = ic->ic_softc;
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
|
||||
DPRINTF(("%s: %s -> %s\n", __func__,
|
||||
ieee80211_state_name[vap->iv_state],
|
||||
@ -838,8 +894,9 @@ static int
|
||||
wi_newstate_hostap(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ieee80211_node *bss;
|
||||
struct wi_softc *sc = ic->ic_softc;
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
int error;
|
||||
|
||||
DPRINTF(("%s: %s -> %s\n", __func__,
|
||||
@ -896,30 +953,10 @@ wi_newstate_hostap(struct ieee80211vap *vap, enum ieee80211_state nstate, int ar
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
wi_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
{
|
||||
struct wi_softc *sc = ic->ic_softc;
|
||||
int error;
|
||||
|
||||
WI_LOCK(sc);
|
||||
if ((sc->sc_flags & WI_FLAGS_RUNNING) == 0) {
|
||||
WI_UNLOCK(sc);
|
||||
return (ENXIO);
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
WI_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
wi_start(sc);
|
||||
WI_UNLOCK(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
wi_start(struct wi_softc *sc)
|
||||
wi_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct ieee80211_frame *wh;
|
||||
struct mbuf *m0;
|
||||
@ -935,8 +972,15 @@ wi_start(struct wi_softc *sc)
|
||||
|
||||
memset(&frmhdr, 0, sizeof(frmhdr));
|
||||
cur = sc->sc_txnext;
|
||||
while (sc->sc_txd[cur].d_len == 0 &&
|
||||
(m0 = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
for (;;) {
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
|
||||
if (m0 == NULL)
|
||||
break;
|
||||
if (sc->sc_txd[cur].d_len != 0) {
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m0);
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
break;
|
||||
}
|
||||
ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
|
||||
|
||||
/* reconstruct 802.3 header */
|
||||
@ -985,16 +1029,28 @@ wi_start(struct wi_softc *sc)
|
||||
m_adj(m0, sizeof(struct ieee80211_frame));
|
||||
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
|
||||
ieee80211_free_node(ni);
|
||||
if (wi_start_tx(sc, &frmhdr, m0))
|
||||
if (wi_start_tx(ifp, &frmhdr, m0))
|
||||
continue;
|
||||
|
||||
sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
wi_start_tx(struct wi_softc *sc, struct wi_frame *frmhdr, struct mbuf *m0)
|
||||
static void
|
||||
wi_start(struct ifnet *ifp)
|
||||
{
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
|
||||
WI_LOCK(sc);
|
||||
wi_start_locked(ifp);
|
||||
WI_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0)
|
||||
{
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
int cur = sc->sc_txnext;
|
||||
int fid, off, error;
|
||||
|
||||
@ -1004,13 +1060,13 @@ wi_start_tx(struct wi_softc *sc, struct wi_frame *frmhdr, struct mbuf *m0)
|
||||
|| wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0;
|
||||
m_freem(m0);
|
||||
if (error) {
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return -1;
|
||||
}
|
||||
sc->sc_txd[cur].d_len = off;
|
||||
if (sc->sc_txcur == cur) {
|
||||
if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
|
||||
device_printf(sc->sc_dev, "xmit failed\n");
|
||||
if_printf(ifp, "xmit failed\n");
|
||||
sc->sc_txd[cur].d_len = 0;
|
||||
return -1;
|
||||
}
|
||||
@ -1024,8 +1080,9 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
|
||||
const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct wi_softc *sc = ic->ic_softc;
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_key *k;
|
||||
struct ieee80211_frame *wh;
|
||||
struct wi_frame frmhdr;
|
||||
@ -1041,6 +1098,7 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
|
||||
memset(&frmhdr, 0, sizeof(frmhdr));
|
||||
cur = sc->sc_txnext;
|
||||
if (sc->sc_txd[cur].d_len != 0) {
|
||||
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
|
||||
rc = ENOBUFS;
|
||||
goto out;
|
||||
}
|
||||
@ -1071,7 +1129,7 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
|
||||
(caddr_t)&frmhdr.wi_whdr);
|
||||
m_adj(m0, sizeof(struct ieee80211_frame));
|
||||
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
|
||||
if (wi_start_tx(sc, &frmhdr, m0) < 0) {
|
||||
if (wi_start_tx(ifp, &frmhdr, m0) < 0) {
|
||||
m0 = NULL;
|
||||
rc = EIO;
|
||||
goto out;
|
||||
@ -1102,7 +1160,7 @@ wi_reset(struct wi_softc *sc)
|
||||
}
|
||||
sc->sc_reset = 1;
|
||||
if (i == WI_INIT_TRIES) {
|
||||
device_printf(sc->sc_dev, "reset failed\n");
|
||||
if_printf(sc->sc_ifp, "reset failed\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1120,6 +1178,7 @@ static void
|
||||
wi_watchdog(void *arg)
|
||||
{
|
||||
struct wi_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
WI_LOCK_ASSERT(sc);
|
||||
|
||||
@ -1127,52 +1186,65 @@ wi_watchdog(void *arg)
|
||||
return;
|
||||
|
||||
if (sc->sc_tx_timer && --sc->sc_tx_timer == 0) {
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
wi_init(sc);
|
||||
if_printf(ifp, "device timeout\n");
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
wi_init_locked(ifp->if_softc);
|
||||
return;
|
||||
}
|
||||
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
|
||||
}
|
||||
|
||||
static void
|
||||
wi_parent(struct ieee80211com *ic)
|
||||
static int
|
||||
wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
struct wi_softc *sc = ic->ic_softc;
|
||||
int startall = 0;
|
||||
struct wi_softc *sc = ifp->if_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifreq *ifr = (struct ifreq *) data;
|
||||
int error = 0, startall = 0;
|
||||
|
||||
WI_LOCK(sc);
|
||||
/*
|
||||
* Can't do promisc and hostap at the same time. If all that's
|
||||
* changing is the promisc flag, try to short-circuit a call to
|
||||
* wi_init() by just setting PROMISC in the hardware.
|
||||
*/
|
||||
if (ic->ic_nrunning > 0) {
|
||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
|
||||
sc->sc_flags & WI_FLAGS_RUNNING) {
|
||||
if (ic->ic_promisc > 0 &&
|
||||
(sc->sc_flags & WI_FLAGS_PROMISC) == 0) {
|
||||
wi_write_val(sc, WI_RID_PROMISC, 1);
|
||||
sc->sc_flags |= WI_FLAGS_PROMISC;
|
||||
} else if (ic->ic_promisc == 0 &&
|
||||
(sc->sc_flags & WI_FLAGS_PROMISC) != 0) {
|
||||
wi_write_val(sc, WI_RID_PROMISC, 0);
|
||||
sc->sc_flags &= ~WI_FLAGS_PROMISC;
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
WI_LOCK(sc);
|
||||
/*
|
||||
* Can't do promisc and hostap at the same time. If all that's
|
||||
* changing is the promisc flag, try to short-circuit a call to
|
||||
* wi_init() by just setting PROMISC in the hardware.
|
||||
*/
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
|
||||
ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
if ((ifp->if_flags ^ sc->sc_if_flags) & IFF_PROMISC) {
|
||||
wi_write_val(sc, WI_RID_PROMISC,
|
||||
(ifp->if_flags & IFF_PROMISC) != 0);
|
||||
} else {
|
||||
wi_init_locked(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
wi_init(sc);
|
||||
wi_init_locked(sc);
|
||||
startall = 1;
|
||||
}
|
||||
} else {
|
||||
wi_init(sc);
|
||||
startall = 1;
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
wi_stop_locked(sc, 1);
|
||||
sc->wi_gone = 0;
|
||||
}
|
||||
} else if (sc->sc_flags & WI_FLAGS_RUNNING) {
|
||||
wi_stop(sc, 1);
|
||||
sc->wi_gone = 0;
|
||||
sc->sc_if_flags = ifp->if_flags;
|
||||
WI_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
||||
break;
|
||||
case SIOCGIFADDR:
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
WI_UNLOCK(sc);
|
||||
if (startall)
|
||||
ieee80211_start_all(ic);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1180,7 +1252,7 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
||||
{
|
||||
struct ieee80211vap *vap = ifp->if_softc;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct wi_softc *sc = ic->ic_softc;
|
||||
struct wi_softc *sc = ic->ic_ifp->if_softc;
|
||||
u_int16_t val;
|
||||
int rate, len;
|
||||
|
||||
@ -1208,7 +1280,8 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
||||
static void
|
||||
wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
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 ieee80211_node *ni = vap->iv_bss;
|
||||
|
||||
@ -1222,7 +1295,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
|
||||
* indicator of the firmware's BSSID. Damp spurious
|
||||
* change-of-BSSID indications.
|
||||
*/
|
||||
if (ic->ic_promisc > 0 &&
|
||||
if ((ifp->if_flags & IFF_PROMISC) != 0 &&
|
||||
!ppsratecheck(&sc->sc_last_syn, &sc->sc_false_syns,
|
||||
WI_MAX_FALSE_SYNS))
|
||||
return;
|
||||
@ -1243,7 +1316,8 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
|
||||
static __noinline void
|
||||
wi_rx_intr(struct wi_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct wi_frame frmhdr;
|
||||
struct mbuf *m;
|
||||
struct ieee80211_frame *wh;
|
||||
@ -1258,7 +1332,7 @@ wi_rx_intr(struct wi_softc *sc)
|
||||
/* First read in the frame header */
|
||||
if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
|
||||
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
|
||||
return;
|
||||
}
|
||||
@ -1269,7 +1343,7 @@ wi_rx_intr(struct wi_softc *sc)
|
||||
status = le16toh(frmhdr.wi_status);
|
||||
if (status & WI_STAT_ERRSTAT) {
|
||||
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
|
||||
return;
|
||||
}
|
||||
@ -1284,7 +1358,7 @@ wi_rx_intr(struct wi_softc *sc)
|
||||
if (off + len > MCLBYTES) {
|
||||
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
|
||||
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
DPRINTF(("wi_rx_intr: oversized packet\n"));
|
||||
return;
|
||||
} else
|
||||
@ -1297,7 +1371,7 @@ wi_rx_intr(struct wi_softc *sc)
|
||||
m = m_gethdr(M_NOWAIT, MT_DATA);
|
||||
if (m == NULL) {
|
||||
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
|
||||
counter_u64_add(ic->ic_ierrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
|
||||
DPRINTF(("wi_rx_intr: MGET failed\n"));
|
||||
return;
|
||||
}
|
||||
@ -1306,6 +1380,7 @@ wi_rx_intr(struct wi_softc *sc)
|
||||
wi_read_bap(sc, fid, sizeof(frmhdr),
|
||||
m->m_data + sizeof(struct ieee80211_frame), len);
|
||||
m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
|
||||
m->m_pkthdr.rcvif = ifp;
|
||||
|
||||
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
|
||||
|
||||
@ -1350,6 +1425,7 @@ wi_rx_intr(struct wi_softc *sc)
|
||||
static __noinline void
|
||||
wi_tx_ex_intr(struct wi_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct wi_frame frmhdr;
|
||||
int fid;
|
||||
|
||||
@ -1364,7 +1440,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
|
||||
*/
|
||||
if ((status & WI_TXSTAT_DISCONNECT) == 0) {
|
||||
if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
|
||||
device_printf(sc->sc_dev, "tx failed");
|
||||
if_printf(ifp, "tx failed");
|
||||
if (status & WI_TXSTAT_RET_ERR)
|
||||
printf(", retry limit exceeded");
|
||||
if (status & WI_TXSTAT_AGED_ERR)
|
||||
@ -1379,7 +1455,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
|
||||
printf(", status=0x%x", status);
|
||||
printf("\n");
|
||||
}
|
||||
counter_u64_add(sc->sc_ic.ic_oerrors, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
} else
|
||||
DPRINTF(("port disconnected\n"));
|
||||
} else
|
||||
@ -1390,6 +1466,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
|
||||
static __noinline void
|
||||
wi_tx_intr(struct wi_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int fid, cur;
|
||||
|
||||
if (sc->wi_gone)
|
||||
@ -1400,17 +1477,19 @@ wi_tx_intr(struct wi_softc *sc)
|
||||
|
||||
cur = sc->sc_txcur;
|
||||
if (sc->sc_txd[cur].d_fid != fid) {
|
||||
device_printf(sc->sc_dev, "bad alloc %x != %x, cur %d nxt %d\n",
|
||||
if_printf(ifp, "bad alloc %x != %x, cur %d nxt %d\n",
|
||||
fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext);
|
||||
return;
|
||||
}
|
||||
sc->sc_tx_timer = 0;
|
||||
sc->sc_txd[cur].d_len = 0;
|
||||
sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;
|
||||
if (sc->sc_txd[cur].d_len != 0) {
|
||||
if (sc->sc_txd[cur].d_len == 0)
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
else {
|
||||
if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
|
||||
0, 0)) {
|
||||
device_printf(sc->sc_dev, "xmit failed\n");
|
||||
if_printf(ifp, "xmit failed\n");
|
||||
sc->sc_txd[cur].d_len = 0;
|
||||
} else {
|
||||
sc->sc_tx_timer = 5;
|
||||
@ -1421,7 +1500,7 @@ wi_tx_intr(struct wi_softc *sc)
|
||||
static __noinline void
|
||||
wi_info_intr(struct wi_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
int i, fid, len, off;
|
||||
u_int16_t ltbuf[2];
|
||||
@ -1495,15 +1574,32 @@ finish:
|
||||
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
wi_get_counter(struct ifnet *ifp, ift_counter cnt)
|
||||
{
|
||||
struct wi_softc *sc;
|
||||
|
||||
sc = if_getsoftc(ifp);
|
||||
|
||||
switch (cnt) {
|
||||
case IFCOUNTER_COLLISIONS:
|
||||
return (sc->sc_stats.wi_tx_single_retries +
|
||||
sc->sc_stats.wi_tx_multi_retries +
|
||||
sc->sc_stats.wi_tx_retry_limit);
|
||||
default:
|
||||
return (if_get_counter_default(ifp, cnt));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
wi_write_multi(struct wi_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap;
|
||||
struct wi_mcast mlist;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
int n;
|
||||
struct ifmultiaddr *ifma;
|
||||
struct wi_mcast mlist;
|
||||
|
||||
if (ic->ic_allmulti > 0 || ic->ic_promisc > 0) {
|
||||
if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
|
||||
allmulti:
|
||||
memset(&mlist, 0, sizeof(mlist));
|
||||
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
|
||||
@ -1511,23 +1607,17 @@ allmulti:
|
||||
}
|
||||
|
||||
n = 0;
|
||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
|
||||
struct ifnet *ifp;
|
||||
struct ifmultiaddr *ifma;
|
||||
|
||||
ifp = vap->iv_ifp;
|
||||
if_maddr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
if (n >= 16)
|
||||
goto allmulti;
|
||||
IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
|
||||
(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
|
||||
n++;
|
||||
}
|
||||
if_maddr_runlock(ifp);
|
||||
if_maddr_rlock(ifp);
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
if (n >= 16)
|
||||
goto allmulti;
|
||||
IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
|
||||
(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
|
||||
n++;
|
||||
}
|
||||
if_maddr_runlock(ifp);
|
||||
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
|
||||
IEEE80211_ADDR_LEN * n);
|
||||
}
|
||||
@ -1548,7 +1638,7 @@ wi_update_promisc(struct ieee80211com *ic)
|
||||
/* XXX handle WEP special case handling? */
|
||||
wi_write_val(sc, WI_RID_PROMISC,
|
||||
(ic->ic_opmode == IEEE80211_M_MONITOR ||
|
||||
(ic->ic_promisc > 0)));
|
||||
(ic->ic_ifp->if_flags & IFF_PROMISC)));
|
||||
WI_UNLOCK(sc);
|
||||
}
|
||||
|
||||
@ -1847,7 +1937,7 @@ wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
|
||||
}
|
||||
|
||||
static int
|
||||
wi_write_bap(struct wi_softc *sc, int id, int off, const void *buf, int buflen)
|
||||
wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
|
||||
{
|
||||
int error, cnt;
|
||||
|
||||
@ -1859,7 +1949,7 @@ wi_write_bap(struct wi_softc *sc, int id, int off, const void *buf, int buflen)
|
||||
return error;
|
||||
}
|
||||
cnt = (buflen + 1) / 2;
|
||||
CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (const uint16_t *)buf, cnt);
|
||||
CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
|
||||
sc->sc_bap_off += cnt * 2;
|
||||
|
||||
return 0;
|
||||
@ -1949,7 +2039,7 @@ wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
|
||||
}
|
||||
|
||||
static int
|
||||
wi_write_rid(struct wi_softc *sc, int rid, const void *buf, int buflen)
|
||||
wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
|
||||
{
|
||||
int error;
|
||||
u_int16_t ltbuf[2];
|
||||
|
@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
|
@ -238,9 +238,7 @@ wi_pci_suspend(device_t dev)
|
||||
{
|
||||
struct wi_softc *sc = device_get_softc(dev);
|
||||
|
||||
WI_LOCK(sc);
|
||||
wi_stop(sc, 1);
|
||||
WI_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -249,15 +247,16 @@ static int
|
||||
wi_pci_resume(device_t dev)
|
||||
{
|
||||
struct wi_softc *sc = device_get_softc(dev);
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
WI_LOCK(sc);
|
||||
if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
|
||||
if (sc->wi_bus_type != WI_BUS_PCI_NATIVE)
|
||||
return (0);
|
||||
WI_UNLOCK(sc);
|
||||
|
||||
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 (ic->ic_nrunning > 0)
|
||||
wi_init(sc);
|
||||
WI_UNLOCK(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -68,8 +68,7 @@ struct wi_vap {
|
||||
#define WI_VAP(vap) ((struct wi_vap *)(vap))
|
||||
|
||||
struct wi_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
struct mbufq sc_snd;
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
struct mtx sc_mtx;
|
||||
struct callout sc_watchdog;
|
||||
@ -108,6 +107,7 @@ struct wi_softc {
|
||||
int wi_cmd_count;
|
||||
|
||||
int sc_flags;
|
||||
int sc_if_flags;
|
||||
int sc_bap_id;
|
||||
int sc_bap_off;
|
||||
|
||||
@ -152,8 +152,6 @@ struct wi_softc {
|
||||
#define WI_FLAGS_HAS_ROAMING 0x0020
|
||||
#define WI_FLAGS_HAS_FRAGTHR 0x0200
|
||||
#define WI_FLAGS_HAS_DBMADJUST 0x0400
|
||||
#define WI_FLAGS_RUNNING 0x0800
|
||||
#define WI_FLAGS_PROMISC 0x1000
|
||||
|
||||
struct wi_card_ident {
|
||||
u_int16_t card_id;
|
||||
@ -182,7 +180,7 @@ int wi_shutdown(device_t);
|
||||
int wi_alloc(device_t, int);
|
||||
void wi_free(device_t);
|
||||
extern devclass_t wi_devclass;
|
||||
void wi_init(void *);
|
||||
void wi_intr(void *);
|
||||
int wi_mgmt_xmit(struct wi_softc *, caddr_t, int);
|
||||
void wi_stop(struct wi_softc *, int);
|
||||
void wi_init(struct wi_softc *);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -72,7 +72,6 @@ struct wpi_tx_ring {
|
||||
struct wpi_tx_cmd *cmd;
|
||||
struct wpi_tx_data data[WPI_TX_RING_COUNT];
|
||||
bus_dma_tag_t data_dmat;
|
||||
struct mbufq snd;
|
||||
int qid;
|
||||
int queued;
|
||||
int cur;
|
||||
@ -165,15 +164,14 @@ struct wpi_fw_info {
|
||||
|
||||
struct wpi_softc {
|
||||
device_t sc_dev;
|
||||
|
||||
struct ifnet *sc_ifp;
|
||||
int sc_debug;
|
||||
|
||||
int sc_flags;
|
||||
#define WPI_PS_PATH (1 << 0)
|
||||
int sc_running;
|
||||
|
||||
struct mtx sc_mtx;
|
||||
struct ieee80211com sc_ic;
|
||||
|
||||
struct mtx tx_mtx;
|
||||
|
||||
/* Shared area. */
|
||||
@ -183,6 +181,7 @@ struct wpi_softc {
|
||||
struct wpi_tx_ring txq[WPI_NTXQUEUES];
|
||||
struct mtx txq_mtx;
|
||||
struct mtx txq_state_mtx;
|
||||
uint32_t txq_active;
|
||||
|
||||
struct wpi_rx_ring rxq;
|
||||
uint64_t rx_tstamp;
|
||||
|
@ -261,7 +261,7 @@ static int
|
||||
wtap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct wtap_softc *sc = ic->ic_softc;
|
||||
struct wtap_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct wtap_vap *avp = WTAP_VAP(vap);
|
||||
struct ieee80211_node *ni = NULL;
|
||||
int error;
|
||||
@ -318,7 +318,7 @@ wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct wtap_softc *sc = ic->ic_softc;
|
||||
struct wtap_softc *sc = ic->ic_ifp->if_softc;
|
||||
struct ieee80211vap *vap;
|
||||
struct wtap_vap *avp;
|
||||
int error;
|
||||
@ -326,13 +326,15 @@ wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
|
||||
|
||||
DWTAP_PRINTF("%s\n", __func__);
|
||||
|
||||
avp = malloc(sizeof(struct wtap_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
||||
avp = malloc(sizeof(struct wtap_vap), M_80211_VAP, M_NOWAIT | M_ZERO);
|
||||
if (avp == NULL)
|
||||
return (NULL);
|
||||
avp->id = sc->id;
|
||||
avp->av_md = sc->sc_md;
|
||||
avp->av_bcinterval = msecs_to_ticks(BEACON_INTRERVAL + 100*sc->id);
|
||||
vap = (struct ieee80211vap *) avp;
|
||||
error = ieee80211_vap_setup(ic, vap, name, unit, IEEE80211_M_MBSS,
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid);
|
||||
flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
|
||||
if (error) {
|
||||
free(avp, M_80211_VAP);
|
||||
return (NULL);
|
||||
@ -349,10 +351,9 @@ wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
|
||||
vap->iv_bmiss = wtap_bmiss;
|
||||
|
||||
/* complete setup */
|
||||
ieee80211_vap_attach(vap, wtap_media_change, ieee80211_media_status,
|
||||
mac);
|
||||
ieee80211_vap_attach(vap, wtap_media_change, ieee80211_media_status);
|
||||
avp->av_dev = make_dev(&wtap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
|
||||
"%s", (const char *)sc->name);
|
||||
"%s", (const char *)ic->ic_ifp->if_xname);
|
||||
|
||||
/* TODO this is a hack to force it to choose the rate we want */
|
||||
ni = ieee80211_ref_node(vap->iv_bss);
|
||||
@ -373,16 +374,148 @@ wtap_vap_delete(struct ieee80211vap *vap)
|
||||
free((struct wtap_vap*) vap, M_80211_VAP);
|
||||
}
|
||||
|
||||
/* NB: This function is not used.
|
||||
* I had the problem of the queue
|
||||
* being empty all the time.
|
||||
* Maybe I am setting the queue wrong?
|
||||
*/
|
||||
static void
|
||||
wtap_parent(struct ieee80211com *ic)
|
||||
wtap_start(struct ifnet *ifp)
|
||||
{
|
||||
struct wtap_softc *sc = ic->ic_softc;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ifnet *icifp = ic->ic_ifp;
|
||||
struct wtap_softc *sc = icifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
|
||||
if (ic->ic_nrunning > 0) {
|
||||
sc->up = 1;
|
||||
ieee80211_start_all(ic);
|
||||
} else
|
||||
sc->up = 0;
|
||||
DWTAP_PRINTF("my_start, with id=%u\n", sc->id);
|
||||
|
||||
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->up == 0)
|
||||
return;
|
||||
for (;;) {
|
||||
if(IFQ_IS_EMPTY(&ifp->if_snd)){
|
||||
printf("queue empty, just trying to see "
|
||||
"if the other queue is empty\n");
|
||||
#if 0
|
||||
printf("queue for id=1, %u\n",
|
||||
IFQ_IS_EMPTY(&global_mscs[1]->ifp->if_snd));
|
||||
printf("queue for id=0, %u\n",
|
||||
IFQ_IS_EMPTY(&global_mscs[0]->ifp->if_snd));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
IFQ_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL) {
|
||||
printf("error dequeueing from ifp->snd\n");
|
||||
break;
|
||||
}
|
||||
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
/*
|
||||
* Check for fragmentation. If this frame
|
||||
* has been broken up verify we have enough
|
||||
* buffers to send all the fragments so all
|
||||
* go out or none...
|
||||
*/
|
||||
#if 0
|
||||
STAILQ_INIT(&frags);
|
||||
#endif
|
||||
if ((m->m_flags & M_FRAG)){
|
||||
printf("dont support frags\n");
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return;
|
||||
}
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
if(wtap_raw_xmit(ni, m, NULL) < 0){
|
||||
printf("error raw_xmiting\n");
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
wtap_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
#if 0
|
||||
DWTAP_PRINTF("%s\n", __func__);
|
||||
uprintf("%s, command %lu\n", __func__, cmd);
|
||||
#endif
|
||||
#define IS_RUNNING(ifp) \
|
||||
((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct wtap_softc *sc = ifp->if_softc;
|
||||
struct ifreq *ifr = (struct ifreq *)data;
|
||||
int error = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
//printf("%s: %s\n", __func__, "SIOCSIFFLAGS");
|
||||
if (IS_RUNNING(ifp)) {
|
||||
DWTAP_PRINTF("running\n");
|
||||
#if 0
|
||||
/*
|
||||
* To avoid rescanning another access point,
|
||||
* do not call ath_init() here. Instead,
|
||||
* only reflect promisc mode settings.
|
||||
*/
|
||||
//ath_mode_init(sc);
|
||||
#endif
|
||||
} else if (ifp->if_flags & IFF_UP) {
|
||||
DWTAP_PRINTF("up\n");
|
||||
sc->up = 1;
|
||||
#if 0
|
||||
/*
|
||||
* Beware of being called during attach/detach
|
||||
* to reset promiscuous mode. In that case we
|
||||
* will still be marked UP but not RUNNING.
|
||||
* However trying to re-init the interface
|
||||
* is the wrong thing to do as we've already
|
||||
* torn down much of our state. There's
|
||||
* probably a better way to deal with this.
|
||||
*/
|
||||
//if (!sc->sc_invalid)
|
||||
// ath_init(sc); /* XXX lose error */
|
||||
#endif
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
ieee80211_start_all(ic);
|
||||
} else {
|
||||
DWTAP_PRINTF("stoping\n");
|
||||
#if 0
|
||||
ath_stop_locked(ifp);
|
||||
#ifdef notyet
|
||||
/* XXX must wakeup in places like ath_vap_delete */
|
||||
if (!sc->sc_invalid)
|
||||
ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SIOCGIFMEDIA:
|
||||
case SIOCSIFMEDIA:
|
||||
#if 0
|
||||
DWTAP_PRINTF("%s: %s\n", __func__, "SIOCGIFMEDIA|SIOCSIFMEDIA");
|
||||
#endif
|
||||
error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
|
||||
break;
|
||||
case SIOCGIFADDR:
|
||||
#if 0
|
||||
DWTAP_PRINTF("%s: %s\n", __func__, "SIOCGIFADDR");
|
||||
#endif
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
default:
|
||||
DWTAP_PRINTF("%s: %s [%lu]\n", __func__, "EINVAL", cmd);
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
return error;
|
||||
#undef IS_RUNNING
|
||||
}
|
||||
|
||||
static void
|
||||
wtap_init(void *arg){
|
||||
|
||||
DWTAP_PRINTF("%s\n", __func__);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -448,7 +581,8 @@ wtap_inject(struct wtap_softc *sc, struct mbuf *m)
|
||||
void
|
||||
wtap_rx_deliver(struct wtap_softc *sc, struct mbuf *m)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211_node *ni;
|
||||
int type;
|
||||
#if 0
|
||||
@ -457,9 +591,11 @@ wtap_rx_deliver(struct wtap_softc *sc, struct mbuf *m)
|
||||
|
||||
DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, m);
|
||||
if (m == NULL) { /* NB: shouldn't happen */
|
||||
ic_printf(ic, "%s: no mbuf!\n", __func__);
|
||||
if_printf(ifp, "%s: no mbuf!\n", __func__);
|
||||
}
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||
|
||||
ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0);
|
||||
|
||||
/*
|
||||
@ -484,7 +620,8 @@ static void
|
||||
wtap_rx_proc(void *arg, int npending)
|
||||
{
|
||||
struct wtap_softc *sc = (struct wtap_softc *)arg;
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct mbuf *m;
|
||||
struct ieee80211_node *ni;
|
||||
int type;
|
||||
@ -507,10 +644,12 @@ wtap_rx_proc(void *arg, int npending)
|
||||
m = bf->m;
|
||||
DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, bf->m);
|
||||
if (m == NULL) { /* NB: shouldn't happen */
|
||||
ic_printf(ic, "%s: no mbuf!\n", __func__);
|
||||
if_printf(ifp, "%s: no mbuf!\n", __func__);
|
||||
free(bf, M_WTAP_RXBUF);
|
||||
return;
|
||||
}
|
||||
|
||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||
#if 0
|
||||
ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0);
|
||||
#endif
|
||||
@ -577,7 +716,7 @@ wtap_update_promisc(struct ieee80211com *ic)
|
||||
}
|
||||
|
||||
static int
|
||||
wtap_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
wtap_if_transmit(struct ifnet *ifp, struct mbuf *m)
|
||||
{
|
||||
struct ieee80211_node *ni =
|
||||
(struct ieee80211_node *) m->m_pkthdr.rcvif;
|
||||
@ -614,7 +753,7 @@ static void
|
||||
wtap_node_free(struct ieee80211_node *ni)
|
||||
{
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct wtap_softc *sc = ic->ic_softc;
|
||||
struct wtap_softc *sc = ic->ic_ifp->if_softc;
|
||||
|
||||
DWTAP_PRINTF("%s\n", __func__);
|
||||
sc->sc_node_free(ni);
|
||||
@ -623,17 +762,41 @@ wtap_node_free(struct ieee80211_node *ni)
|
||||
int32_t
|
||||
wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp;
|
||||
struct ieee80211com *ic;
|
||||
char wtap_name[] = {'w','T','a','p',sc->id,
|
||||
'_','t','a','s','k','q','\0'};
|
||||
|
||||
DWTAP_PRINTF("%s\n", __func__);
|
||||
|
||||
ifp = if_alloc(IFT_IEEE80211);
|
||||
if (ifp == NULL) {
|
||||
printf("can not if_alloc()\n");
|
||||
return -1;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
if_initname(ifp, "wtap", sc->id);
|
||||
|
||||
sc->sc_ifp = ifp;
|
||||
sc->up = 0;
|
||||
|
||||
STAILQ_INIT(&sc->sc_rxbuf);
|
||||
sc->sc_tq = taskqueue_create("wtap_taskq", M_NOWAIT | M_ZERO,
|
||||
sc->sc_tq = taskqueue_create(wtap_name, M_NOWAIT | M_ZERO,
|
||||
taskqueue_thread_enqueue, &sc->sc_tq);
|
||||
taskqueue_start_threads(&sc->sc_tq, 1, PI_SOFT, "%s taskQ", sc->name);
|
||||
taskqueue_start_threads(&sc->sc_tq, 1, PI_SOFT, "%s taskQ",
|
||||
ifp->if_xname);
|
||||
TASK_INIT(&sc->sc_rxtask, 0, wtap_rx_proc, sc);
|
||||
|
||||
ifp->if_softc = sc;
|
||||
ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
|
||||
ifp->if_start = wtap_start;
|
||||
ifp->if_ioctl = wtap_ioctl;
|
||||
ifp->if_init = wtap_init;
|
||||
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_name = sc->name;
|
||||
ic->ic_phytype = IEEE80211_T_DS;
|
||||
@ -652,8 +815,17 @@ wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
|
||||
ic->ic_channels[0].ic_flags = IEEE80211_CHAN_B;
|
||||
ic->ic_channels[0].ic_freq = 2412;
|
||||
|
||||
IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
|
||||
ieee80211_ifattach(ic);
|
||||
ieee80211_ifattach(ic, macaddr);
|
||||
|
||||
#if 0
|
||||
/* new prototype hook-ups */
|
||||
msc->if_input = ifp->if_input;
|
||||
ifp->if_input = myath_if_input;
|
||||
msc->if_output = ifp->if_output;
|
||||
ifp->if_output = myath_if_output;
|
||||
#endif
|
||||
sc->if_transmit = ifp->if_transmit;
|
||||
ifp->if_transmit = wtap_if_transmit;
|
||||
|
||||
/* override default methods */
|
||||
ic->ic_newassoc = wtap_newassoc;
|
||||
@ -663,14 +835,15 @@ wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
|
||||
ic->ic_raw_xmit = wtap_raw_xmit;
|
||||
ic->ic_update_mcast = wtap_update_mcast;
|
||||
ic->ic_update_promisc = wtap_update_promisc;
|
||||
ic->ic_transmit = wtap_transmit;
|
||||
ic->ic_parent = wtap_parent;
|
||||
|
||||
sc->sc_node_alloc = ic->ic_node_alloc;
|
||||
ic->ic_node_alloc = wtap_node_alloc;
|
||||
sc->sc_node_free = ic->ic_node_free;
|
||||
ic->ic_node_free = wtap_node_free;
|
||||
|
||||
#if 0
|
||||
ic->ic_node_getsignal = myath_node_getsignal;
|
||||
#endif
|
||||
ic->ic_scan_start = wtap_scan_start;
|
||||
ic->ic_scan_end = wtap_scan_end;
|
||||
ic->ic_set_channel = wtap_set_channel;
|
||||
@ -709,11 +882,13 @@ wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
|
||||
int32_t
|
||||
wtap_detach(struct wtap_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
DWTAP_PRINTF("%s\n", __func__);
|
||||
ieee80211_ageq_drain(&ic->ic_stageq);
|
||||
ieee80211_ifdetach(ic);
|
||||
if_free(ifp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -130,14 +130,18 @@ struct wtap_vap {
|
||||
struct taskqueue;
|
||||
|
||||
struct wtap_softc {
|
||||
struct ieee80211com sc_ic;
|
||||
char name[7]; /* wtapXX\0 */
|
||||
int32_t id;
|
||||
int32_t up;
|
||||
struct ifnet *sc_ifp; /* interface common */
|
||||
struct wtap_medium *sc_md; /* interface medium */
|
||||
struct ieee80211_node* (* sc_node_alloc)
|
||||
(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]);
|
||||
void (*sc_node_free)(struct ieee80211_node *);
|
||||
int (*if_output) /* output routine (enqueue) */
|
||||
(struct ifnet *, struct mbuf *, struct sockaddr *, struct route *);
|
||||
void (*if_input) (struct ifnet *, struct mbuf *);/* from h/w driver */
|
||||
int (*if_transmit)(struct ifnet *, struct mbuf *);/* output routine */
|
||||
struct mtx sc_mtx; /* master lock (recursive) */
|
||||
struct taskqueue *sc_tq; /* private task queue */
|
||||
wtap_bufhead sc_rxbuf; /* receive buffer */
|
||||
|
@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sbuf.h>
|
||||
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
@ -92,6 +91,8 @@ static void ieee80211_syncflag_ext_locked(struct ieee80211com *ic, int flag);
|
||||
static int ieee80211_media_setup(struct ieee80211com *ic,
|
||||
struct ifmedia *media, int caps, int addsta,
|
||||
ifm_change_cb_t media_change, ifm_stat_cb_t media_stat);
|
||||
static void ieee80211com_media_status(struct ifnet *, struct ifmediareq *);
|
||||
static int ieee80211com_media_change(struct ifnet *);
|
||||
static int media_status(enum ieee80211_opmode,
|
||||
const struct ieee80211_channel *);
|
||||
static uint64_t ieee80211_get_counter(struct ifnet *, ift_counter);
|
||||
@ -120,7 +121,7 @@ static const struct ieee80211_rateset ieee80211_rateset_11g =
|
||||
* all available channels as active, and pick
|
||||
* a default channel if not already specified.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
ieee80211_chan_init(struct ieee80211com *ic)
|
||||
{
|
||||
#define DEFAULTRATES(m, def) do { \
|
||||
@ -237,6 +238,29 @@ null_update_promisc(struct ieee80211com *ic)
|
||||
ic_printf(ic, "need promiscuous mode update callback\n");
|
||||
}
|
||||
|
||||
static int
|
||||
null_transmit(struct ifnet *ifp, struct mbuf *m)
|
||||
{
|
||||
m_freem(m);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return EACCES; /* XXX EIO/EPERM? */
|
||||
}
|
||||
|
||||
static int
|
||||
null_output(struct ifnet *ifp, struct mbuf *m,
|
||||
const struct sockaddr *dst, struct route *ro)
|
||||
{
|
||||
if_printf(ifp, "discard raw packet\n");
|
||||
return null_transmit(ifp, m);
|
||||
}
|
||||
|
||||
static void
|
||||
null_input(struct ifnet *ifp, struct mbuf *m)
|
||||
{
|
||||
if_printf(ifp, "if_input should not be called\n");
|
||||
m_freem(m);
|
||||
}
|
||||
|
||||
static void
|
||||
null_update_chw(struct ieee80211com *ic)
|
||||
{
|
||||
@ -257,43 +281,19 @@ ic_printf(struct ieee80211com *ic, const char * fmt, ...)
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static LIST_HEAD(, ieee80211com) ic_head = LIST_HEAD_INITIALIZER(ic_head);
|
||||
static struct mtx ic_list_mtx;
|
||||
MTX_SYSINIT(ic_list, &ic_list_mtx, "ieee80211com list", MTX_DEF);
|
||||
|
||||
static int
|
||||
sysctl_ieee80211coms(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct ieee80211com *ic;
|
||||
struct sbuf *sb;
|
||||
char *sp;
|
||||
int error;
|
||||
|
||||
sb = sbuf_new_auto();
|
||||
sp = "";
|
||||
mtx_lock(&ic_list_mtx);
|
||||
LIST_FOREACH(ic, &ic_head, ic_next) {
|
||||
sbuf_printf(sb, "%s%s", sp, ic->ic_name);
|
||||
sp = " ";
|
||||
}
|
||||
mtx_unlock(&ic_list_mtx);
|
||||
sbuf_finish(sb);
|
||||
error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
|
||||
sbuf_delete(sb);
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_net_wlan, OID_AUTO, devices,
|
||||
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
|
||||
sysctl_ieee80211coms, "A", "names of available 802.11 devices");
|
||||
|
||||
/*
|
||||
* Attach/setup the common net80211 state. Called by
|
||||
* the driver on attach to prior to creating any vap's.
|
||||
*/
|
||||
void
|
||||
ieee80211_ifattach(struct ieee80211com *ic)
|
||||
ieee80211_ifattach(struct ieee80211com *ic,
|
||||
const uint8_t macaddr[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct sockaddr_dl *sdl;
|
||||
struct ifaddr *ifa;
|
||||
|
||||
KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type));
|
||||
|
||||
IEEE80211_LOCK_INIT(ic, ic->ic_name);
|
||||
IEEE80211_TX_LOCK_INIT(ic, ic->ic_name);
|
||||
@ -311,7 +311,7 @@ ieee80211_ifattach(struct ieee80211com *ic)
|
||||
* available channels as active, and pick a default
|
||||
* channel if not already specified.
|
||||
*/
|
||||
ieee80211_chan_init(ic);
|
||||
ieee80211_media_init(ic);
|
||||
|
||||
ic->ic_update_mcast = null_update_mcast;
|
||||
ic->ic_update_promisc = null_update_promisc;
|
||||
@ -336,9 +336,28 @@ ieee80211_ifattach(struct ieee80211com *ic)
|
||||
|
||||
ieee80211_sysctl_attach(ic);
|
||||
|
||||
mtx_lock(&ic_list_mtx);
|
||||
LIST_INSERT_HEAD(&ic_head, ic, ic_next);
|
||||
mtx_unlock(&ic_list_mtx);
|
||||
ifp->if_addrlen = IEEE80211_ADDR_LEN;
|
||||
ifp->if_hdrlen = 0;
|
||||
|
||||
CURVNET_SET(vnet0);
|
||||
|
||||
if_attach(ifp);
|
||||
|
||||
ifp->if_mtu = IEEE80211_MTU_MAX;
|
||||
ifp->if_broadcastaddr = ieee80211broadcastaddr;
|
||||
ifp->if_output = null_output;
|
||||
ifp->if_input = null_input; /* just in case */
|
||||
ifp->if_resolvemulti = NULL; /* NB: callers check */
|
||||
|
||||
ifa = ifaddr_byindex(ifp->if_index);
|
||||
KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__));
|
||||
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
|
||||
sdl->sdl_type = IFT_ETHER; /* XXX IFT_IEEE80211? */
|
||||
sdl->sdl_alen = IEEE80211_ADDR_LEN;
|
||||
IEEE80211_ADDR_COPY(LLADDR(sdl), macaddr);
|
||||
ifa_free(ifa);
|
||||
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -350,11 +369,16 @@ ieee80211_ifattach(struct ieee80211com *ic)
|
||||
void
|
||||
ieee80211_ifdetach(struct ieee80211com *ic)
|
||||
{
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
mtx_lock(&ic_list_mtx);
|
||||
LIST_REMOVE(ic, ic_next);
|
||||
mtx_unlock(&ic_list_mtx);
|
||||
/*
|
||||
* This detaches the main interface, but not the vaps.
|
||||
* Each VAP may be in a separate VIMAGE.
|
||||
*/
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
if_detach(ifp);
|
||||
CURVNET_RESTORE();
|
||||
|
||||
/*
|
||||
* The VAP is responsible for setting and clearing
|
||||
@ -378,6 +402,8 @@ ieee80211_ifdetach(struct ieee80211com *ic)
|
||||
ieee80211_power_detach(ic);
|
||||
ieee80211_node_detach(ic);
|
||||
|
||||
/* XXX VNET needed? */
|
||||
ifmedia_removeall(&ic->ic_media);
|
||||
counter_u64_free(ic->ic_ierrors);
|
||||
counter_u64_free(ic->ic_oerrors);
|
||||
|
||||
@ -386,20 +412,6 @@ ieee80211_ifdetach(struct ieee80211com *ic)
|
||||
IEEE80211_LOCK_DESTROY(ic);
|
||||
}
|
||||
|
||||
struct ieee80211com *
|
||||
ieee80211_find_com(const char *name)
|
||||
{
|
||||
struct ieee80211com *ic;
|
||||
|
||||
mtx_lock(&ic_list_mtx);
|
||||
LIST_FOREACH(ic, &ic_head, ic_next)
|
||||
if (strcmp(ic->ic_name, name) == 0)
|
||||
break;
|
||||
mtx_unlock(&ic_list_mtx);
|
||||
|
||||
return (ic);
|
||||
}
|
||||
|
||||
/*
|
||||
* Default reset method for use with the ioctl support. This
|
||||
* method is invoked after any state change in the 802.11
|
||||
@ -448,7 +460,8 @@ ieee80211_get_counter(struct ifnet *ifp, ift_counter cnt)
|
||||
int
|
||||
ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
|
||||
const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode,
|
||||
int flags, const uint8_t bssid[IEEE80211_ADDR_LEN])
|
||||
int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t macaddr[IEEE80211_ADDR_LEN])
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
|
||||
@ -477,7 +490,6 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
|
||||
vap->iv_htextcaps = ic->ic_htextcaps;
|
||||
vap->iv_opmode = opmode;
|
||||
vap->iv_caps |= ieee80211_opcap[opmode];
|
||||
vap->iv_myaddr = ic->ic_macaddr;
|
||||
switch (opmode) {
|
||||
case IEEE80211_M_WDS:
|
||||
/*
|
||||
@ -544,6 +556,8 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
|
||||
*/
|
||||
vap->iv_reset = default_reset;
|
||||
|
||||
IEEE80211_ADDR_COPY(vap->iv_myaddr, macaddr);
|
||||
|
||||
ieee80211_sysctl_vattach(vap);
|
||||
ieee80211_crypto_vattach(vap);
|
||||
ieee80211_node_vattach(vap);
|
||||
@ -567,8 +581,8 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
|
||||
* from this call the vap is ready for use.
|
||||
*/
|
||||
int
|
||||
ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change,
|
||||
ifm_stat_cb_t media_stat, const uint8_t macaddr[IEEE80211_ADDR_LEN])
|
||||
ieee80211_vap_attach(struct ieee80211vap *vap,
|
||||
ifm_change_cb_t media_change, ifm_stat_cb_t media_stat)
|
||||
{
|
||||
struct ifnet *ifp = vap->iv_ifp;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
@ -596,8 +610,7 @@ ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change,
|
||||
if (maxrate)
|
||||
ifp->if_baudrate = IF_Mbps(maxrate);
|
||||
|
||||
ether_ifattach(ifp, macaddr);
|
||||
vap->iv_myaddr = IF_LLADDR(ifp);
|
||||
ether_ifattach(ifp, vap->iv_myaddr);
|
||||
/* hook output method setup by ether_ifattach */
|
||||
vap->iv_output = ifp->if_output;
|
||||
ifp->if_output = ieee80211_output;
|
||||
@ -613,6 +626,8 @@ ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change,
|
||||
ieee80211_syncflag_locked(ic, IEEE80211_F_BURST);
|
||||
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_HT);
|
||||
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
|
||||
ieee80211_syncifflag_locked(ic, IFF_PROMISC);
|
||||
ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
|
||||
IEEE80211_UNLOCK(ic);
|
||||
|
||||
return 1;
|
||||
@ -662,10 +677,8 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
|
||||
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
|
||||
/* NB: this handles the bpfdetach done below */
|
||||
ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_BPF);
|
||||
if (vap->iv_ifflags & IFF_PROMISC)
|
||||
ieee80211_promisc(vap, false);
|
||||
if (vap->iv_ifflags & IFF_ALLMULTI)
|
||||
ieee80211_allmulti(vap, false);
|
||||
ieee80211_syncifflag_locked(ic, IFF_PROMISC);
|
||||
ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
|
||||
IEEE80211_UNLOCK(ic);
|
||||
|
||||
ifmedia_removeall(&vap->iv_media);
|
||||
@ -690,57 +703,49 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
|
||||
}
|
||||
|
||||
/*
|
||||
* Count number of vaps in promisc, and issue promisc on
|
||||
* parent respectively.
|
||||
* Synchronize flag bit state in the parent ifnet structure
|
||||
* according to the state of all vap ifnet's. This is used,
|
||||
* for example, to handle IFF_PROMISC and IFF_ALLMULTI.
|
||||
*/
|
||||
void
|
||||
ieee80211_promisc(struct ieee80211vap *vap, bool on)
|
||||
ieee80211_syncifflag_locked(struct ieee80211com *ic, int flag)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
struct ieee80211vap *vap;
|
||||
int bit, oflags;
|
||||
|
||||
/*
|
||||
* XXX the bridge sets PROMISC but we don't want to
|
||||
* enable it on the device, discard here so all the
|
||||
* drivers don't need to special-case it
|
||||
*/
|
||||
if (!(vap->iv_opmode == IEEE80211_M_MONITOR ||
|
||||
(vap->iv_opmode == IEEE80211_M_AHDEMO &&
|
||||
(vap->iv_caps & IEEE80211_C_TDMA) == 0)))
|
||||
return;
|
||||
IEEE80211_LOCK_ASSERT(ic);
|
||||
|
||||
IEEE80211_LOCK(ic);
|
||||
if (on) {
|
||||
if (++ic->ic_promisc == 1)
|
||||
ieee80211_runtask(ic, &ic->ic_promisc_task);
|
||||
} else {
|
||||
KASSERT(ic->ic_promisc > 0, ("%s: ic %p not promisc",
|
||||
__func__, ic));
|
||||
if (--ic->ic_promisc == 0)
|
||||
ieee80211_runtask(ic, &ic->ic_promisc_task);
|
||||
bit = 0;
|
||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
|
||||
if (vap->iv_ifp->if_flags & flag) {
|
||||
/*
|
||||
* XXX the bridge sets PROMISC but we don't want to
|
||||
* enable it on the device, discard here so all the
|
||||
* drivers don't need to special-case it
|
||||
*/
|
||||
if (flag == IFF_PROMISC &&
|
||||
!(vap->iv_opmode == IEEE80211_M_MONITOR ||
|
||||
(vap->iv_opmode == IEEE80211_M_AHDEMO &&
|
||||
(vap->iv_caps & IEEE80211_C_TDMA) == 0)))
|
||||
continue;
|
||||
bit = 1;
|
||||
break;
|
||||
}
|
||||
oflags = ifp->if_flags;
|
||||
if (bit)
|
||||
ifp->if_flags |= flag;
|
||||
else
|
||||
ifp->if_flags &= ~flag;
|
||||
if ((ifp->if_flags ^ oflags) & flag) {
|
||||
/* XXX should we return 1/0 and let caller do this? */
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
if (flag == IFF_PROMISC)
|
||||
ieee80211_runtask(ic, &ic->ic_promisc_task);
|
||||
else if (flag == IFF_ALLMULTI)
|
||||
ieee80211_runtask(ic, &ic->ic_mcast_task);
|
||||
}
|
||||
}
|
||||
IEEE80211_UNLOCK(ic);
|
||||
}
|
||||
|
||||
/*
|
||||
* Count number of vaps in allmulti, and issue allmulti on
|
||||
* parent respectively.
|
||||
*/
|
||||
void
|
||||
ieee80211_allmulti(struct ieee80211vap *vap, bool on)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
|
||||
IEEE80211_LOCK(ic);
|
||||
if (on) {
|
||||
if (++ic->ic_allmulti == 1)
|
||||
ieee80211_runtask(ic, &ic->ic_mcast_task);
|
||||
} else {
|
||||
KASSERT(ic->ic_allmulti > 0, ("%s: ic %p not allmulti",
|
||||
__func__, ic));
|
||||
if (--ic->ic_allmulti == 0)
|
||||
ieee80211_runtask(ic, &ic->ic_mcast_task);
|
||||
}
|
||||
IEEE80211_UNLOCK(ic);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1229,6 +1234,39 @@ ieee80211_media_setup(struct ieee80211com *ic,
|
||||
return maxrate;
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_media_init(struct ieee80211com *ic)
|
||||
{
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
int maxrate;
|
||||
|
||||
/* NB: this works because the structure is initialized to zero */
|
||||
if (!LIST_EMPTY(&ic->ic_media.ifm_list)) {
|
||||
/*
|
||||
* We are re-initializing the channel list; clear
|
||||
* the existing media state as the media routines
|
||||
* don't suppress duplicates.
|
||||
*/
|
||||
ifmedia_removeall(&ic->ic_media);
|
||||
}
|
||||
ieee80211_chan_init(ic);
|
||||
|
||||
/*
|
||||
* Recalculate media settings in case new channel list changes
|
||||
* the set of available modes.
|
||||
*/
|
||||
maxrate = ieee80211_media_setup(ic, &ic->ic_media, ic->ic_caps, 1,
|
||||
ieee80211com_media_change, ieee80211com_media_status);
|
||||
/* NB: strip explicit mode; we're actually in autoselect */
|
||||
ifmedia_set(&ic->ic_media,
|
||||
media_status(ic->ic_opmode, ic->ic_curchan) &~
|
||||
(IFM_MMASK | IFM_IEEE80211_TURBO));
|
||||
if (maxrate)
|
||||
ifp->if_baudrate = IF_Mbps(maxrate);
|
||||
|
||||
/* XXX need to propagate new media settings to vap's */
|
||||
}
|
||||
|
||||
/* XXX inline or eliminate? */
|
||||
const struct ieee80211_rateset *
|
||||
ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *c)
|
||||
@ -1356,6 +1394,15 @@ media2mode(const struct ifmedia_entry *ime, uint32_t flags, uint16_t *mode)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a media change request on the underlying interface.
|
||||
*/
|
||||
int
|
||||
ieee80211com_media_change(struct ifnet *ifp)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a media change request on the vap interface.
|
||||
*/
|
||||
@ -1433,6 +1480,23 @@ media_status(enum ieee80211_opmode opmode, const struct ieee80211_channel *chan)
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
ieee80211com_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
||||
{
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap;
|
||||
|
||||
imr->ifm_status = IFM_AVALID;
|
||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
|
||||
if (vap->iv_ifp->if_flags & IFF_UP) {
|
||||
imr->ifm_status |= IFM_ACTIVE;
|
||||
break;
|
||||
}
|
||||
imr->ifm_active = media_status(ic->ic_opmode, ic->ic_curchan);
|
||||
if (imr->ifm_status & IFM_ACTIVE)
|
||||
imr->ifm_current = imr->ifm_active;
|
||||
}
|
||||
|
||||
void
|
||||
ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
||||
{
|
||||
|
@ -520,7 +520,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
|
||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
|
||||
db_printf(" %s(%p)", vap->iv_ifp->if_xname, vap);
|
||||
db_printf("\n");
|
||||
db_printf("\tsoftc %p", ic->ic_softc);
|
||||
db_printf("\tifp %p(%s)", ic->ic_ifp, ic->ic_ifp->if_xname);
|
||||
db_printf("\tname %s", ic->ic_name);
|
||||
db_printf(" comlock %p", &ic->ic_comlock);
|
||||
db_printf("\n");
|
||||
@ -528,6 +528,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
|
||||
db_printf(" phytype %d", ic->ic_phytype);
|
||||
db_printf(" opmode %s", ieee80211_opmode_name[ic->ic_opmode]);
|
||||
db_printf("\n");
|
||||
db_printf("\tmedia %p", &ic->ic_media);
|
||||
db_printf(" inact %p", &ic->ic_inact);
|
||||
db_printf("\n");
|
||||
|
||||
|
@ -69,27 +69,58 @@ static MALLOC_DEFINE(M_80211_COM, "80211com", "802.11 com state");
|
||||
static const char wlanname[] = "wlan";
|
||||
static struct if_clone *wlan_cloner;
|
||||
|
||||
/*
|
||||
* Allocate/free com structure in conjunction with ifnet;
|
||||
* these routines are registered with if_register_com_alloc
|
||||
* below and are called automatically by the ifnet code
|
||||
* when the ifnet of the parent device is created.
|
||||
*/
|
||||
static void *
|
||||
wlan_alloc(u_char type, struct ifnet *ifp)
|
||||
{
|
||||
struct ieee80211com *ic;
|
||||
|
||||
ic = IEEE80211_MALLOC(sizeof(struct ieee80211com), M_80211_COM,
|
||||
IEEE80211_M_WAITOK | IEEE80211_M_ZERO);
|
||||
ic->ic_ifp = ifp;
|
||||
|
||||
return (ic);
|
||||
}
|
||||
|
||||
static void
|
||||
wlan_free(void *ic, u_char type)
|
||||
{
|
||||
IEEE80211_FREE(ic, M_80211_COM);
|
||||
}
|
||||
|
||||
static int
|
||||
wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
|
||||
{
|
||||
struct ieee80211_clone_params cp;
|
||||
struct ieee80211vap *vap;
|
||||
struct ieee80211com *ic;
|
||||
struct ifnet *ifp;
|
||||
int error;
|
||||
|
||||
error = copyin(params, &cp, sizeof(cp));
|
||||
if (error)
|
||||
return error;
|
||||
ic = ieee80211_find_com(cp.icp_parent);
|
||||
if (ic == NULL)
|
||||
ifp = ifunit(cp.icp_parent);
|
||||
if (ifp == NULL)
|
||||
return ENXIO;
|
||||
/* XXX move printfs to DIAGNOSTIC before release */
|
||||
if (ifp->if_type != IFT_IEEE80211) {
|
||||
if_printf(ifp, "%s: reject, not an 802.11 device\n", __func__);
|
||||
return ENXIO;
|
||||
}
|
||||
if (cp.icp_opmode >= IEEE80211_OPMODE_MAX) {
|
||||
ic_printf(ic, "%s: invalid opmode %d\n", __func__,
|
||||
cp.icp_opmode);
|
||||
if_printf(ifp, "%s: invalid opmode %d\n",
|
||||
__func__, cp.icp_opmode);
|
||||
return EINVAL;
|
||||
}
|
||||
ic = ifp->if_l2com;
|
||||
if ((ic->ic_caps & ieee80211_opcap[cp.icp_opmode]) == 0) {
|
||||
ic_printf(ic, "%s mode not supported\n",
|
||||
if_printf(ifp, "%s mode not supported\n",
|
||||
ieee80211_opmode_name[cp.icp_opmode]);
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
@ -100,13 +131,13 @@ wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
|
||||
(1)
|
||||
#endif
|
||||
) {
|
||||
ic_printf(ic, "TDMA not supported\n");
|
||||
if_printf(ifp, "TDMA not supported\n");
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
vap = ic->ic_vap_create(ic, wlanname, unit,
|
||||
cp.icp_opmode, cp.icp_flags, cp.icp_bssid,
|
||||
cp.icp_flags & IEEE80211_CLONE_MACADDR ?
|
||||
cp.icp_macaddr : ic->ic_macaddr);
|
||||
cp.icp_macaddr : (const uint8_t *)IF_LLADDR(ifp));
|
||||
|
||||
return (vap == NULL ? EIO : 0);
|
||||
}
|
||||
@ -497,19 +528,17 @@ ieee80211_process_callback(struct ieee80211_node *ni,
|
||||
* (the callers will first need modifying.)
|
||||
*/
|
||||
int
|
||||
ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
|
||||
ieee80211_parent_xmitpkt(struct ieee80211com *ic,
|
||||
struct mbuf *m)
|
||||
{
|
||||
int error;
|
||||
|
||||
struct ifnet *parent = ic->ic_ifp;
|
||||
/*
|
||||
* Assert the IC TX lock is held - this enforces the
|
||||
* processing -> queuing order is maintained
|
||||
*/
|
||||
IEEE80211_TX_LOCK_ASSERT(ic);
|
||||
error = ic->ic_transmit(ic, m);
|
||||
if (error)
|
||||
m_freem(m);
|
||||
return (error);
|
||||
|
||||
return (parent->if_transmit(parent, m));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -807,6 +836,7 @@ ieee80211_load_module(const char *modname)
|
||||
}
|
||||
|
||||
static eventhandler_tag wlan_bpfevent;
|
||||
static eventhandler_tag wlan_ifllevent;
|
||||
|
||||
static void
|
||||
bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
|
||||
@ -834,6 +864,33 @@ bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wlan_iflladdr(void *arg __unused, struct ifnet *ifp)
|
||||
{
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
struct ieee80211vap *vap, *next;
|
||||
|
||||
if (ifp->if_type != IFT_IEEE80211 || ic == NULL)
|
||||
return;
|
||||
|
||||
IEEE80211_LOCK(ic);
|
||||
TAILQ_FOREACH_SAFE(vap, &ic->ic_vaps, iv_next, next) {
|
||||
/*
|
||||
* If the MAC address has changed on the parent and it was
|
||||
* copied to the vap on creation then re-sync.
|
||||
*/
|
||||
if (vap->iv_ic == ic &&
|
||||
(vap->iv_flags_ext & IEEE80211_FEXT_UNIQMAC) == 0) {
|
||||
IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp));
|
||||
IEEE80211_UNLOCK(ic);
|
||||
if_setlladdr(vap->iv_ifp, IF_LLADDR(ifp),
|
||||
IEEE80211_ADDR_LEN);
|
||||
IEEE80211_LOCK(ic);
|
||||
}
|
||||
}
|
||||
IEEE80211_UNLOCK(ic);
|
||||
}
|
||||
|
||||
/*
|
||||
* Module glue.
|
||||
*
|
||||
@ -848,12 +905,17 @@ wlan_modevent(module_t mod, int type, void *unused)
|
||||
printf("wlan: <802.11 Link Layer>\n");
|
||||
wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track,
|
||||
bpf_track, 0, EVENTHANDLER_PRI_ANY);
|
||||
wlan_ifllevent = EVENTHANDLER_REGISTER(iflladdr_event,
|
||||
wlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
|
||||
wlan_cloner = if_clone_simple(wlanname, wlan_clone_create,
|
||||
wlan_clone_destroy, 0);
|
||||
if_register_com_alloc(IFT_IEEE80211, wlan_alloc, wlan_free);
|
||||
return 0;
|
||||
case MOD_UNLOAD:
|
||||
if_deregister_com_alloc(IFT_IEEE80211);
|
||||
if_clone_detach(wlan_cloner);
|
||||
EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent);
|
||||
EVENTHANDLER_DEREGISTER(iflladdr_event, wlan_ifllevent);
|
||||
return 0;
|
||||
}
|
||||
return EINVAL;
|
||||
|
@ -1329,12 +1329,13 @@ static int
|
||||
setmlme_dropsta(struct ieee80211vap *vap,
|
||||
const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop)
|
||||
{
|
||||
struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ieee80211_node_table *nt = &ic->ic_sta;
|
||||
struct ieee80211_node *ni;
|
||||
int error = 0;
|
||||
|
||||
/* NB: the broadcast address means do 'em all */
|
||||
if (!IEEE80211_ADDR_EQ(mac, vap->iv_ifp->if_broadcastaddr)) {
|
||||
if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) {
|
||||
IEEE80211_NODE_LOCK(nt);
|
||||
ni = ieee80211_find_node_locked(nt, mac);
|
||||
IEEE80211_NODE_UNLOCK(nt);
|
||||
@ -2528,9 +2529,14 @@ ieee80211_scanreq(struct ieee80211vap *vap, struct ieee80211_scan_req *sr)
|
||||
static __noinline int
|
||||
ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ieee80211_scan_req sr; /* XXX off stack? */
|
||||
int error;
|
||||
|
||||
/* NB: parent must be running */
|
||||
if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
|
||||
return ENXIO;
|
||||
|
||||
if (ireq->i_len != sizeof(sr))
|
||||
return EINVAL;
|
||||
error = copyin(ireq->i_data, &sr, sizeof(sr));
|
||||
@ -3294,6 +3300,41 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rebuild the parent's multicast address list after an add/del
|
||||
* of a multicast address for a vap. We have no way to tell
|
||||
* what happened above to optimize the work so we purge the entire
|
||||
* list and rebuild from scratch. This is way expensive.
|
||||
* Note also the half-baked workaround for if_addmulti calling
|
||||
* back to the parent device; there's no way to insert mcast
|
||||
* entries quietly and/or cheaply.
|
||||
*/
|
||||
static void
|
||||
ieee80211_ioctl_updatemulti(struct ieee80211com *ic)
|
||||
{
|
||||
struct ifnet *parent = ic->ic_ifp;
|
||||
struct ieee80211vap *vap;
|
||||
void *ioctl;
|
||||
|
||||
IEEE80211_LOCK(ic);
|
||||
if_delallmulti(parent);
|
||||
ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */
|
||||
parent->if_ioctl = NULL;
|
||||
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
|
||||
struct ifnet *ifp = vap->iv_ifp;
|
||||
struct ifmultiaddr *ifma;
|
||||
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
(void) if_addmulti(parent, ifma->ifma_addr, NULL);
|
||||
}
|
||||
}
|
||||
parent->if_ioctl = ioctl;
|
||||
ieee80211_runtask(ic, &ic->ic_mcast_task);
|
||||
IEEE80211_UNLOCK(ic);
|
||||
}
|
||||
|
||||
int
|
||||
ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
@ -3306,11 +3347,8 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
switch (cmd) {
|
||||
case SIOCSIFFLAGS:
|
||||
IEEE80211_LOCK(ic);
|
||||
if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_PROMISC)
|
||||
ieee80211_promisc(vap, ifp->if_flags & IFF_PROMISC);
|
||||
if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_ALLMULTI)
|
||||
ieee80211_allmulti(vap, ifp->if_flags & IFF_ALLMULTI);
|
||||
vap->iv_ifflags = ifp->if_flags;
|
||||
ieee80211_syncifflag_locked(ic, IFF_PROMISC);
|
||||
ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
/*
|
||||
* Bring ourself up unless we're already operational.
|
||||
@ -3333,7 +3371,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
break;
|
||||
case SIOCADDMULTI:
|
||||
case SIOCDELMULTI:
|
||||
ieee80211_runtask(ic, &ic->ic_mcast_task);
|
||||
ieee80211_ioctl_updatemulti(ic);
|
||||
break;
|
||||
case SIOCSIFMEDIA:
|
||||
case SIOCGIFMEDIA:
|
||||
@ -3389,16 +3427,17 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
/* Pass NDIS ioctls up to the driver */
|
||||
case SIOCGDRVSPEC:
|
||||
case SIOCSDRVSPEC:
|
||||
case SIOCGPRIVATE_0: {
|
||||
struct ifnet *parent = vap->iv_ic->ic_ifp;
|
||||
error = parent->if_ioctl(parent, cmd, data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/*
|
||||
* Pass unknown ioctls first to the driver, and if it
|
||||
* returns ENOTTY, then to the generic Ethernet handler.
|
||||
*/
|
||||
if (ic->ic_ioctl != NULL &&
|
||||
(error = ic->ic_ioctl(ic, cmd, data)) != ENOTTY)
|
||||
break;
|
||||
error = ether_ioctl(ifp, cmd, data);
|
||||
break;
|
||||
}
|
||||
return (error);
|
||||
return error;
|
||||
}
|
||||
|
@ -254,6 +254,10 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m,
|
||||
/* NB: IFQ_HANDOFF reclaims mbuf */
|
||||
ieee80211_free_node(ni);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
} else {
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast);
|
||||
if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
|
||||
}
|
||||
ic->ic_lastdata = ticks;
|
||||
|
||||
@ -426,6 +430,17 @@ ieee80211_vap_transmit(struct ifnet *ifp, struct mbuf *m)
|
||||
{
|
||||
struct ieee80211vap *vap = ifp->if_softc;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ifnet *parent = ic->ic_ifp;
|
||||
|
||||
/* NB: parent must be up and running */
|
||||
if (!IFNET_IS_UP_RUNNING(parent)) {
|
||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
|
||||
"%s: ignore queue, parent %s not up+running\n",
|
||||
__func__, parent->if_xname);
|
||||
m_freem(m);
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
return (ENETDOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
* No data frames go out unless we're running.
|
||||
@ -492,7 +507,6 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
struct mbuf *m, const struct ieee80211_bpf_params *params)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Set node - the caller has taken a reference, so ensure
|
||||
@ -514,10 +528,7 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni,
|
||||
if (params)
|
||||
(void) ieee80211_add_xmit_params(m, params);
|
||||
|
||||
error = ic->ic_raw_xmit(ni, m, params);
|
||||
if (error)
|
||||
if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1);
|
||||
return (error);
|
||||
return (ic->ic_raw_xmit(ni, m, params));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3446,15 +3457,6 @@ ieee80211_tx_complete(struct ieee80211_node *ni, struct mbuf *m, int status)
|
||||
{
|
||||
|
||||
if (ni != NULL) {
|
||||
struct ifnet *ifp = ni->ni_vap->iv_ifp;
|
||||
|
||||
if (status == 0) {
|
||||
if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
|
||||
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
|
||||
if (m->m_flags & M_MCAST)
|
||||
if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
|
||||
} else
|
||||
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
|
||||
if (m->m_flags & M_TXCB)
|
||||
ieee80211_process_callback(ni, m, status);
|
||||
ieee80211_free_node(ni);
|
||||
|
@ -418,6 +418,7 @@ pwrsave_flushq(struct ieee80211_node *ni)
|
||||
struct ieee80211com *ic = ni->ni_ic;
|
||||
struct ieee80211vap *vap = ni->ni_vap;
|
||||
struct ieee80211_psq_head *qhead;
|
||||
struct ifnet *parent, *ifp;
|
||||
struct mbuf *parent_q = NULL, *ifp_q = NULL;
|
||||
struct mbuf *m;
|
||||
|
||||
@ -428,51 +429,59 @@ pwrsave_flushq(struct ieee80211_node *ni)
|
||||
qhead = &psq->psq_head[0]; /* 802.11 frames */
|
||||
if (qhead->head != NULL) {
|
||||
/* XXX could dispatch through vap and check M_ENCAP */
|
||||
parent = vap->iv_ic->ic_ifp;
|
||||
/* XXX need different driver interface */
|
||||
/* XXX bypasses q max and OACTIVE */
|
||||
parent_q = qhead->head;
|
||||
qhead->head = qhead->tail = NULL;
|
||||
qhead->len = 0;
|
||||
}
|
||||
} else
|
||||
parent = NULL;
|
||||
|
||||
qhead = &psq->psq_head[1]; /* 802.3 frames */
|
||||
if (qhead->head != NULL) {
|
||||
ifp = vap->iv_ifp;
|
||||
/* XXX need different driver interface */
|
||||
/* XXX bypasses q max and OACTIVE */
|
||||
ifp_q = qhead->head;
|
||||
qhead->head = qhead->tail = NULL;
|
||||
qhead->len = 0;
|
||||
}
|
||||
} else
|
||||
ifp = NULL;
|
||||
psq->psq_len = 0;
|
||||
IEEE80211_PSQ_UNLOCK(psq);
|
||||
|
||||
/* NB: do this outside the psq lock */
|
||||
/* XXX packets might get reordered if parent is OACTIVE */
|
||||
/* parent frames, should be encapsulated */
|
||||
while (parent_q != NULL) {
|
||||
m = parent_q;
|
||||
parent_q = m->m_nextpkt;
|
||||
m->m_nextpkt = NULL;
|
||||
/* must be encapsulated */
|
||||
KASSERT((m->m_flags & M_ENCAP),
|
||||
("%s: parentq with non-M_ENCAP frame!\n",
|
||||
__func__));
|
||||
/*
|
||||
* For encaped frames, we need to free the node
|
||||
* reference upon failure.
|
||||
*/
|
||||
if (ieee80211_parent_xmitpkt(ic, m) != 0)
|
||||
ieee80211_free_node(ni);
|
||||
if (parent != NULL) {
|
||||
while (parent_q != NULL) {
|
||||
m = parent_q;
|
||||
parent_q = m->m_nextpkt;
|
||||
m->m_nextpkt = NULL;
|
||||
/* must be encapsulated */
|
||||
KASSERT((m->m_flags & M_ENCAP),
|
||||
("%s: parentq with non-M_ENCAP frame!\n",
|
||||
__func__));
|
||||
/*
|
||||
* For encaped frames, we need to free the node
|
||||
* reference upon failure.
|
||||
*/
|
||||
if (ieee80211_parent_xmitpkt(ic, m) != 0)
|
||||
ieee80211_free_node(ni);
|
||||
}
|
||||
}
|
||||
|
||||
/* VAP frames, aren't encapsulated */
|
||||
while (ifp_q != NULL) {
|
||||
m = ifp_q;
|
||||
ifp_q = m->m_nextpkt;
|
||||
m->m_nextpkt = NULL;
|
||||
KASSERT((!(m->m_flags & M_ENCAP)),
|
||||
("%s: vapq with M_ENCAP frame!\n", __func__));
|
||||
(void) ieee80211_vap_xmitpkt(vap, m);
|
||||
if (ifp != NULL) {
|
||||
while (ifp_q != NULL) {
|
||||
m = ifp_q;
|
||||
ifp_q = m->m_nextpkt;
|
||||
m->m_nextpkt = NULL;
|
||||
KASSERT((!(m->m_flags & M_ENCAP)),
|
||||
("%s: vapq with M_ENCAP frame!\n", __func__));
|
||||
(void) ieee80211_vap_xmitpkt(vap, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,23 +122,23 @@ null_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
void
|
||||
ieee80211_proto_attach(struct ieee80211com *ic)
|
||||
{
|
||||
uint8_t hdrlen;
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
|
||||
/* override the 802.3 setting */
|
||||
hdrlen = ic->ic_headroom
|
||||
ifp->if_hdrlen = ic->ic_headroom
|
||||
+ sizeof(struct ieee80211_qosframe_addr4)
|
||||
+ IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN
|
||||
+ IEEE80211_WEP_EXTIVLEN;
|
||||
/* XXX no way to recalculate on ifdetach */
|
||||
if (ALIGN(hdrlen) > max_linkhdr) {
|
||||
if (ALIGN(ifp->if_hdrlen) > max_linkhdr) {
|
||||
/* XXX sanity check... */
|
||||
max_linkhdr = ALIGN(hdrlen);
|
||||
max_linkhdr = ALIGN(ifp->if_hdrlen);
|
||||
max_hdr = max_linkhdr + max_protohdr;
|
||||
max_datalen = MHLEN - max_hdr;
|
||||
}
|
||||
ic->ic_protmode = IEEE80211_PROT_CTSONLY;
|
||||
|
||||
TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ic);
|
||||
TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ifp);
|
||||
TASK_INIT(&ic->ic_mcast_task, 0, update_mcast, ic);
|
||||
TASK_INIT(&ic->ic_promisc_task, 0, update_promisc, ic);
|
||||
TASK_INIT(&ic->ic_chan_task, 0, update_channel, ic);
|
||||
@ -188,10 +188,7 @@ ieee80211_proto_vattach(struct ieee80211vap *vap)
|
||||
int i;
|
||||
|
||||
/* override the 802.3 setting */
|
||||
ifp->if_hdrlen = ic->ic_headroom
|
||||
+ sizeof(struct ieee80211_qosframe_addr4)
|
||||
+ IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN
|
||||
+ IEEE80211_WEP_EXTIVLEN;
|
||||
ifp->if_hdrlen = ic->ic_ifp->if_hdrlen;
|
||||
|
||||
vap->iv_rtsthreshold = IEEE80211_RTS_DEFAULT;
|
||||
vap->iv_fragthreshold = IEEE80211_FRAG_DEFAULT;
|
||||
@ -1158,9 +1155,9 @@ ieee80211_wme_updateparams(struct ieee80211vap *vap)
|
||||
static void
|
||||
parent_updown(void *arg, int npending)
|
||||
{
|
||||
struct ieee80211com *ic = arg;
|
||||
struct ifnet *parent = arg;
|
||||
|
||||
ic->ic_parent(ic);
|
||||
parent->if_ioctl(parent, SIOCSIFFLAGS, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1227,6 +1224,7 @@ ieee80211_start_locked(struct ieee80211vap *vap)
|
||||
{
|
||||
struct ifnet *ifp = vap->iv_ifp;
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ifnet *parent = ic->ic_ifp;
|
||||
|
||||
IEEE80211_LOCK_ASSERT(ic);
|
||||
|
||||
@ -1248,10 +1246,12 @@ ieee80211_start_locked(struct ieee80211vap *vap)
|
||||
* We are not running; if this we are the first vap
|
||||
* to be brought up auto-up the parent if necessary.
|
||||
*/
|
||||
if (ic->ic_nrunning++ == 0) {
|
||||
if (ic->ic_nrunning++ == 0 &&
|
||||
(parent->if_drv_flags & IFF_DRV_RUNNING) == 0) {
|
||||
IEEE80211_DPRINTF(vap,
|
||||
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
|
||||
"%s: up parent %s\n", __func__, ic->ic_name);
|
||||
"%s: up parent %s\n", __func__, parent->if_xname);
|
||||
parent->if_flags |= IFF_UP;
|
||||
ieee80211_runtask(ic, &ic->ic_parent_task);
|
||||
return;
|
||||
}
|
||||
@ -1260,7 +1260,8 @@ ieee80211_start_locked(struct ieee80211vap *vap)
|
||||
* If the parent is up and running, then kick the
|
||||
* 802.11 state machine as appropriate.
|
||||
*/
|
||||
if (vap->iv_roaming != IEEE80211_ROAMING_MANUAL) {
|
||||
if ((parent->if_drv_flags & IFF_DRV_RUNNING) &&
|
||||
vap->iv_roaming != IEEE80211_ROAMING_MANUAL) {
|
||||
if (vap->iv_opmode == IEEE80211_M_STA) {
|
||||
#if 0
|
||||
/* XXX bypasses scan too easily; disable for now */
|
||||
@ -1343,6 +1344,7 @@ ieee80211_stop_locked(struct ieee80211vap *vap)
|
||||
{
|
||||
struct ieee80211com *ic = vap->iv_ic;
|
||||
struct ifnet *ifp = vap->iv_ifp;
|
||||
struct ifnet *parent = ic->ic_ifp;
|
||||
|
||||
IEEE80211_LOCK_ASSERT(ic);
|
||||
|
||||
@ -1352,10 +1354,12 @@ ieee80211_stop_locked(struct ieee80211vap *vap)
|
||||
ieee80211_new_state_locked(vap, IEEE80211_S_INIT, -1);
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
|
||||
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; /* mark us stopped */
|
||||
if (--ic->ic_nrunning == 0) {
|
||||
if (--ic->ic_nrunning == 0 &&
|
||||
(parent->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
IEEE80211_DPRINTF(vap,
|
||||
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
|
||||
"down parent %s\n", ic->ic_name);
|
||||
"down parent %s\n", parent->if_xname);
|
||||
parent->if_flags &= ~IFF_UP;
|
||||
ieee80211_runtask(ic, &ic->ic_parent_task);
|
||||
}
|
||||
}
|
||||
|
@ -56,8 +56,7 @@ void ieee80211_proto_detach(struct ieee80211com *);
|
||||
void ieee80211_proto_vattach(struct ieee80211vap *);
|
||||
void ieee80211_proto_vdetach(struct ieee80211vap *);
|
||||
|
||||
void ieee80211_promisc(struct ieee80211vap *, bool);
|
||||
void ieee80211_allmulti(struct ieee80211vap *, bool);
|
||||
void ieee80211_syncifflag_locked(struct ieee80211com *, int flag);
|
||||
void ieee80211_syncflag(struct ieee80211vap *, int flag);
|
||||
void ieee80211_syncflag_ht(struct ieee80211vap *, int flag);
|
||||
void ieee80211_syncflag_ext(struct ieee80211vap *, int flag);
|
||||
|
@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
@ -486,7 +487,7 @@ ieee80211_setregdomain(struct ieee80211vap *vap,
|
||||
memset(&ic->ic_channels[ic->ic_nchans], 0,
|
||||
(IEEE80211_CHAN_MAX - ic->ic_nchans) *
|
||||
sizeof(struct ieee80211_channel));
|
||||
ieee80211_chan_init(ic);
|
||||
ieee80211_media_init(ic);
|
||||
|
||||
/*
|
||||
* Invalidate channel-related state.
|
||||
|
@ -1706,6 +1706,26 @@ static const struct ieee80211_scanner adhoc_default = {
|
||||
IEEE80211_SCANNER_ALG(ibss, IEEE80211_M_IBSS, adhoc_default);
|
||||
IEEE80211_SCANNER_ALG(ahdemo, IEEE80211_M_AHDEMO, adhoc_default);
|
||||
|
||||
static void
|
||||
ap_force_promisc(struct ieee80211com *ic)
|
||||
{
|
||||
struct ifnet *ifp = ic->ic_ifp;
|
||||
|
||||
IEEE80211_LOCK(ic);
|
||||
/* set interface into promiscuous mode */
|
||||
ifp->if_flags |= IFF_PROMISC;
|
||||
ieee80211_runtask(ic, &ic->ic_promisc_task);
|
||||
IEEE80211_UNLOCK(ic);
|
||||
}
|
||||
|
||||
static void
|
||||
ap_reset_promisc(struct ieee80211com *ic)
|
||||
{
|
||||
IEEE80211_LOCK(ic);
|
||||
ieee80211_syncifflag_locked(ic, IFF_PROMISC);
|
||||
IEEE80211_UNLOCK(ic);
|
||||
}
|
||||
|
||||
static int
|
||||
ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
|
||||
{
|
||||
@ -1721,7 +1741,7 @@ ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
|
||||
st->st_scangen++;
|
||||
st->st_newscan = 1;
|
||||
|
||||
ieee80211_promisc(vap, true);
|
||||
ap_force_promisc(vap->iv_ic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1731,7 +1751,7 @@ ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
|
||||
static int
|
||||
ap_cancel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
|
||||
{
|
||||
ieee80211_promisc(vap, false);
|
||||
ap_reset_promisc(vap->iv_ic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1805,7 +1825,7 @@ ap_end(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ieee80211_promisc(vap, false);
|
||||
ap_reset_promisc(ic);
|
||||
if (ss->ss_flags & (IEEE80211_SCAN_NOPICK | IEEE80211_SCAN_NOJOIN)) {
|
||||
/*
|
||||
* Manual/background scan, don't select+join the
|
||||
|
@ -116,15 +116,16 @@ struct ieee80211_superg;
|
||||
struct ieee80211_frame;
|
||||
|
||||
struct ieee80211com {
|
||||
struct ifnet *ic_ifp; /* associated device */
|
||||
void *ic_softc; /* driver softc */
|
||||
const char *ic_name; /* usually device name */
|
||||
ieee80211_com_lock_t ic_comlock; /* state update lock */
|
||||
ieee80211_tx_lock_t ic_txlock; /* ic/vap TX lock */
|
||||
LIST_ENTRY(ieee80211com) ic_next; /* on global list */
|
||||
TAILQ_HEAD(, ieee80211vap) ic_vaps; /* list of vap instances */
|
||||
int ic_headroom; /* driver tx headroom needs */
|
||||
enum ieee80211_phytype ic_phytype; /* XXX wrong for multi-mode */
|
||||
enum ieee80211_opmode ic_opmode; /* operation mode */
|
||||
struct ifmedia ic_media; /* interface media config */
|
||||
struct callout ic_inact; /* inactivity processing */
|
||||
struct taskqueue *ic_tq; /* deferred state thread */
|
||||
struct task ic_parent_task; /* deferred parent processing */
|
||||
@ -150,7 +151,6 @@ struct ieee80211com {
|
||||
uint8_t ic_allmulti; /* vap's needing all multicast*/
|
||||
uint8_t ic_nrunning; /* vap's marked running */
|
||||
uint8_t ic_curmode; /* current mode */
|
||||
uint8_t ic_macaddr[IEEE80211_ADDR_LEN];
|
||||
uint16_t ic_bintval; /* beacon interval */
|
||||
uint16_t ic_lintval; /* listen interval */
|
||||
uint16_t ic_holdover; /* PM hold over duration */
|
||||
@ -241,11 +241,6 @@ struct ieee80211com {
|
||||
const uint8_t [IEEE80211_ADDR_LEN],
|
||||
const uint8_t [IEEE80211_ADDR_LEN]);
|
||||
void (*ic_vap_delete)(struct ieee80211vap *);
|
||||
/* device specific ioctls */
|
||||
int (*ic_ioctl)(struct ieee80211com *,
|
||||
u_long, void *);
|
||||
/* start/stop device */
|
||||
void (*ic_parent)(struct ieee80211com *);
|
||||
/* operating mode attachment */
|
||||
ieee80211vap_attach ic_vattach[IEEE80211_OPMODE_MAX];
|
||||
/* return hardware/radio capabilities */
|
||||
@ -259,9 +254,6 @@ struct ieee80211com {
|
||||
int (*ic_set_quiet)(struct ieee80211_node *,
|
||||
u_int8_t *quiet_elm);
|
||||
|
||||
/* regular transmit */
|
||||
int (*ic_transmit)(struct ieee80211com *,
|
||||
struct mbuf *);
|
||||
/* send/recv 802.11 management frame */
|
||||
int (*ic_send_mgmt)(struct ieee80211_node *,
|
||||
int, int);
|
||||
@ -359,15 +351,14 @@ struct ieee80211vap {
|
||||
|
||||
TAILQ_ENTRY(ieee80211vap) iv_next; /* list of vap instances */
|
||||
struct ieee80211com *iv_ic; /* back ptr to common state */
|
||||
const uint8_t *iv_myaddr; /* MAC address: ifp or ic */
|
||||
uint32_t iv_debug; /* debug msg flags */
|
||||
struct ieee80211_stats iv_stats; /* statistics */
|
||||
|
||||
uint8_t iv_myaddr[IEEE80211_ADDR_LEN];
|
||||
uint32_t iv_flags; /* state flags */
|
||||
uint32_t iv_flags_ext; /* extended state flags */
|
||||
uint32_t iv_flags_ht; /* HT state flags */
|
||||
uint32_t iv_flags_ven; /* vendor state flags */
|
||||
uint32_t iv_ifflags; /* ifnet flags */
|
||||
uint32_t iv_caps; /* capabilities */
|
||||
uint32_t iv_htcaps; /* HT capabilities */
|
||||
uint32_t iv_htextcaps; /* HT extended capabilities */
|
||||
@ -690,24 +681,24 @@ MALLOC_DECLARE(M_80211_VAP);
|
||||
"\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS"
|
||||
|
||||
int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3);
|
||||
void ieee80211_ifattach(struct ieee80211com *);
|
||||
void ieee80211_ifattach(struct ieee80211com *,
|
||||
const uint8_t macaddr[IEEE80211_ADDR_LEN]);
|
||||
void ieee80211_ifdetach(struct ieee80211com *);
|
||||
int ieee80211_vap_setup(struct ieee80211com *, struct ieee80211vap *,
|
||||
const char name[IFNAMSIZ], int unit,
|
||||
enum ieee80211_opmode opmode, int flags,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN]);
|
||||
int ieee80211_vap_attach(struct ieee80211vap *,
|
||||
ifm_change_cb_t, ifm_stat_cb_t,
|
||||
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
||||
const uint8_t macaddr[IEEE80211_ADDR_LEN]);
|
||||
int ieee80211_vap_attach(struct ieee80211vap *,
|
||||
ifm_change_cb_t, ifm_stat_cb_t);
|
||||
void ieee80211_vap_detach(struct ieee80211vap *);
|
||||
const struct ieee80211_rateset *ieee80211_get_suprates(struct ieee80211com *ic,
|
||||
const struct ieee80211_channel *);
|
||||
void ieee80211_announce(struct ieee80211com *);
|
||||
void ieee80211_announce_channels(struct ieee80211com *);
|
||||
void ieee80211_drain(struct ieee80211com *);
|
||||
void ieee80211_chan_init(struct ieee80211com *);
|
||||
void ieee80211_media_init(struct ieee80211com *);
|
||||
struct ieee80211com *ieee80211_find_vap(const uint8_t mac[IEEE80211_ADDR_LEN]);
|
||||
struct ieee80211com *ieee80211_find_com(const char *name);
|
||||
int ieee80211_media_change(struct ifnet *);
|
||||
void ieee80211_media_status(struct ifnet *, struct ifmediareq *);
|
||||
int ieee80211_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
|
Loading…
x
Reference in New Issue
Block a user