Index: etc/network.subr =================================================================== --- etc/network.subr +++ etc/network.subr @@ -1249,6 +1249,38 @@ fi } +# wlan_up +# Create IEEE802.3 interfaces. +# +wlan_up() +{ + local _list _iflist wlan parent ifn + _list= + _iflist=$* + + for wlan in `set | egrep ^wlans_[a-z]+[0-9]+=[a-z]+[0-9]+`; do + # Parse wlans_$parent=$ifn + wlan=`echo $wlan | sed -E 's/wlans_([a-z]+[0-9]+)=([a-z]+[0-9]+)/\1:\2/'` + OIFS=$IFS; IFS=:; set -- $wlan; parent=$1; ifn=$2; IFS=$OIFS + case $_iflist in + ""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn) ;; + *) continue ;; + esac + # Skip if ${ifn} already exists. + if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then + continue + fi + ${IFCONFIG_CMD} ${ifn} create wlandev ${parent} + if [ $? -eq 0 ]; then + _list="$_list $ifn" + fi + done + if [ -n "${_list# }" ]; then + echo "Created wlan interfaces: ${_list# }." + fi + debug "Wlans: ${_list# }" +} + # clone_up # Create cloneable interfaces. # Index: etc/rc.d/netif =================================================================== --- etc/rc.d/netif +++ etc/rc.d/netif @@ -37,6 +37,7 @@ rcvar="${name}_enable" start_cmd="netif_start" stop_cmd="netif_stop" +wlanup_cmd="wlan_up" cloneup_cmd="clone_up" clonedown_cmd="clone_down" clear_cmd="doclear" @@ -65,6 +66,9 @@ trap : 2 fi + # Create IEEE802.3 interface + wlan_up $cmdifn + # Create cloned interfaces clone_up $cmdifn Index: sys/dev/ath/ath_rate/sample/sample.h =================================================================== --- sys/dev/ath/ath_rate/sample/sample.h +++ sys/dev/ath/ath_rate/sample/sample.h @@ -134,8 +134,7 @@ int long_retries, int is_ht40) { const HAL_RATE_TABLE *rt = sc->sc_currates; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; int rts, cts; unsigned t_slot = 20; Index: sys/dev/ath/ath_rate/sample/sample.c =================================================================== --- sys/dev/ath/ath_rate/sample/sample.c +++ sys/dev/ath/ath_rate/sample/sample.c @@ -488,8 +488,7 @@ #define RATE(ix) (DOT11RATE(ix) / 2) struct sample_node *sn = ATH_NODE_SAMPLE(an); struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; const HAL_RATE_TABLE *rt = sc->sc_currates; const int size_bin = size_to_bin(frameLen); int rix, mrr, best_rix, change_rates; @@ -856,8 +855,7 @@ const struct ath_rc_series *rc, const struct ath_tx_status *ts, int frame_size, int nframes, int nbad) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct sample_node *sn = ATH_NODE_SAMPLE(an); int final_rix, short_tries, long_tries; const HAL_RATE_TABLE *rt = sc->sc_currates; @@ -1303,8 +1301,7 @@ ath_rate_sysctl_stats(SYSCTL_HANDLER_ARGS) { struct ath_softc *sc = arg1; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; int error, v; v = 0; Index: sys/dev/ath/if_ath.c =================================================================== --- sys/dev/ath/if_ath.c +++ sys/dev/ath/if_ath.c @@ -151,15 +151,15 @@ const uint8_t [IEEE80211_ADDR_LEN], const uint8_t [IEEE80211_ADDR_LEN]); static void ath_vap_delete(struct ieee80211vap *); -static void ath_init(void *); -static void ath_stop_locked(struct ifnet *); -static void ath_stop(struct ifnet *); +static void ath_init(struct ath_softc *); +static void ath_stop_locked(struct ath_softc *); +static void ath_stop(struct ath_softc *); static int ath_reset_vap(struct ieee80211vap *, u_long); -static int ath_transmit(struct ifnet *ifp, struct mbuf *m); -static void ath_qflush(struct ifnet *ifp); +static int ath_transmit(struct ieee80211com *, struct mbuf *); static int ath_media_change(struct ifnet *); static void ath_watchdog(void *); -static int ath_ioctl(struct ifnet *, u_long, caddr_t); +static int ath_ioctl(struct ieee80211com *, u_long, void *); +static void ath_parent(struct ieee80211com *); static void ath_fatal_proc(void *, int); static void ath_bmiss_vap(struct ieee80211vap *); static void ath_bmiss_proc(void *, int); @@ -571,34 +571,19 @@ int ath_attach(u_int16_t devid, struct ath_softc *sc) { - struct ifnet *ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = NULL; HAL_STATUS status; int error = 0, i; u_int wmodes; - uint8_t macaddr[IEEE80211_ADDR_LEN]; int rx_chainmask, tx_chainmask; HAL_OPS_CONFIG ah_config; DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid); - CURVNET_SET(vnet0); - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(sc->sc_dev, "can not if_alloc()\n"); - error = ENOSPC; - CURVNET_RESTORE(); - goto bad; - } - ic = ifp->if_l2com; ic->ic_softc = sc; ic->ic_name = device_get_nameunit(sc->sc_dev); - if_initname(ifp, device_get_name(sc->sc_dev), - device_get_unit(sc->sc_dev)); - CURVNET_RESTORE(); - /* * Configure the initial configuration data. * @@ -732,8 +717,8 @@ sc->sc_tq = taskqueue_create("ath_taskq", M_NOWAIT, taskqueue_thread_enqueue, &sc->sc_tq); - taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, - "%s taskq", ifp->if_xname); + taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq", + device_get_nameunit(sc->sc_dev)); TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc); TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc); @@ -876,17 +861,6 @@ ath_led_config(sc); ath_hal_setledstate(ah, HAL_LED_INIT); - ifp->if_softc = sc; - ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; - ifp->if_transmit = ath_transmit; - ifp->if_qflush = ath_qflush; - ifp->if_ioctl = ath_ioctl; - ifp->if_init = ath_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; /* XXX not right but it's not used anywhere important */ ic->ic_phytype = IEEE80211_T_OFDM; ic->ic_opmode = IEEE80211_M_STA; @@ -1208,11 +1182,11 @@ sc->sc_hasveol = ath_hal_hasveol(ah); /* get mac address from kenv first, then hardware */ - if (ath_fetch_mac_kenv(sc, macaddr) == 0) { + if (ath_fetch_mac_kenv(sc, ic->ic_macaddr) == 0) { /* Tell the HAL now about the new MAC */ - ath_hal_setmac(ah, macaddr); + ath_hal_setmac(ah, ic->ic_macaddr); } else { - ath_hal_getmac(ah, macaddr); + ath_hal_getmac(ah, ic->ic_macaddr); } if (sc->sc_hasbmask) @@ -1221,12 +1195,15 @@ /* NB: used to size node table key mapping array */ ic->ic_max_keyix = sc->sc_keymax; /* call MI attach routine. */ - ieee80211_ifattach(ic, macaddr); + ieee80211_ifattach(ic); ic->ic_setregdomain = ath_setregdomain; ic->ic_getradiocaps = ath_getradiocaps; sc->sc_opmode = HAL_M_STA; /* override default methods */ + ic->ic_ioctl = ath_ioctl; + ic->ic_parent = ath_parent; + ic->ic_transmit = ath_transmit; ic->ic_newassoc = ath_newassoc; ic->ic_updateslot = ath_updateslot; ic->ic_wme.wme_update = ath_wme_update; @@ -1322,16 +1299,6 @@ bad: if (ah) ath_hal_detach(ah); - - /* - * To work around scoping issues with CURVNET_SET/CURVNET_RESTORE.. - */ - if (ifp != NULL && ifp->if_vnet) { - CURVNET_SET(ifp->if_vnet); - if_free(ifp); - CURVNET_RESTORE(); - } else if (ifp != NULL) - if_free(ifp); sc->sc_invalid = 1; return error; } @@ -1339,10 +1306,6 @@ int ath_detach(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - - DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n", - __func__, ifp->if_flags); /* * NB: the order of these is important: @@ -1367,14 +1330,14 @@ ATH_LOCK(sc); ath_power_set_power_state(sc, HAL_PM_AWAKE); ath_power_setpower(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); /* * Stop things cleanly. */ - ath_stop(ifp); + ath_stop_locked(sc); + ATH_UNLOCK(sc); - ieee80211_ifdetach(ifp->if_l2com); + ieee80211_ifdetach(&sc->sc_ic); taskqueue_free(sc->sc_tq); #ifdef ATH_TX99_DIAG if (sc->sc_tx99 != NULL) @@ -1394,10 +1357,6 @@ ath_tx_cleanup(sc); ath_hal_detach(sc->sc_ah); /* NB: sets chip in full sleep */ - CURVNET_SET(ifp->if_vnet); - if_free(ifp); - CURVNET_RESTORE(); - return 0; } @@ -1473,7 +1432,7 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac0[IEEE80211_ADDR_LEN]) { - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_vap *avp; struct ieee80211vap *vap; uint8_t mac[IEEE80211_ADDR_LEN]; @@ -1581,8 +1540,7 @@ vap = &avp->av_vap; /* XXX can't hold mutex across if_alloc */ ATH_UNLOCK(sc); - error = ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, - bssid, mac); + error = ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); ATH_LOCK(sc); if (error != 0) { device_printf(sc->sc_dev, "%s: error %d creating vap\n", @@ -1716,7 +1674,8 @@ ATH_UNLOCK(sc); /* complete setup */ - ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status); + ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status, + mac); return vap; bad2: reclaim_address(sc, mac); @@ -1731,8 +1690,7 @@ ath_vap_delete(struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_hal *ah = sc->sc_ah; struct ath_vap *avp = ATH_VAP(vap); @@ -1741,7 +1699,7 @@ ATH_UNLOCK(sc); DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + if (sc->sc_running) { /* * Quiesce the hardware while we remove the vap. In * particular we need to reclaim all references to @@ -1824,7 +1782,7 @@ #endif free(avp, M_80211_VAP); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + if (sc->sc_running) { /* * Restart rx+tx machines if still running (RUNNING will * be reset if we just destroyed the last vap). @@ -1851,13 +1809,9 @@ void ath_suspend(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n", - __func__, ifp->if_flags); + struct ieee80211com *ic = &sc->sc_ic; - sc->sc_resume_up = (ifp->if_flags & IFF_UP) != 0; + sc->sc_resume_up = ic->ic_nrunning != 0; ieee80211_suspend_all(ic); /* @@ -1898,8 +1852,7 @@ static void ath_reset_keycache(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; int i; @@ -1941,8 +1894,7 @@ void ath_resume(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; HAL_STATUS status; @@ -2015,12 +1967,8 @@ void ath_shutdown(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - - DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n", - __func__, ifp->if_flags); - ath_stop(ifp); + ath_stop(sc); /* NB: no point powering down chip as we're about to reboot */ } @@ -2031,7 +1979,6 @@ ath_intr(void *arg) { struct ath_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; struct ath_hal *ah = sc->sc_ah; HAL_INT status = 0; uint32_t txqs; @@ -2070,12 +2017,11 @@ ath_power_set_power_state(sc, HAL_PM_AWAKE); ATH_UNLOCK(sc); - if ((ifp->if_flags & IFF_UP) == 0 || - (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { + if (sc->sc_ic.ic_nrunning == 0 && sc->sc_running == 0) { HAL_INT status; - DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags 0x%x\n", - __func__, ifp->if_flags); + DPRINTF(sc, ATH_DEBUG_ANY, "%s: ic_nrunning %d sc_running %d\n", + __func__, sc->sc_ic.ic_nrunning, sc->sc_running); ath_hal_getisr(ah, &status); /* clear ISR */ ath_hal_intrset(ah, 0); /* disable further intr's */ ATH_PCU_UNLOCK(sc); @@ -2313,7 +2259,6 @@ ath_fatal_proc(void *arg, int pending) { struct ath_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; u_int32_t *state; u_int32_t len; void *sp; @@ -2331,13 +2276,13 @@ "0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n", state[0], state[1] , state[2], state[3], state[4], state[5]); } - ath_reset(ifp, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS); } static void ath_bmiss_vap(struct ieee80211vap *vap) { - struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct ath_softc *sc = vap->iv_ic->ic_softc; /* * Workaround phantom bmiss interrupts by sanity-checking @@ -2358,8 +2303,6 @@ ATH_UNLOCK(sc); if ((vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) == 0) { - struct ifnet *ifp = vap->iv_ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; u_int64_t lastrx = sc->sc_lastrx; u_int64_t tsf = ath_hal_gettsf64(sc->sc_ah); /* XXX should take a locked ref to iv_bss */ @@ -2417,7 +2360,6 @@ ath_bmiss_proc(void *arg, int pending) { struct ath_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; uint32_t hangs; DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending); @@ -2435,12 +2377,12 @@ * to clear. */ if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) { - ath_reset(ifp, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS); device_printf(sc->sc_dev, "bb hang detected (0x%x), resetting\n", hangs); } else { - ath_reset(ifp, ATH_RESET_NOLOSS); - ieee80211_beacon_miss(ifp->if_l2com); + ath_reset(sc, ATH_RESET_NOLOSS); + ieee80211_beacon_miss(&sc->sc_ic); } /* Force a beacon resync, in case they've drifted */ @@ -2460,8 +2402,7 @@ static void ath_settkipmic(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; if ((ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP) && !sc->sc_wmetkipmic) { if (ic->ic_flags & IEEE80211_F_WME) { @@ -2475,11 +2416,9 @@ } static void -ath_init(void *arg) +ath_init(struct ath_softc *sc) { - struct ath_softc *sc = (struct ath_softc *) arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; HAL_STATUS status; @@ -2498,7 +2437,7 @@ * Stop anything previously setup. This is safe * whether this is the first time through or not. */ - ath_stop_locked(ifp); + ath_stop_locked(sc); /* * The basic interface to setting the hardware in a good @@ -2624,7 +2563,7 @@ DPRINTF(sc, ATH_DEBUG_RESET, "%s: imask=0x%x\n", __func__, sc->sc_imask); - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_running = 1; callout_reset(&sc->sc_wd_ch, hz, ath_watchdog, sc); ath_hal_intrset(ah, sc->sc_imask); @@ -2640,14 +2579,10 @@ } static void -ath_stop_locked(struct ifnet *ifp) +ath_stop_locked(struct ath_softc *sc) { - struct ath_softc *sc = ifp->if_softc; struct ath_hal *ah = sc->sc_ah; - DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n", - __func__, sc->sc_invalid, ifp->if_flags); - ATH_LOCK_ASSERT(sc); /* @@ -2655,7 +2590,7 @@ */ ath_power_set_power_state(sc, HAL_PM_AWAKE); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + if (sc->sc_running) { /* * Shutdown the hardware and driver: * reset 802.11 state machine @@ -2677,7 +2612,7 @@ #endif callout_stop(&sc->sc_wd_ch); sc->sc_wd_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + sc->sc_running = 0; if (!sc->sc_invalid) { if (sc->sc_softled) { callout_stop(&sc->sc_ledtimer); @@ -2829,12 +2764,11 @@ */ static void -ath_stop(struct ifnet *ifp) +ath_stop(struct ath_softc *sc) { - struct ath_softc *sc = ifp->if_softc; - + ATH_LOCK(sc); - ath_stop_locked(ifp); + ath_stop_locked(sc); ATH_UNLOCK(sc); } @@ -2846,10 +2780,9 @@ * to reset or reload hardware state. */ int -ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) +ath_reset(struct ath_softc *sc, ATH_RESET_TYPE reset_type) { - struct ath_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; HAL_STATUS status; int i; @@ -3011,15 +2944,6 @@ } } - /* - * This may have been set during an ath_start() call which - * set this once it detected a concurrent TX was going on. - * So, clear it. - */ - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - ATH_LOCK(sc); ath_power_restore_power_state(sc); ATH_UNLOCK(sc); @@ -3041,8 +2965,7 @@ ath_reset_vap(struct ieee80211vap *vap, u_long cmd) { struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_hal *ah = sc->sc_ah; switch (cmd) { @@ -3057,7 +2980,7 @@ return 0; } /* XXX? Full or NOLOSS? */ - return ath_reset(ifp, ATH_RESET_FULL); + return ath_reset(sc, ATH_RESET_FULL); } struct ath_buf * @@ -3217,24 +3140,12 @@ bf = _ath_getbuf_locked(sc, ATH_BUFTYPE_NORMAL); ATH_TXBUF_UNLOCK(sc); if (bf == NULL) { - struct ifnet *ifp = sc->sc_ifp; - DPRINTF(sc, ATH_DEBUG_XMIT, "%s: stop queue\n", __func__); sc->sc_stats.ast_tx_qstop++; - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); } return bf; } -static void -ath_qflush(struct ifnet *ifp) -{ - - /* XXX TODO */ -} - /* * Transmit a single frame. * @@ -3242,10 +3153,9 @@ * fails, so don't free the node reference here. */ static int -ath_transmit(struct ifnet *ifp, struct mbuf *m) +ath_transmit(struct ieee80211com *ic, struct mbuf *m) { - struct ieee80211com *ic = ifp->if_l2com; - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ieee80211_node *ni; struct mbuf *next; struct ath_buf *bf; @@ -3260,10 +3170,7 @@ DPRINTF(sc, ATH_DEBUG_XMIT, "%s: sc_inreset_cnt > 0; bailing\n", __func__); ATH_PCU_UNLOCK(sc); - IF_LOCK(&ifp->if_snd); sc->sc_stats.ast_tx_qstop++; - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_task: OACTIVE, finish"); return (ENOBUFS); /* XXX should be EINVAL or? */ } @@ -3303,8 +3210,6 @@ if ((!(m->m_flags & M_EAPOL)) && (ATH_NODE(ni)->an_swq_depth > sc->sc_txq_node_maxdepth)) { sc->sc_stats.ast_tx_nodeq_overflow++; - m_freem(m); - m = NULL; retval = ENOBUFS; goto finish; } @@ -3328,8 +3233,6 @@ if ((!(m->m_flags & M_EAPOL)) && (sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree)) { sc->sc_stats.ast_tx_nobuf++; - m_freem(m); - m = NULL; retval = ENOBUFS; goto finish; } @@ -3357,11 +3260,6 @@ * above. */ sc->sc_stats.ast_tx_nobuf++; - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - m_freem(m); - m = NULL; retval = ENOBUFS; goto finish; } @@ -3383,8 +3281,13 @@ DPRINTF(sc, ATH_DEBUG_XMIT, "%s: out of txfrag buffers\n", __func__); sc->sc_stats.ast_tx_nofrag++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); + /* + * XXXGL: is mbuf valid after ath_txfrag_setup? If yes, + * we shouldn't free it but return back. + */ ath_freetx(m); + m = NULL; goto bad; } @@ -3426,12 +3329,6 @@ } } - /* - * Bump the ifp output counter. - * - * XXX should use atomics? - */ - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); nextfrag: /* * Pass the frame to the h/w for transmission. @@ -3451,7 +3348,7 @@ next = m->m_nextpkt; if (ath_tx_start(sc, ni, bf, m)) { bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); reclaim: bf->bf_m = NULL; bf->bf_node = NULL; @@ -3535,8 +3432,7 @@ static void ath_key_update_begin(struct ieee80211vap *vap) { - struct ifnet *ifp = vap->iv_ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; + struct ath_softc *sc = vap->iv_ic->ic_softc; DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); taskqueue_block(sc->sc_tq); @@ -3545,8 +3441,7 @@ static void ath_key_update_end(struct ieee80211vap *vap) { - struct ifnet *ifp = vap->iv_ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; + struct ath_softc *sc = vap->iv_ic->ic_softc; DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); taskqueue_unblock(sc->sc_tq); @@ -3577,32 +3472,41 @@ static void ath_update_mcast_hw(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; u_int32_t mfilt[2]; /* calculate and install multicast filter */ - if ((ifp->if_flags & IFF_ALLMULTI) == 0) { + if (ic->ic_allmulti == 0) { + struct ieee80211vap *vap; + struct ifnet *ifp; struct ifmultiaddr *ifma; + /* * Merge multicast addresses to form the hardware filter. */ mfilt[0] = mfilt[1] = 0; - if_maddr_rlock(ifp); /* XXX need some fiddling to remove? */ - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - caddr_t dl; - u_int32_t val; - u_int8_t pos; - - /* calculate XOR of eight 6bit values */ - dl = LLADDR((struct sockaddr_dl *) ifma->ifma_addr); - val = LE_READ_4(dl + 0); - pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - val = LE_READ_4(dl + 3); - pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - pos &= 0x3f; - mfilt[pos / 32] |= (1 << (pos % 32)); + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { + ifp = vap->iv_ifp; + if_maddr_rlock(ifp); + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + caddr_t dl; + uint32_t val; + uint8_t pos; + + /* calculate XOR of eight 6bit values */ + dl = LLADDR((struct sockaddr_dl *) + ifma->ifma_addr); + val = LE_READ_4(dl + 0); + pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ + val; + val = LE_READ_4(dl + 3); + pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ + val; + pos &= 0x3f; + mfilt[pos / 32] |= (1 << (pos % 32)); + } + if_maddr_runlock(ifp); } - if_maddr_runlock(ifp); } else mfilt[0] = mfilt[1] = ~0; @@ -3635,7 +3539,7 @@ void ath_mode_init(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; u_int32_t rfilt; @@ -3646,15 +3550,8 @@ /* configure operational mode */ ath_hal_setopmode(ah); - DPRINTF(sc, ATH_DEBUG_STATE | ATH_DEBUG_MODE, - "%s: ah=%p, ifp=%p, if_addr=%p\n", - __func__, - ah, - ifp, - (ifp == NULL) ? NULL : ifp->if_addr); - /* handle any link-level address change */ - ath_hal_setmac(ah, IF_LLADDR(ifp)); + ath_hal_setmac(ah, ic->ic_macaddr); /* calculate and install multicast filter */ ath_update_mcast_hw(sc); @@ -3666,7 +3563,7 @@ void ath_setslottime(struct ath_softc *sc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; u_int usec; @@ -3750,12 +3647,11 @@ ath_reset_proc(void *arg, int pending) { struct ath_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; #if 0 device_printf(sc->sc_dev, "%s: resetting\n", __func__); #endif - ath_reset(ifp, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS); } /* @@ -3765,7 +3661,6 @@ ath_bstuck_proc(void *arg, int pending) { struct ath_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; uint32_t hangs = 0; if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) @@ -3783,7 +3678,7 @@ * This assumes that there's no simultaneous channel mode change * occuring. */ - ath_reset(ifp, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS); } static void @@ -4153,7 +4048,7 @@ ath_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) { struct ieee80211com *ic = vap->iv_ic; - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space; struct ath_node *an; @@ -4180,7 +4075,7 @@ ath_node_cleanup(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__, ni->ni_macaddr, ":", ATH_NODE(ni)); @@ -4195,7 +4090,7 @@ ath_node_free(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__, ni->ni_macaddr, ":", ATH_NODE(ni)); @@ -4207,7 +4102,7 @@ ath_node_getsignal(const struct ieee80211_node *ni, int8_t *rssi, int8_t *noise) { struct ieee80211com *ic = ni->ni_ic; - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_hal *ah = sc->sc_ah; *rssi = ic->ic_node_getrssi(ni); @@ -4345,8 +4240,7 @@ { #define ATH_EXPONENT_TO_VALUE(v) ((1<sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ath_txq *txq = sc->sc_ac2q[ac]; struct wmeParams *wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac]; struct ath_hal *ah = sc->sc_ah; @@ -4419,7 +4313,7 @@ int ath_wme_update(struct ieee80211com *ic) { - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; return !ath_txq_update(sc, WME_AC_BE) || !ath_txq_update(sc, WME_AC_BK) || @@ -4470,8 +4364,7 @@ struct ath_buf *bf) { struct ieee80211_node *ni = bf->bf_node; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; int sr, lr, pri; if (ts->ts_status == 0) { @@ -4826,7 +4719,6 @@ ath_tx_proc_q0(void *arg, int npending) { struct ath_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; uint32_t txqs; ATH_PCU_LOCK(sc); @@ -4847,9 +4739,6 @@ sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah); if (TXQACTIVE(txqs, sc->sc_cabq->axq_qnum)) ath_tx_processq(sc, sc->sc_cabq, 1); - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); sc->sc_wd_timer = 0; if (sc->sc_softled) @@ -4874,7 +4763,6 @@ ath_tx_proc_q0123(void *arg, int npending) { struct ath_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; int nacked; uint32_t txqs; @@ -4908,9 +4796,6 @@ if (nacked) sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah); - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); sc->sc_wd_timer = 0; if (sc->sc_softled) @@ -4934,7 +4819,6 @@ ath_tx_proc(void *arg, int npending) { struct ath_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; int i, nacked; uint32_t txqs; @@ -4960,10 +4844,6 @@ if (nacked) sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah); - /* XXX check this inside of IF_LOCK? */ - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); sc->sc_wd_timer = 0; if (sc->sc_softled) @@ -5274,7 +5154,7 @@ txq->axq_aggr_depth--; #ifdef ATH_DEBUG if (sc->sc_debug & ATH_DEBUG_RESET) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; int status = 0; /* @@ -5419,9 +5299,8 @@ ath_legacy_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type) { struct ath_hal *ah = sc->sc_ah; - struct ifnet *ifp = sc->sc_ifp; - int i; struct ath_buf *bf_last; + int i; (void) ath_stoptxdma(sc); @@ -5473,15 +5352,12 @@ ath_printtxbuf(sc, bf, sc->sc_bhalq, 0, ath_hal_txprocdesc(ah, bf->bf_lastds, &bf->bf_status.ds_txstat) == HAL_OK); - ieee80211_dump_pkt(ifp->if_l2com, + ieee80211_dump_pkt(&sc->sc_ic, mtod(bf->bf_m, const uint8_t *), bf->bf_m->m_len, 0, -1); } } #endif /* ATH_DEBUG */ - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); sc->sc_wd_timer = 0; } @@ -5512,8 +5388,7 @@ static int ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; int ret = 0; @@ -5648,9 +5523,6 @@ ath_hal_intrset(ah, sc->sc_imask); ATH_PCU_UNLOCK(sc); - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); ath_txrx_start(sc); /* XXX ath_start? */ @@ -5666,8 +5538,7 @@ { struct ath_softc *sc = arg; struct ath_hal *ah = sc->sc_ah; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; HAL_BOOL longCal, isCalDone = AH_TRUE; HAL_BOOL aniCal, shortCal = AH_FALSE; int nextcal; @@ -5793,12 +5664,12 @@ static void ath_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_hal *ah = sc->sc_ah; u_int32_t rfilt; /* XXX calibration timer? */ + /* XXXGL: is constant ieee80211broadcastaddr a correct choice? */ ATH_LOCK(sc); sc->sc_scanning = 1; @@ -5808,18 +5679,17 @@ ATH_PCU_LOCK(sc); ath_hal_setrxfilter(ah, rfilt); - ath_hal_setassocid(ah, ifp->if_broadcastaddr, 0); + ath_hal_setassocid(ah, ieee80211broadcastaddr, 0); ATH_PCU_UNLOCK(sc); DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0\n", - __func__, rfilt, ether_sprintf(ifp->if_broadcastaddr)); + __func__, rfilt, ether_sprintf(ieee80211broadcastaddr)); } static void ath_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_hal *ah = sc->sc_ah; u_int32_t rfilt; @@ -5859,8 +5729,7 @@ static void ath_update_chw(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; DPRINTF(sc, ATH_DEBUG_STATE, "%s: called\n", __func__); ath_set_channel(ic); @@ -5870,8 +5739,7 @@ static void ath_set_channel(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; ATH_LOCK(sc); ath_power_set_power_state(sc, HAL_PM_AWAKE); @@ -5913,7 +5781,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct ieee80211com *ic = vap->iv_ic; - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_vap *avp = ATH_VAP(vap); struct ath_hal *ah = sc->sc_ah; struct ieee80211_node *ni = NULL; @@ -6249,7 +6117,7 @@ ath_setup_stationkey(struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; - struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct ath_softc *sc = vap->iv_ic->ic_softc; ieee80211_keyix keyix, rxkeyix; /* XXX should take a locked ref to vap->iv_bss */ @@ -6282,7 +6150,7 @@ { struct ath_node *an = ATH_NODE(ni); struct ieee80211vap *vap = ni->ni_vap; - struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct ath_softc *sc = vap->iv_ic->ic_softc; const struct ieee80211_txparam *tp = ni->ni_txparms; an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate); @@ -6334,7 +6202,7 @@ ath_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *reg, int nchans, struct ieee80211_channel chans[]) { - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_hal *ah = sc->sc_ah; HAL_STATUS status; @@ -6358,7 +6226,7 @@ ath_getradiocaps(struct ieee80211com *ic, int maxchans, int *nchans, struct ieee80211_channel chans[]) { - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_hal *ah = sc->sc_ah; DPRINTF(sc, ATH_DEBUG_REGDOMAIN, "%s: use rd %u cc %d\n", @@ -6373,8 +6241,7 @@ static int ath_getchannels(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; HAL_STATUS status; @@ -6536,12 +6403,12 @@ ath_watchdog(void *arg) { struct ath_softc *sc = arg; + struct ieee80211com *ic = &sc->sc_ic; int do_reset = 0; ATH_LOCK_ASSERT(sc); if (sc->sc_wd_timer != 0 && --sc->sc_wd_timer == 0) { - struct ifnet *ifp = sc->sc_ifp; uint32_t hangs; ath_power_set_power_state(sc, HAL_PM_AWAKE); @@ -6553,7 +6420,7 @@ } else device_printf(sc->sc_dev, "device timeout\n"); do_reset = 1; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(ic->ic_oerrors, 1); sc->sc_stats.ast_watchdog++; ath_power_restore_power_state(sc); @@ -6579,7 +6446,7 @@ ath_ioctl_ratestats(struct ath_softc *sc, struct ath_rateioctl *rs) { struct ath_node *an; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; int error = 0; @@ -6685,31 +6552,23 @@ } #endif /* ATH_DIAGAPI */ -static int -ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +ath_parent(struct ieee80211com *ic) { -#define IS_RUNNING(ifp) \ - ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) - struct ath_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *)data; - const HAL_RATE_TABLE *rt; - int error = 0; + struct ath_softc *sc = ic->ic_softc; - switch (cmd) { - case SIOCSIFFLAGS: - if (IS_RUNNING(ifp)) { - /* - * To avoid rescanning another access point, - * do not call ath_init() here. Instead, - * only reflect promisc mode settings. - */ - ATH_LOCK(sc); + ATH_LOCK(sc); + if (ic->ic_nrunning > 0) { + /* + * To avoid rescanning another access point, + * do not call ath_init() here. Instead, + * only reflect promisc mode settings. + */ + if (sc->sc_running) { ath_power_set_power_state(sc, HAL_PM_AWAKE); ath_mode_init(sc); ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - } else if (ifp->if_flags & IFF_UP) { + } else if (!sc->sc_invalid) { /* * Beware of being called during attach/detach * to reset promiscuous mode. In that case we @@ -6719,26 +6578,40 @@ * 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 */ - } else { - ATH_LOCK(sc); - ath_stop_locked(ifp); - if (!sc->sc_invalid) - ath_power_setpower(sc, HAL_PM_FULL_SLEEP); ATH_UNLOCK(sc); + ath_init(sc); /* XXX lose error */ + return; } - break; - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - case SIOCGATHSTATS: + } else { + ath_stop_locked(sc); + if (!sc->sc_invalid) + ath_power_setpower(sc, HAL_PM_FULL_SLEEP); + } + ATH_UNLOCK(sc); +} + +static int +ath_ioctl(struct ieee80211com *ic, u_long cmd, void *data) +{ + struct ifreq *ifr = data; + struct ath_softc *sc = ic->ic_softc; + + switch (cmd) { + case SIOCGATHSTATS: { + struct ieee80211vap *vap; + struct ifnet *ifp; + const HAL_RATE_TABLE *rt; + /* NB: embed these numbers to get a consistent view */ - sc->sc_stats.ast_tx_packets = ifp->if_get_counter(ifp, - IFCOUNTER_OPACKETS); - sc->sc_stats.ast_rx_packets = ifp->if_get_counter(ifp, - IFCOUNTER_IPACKETS); + sc->sc_stats.ast_tx_packets = 0; + sc->sc_stats.ast_rx_packets = 0; + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { + ifp = vap->iv_ifp; + sc->sc_stats.ast_tx_packets += ifp->if_get_counter(ifp, + IFCOUNTER_OPACKETS); + sc->sc_stats.ast_rx_packets += ifp->if_get_counter(ifp, + IFCOUNTER_IPACKETS); + } sc->sc_stats.ast_tx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgtxrssi); sc->sc_stats.ast_rx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgrssi); #ifdef IEEE80211_SUPPORT_TDMA @@ -6752,10 +6625,13 @@ sc->sc_stats.ast_tx_rate |= IEEE80211_RATE_MCS; return copyout(&sc->sc_stats, ifr->ifr_data, sizeof (sc->sc_stats)); + } case SIOCGATHAGSTATS: return copyout(&sc->sc_aggr_stats, ifr->ifr_data, sizeof (sc->sc_aggr_stats)); - case SIOCZATHSTATS: + case SIOCZATHSTATS: { + int error; + error = priv_check(curthread, PRIV_DRIVER); if (error == 0) { memset(&sc->sc_stats, 0, sizeof(sc->sc_stats)); @@ -6764,30 +6640,21 @@ memset(&sc->sc_intr_stats, 0, sizeof(sc->sc_intr_stats)); } - break; + return (error); + } #ifdef ATH_DIAGAPI case SIOCGATHDIAG: - error = ath_ioctl_diag(sc, (struct ath_diag *) ifr); - break; + return (ath_ioctl_diag(sc, data)); case SIOCGATHPHYERR: - error = ath_ioctl_phyerr(sc,(struct ath_diag*) ifr); - break; + return (ath_ioctl_phyerr(sc, data)); #endif case SIOCGATHSPECTRAL: - error = ath_ioctl_spectral(sc,(struct ath_diag*) ifr); - break; + return (ath_ioctl_spectral(sc, data)); case SIOCGATHNODERATESTATS: - error = ath_ioctl_ratestats(sc, (struct ath_rateioctl *) ifr); - break; - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; + return (ath_ioctl_ratestats(sc, data)); default: - error = EINVAL; - break; + return (ENOTTY); } - return error; -#undef IS_RUNNING } /* @@ -6828,8 +6695,7 @@ ath_dfs_tasklet(void *p, int npending) { struct ath_softc *sc = (struct ath_softc *) p; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; /* * If previous processing has found a radar event, @@ -6861,7 +6727,7 @@ #ifdef ATH_SW_PSQ struct ath_node *an = ATH_NODE(ni); struct ieee80211com *ic = ni->ni_ic; - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_vap *avp = ATH_VAP(ni->ni_vap); /* XXX and no TXQ locks should be held here */ @@ -6928,7 +6794,7 @@ { #ifdef ATH_SW_PSQ struct ieee80211com *ic = ni->ni_ic; - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_node *an = ATH_NODE(ni); struct ath_vap *avp = ATH_VAP(ni->ni_vap); int changed = 0; @@ -7133,7 +6999,7 @@ struct ath_node *an; struct ath_vap *avp; struct ieee80211com *ic = ni->ni_ic; - struct ath_softc *sc = ic->ic_ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; int tid; /* Just paranoia */ Index: sys/dev/ath/if_ath_beacon.c =================================================================== --- sys/dev/ath/if_ath_beacon.c +++ sys/dev/ath/if_ath_beacon.c @@ -134,7 +134,7 @@ ath_beaconq_config(struct ath_softc *sc) { #define ATH_EXPONENT_TO_VALUE(v) ((1<<(v))-1) - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; HAL_TXQ_INFO qi; @@ -464,7 +464,7 @@ } if (sc->sc_stagbeacons) { /* staggered beacons */ - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tsftu; tsftu = ath_hal_gettsf32(ah) >> 10; @@ -917,7 +917,7 @@ ((((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_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; u_int32_t nexttbtt, intval, tsftu; u_int32_t nexttbtt_u8, intval_u8; Index: sys/dev/ath/if_ath_debug.h =================================================================== --- sys/dev/ath/if_ath_debug.h +++ sys/dev/ath/if_ath_debug.h @@ -91,9 +91,7 @@ extern uint64_t ath_debug; -#define IFF_DUMPPKTS(sc, m) \ - ((sc->sc_debug & (m)) || \ - (sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) +#define IFF_DUMPPKTS(sc, m) ((sc->sc_debug & (m)) #define DPRINTF(sc, m, fmt, ...) do { \ if (sc->sc_debug & (m)) \ device_printf(sc->sc_dev, fmt, __VA_ARGS__); \ @@ -112,8 +110,7 @@ #else /* ATH_DEBUG */ #define ATH_KTR(_sc, _km, _kf, ...) do { } while (0) -#define IFF_DUMPPKTS(sc, m) \ - ((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2)) +#define IFF_DUMPPKTS(sc, m) (0) #define DPRINTF(sc, m, fmt, ...) do { \ (void) sc; \ } while (0) Index: sys/dev/ath/if_ath_keycache.c =================================================================== --- sys/dev/ath/if_ath_keycache.c +++ sys/dev/ath/if_ath_keycache.c @@ -425,7 +425,7 @@ ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) { - struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct ath_softc *sc = vap->iv_ic->ic_softc; /* * Group key allocation must be handled specially for @@ -493,7 +493,7 @@ int ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) { - struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct ath_softc *sc = vap->iv_ic->ic_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 @@ 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_ifp->if_softc; + struct ath_softc *sc = vap->iv_ic->ic_softc; return ath_keyset(sc, vap, k, vap->iv_bss); } Index: sys/dev/ath/if_ath_misc.h =================================================================== --- sys/dev/ath/if_ath_misc.h +++ sys/dev/ath/if_ath_misc.h @@ -65,7 +65,7 @@ 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 ifnet *, ATH_RESET_TYPE); +extern int ath_reset(struct ath_softc *, 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, Index: sys/dev/ath/if_ath_rx.c =================================================================== --- sys/dev/ath/if_ath_rx.c +++ sys/dev/ath/if_ath_rx.c @@ -154,8 +154,7 @@ u_int32_t ath_calcrxfilter(struct ath_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; u_int32_t rfilt; rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST; @@ -164,7 +163,7 @@ if (ic->ic_opmode != IEEE80211_M_STA) rfilt |= HAL_RX_FILTER_PROBEREQ; /* XXX ic->ic_monvaps != 0? */ - if (ic->ic_opmode == IEEE80211_M_MONITOR || (ifp->if_flags & IFF_PROMISC)) + if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_promisc > 0) rfilt |= HAL_RX_FILTER_PROM; /* @@ -330,7 +329,7 @@ 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_ifp->if_softc; + struct ath_softc *sc = vap->iv_ic->ic_softc; uint64_t tsf_beacon_old, tsf_beacon; uint64_t nexttbtt; int64_t tsf_delta; @@ -463,10 +462,9 @@ #ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT static void -ath_rx_tap_vendor(struct ifnet *ifp, struct mbuf *m, +ath_rx_tap_vendor(struct ath_softc *sc, 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); @@ -529,14 +527,13 @@ #endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */ static void -ath_rx_tap(struct ifnet *ifp, struct mbuf *m, +ath_rx_tap(struct ath_softc *sc, 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; @@ -560,7 +557,7 @@ 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 = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; if ((rs->rs_flags & HAL_RX_2040) == 0) sc->sc_rx_th.wr_chan_flags |= CHAN_HT20; @@ -617,8 +614,7 @@ { uint64_t rstamp; int len, type; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; int is_good = 0; struct ath_rx_edma *re = &sc->sc_rxedma[qtype]; @@ -704,7 +700,7 @@ rs->rs_keyix-32 : rs->rs_keyix); } } - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); rx_error: /* * Cleanup any pending partial frame. @@ -724,9 +720,9 @@ /* NB: bpf needs the mbuf length setup */ len = rs->rs_datalen; m->m_pkthdr.len = m->m_len = len; - ath_rx_tap(ifp, m, rs, rstamp, nf); + ath_rx_tap(sc, m, rs, rstamp, nf); #ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT - ath_rx_tap_vendor(ifp, m, rs, rstamp, nf); + ath_rx_tap_vendor(sc, m, rs, rstamp, nf); #endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */ ieee80211_radiotap_rx_all(ic, m); } @@ -749,7 +745,6 @@ 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; @@ -766,10 +761,8 @@ re->m_rxpending = NULL; } else { /* - * Normal single-descriptor receive; setup - * the rcvif and packet length. + * Normal single-descriptor receive; setup packet length. */ - m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = len; } @@ -830,7 +823,6 @@ rs->rs_antenna |= 0x4; } - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); sc->sc_stats.ast_ant_rx[rs->rs_antenna]++; /* @@ -841,9 +833,9 @@ * noise setting is filled in above. */ if (ieee80211_radiotap_active(ic)) { - ath_rx_tap(ifp, m, rs, rstamp, nf); + ath_rx_tap(sc, m, rs, rstamp, nf); #ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT - ath_rx_tap_vendor(ifp, m, rs, rstamp, nf); + ath_rx_tap_vendor(sc, m, rs, rstamp, nf); #endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */ } @@ -991,10 +983,9 @@ ((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 = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; #endif struct ath_desc *ds; struct ath_rx_status *rs; @@ -1189,15 +1180,10 @@ 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. @@ -1219,7 +1205,7 @@ sc->sc_rxproc_cnt--; ATH_PCU_UNLOCK(sc); } - +#undef PA2DESC #undef ATH_RX_MAX /* Index: sys/dev/ath/if_ath_rx_edma.c =================================================================== --- sys/dev/ath/if_ath_rx_edma.c +++ sys/dev/ath/if_ath_rx_edma.c @@ -579,9 +579,8 @@ 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 = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; #endif DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called; npending=%d\n", @@ -617,14 +616,9 @@ 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); Index: sys/dev/ath/if_ath_sysctl.c =================================================================== --- sys/dev/ath/if_ath_sysctl.c +++ sys/dev/ath/if_ath_sysctl.c @@ -288,7 +288,6 @@ ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS) { struct ath_softc *sc = arg1; - struct ifnet *ifp = sc->sc_ifp; u_int32_t scale; int error; @@ -297,8 +296,7 @@ if (error || !req->newptr) return error; return !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL : - (ifp->if_drv_flags & IFF_DRV_RUNNING) ? - ath_reset(ifp, ATH_RESET_NOLOSS) : 0; + (sc->sc_running) ? ath_reset(sc, ATH_RESET_NOLOSS) : 0; } static int @@ -318,7 +316,6 @@ 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 = ath_hal_getrfkill(ah); int error; @@ -330,8 +327,7 @@ return 0; if (!ath_hal_setrfkill(ah, rfkill)) return EINVAL; - return (ifp->if_drv_flags & IFF_DRV_RUNNING) ? - ath_reset(ifp, ATH_RESET_FULL) : 0; + return (sc->sc_running ? ath_reset(sc, ATH_RESET_FULL) : 0); } static int @@ -508,8 +504,8 @@ * doesn't reset ANI related registers, so it'll leave * things in an inconsistent state. */ - if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) - ath_reset(sc->sc_ifp, ATH_RESET_NOLOSS); + if (sc->sc_running) + ath_reset(sc, ATH_RESET_NOLOSS); return 0; } Index: sys/dev/ath/if_ath_tdma.c =================================================================== --- sys/dev/ath/if_ath_tdma.c +++ sys/dev/ath/if_ath_tdma.c @@ -359,7 +359,7 @@ #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_ifp->if_softc; + struct ath_softc *sc = ic->ic_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; Index: sys/dev/ath/if_ath_tx.c =================================================================== --- sys/dev/ath/if_ath_tx.c +++ sys/dev/ath/if_ath_tx.c @@ -1051,8 +1051,7 @@ uint16_t flags; int shortPreamble; const HAL_RATE_TABLE *rt = sc->sc_currates; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; flags = bf->bf_state.bfs_txflags; rix = bf->bf_state.bfs_rc[0].rix; @@ -1545,8 +1544,7 @@ { struct ieee80211vap *vap = ni->ni_vap; struct ath_hal *ah = sc->sc_ah; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams; int error, iswep, ismcast, isfrag, ismrr; int keyix, hdrlen, pktlen, try0 = 0; @@ -2074,8 +2072,7 @@ struct ath_buf *bf, struct mbuf *m0, const struct ieee80211_bpf_params *params) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; struct ieee80211vap *vap = ni->ni_vap; int error, ismcast, ismrr; @@ -2340,8 +2337,7 @@ const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ath_softc *sc = ifp->if_softc; + struct ath_softc *sc = ic->ic_softc; struct ath_buf *bf; struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); int error = 0; @@ -2364,10 +2360,9 @@ ATH_TX_LOCK(sc); - 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"); + 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); m_freem(m); error = ENETDOWN; goto bad; @@ -2424,7 +2419,6 @@ } } sc->sc_wd_timer = 5; - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); sc->sc_stats.ast_tx_raw++; /* @@ -2473,7 +2467,6 @@ 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); @@ -5731,7 +5724,7 @@ 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_ifp->if_softc; + struct ath_softc *sc = ni->ni_ic->ic_softc; int tid = tap->txa_tid; struct ath_node *an = ATH_NODE(ni); struct ath_tid *atid = &an->an_tid[tid]; @@ -5809,7 +5802,7 @@ 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_ifp->if_softc; + struct ath_softc *sc = ni->ni_ic->ic_softc; int tid = tap->txa_tid; struct ath_node *an = ATH_NODE(ni); struct ath_tid *atid = &an->an_tid[tid]; @@ -5856,7 +5849,7 @@ void ath_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) { - struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct ath_softc *sc = ni->ni_ic->ic_softc; int tid = tap->txa_tid; struct ath_node *an = ATH_NODE(ni); struct ath_tid *atid = &an->an_tid[tid]; @@ -5991,7 +5984,7 @@ ath_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap, int status) { - struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct ath_softc *sc = ni->ni_ic->ic_softc; int tid = tap->txa_tid; struct ath_node *an = ATH_NODE(ni); struct ath_tid *atid = &an->an_tid[tid]; @@ -6064,7 +6057,7 @@ ath_addba_response_timeout(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap) { - struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct ath_softc *sc = ni->ni_ic->ic_softc; int tid = tap->txa_tid; struct ath_node *an = ATH_NODE(ni); struct ath_tid *atid = &an->an_tid[tid]; Index: sys/dev/ath/if_ath_tx_edma.c =================================================================== --- sys/dev/ath/if_ath_tx_edma.c +++ sys/dev/ath/if_ath_tx_edma.c @@ -537,7 +537,6 @@ 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__); @@ -579,9 +578,6 @@ /* 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; } @@ -834,12 +830,6 @@ 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, Index: sys/dev/ath/if_athvar.h =================================================================== --- sys/dev/ath/if_athvar.h +++ sys/dev/ath/if_athvar.h @@ -555,8 +555,8 @@ }; struct ath_softc { - struct ifnet *sc_ifp; /* interface common */ - struct ath_stats sc_stats; /* interface statistics */ + struct ieee80211com sc_ic; + struct ath_stats sc_stats; /* device statistics */ struct ath_tx_aggr_stats sc_aggr_stats; struct ath_intr_stats sc_intr_stats; uint64_t sc_debug; @@ -650,7 +650,8 @@ /* * Second set of flags. */ - u_int32_t sc_use_ent : 1, + u_int32_t sc_running : 1, /* initialized */ + sc_use_ent : 1, sc_rx_stbc : 1, sc_tx_stbc : 1, sc_hasenforcetxop : 1, /* support enforce TxOP */ Index: sys/dev/bwi/bwimac.c =================================================================== --- sys/dev/bwi/bwimac.c +++ sys/dev/bwi/bwimac.c @@ -832,11 +832,11 @@ uint8_t fw_type) { const struct bwi_fwhdr *hdr; - struct ifnet *ifp = sc->sc_ifp; if (fw->datasize < sizeof(*hdr)) { - if_printf(ifp, "invalid firmware (%s): invalid size %zu\n", - fw->name, fw->datasize); + device_printf(sc->sc_dev, + "invalid firmware (%s): invalid size %zu\n", + fw->name, fw->datasize); return 0; } @@ -847,25 +847,26 @@ * Don't verify IV's size, it has different meaning */ if (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)); + 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)); return 0; } } if (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); + device_printf(sc->sc_dev, + "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) { - if_printf(ifp, "invalid firmware (%s): wrong generation, " - "fw %d, target %d\n", fw->name, - 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); return 0; } return 1; @@ -1002,7 +1003,6 @@ 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,7 +1057,8 @@ DELAY(10); } if (i == NRETRY) { - if_printf(ifp, "firmware (ucode&pcm) loading timed out\n"); + device_printf(sc->sc_dev, + "firmware (ucode&pcm) loading timed out\n"); return ETIMEDOUT; } @@ -1067,12 +1068,14 @@ fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV); if (fw_rev > BWI_FW_VERSION3_REVMAX) { - if_printf(ifp, "firmware version 4 is not supported yet\n"); + device_printf(sc->sc_dev, + "firmware version 4 is not supported yet\n"); return ENODEV; } - 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)); + 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)); return 0; } @@ -1132,7 +1135,6 @@ 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; @@ -1155,7 +1157,7 @@ int sz = 0; if (iv_img_size < sizeof(iv->iv_ofs)) { - if_printf(ifp, "invalid IV image, ofs\n"); + device_printf(sc->sc_dev, "invalid IV image, ofs\n"); return EINVAL; } iv_img_size -= sizeof(iv->iv_ofs); @@ -1165,7 +1167,7 @@ ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK); if (ofs >= 0x1000) { - if_printf(ifp, "invalid ofs (0x%04x) " + device_printf(sc->sc_dev, "invalid ofs (0x%04x) " "for %dth iv\n", ofs, i); return EINVAL; } @@ -1174,7 +1176,8 @@ uint32_t val32; if (iv_img_size < sizeof(iv->iv_val.val32)) { - if_printf(ifp, "invalid IV image, val32\n"); + device_printf(sc->sc_dev, + "invalid IV image, val32\n"); return EINVAL; } iv_img_size -= sizeof(iv->iv_val.val32); @@ -1186,7 +1189,8 @@ uint16_t val16; if (iv_img_size < sizeof(iv->iv_val.val16)) { - if_printf(ifp, "invalid IV image, val16\n"); + device_printf(sc->sc_dev, + "invalid IV image, val16\n"); return EINVAL; } iv_img_size -= sizeof(iv->iv_val.val16); @@ -1200,7 +1204,8 @@ } if (iv_img_size != 0) { - if_printf(ifp, "invalid IV image, size left %d\n", iv_img_size); + device_printf(sc->sc_dev, "invalid IV image, size left %d\n", + iv_img_size); return EINVAL; } return 0; @@ -1209,19 +1214,19 @@ static int bwi_mac_fw_init(struct bwi_mac *mac) { - struct ifnet *ifp = mac->mac_sc->sc_ifp; + device_t dev = mac->mac_sc->sc_dev; int error; error = bwi_mac_fw_load_iv(mac, mac->mac_iv); if (error) { - if_printf(ifp, "load IV failed\n"); + device_printf(dev, "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) - if_printf(ifp, "load ExtIV failed\n"); + device_printf(dev, "load ExtIV failed\n"); } return error; } @@ -1230,8 +1235,7 @@ bwi_mac_opmode_init(struct bwi_mac *mac) { struct bwi_softc *sc = mac->mac_sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t mac_status; uint16_t pre_tbtt; @@ -1280,7 +1284,7 @@ break; } - if (ic->ic_ifp->if_flags & IFF_PROMISC) + if (ic->ic_promisc > 0) mac_status |= BWI_MAC_STATUS_PROMISC; CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status); @@ -1331,8 +1335,7 @@ { struct bwi_softc *sc = mac->mac_sc; struct bwi_phy *phy = &mac->mac_phy; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; const struct ieee80211_rate_table *rt; struct bwi_retry_lim lim; uint16_t cw_min; @@ -1915,8 +1918,7 @@ bwi_mac_lock(struct bwi_mac *mac) { struct bwi_softc *sc = mac->mac_sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0, ("mac_flags 0x%x", mac->mac_flags)); @@ -1939,8 +1941,7 @@ bwi_mac_unlock(struct bwi_mac *mac) { struct bwi_softc *sc = mac->mac_sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED, ("mac_flags 0x%x", mac->mac_flags)); Index: sys/dev/bwi/bwiphy.c =================================================================== --- sys/dev/bwi/bwiphy.c +++ sys/dev/bwi/bwiphy.c @@ -429,7 +429,7 @@ bwi_phy_init_11b_rev2(struct bwi_mac *mac) { /* TODO:11B */ - if_printf(mac->mac_sc->sc_ifp, + device_printf(mac->mac_sc->sc_dev, "%s is not implemented yet\n", __func__); } Index: sys/dev/bwi/bwirf.c =================================================================== --- sys/dev/bwi/bwirf.c +++ sys/dev/bwi/bwirf.c @@ -1260,7 +1260,6 @@ 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; @@ -1329,7 +1328,7 @@ PHY_WRITE(mac, 0x812, 0xb2); } - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + if ((sc->sc_flags & BWI_F_RUNNING) == 0) tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac); PHY_WRITE(mac, 0x80f, 0x8078); @@ -1352,7 +1351,7 @@ PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0); } - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + if ((sc->sc_flags & BWI_F_RUNNING) == 0) tpctl = NULL; bwi_rf_lo_adjust(mac, tpctl); @@ -1462,7 +1461,7 @@ 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 ifnet *ifp = mac->mac_sc->sc_ifp; + struct bwi_softc *sc = mac->mac_sc; struct bwi_rf_lo lo_save, *lo; uint8_t devi_ctrl = 0; int idx, adj_rf7a = 0; @@ -1476,7 +1475,7 @@ for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) { uint16_t tp_ctrl2, rf7a; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { + if ((sc->sc_flags & BWI_F_RUNNING) == 0) { if (idx == 0) { bzero(&lo_save, sizeof(lo_save)); } else if (init_rf_atten < 0) { Index: sys/dev/bwi/if_bwi.c =================================================================== --- sys/dev/bwi/if_bwi.c +++ sys/dev/bwi/if_bwi.c @@ -102,10 +102,10 @@ const uint8_t [IEEE80211_ADDR_LEN], const uint8_t [IEEE80211_ADDR_LEN]); static void bwi_vap_delete(struct ieee80211vap *); -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 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 int bwi_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); static void bwi_watchdog(void *); @@ -352,14 +352,12 @@ int bwi_attach(struct bwi_softc *sc) { - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_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); @@ -371,8 +369,8 @@ 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 @@ -450,25 +448,6 @@ 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); /* @@ -485,13 +464,13 @@ setbit(&bands, IEEE80211_MODE_11G); } - 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)) { + 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)) { device_printf(dev, "invalid MAC address: %6D\n", - macaddr, ":"); + ic->ic_macaddr, ":"); } } } else if (phy->phy_mode == IEEE80211_MODE_11A) { @@ -510,7 +489,6 @@ /* 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 | @@ -520,7 +498,7 @@ IEEE80211_C_BGSCAN | IEEE80211_C_MONITOR; ic->ic_opmode = IEEE80211_M_STA; - ieee80211_ifattach(ic, macaddr); + ieee80211_ifattach(ic); ic->ic_headroom = sizeof(struct bwi_txbuf_hdr); @@ -532,6 +510,8 @@ 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); @@ -577,8 +557,7 @@ int bwi_detach(struct bwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; int i; bwi_stop(sc, 1); @@ -590,7 +569,6 @@ 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); BWI_LOCK_DESTROY(sc); @@ -609,14 +587,11 @@ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return NULL; - bvp = (struct bwi_vap *) malloc(sizeof(struct bwi_vap), - M_80211_VAP, M_WAITOK | M_ZERO); - if (bvp == NULL) - return NULL; + bvp = malloc(sizeof(struct bwi_vap), M_80211_VAP, M_WAITOK | M_ZERO); 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, mac); + flags | IEEE80211_CLONE_NOBEACONS, bssid); /* override default methods */ bvp->bv_newstate = vap->iv_newstate; @@ -627,7 +602,8 @@ ieee80211_ratectl_init(vap); /* complete setup */ - ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status); + ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status, + mac); ic->ic_opmode = opmode; return vap; } @@ -651,9 +627,8 @@ void bwi_resume(struct bwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - if (ifp->if_flags & IFF_UP) + if (sc->sc_ic.ic_nrunning > 0) bwi_init(sc); } @@ -1217,27 +1192,26 @@ } static void -bwi_init(void *xsc) +bwi_init(struct bwi_softc *sc) { - struct bwi_softc *sc = xsc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; BWI_LOCK(sc); bwi_init_statechg(sc, 1); BWI_UNLOCK(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->sc_flags & BWI_F_RUNNING) ieee80211_start_all(ic); /* start all vap's */ } 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); @@ -1247,20 +1221,21 @@ mac = &sc->sc_mac[0]; error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL); if (error) { - if_printf(ifp, "%s: error %d on regwin switch\n", + device_printf(sc->sc_dev, "%s: error %d on regwin switch\n", __func__, error); goto bad; } error = bwi_mac_init(mac); if (error) { - if_printf(ifp, "%s: error %d on MAC init\n", __func__, error); + device_printf(sc->sc_dev, "%s: error %d on MAC init\n", + __func__, error); goto bad; } 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, IF_LLADDR(ifp)); + bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, sc->sc_ic.ic_macaddr); bwi_mac_reset_hwkeys(mac); @@ -1278,7 +1253,8 @@ CSR_READ_4(sc, BWI_TXSTATUS1); } if (i == NRETRY) - if_printf(ifp, "%s: can't drain TX status\n", __func__); + device_printf(sc->sc_dev, + "%s: can't drain TX status\n", __func__); #undef NRETRY } @@ -1288,14 +1264,14 @@ /* Start MAC */ error = bwi_mac_start(mac); if (error) { - if_printf(ifp, "%s: error %d starting MAC\n", __func__, error); + device_printf(sc->sc_dev, "%s: error %d starting MAC\n", + __func__, error); goto bad; } /* Clear stop flag before enabling interrupt */ sc->sc_flags &= ~BWI_F_STOP; - - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_flags |= BWI_F_RUNNING; callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc); /* Enable intrs */ @@ -1305,135 +1281,110 @@ bwi_stop_locked(sc, 1); } -static int -bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +bwi_parent(struct ieee80211com *ic) { -#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; + struct bwi_softc *sc = ic->ic_softc; + int startall = 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; - } + BWI_LOCK(sc); + if (ic->ic_nrunning > 0) { + struct bwi_mac *mac; + int promisc = -1; - if (promisc >= 0) - bwi_mac_set_promisc(mac, promisc); - } + 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_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); + 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; } - BWI_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; -#undef IS_RUNNING + } else if (sc->sc_flags & BWI_F_RUNNING) + bwi_stop_locked(sc, 1); + BWI_UNLOCK(sc); + if (startall) + ieee80211_start_all(ic); } -static void -bwi_start(struct ifnet *ifp) +static int +bwi_transmit(struct ieee80211com *ic, struct mbuf *m) { - struct bwi_softc *sc = ifp->if_softc; + struct bwi_softc *sc = ic->ic_softc; + int error; BWI_LOCK(sc); - bwi_start_locked(ifp); + if ((sc->sc_flags & BWI_F_RUNNING) == 0) { + BWI_UNLOCK(sc); + return (ENXIO); + } + error = mbufq_enqueue(&sc->sc_snd, m); + if (error) { + BWI_UNLOCK(sc); + return (error); + } + bwi_start_locked(sc); BWI_UNLOCK(sc); + return (0); } static void -bwi_start_locked(struct ifnet *ifp) +bwi_start_locked(struct bwi_softc *sc) { - struct bwi_softc *sc = ifp->if_softc; struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; struct ieee80211_frame *wh; struct ieee80211_node *ni; - struct ieee80211_key *k; struct mbuf *m; int trans, idx; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; + BWI_ASSERT_LOCKED(sc); trans = 0; idx = tbd->tbd_idx; - while (tbd->tbd_buf[idx].tb_mbuf == NULL) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); /* XXX: LOCK */ - if (m == NULL) - break; - + while (tbd->tbd_buf[idx].tb_mbuf == NULL && + tbd->tbd_used + BWI_TX_NSPRDESC < BWI_TX_NDESC && + (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; wh = mtod(m, struct ieee80211_frame *); - 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; - } + 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; } - 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 (ni != NULL) { + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + } else + counter_u64_add(sc->sc_ic.ic_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; + tbd->tbd_idx = idx; if (trans) sc->sc_tx_timer = 5; } @@ -1443,13 +1394,12 @@ const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct bwi_softc *sc = ifp->if_softc; + struct bwi_softc *sc = ic->ic_softc; /* XXX wme? */ struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; int idx, error; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { + if ((sc->sc_flags & BWI_F_RUNNING) == 0) { ieee80211_free_node(ni); m_freem(m); return ENETDOWN; @@ -1472,16 +1422,12 @@ error = bwi_encap_raw(sc, idx, m, ni, params); } if (error == 0) { - 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_used++; 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; } @@ -1490,14 +1436,12 @@ 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) { - if_printf(ifp, "watchdog timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + device_printf(sc->sc_dev, "watchdog timeout\n"); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task); } callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc); @@ -1514,7 +1458,6 @@ 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; @@ -1525,7 +1468,7 @@ sc->sc_led_blinking = 0; sc->sc_flags |= BWI_F_STOP; - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + if (sc->sc_flags & BWI_F_RUNNING) { KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, ("current regwin type %d", sc->sc_cur_regwin->rw_type)); mac = (struct bwi_mac *)sc->sc_cur_regwin; @@ -1557,14 +1500,13 @@ sc->sc_tx_timer = 0; callout_stop(&sc->sc_watchdog_timer); - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_flags &= ~BWI_F_RUNNING; } 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]; @@ -1572,7 +1514,7 @@ BWI_LOCK(sc); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || + if ((sc->sc_flags & BWI_F_RUNNING) == 0 || (sc->sc_flags & BWI_F_STOP)) { BWI_UNLOCK(sc); return; @@ -1615,7 +1557,7 @@ i, txrx_intr_status[i]); if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) { - if_printf(ifp, + device_printf(sc->sc_dev, "%s: intr fatal TX/RX (%d) error 0x%08x\n", __func__, i, txrx_intr_status[i]); txrx_error = 1; @@ -1653,7 +1595,8 @@ */ if (intr_status & BWI_INTR_PHY_TXERR) { if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) { - if_printf(ifp, "%s: intr PHY TX error\n", __func__); + device_printf(sc->sc_dev, "%s: intr PHY TX error\n", + __func__); taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task); BWI_UNLOCK(sc); return; @@ -1668,7 +1611,7 @@ bwi_mac_config_ps(mac); if (intr_status & BWI_INTR_EO_ATIM) - if_printf(ifp, "EO_ATIM\n"); + device_printf(sc->sc_dev, "EO_ATIM\n"); if (intr_status & BWI_INTR_PMQ) { for (;;) { @@ -1679,7 +1622,7 @@ } if (intr_status & BWI_INTR_NOISE) - if_printf(ifp, "intr noise\n"); + device_printf(sc->sc_dev, "intr noise\n"); if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) { rx_data = sc->sc_rxeof(sc); @@ -1728,7 +1671,7 @@ static void bwi_scan_start(struct ieee80211com *ic) { - struct bwi_softc *sc = ic->ic_ifp->if_softc; + struct bwi_softc *sc = ic->ic_softc; BWI_LOCK(sc); /* Enable MAC beacon promiscuity */ @@ -1739,7 +1682,7 @@ static void bwi_set_channel(struct ieee80211com *ic) { - struct bwi_softc *sc = ic->ic_ifp->if_softc; + struct bwi_softc *sc = ic->ic_softc; struct ieee80211_channel *c = ic->ic_curchan; struct bwi_mac *mac; @@ -1765,7 +1708,7 @@ static void bwi_scan_end(struct ieee80211com *ic) { - struct bwi_softc *sc = ic->ic_ifp->if_softc; + struct bwi_softc *sc = ic->ic_softc; BWI_LOCK(sc); CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN); @@ -1777,9 +1720,8 @@ { struct bwi_vap *bvp = BWI_VAP(vap); struct ieee80211com *ic= vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; + struct bwi_softc *sc = ic->ic_softc; enum ieee80211_state ostate = vap->iv_state; - struct bwi_softc *sc = ifp->if_softc; struct bwi_mac *mac; int error; @@ -2625,8 +2567,7 @@ { struct bwi_ring_data *rd = &sc->sc_rx_rdata; struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; int idx, rx_data = 0; idx = rbd->rbd_idx; @@ -2645,7 +2586,7 @@ BUS_DMASYNC_POSTREAD); if (bwi_newbuf(sc, idx, 0)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto next; } @@ -2659,9 +2600,10 @@ buflen = le16toh(hdr->rxh_buflen); if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) { - if_printf(ifp, "%s: zero length data, hdr_extra %d\n", - __func__, hdr_extra); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + device_printf(sc->sc_dev, + "%s: zero length data, hdr_extra %d\n", + __func__, hdr_extra); + counter_u64_add(ic->ic_ierrors, 1); m_freem(m); goto next; } @@ -2670,7 +2612,6 @@ 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); @@ -2804,7 +2745,6 @@ { struct bwi_ring_data *rd; struct bwi_txbuf_data *tbd; - struct ifnet *ifp = sc->sc_ifp; uint32_t state, val; int i; @@ -2825,8 +2765,9 @@ DELAY(1000); } if (i == NRETRY) { - if_printf(ifp, "%s: wait for TX ring(%d) stable timed out\n", - __func__, ring_idx); + device_printf(sc->sc_dev, + "%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); @@ -2839,7 +2780,7 @@ DELAY(1000); } if (i == NRETRY) - if_printf(ifp, "%s: reset TX ring (%d) timed out\n", + device_printf(sc->sc_dev, "%s: reset TX ring (%d) timed out\n", __func__, ring_idx); #undef NRETRY @@ -2947,8 +2888,7 @@ struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; 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]; @@ -3024,7 +2964,8 @@ */ M_PREPEND(m, sizeof(*hdr), M_NOWAIT); if (m == NULL) { - if_printf(ifp, "%s: prepend TX header failed\n", __func__); + device_printf(sc->sc_dev, "%s: prepend TX header failed\n", + __func__); return ENOBUFS; } hdr = mtod(m, struct bwi_txbuf_hdr *); @@ -3073,7 +3014,7 @@ 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) { - if_printf(ifp, "%s: can't load TX buffer (1) %d\n", + device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n", __func__, error); goto back; } @@ -3083,8 +3024,8 @@ m_new = m_defrag(m, M_NOWAIT); if (m_new == NULL) { - if_printf(ifp, "%s: can't defrag TX buffer\n", - __func__); + device_printf(sc->sc_dev, + "%s: can't defrag TX buffer\n", __func__); error = ENOBUFS; goto back; } else { @@ -3095,7 +3036,8 @@ bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT); if (error) { - if_printf(ifp, "%s: can't load TX buffer (2) %d\n", + device_printf(sc->sc_dev, + "%s: can't load TX buffer (2) %d\n", __func__, error); goto back; } @@ -3137,7 +3079,6 @@ 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]; @@ -3204,7 +3145,8 @@ */ M_PREPEND(m, sizeof(*hdr), M_NOWAIT); if (m == NULL) { - if_printf(ifp, "%s: prepend TX header failed\n", __func__); + device_printf(sc->sc_dev, "%s: prepend TX header failed\n", + __func__); return ENOBUFS; } hdr = mtod(m, struct bwi_txbuf_hdr *); @@ -3252,14 +3194,15 @@ struct mbuf *m_new; if (error != EFBIG) { - if_printf(ifp, "%s: can't load TX buffer (1) %d\n", + device_printf(sc->sc_dev, + "%s: can't load TX buffer (1) %d\n", __func__, error); goto back; } m_new = m_defrag(m, M_NOWAIT); if (m_new == NULL) { - if_printf(ifp, "%s: can't defrag TX buffer\n", - __func__); + device_printf(sc->sc_dev, + "%s: can't defrag TX buffer\n", __func__); error = ENOBUFS; goto back; } @@ -3268,7 +3211,8 @@ bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT); if (error) { - if_printf(ifp, "%s: can't load TX buffer (2) %d\n", + device_printf(sc->sc_dev, + "%s: can't load TX buffer (2) %d\n", __func__, error); goto back; } @@ -3312,7 +3256,6 @@ static void bwi_txeof_status32(struct bwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; uint32_t val, ctrl_base; int end_idx; @@ -3327,8 +3270,7 @@ CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX, end_idx * sizeof(struct bwi_desc32)); - if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) - ifp->if_start(ifp); + bwi_start_locked(sc); } static void @@ -3340,7 +3282,6 @@ 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; @@ -3348,7 +3289,7 @@ struct ieee80211vap *vap; if (tx_id == 0) { - if_printf(ifp, "%s: zero tx id\n", __func__); + device_printf(sc->sc_dev, "%s: zero tx id\n", __func__); return; } @@ -3369,8 +3310,7 @@ bus_dmamap_unload(sc->sc_buf_dtag, tb->tb_dmap); - ni = tb->tb_ni; - if (tb->tb_ni != NULL) { + if ((ni = tb->tb_ni) != NULL) { const struct bwi_txbuf_hdr *hdr = mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *); vap = ni->ni_vap; @@ -3388,24 +3328,14 @@ (data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS : IEEE80211_RATECTL_TX_FAILURE, &acked, NULL); } - - /* - * 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); + ieee80211_tx_complete(ni, tb->tb_mbuf, !acked); tb->tb_ni = NULL; - } - m_freem(tb->tb_mbuf); + } else + 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 @@ -3437,7 +3367,6 @@ static void bwi_txeof(struct bwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; for (;;) { uint32_t tx_status0, tx_status1; @@ -3460,8 +3389,7 @@ data_txcnt); } - if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) - ifp->if_start(ifp); + bwi_start_locked(sc); } static int @@ -3709,7 +3637,6 @@ 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; @@ -3722,7 +3649,7 @@ bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid); - bcopy(IF_LLADDR(ifp), buf.myaddr, sizeof(buf.myaddr)); + bcopy(sc->sc_ic.ic_macaddr, buf.myaddr, sizeof(buf.myaddr)); bcopy(bssid, buf.bssid, sizeof(buf.bssid)); n = sizeof(buf) / sizeof(val); @@ -3745,7 +3672,7 @@ struct bwi_mac *mac; BWI_LOCK(sc); - if (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) { + if (sc->sc_flags & BWI_F_RUNNING) { DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__); KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, @@ -3761,16 +3688,12 @@ 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(ic->ic_opmode != IEEE80211_M_MONITOR, - ("opmode %d", ic->ic_opmode)); + KASSERT(sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR, + ("opmode %d", sc->sc_ic.ic_opmode)); KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC, ("current regwin type %d", sc->sc_cur_regwin->rw_type)); @@ -3912,8 +3835,7 @@ static void bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint16_t val; int i; @@ -3922,7 +3844,7 @@ sc->sc_led_blinking = 0; } - if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + if ((sc->sc_flags & BWI_F_RUNNING) == 0) return; val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL); @@ -4050,13 +3972,12 @@ bwi_restart(void *xsc, int pending) { struct bwi_softc *sc = xsc; - struct ifnet *ifp = sc->sc_ifp; - if_printf(ifp, "%s begin, help!\n", __func__); + device_printf(sc->sc_dev, "%s begin, help!\n", __func__); BWI_LOCK(sc); - bwi_init_statechg(xsc, 0); + bwi_init_statechg(sc, 0); #if 0 - bwi_start_locked(ifp); + bwi_start_locked(sc); #endif BWI_UNLOCK(sc); } Index: sys/dev/bwi/if_bwivar.h =================================================================== --- sys/dev/bwi/if_bwivar.h +++ sys/dev/bwi/if_bwivar.h @@ -541,10 +541,11 @@ #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_ */ @@ -647,6 +648,7 @@ #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 Index: sys/dev/iwi/if_iwi.c =================================================================== --- sys/dev/iwi/if_iwi.c +++ sys/dev/iwi/if_iwi.c @@ -166,14 +166,15 @@ 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 ifnet *, struct mbuf *, +static int iwi_tx_start(struct iwi_softc *, 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_locked(struct ifnet *); -static void iwi_start(struct ifnet *); +static void iwi_start(struct iwi_softc *); +static int iwi_transmit(struct ieee80211com *, struct mbuf *); static void iwi_watchdog(void *); -static int iwi_ioctl(struct ifnet *, u_long, caddr_t); +static int iwi_ioctl(struct ieee80211com *, u_long, void *); +static void iwi_parent(struct ieee80211com *); 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 *); @@ -269,23 +270,15 @@ iwi_attach(device_t dev) { struct iwi_softc *sc = device_get_softc(dev); - struct ifnet *ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_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); @@ -353,17 +346,6 @@ 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; @@ -385,14 +367,14 @@ /* read MAC address from EEPROM */ val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0); - macaddr[0] = val & 0xff; - macaddr[1] = val >> 8; + ic->ic_macaddr[0] = val & 0xff; + ic->ic_macaddr[1] = val >> 8; val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 1); - macaddr[2] = val & 0xff; - macaddr[3] = val >> 8; + ic->ic_macaddr[2] = val & 0xff; + ic->ic_macaddr[3] = val >> 8; val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 2); - macaddr[4] = val & 0xff; - macaddr[5] = val >> 8; + ic->ic_macaddr[4] = val & 0xff; + ic->ic_macaddr[5] = val >> 8; bands = 0; setbit(&bands, IEEE80211_MODE_11B); @@ -401,7 +383,7 @@ setbit(&bands, IEEE80211_MODE_11A); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, macaddr); + ieee80211_ifattach(ic); /* override default methods */ ic->ic_node_alloc = iwi_node_alloc; sc->sc_node_free = ic->ic_node_free; @@ -416,6 +398,9 @@ 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), @@ -450,8 +435,7 @@ iwi_detach(device_t dev) { struct iwi_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; bus_teardown_intr(dev, sc->irq, sc->sc_ih); @@ -482,11 +466,10 @@ sc->mem); delete_unrhdr(sc->sc_unr); + mbufq_drain(&sc->sc_snd); IWI_LOCK_DESTROY(sc); - if_free(ifp); - return 0; } @@ -496,8 +479,7 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct ifnet *ifp = ic->ic_ifp; - struct iwi_softc *sc = ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; struct iwi_vap *ivp; struct ieee80211vap *vap; int i; @@ -519,12 +501,9 @@ if (iwi_init_fw_dma(sc, i)) return NULL; - ivp = (struct iwi_vap *) malloc(sizeof(struct iwi_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (ivp == NULL) - return NULL; + ivp = malloc(sizeof(struct iwi_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &ivp->iwi_vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); /* override the default, the setting comes from the linux driver */ vap->iv_bmissthreshold = 24; /* override with driver methods */ @@ -532,7 +511,8 @@ vap->iv_newstate = iwi_newstate; /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status); + ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status, + mac); ic->ic_opmode = opmode; return vap; } @@ -859,7 +839,7 @@ iwi_suspend(device_t dev) { struct iwi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; ieee80211_suspend_all(ic); return 0; @@ -869,7 +849,7 @@ iwi_resume(device_t dev) { struct iwi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; pci_write_config(dev, 0x41, 0, 1); @@ -895,7 +875,7 @@ iwi_node_free(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; - struct iwi_softc *sc = ic->ic_ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; struct iwi_node *in = (struct iwi_node *)ni; if (in->in_station != -1) { @@ -939,7 +919,7 @@ { struct ieee80211vap *vap = ifp->if_softc; struct ieee80211com *ic = vap->iv_ic; - struct iwi_softc *sc = ic->ic_ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; struct ieee80211_node *ni; /* read current transmission rate from adapter */ @@ -955,8 +935,7 @@ { struct iwi_vap *ivp = IWI_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct iwi_softc *sc = ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; IWI_LOCK_DECL; DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__, @@ -1061,7 +1040,7 @@ static int iwi_wme_setparams(struct iwi_softc *sc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; const struct wmeParams *wmep; int ac; @@ -1095,7 +1074,7 @@ static int iwi_wme_update(struct ieee80211com *ic) { - struct iwi_softc *sc = ic->ic_ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); /* @@ -1189,8 +1168,7 @@ static void iwi_setcurchan(struct iwi_softc *sc, int chan) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; sc->curchan = chan; ieee80211_radiotap_chan_change(ic); @@ -1200,8 +1178,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i, struct iwi_frame *frame) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct mbuf *mnew, *m; struct ieee80211_node *ni; int type, error, framelen; @@ -1237,7 +1214,7 @@ */ mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mnew == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return; } @@ -1258,7 +1235,7 @@ panic("%s: could not load old rx mbuf", device_get_name(sc->sc_dev)); } - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return; } @@ -1271,7 +1248,6 @@ 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; @@ -1410,8 +1386,7 @@ static void iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct iwi_notif_scan_channel *chan; struct iwi_notif_scan_complete *scan; @@ -1632,47 +1607,33 @@ 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); - for (; txq->next != hw;) { + while (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); - 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); + ieee80211_tx_complete(data->ni, data->m, 0); data->ni = NULL; - - DPRINTFN(15, ("tx done idx=%u\n", txq->next)); - - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - + data->m = NULL; 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_locked(ifp); + iwi_start(sc); } static void iwi_fatal_error_intr(struct iwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); device_printf(sc->sc_dev, "firmware error\n"); @@ -1688,10 +1649,8 @@ static void iwi_radio_off_intr(struct iwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - ieee80211_runtask(ic, &sc->sc_radiofftask); + ieee80211_runtask(&sc->sc_ic, &sc->sc_radiofftask); } static void @@ -1806,10 +1765,9 @@ } static int -iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni, +iwi_tx_start(struct iwi_softc *sc, 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; @@ -1852,9 +1810,10 @@ 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, @@ -1980,141 +1939,139 @@ 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_locked(struct ifnet *ifp) +iwi_start(struct iwi_softc *sc) { - struct iwi_softc *sc = ifp->if_softc; struct mbuf *m; struct ieee80211_node *ni; int ac; IWI_LOCK_ASSERT(sc); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { 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 */ - IFQ_DRV_PREPEND(&ifp->if_snd, m); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; + mbufq_prepend(&sc->sc_snd, m); break; } - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - if (iwi_tx_start(ifp, m, ni, ac) != 0) { + if (iwi_tx_start(sc, m, ni, ac) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(ni->ni_vap->iv_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 ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; IWI_LOCK_ASSERT(sc); if (sc->sc_tx_timer > 0) { if (--sc->sc_tx_timer == 0) { - if_printf(ifp, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + device_printf(sc->sc_dev, "device timeout\n"); + counter_u64_add(ic->ic_oerrors, 1); ieee80211_runtask(ic, &sc->sc_restarttask); } } if (sc->sc_state_timer > 0) { if (--sc->sc_state_timer == 0) { - if_printf(ifp, "firmware stuck in state %d, resetting\n", + device_printf(sc->sc_dev, + "firmware stuck in state %d, resetting\n", sc->fw_state); - if (sc->fw_state == IWI_FW_SCANNING) { - struct ieee80211com *ic = ifp->if_l2com; + if (sc->fw_state == IWI_FW_SCANNING) 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) { - if_printf(ifp, "firmware command timeout, resetting\n"); + device_printf(sc->sc_dev, + "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 ifnet *ifp, u_long cmd, caddr_t data) +iwi_ioctl(struct ieee80211com *ic, u_long cmd, void *data) { - struct iwi_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + struct ifreq *ifr = data; + struct iwi_softc *sc = ic->ic_softc; + int error; 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 = EINVAL; + error = ENOTTY; break; } - return error; + IWI_UNLOCK(sc); + + return (error); } static void @@ -2593,8 +2550,7 @@ static int iwi_config(struct iwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct iwi_configuration config; struct iwi_rateset rs; struct iwi_txpower power; @@ -2603,8 +2559,8 @@ IWI_LOCK_ASSERT(sc); - DPRINTF(("Setting MAC address to %6D\n", IF_LLADDR(ifp), ":")); - error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp), + DPRINTF(("Setting MAC address to %6D\n", ic->ic_macaddr, ":")); + error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, ic->ic_macaddr, IEEE80211_ADDR_LEN); if (error != 0) return error; @@ -2724,7 +2680,7 @@ static int iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan) { - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_channel *chan; struct ieee80211_scan_state *ss; struct iwi_scan_ext scan; @@ -2741,7 +2697,6 @@ } IWI_STATE_BEGIN(sc, IWI_FW_SCANNING); - ic = sc->sc_ifp->if_l2com; ss = ic->ic_scan; memset(&scan, 0, sizeof scan); @@ -3128,7 +3083,6 @@ static void iwi_init_locked(struct iwi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; struct iwi_rx_data *data; int i; @@ -3202,8 +3156,7 @@ } callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_running = 1; return; fail: IWI_STATE_END(sc, IWI_FW_LOADING); @@ -3215,15 +3168,14 @@ iwi_init(void *priv) { struct iwi_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; IWI_LOCK_DECL; IWI_LOCK(sc); iwi_init_locked(sc); IWI_UNLOCK(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->sc_running) ieee80211_start_all(ic); } @@ -3231,11 +3183,10 @@ iwi_stop_locked(void *priv) { struct iwi_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; IWI_LOCK_ASSERT(sc); - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_running = 0; if (sc->sc_softled) { callout_stop(&sc->sc_ledtimer); @@ -3296,7 +3247,7 @@ iwi_radio_on(void *arg, int pending) { struct iwi_softc *sc = arg; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; device_printf(sc->sc_dev, "radio turned on\n"); @@ -3317,10 +3268,7 @@ * it is enabled so we must poll for the latter. */ if (!iwi_getrfkill(sc)) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - ieee80211_runtask(ic, &sc->sc_radiontask); + ieee80211_runtask(&sc->sc_ic, &sc->sc_radiontask); return; } callout_reset(&sc->sc_rftimer, 2*hz, iwi_rfkill_poll, sc); @@ -3330,7 +3278,7 @@ iwi_radio_off(void *arg, int pending) { struct iwi_softc *sc = arg; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; IWI_LOCK_DECL; device_printf(sc->sc_dev, "radio turned off\n"); @@ -3594,8 +3542,8 @@ static void iwi_set_channel(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct iwi_softc *sc = ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; + if (sc->fw_state == IWI_FW_IDLE) iwi_setcurchan(sc, ic->ic_curchan->ic_ieee); } @@ -3604,8 +3552,7 @@ iwi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) { struct ieee80211vap *vap = ss->ss_vap; - struct ifnet *ifp = vap->iv_ic->ic_ifp; - struct iwi_softc *sc = ifp->if_softc; + struct iwi_softc *sc = vap->iv_ic->ic_softc; IWI_LOCK_DECL; IWI_LOCK(sc); @@ -3623,8 +3570,7 @@ static void iwi_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct iwi_softc *sc = ifp->if_softc; + struct iwi_softc *sc = ic->ic_softc; IWI_LOCK_DECL; IWI_LOCK(sc); Index: sys/dev/iwi/if_iwivar.h =================================================================== --- sys/dev/iwi/if_iwivar.h +++ sys/dev/iwi/if_iwivar.h @@ -125,11 +125,13 @@ #define IWI_VAP(vap) ((struct iwi_vap *)(vap)) struct iwi_softc { - struct ifnet *sc_ifp; - void (*sc_node_free)(struct ieee80211_node *); + struct mtx sc_mtx; + struct ieee80211com sc_ic; + struct mbufq sc_snd; device_t sc_dev; - struct mtx sc_mtx; + void (*sc_node_free)(struct ieee80211_node *); + uint8_t sc_mcast[IEEE80211_ADDR_LEN]; struct unrhdr *sc_unr; @@ -193,7 +195,8 @@ struct task sc_wmetask; /* set wme parameters */ struct task sc_monitortask; - unsigned int sc_softled : 1, /* enable LED gpio status */ + unsigned int sc_running : 1, /* initialized */ + 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 */ Index: sys/dev/iwn/if_iwn.c =================================================================== --- sys/dev/iwn/if_iwn.c +++ sys/dev/iwn/if_iwn.c @@ -235,10 +235,11 @@ 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 void iwn_start(struct ifnet *); -static void iwn_start_locked(struct ifnet *); +static int iwn_transmit(struct ieee80211com *, struct mbuf *); +static void iwn_start_locked(struct iwn_softc *); static void iwn_watchdog(void *); -static int iwn_ioctl(struct ifnet *, u_long, caddr_t); +static int iwn_ioctl(struct ieee80211com *, u_long , void *); +static void iwn_parent(struct ieee80211com *); 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); @@ -336,7 +337,7 @@ 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(void *); +static void iwn_init(struct iwn_softc *); static void iwn_stop_locked(struct iwn_softc *); static void iwn_stop(struct iwn_softc *); static void iwn_scan_start(struct ieee80211com *); @@ -406,9 +407,7 @@ { 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; @@ -464,6 +463,7 @@ } 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,14 +549,7 @@ /* Clear pending interrupts. */ IWN_WRITE(sc, IWN_INT, 0xffffffff); - 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 = &sc->sc_ic; ic->ic_softc = sc; ic->ic_name = device_get_nameunit(dev); ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ @@ -581,7 +574,7 @@ ; /* Read MAC address, channels, etc from EEPROM. */ - if ((error = iwn_read_eeprom(sc, macaddr)) != 0) { + if ((error = iwn_read_eeprom(sc, ic->ic_macaddr)) != 0) { device_printf(dev, "could not read EEPROM, error %d\n", error); goto fail; @@ -599,7 +592,7 @@ if (bootverbose) { device_printf(dev, "MIMO %dT%dR, %.4s, address %6D\n", sc->ntxchains, sc->nrxchains, sc->eeprom_domain, - macaddr, ":"); + ic->ic_macaddr, ":"); } if (sc->sc_flags & IWN_FLAG_HAS_11N) { @@ -640,19 +633,12 @@ ; } - 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); + ieee80211_ifattach(ic); 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; @@ -1293,10 +1279,9 @@ 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(ic, + ieee80211_radiotap_attach(&sc->sc_ic, &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), IWN_TX_RADIOTAP_PRESENT, &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), @@ -1326,21 +1311,14 @@ 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; - 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; + ivp = malloc(sizeof(struct iwn_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &ivp->iv_vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac1); + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); 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; @@ -1349,7 +1327,8 @@ ieee80211_ratectl_init(vap); /* Complete setup. */ - ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status); + ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status, + mac); ic->ic_opmode = opmode; return vap; } @@ -1390,24 +1369,19 @@ 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 (ifp != NULL) { - ic = ifp->if_l2com; - + if (sc->sc_ic.ic_softc != NULL) { /* Free the mbuf queue and node references */ IWN_LOCK(sc); iwn_xmit_queue_drain(sc); IWN_UNLOCK(sc); - ieee80211_draintask(ic, &sc->sc_reinit_task); - ieee80211_draintask(ic, &sc->sc_radioon_task); - ieee80211_draintask(ic, &sc->sc_radiooff_task); - + 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); iwn_stop(sc); taskqueue_drain_all(sc->sc_tq); @@ -1415,9 +1389,11 @@ callout_drain(&sc->watchdog_to); callout_drain(&sc->calib_to); - ieee80211_ifdetach(ic); + ieee80211_ifdetach(&sc->sc_ic); } + mbufq_drain(&sc->sc_snd); + /* Uninstall interrupt handler. */ if (sc->irq != NULL) { bus_teardown_intr(dev, sc->irq, sc->sc_ih); @@ -1440,9 +1416,6 @@ 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; @@ -1461,9 +1434,8 @@ iwn_suspend(device_t dev) { struct iwn_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - ieee80211_suspend_all(ic); + ieee80211_suspend_all(&sc->sc_ic); return 0; } @@ -1471,12 +1443,11 @@ 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(ic); + ieee80211_resume_all(&sc->sc_ic); return 0; } @@ -2385,8 +2356,7 @@ static void iwn_read_eeprom_band(struct iwn_softc *sc, int n) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct iwn_eeprom_chan *channels = sc->eeprom_channels[n]; const struct iwn_chan_band *band = &iwn_bands[n]; struct ieee80211_channel *c; @@ -2445,8 +2415,7 @@ static void iwn_read_eeprom_ht40(struct iwn_softc *sc, int n) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct iwn_eeprom_chan *channels = sc->eeprom_channels[n]; const struct iwn_chan_band *band = &iwn_bands[n]; struct ieee80211_channel *c, *cent, *extc; @@ -2514,8 +2483,7 @@ static void iwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; iwn_read_prom_data(sc, addr, &sc->eeprom_channels[n], iwn_bands[n].nchan * sizeof (struct iwn_eeprom_chan)); @@ -2583,8 +2551,7 @@ iwn_read_eeprom_enhinfo(struct iwn_softc *sc) { struct iwn_eeprom_enhinfo enhinfo[35]; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_channel *c; uint16_t val, base; int8_t maxpwr; @@ -2967,8 +2934,7 @@ struct iwn_rx_data *data) { struct iwn_ops *ops = &sc->ops; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct iwn_rx_ring *ring = &sc->rxq; struct ieee80211_frame *wh; struct ieee80211_node *ni; @@ -3015,14 +2981,14 @@ if ((flags & IWN_RX_NOERROR) != IWN_RX_NOERROR) { DPRINTF(sc, IWN_DEBUG_RECV, "%s: RX flags error %x\n", __func__, flags); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_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); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return; } @@ -3030,7 +2996,7 @@ if (m1 == NULL) { DPRINTF(sc, IWN_DEBUG_ANY, "%s: no mbuf to restock ring\n", __func__); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return; } bus_dmamap_unload(ring->data_dmat, data->map); @@ -3053,7 +3019,7 @@ ring->desc[ring->cur] = htole32(paddr >> 8); bus_dmamap_sync(ring->data_dmat, ring->desc_dma.map, BUS_DMASYNC_PREWRITE); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return; } @@ -3065,7 +3031,6 @@ BUS_DMASYNC_PREWRITE); /* Finalize mbuf. */ - m->m_pkthdr.rcvif = ifp; m->m_data = head; m->m_pkthdr.len = m->m_len = len; @@ -3159,7 +3124,6 @@ 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); @@ -3240,12 +3204,10 @@ 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); @@ -3391,8 +3353,7 @@ struct iwn_rx_data *data) { struct iwn_ops *ops = &sc->ops; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct iwn_calib_state *calib = &sc->calib; struct iwn_stats *stats = (struct iwn_stats *)(desc + 1); @@ -3565,7 +3526,6 @@ 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; @@ -3586,15 +3546,12 @@ /* * Update rate control statistics for the node. */ - if (status & IWN_TX_FAIL) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + if (status & IWN_TX_FAIL) ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); - } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + else ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); - } /* * Channels marked for "radar" require traffic to be received @@ -3620,11 +3577,8 @@ sc->sc_tx_timer = 0; if (--ring->queued < IWN_TX_RING_LOMARK) { sc->qfullmsk &= ~(1 << ring->qid); - if (sc->qfullmsk == 0 && - (ifp->if_drv_flags & IFF_DRV_OACTIVE)) { - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - iwn_start_locked(ifp); - } + if (sc->qfullmsk == 0) + iwn_start_locked(sc); } DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); @@ -3669,7 +3623,6 @@ 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; @@ -3808,11 +3761,8 @@ sc->sc_tx_timer = 0; if (ring->queued < IWN_TX_RING_LOMARK) { sc->qfullmsk &= ~(1 << ring->qid); - if (sc->qfullmsk == 0 && - (ifp->if_drv_flags & IFF_DRV_OACTIVE)) { - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - iwn_start_locked(ifp); - } + if (sc->qfullmsk == 0) + iwn_start_locked(sc); } DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__); @@ -3826,8 +3776,7 @@ iwn_notif_intr(struct iwn_softc *sc) { struct iwn_ops *ops = &sc->ops; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint16_t hw; @@ -4021,8 +3970,7 @@ static void iwn_rftoggle_intr(struct iwn_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp = IWN_READ(sc, IWN_GP_CNTRL); IWN_LOCK_ASSERT(sc); @@ -4101,7 +4049,6 @@ iwn_intr(void *arg) { struct iwn_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; uint32_t r1, r2, tmp; IWN_LOCK(sc); @@ -4194,7 +4141,7 @@ done: /* Re-enable interrupts. */ - if (ifp->if_flags & IFF_UP) + if (sc->sc_flags & IWN_FLAG_RUNNING) IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask); IWN_UNLOCK(sc); @@ -4678,9 +4625,7 @@ 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; @@ -4921,13 +4866,12 @@ const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct iwn_softc *sc = ifp->if_softc; + struct iwn_softc *sc = ic->ic_softc; int error = 0; DPRINTF(sc, IWN_DEBUG_XMIT | IWN_DEBUG_TRACE, "->%s begin\n", __func__); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { + if ((sc->sc_flags & IWN_FLAG_RUNNING) == 0) { ieee80211_free_node(ni); m_freem(m); return ENETDOWN; @@ -4968,7 +4912,6 @@ 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; @@ -4979,20 +4922,32 @@ return error; } -static void -iwn_start(struct ifnet *ifp) +static int +iwn_transmit(struct ieee80211com *ic, struct mbuf *m) { - struct iwn_softc *sc = ifp->if_softc; + struct iwn_softc *sc; + int error; + + sc = ic->ic_softc; IWN_LOCK(sc); - iwn_start_locked(ifp); + 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_UNLOCK(sc); + return (0); } static void -iwn_start_locked(struct ifnet *ifp) +iwn_start_locked(struct iwn_softc *sc) { - struct iwn_softc *sc = ifp->if_softc; struct ieee80211_node *ni; struct mbuf *m; @@ -5007,27 +4962,16 @@ } DPRINTF(sc, IWN_DEBUG_XMIT, "%s: called\n", __func__); - - 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; + while (sc->qfullmsk == 0 && + (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { 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__); } @@ -5035,12 +4979,11 @@ iwn_watchdog(void *arg) { struct iwn_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; IWN_LOCK_ASSERT(sc); - KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running")); + KASSERT(sc->sc_flags & IWN_FLAG_RUNNING, ("not running")); DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); @@ -5055,41 +4998,13 @@ } static int -iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +iwn_ioctl(struct ieee80211com *ic, u_long cmd, void *data) { - 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; - + struct ifreq *ifr = data; + struct iwn_softc *sc = ic->ic_softc; + int error = 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? */ @@ -5103,10 +5018,35 @@ IWN_UNLOCK(sc); break; default: - error = EINVAL; + error = ENOTTY; break; } - return error; + 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); } /* @@ -5340,8 +5280,7 @@ iwn_add_broadcast_node(struct iwn_softc *sc, int async) { struct iwn_ops *ops = &sc->ops; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct iwn_node_info node; struct iwn_cmd_link_quality linkq; uint8_t txant; @@ -5352,7 +5291,7 @@ sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX]; memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.macaddr, ifp->if_broadcastaddr); + IEEE80211_ADDR_COPY(node.macaddr, ieee80211broadcastaddr); 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) @@ -5501,8 +5440,7 @@ static void iwn4965_power_calibration(struct iwn_softc *sc, int temp) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); @@ -5872,8 +5810,7 @@ { struct iwn_ops *ops = &sc->ops; struct iwn_calib_state *calib = &sc->calib; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t val; int i; @@ -6507,8 +6444,9 @@ iwn_config(struct iwn_softc *sc) { struct iwn_ops *ops = &sc->ops; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + const uint8_t *macaddr; uint32_t txmask; uint16_t rxchain; int error; @@ -6590,8 +6528,9 @@ /* 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)); - IEEE80211_ADDR_COPY(sc->rxon->myaddr, IF_LLADDR(ifp)); - IEEE80211_ADDR_COPY(sc->rxon->wlap, IF_LLADDR(ifp)); + macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr; + IEEE80211_ADDR_COPY(sc->rxon->myaddr, macaddr); + IEEE80211_ADDR_COPY(sc->rxon->wlap, macaddr); 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)) @@ -6699,7 +6638,7 @@ static uint16_t iwn_limit_dwell(struct iwn_softc *sc, uint16_t dwell_time) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = NULL; int bintval = 0; @@ -6747,8 +6686,7 @@ iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap, struct ieee80211_scan_state *ss, struct ieee80211_channel *c) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = vap->iv_bss; struct iwn_scan_hdr *hdr; struct iwn_cmd_data *tx; @@ -6886,9 +6824,9 @@ 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, ifp->if_broadcastaddr); - IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(ifp)); - IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr); + 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); *(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */ *(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */ @@ -7007,8 +6945,7 @@ iwn_auth(struct iwn_softc *sc, struct ieee80211vap *vap) { struct iwn_ops *ops = &sc->ops; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = vap->iv_bss; int error; @@ -7076,8 +7013,7 @@ iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap) { struct iwn_ops *ops = &sc->ops; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni = vap->iv_bss; struct iwn_node_info node; uint32_t htflags = 0; @@ -8663,8 +8599,7 @@ iwn_radio_on(void *arg0, int pending) { struct iwn_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); @@ -8679,8 +8614,7 @@ iwn_radio_off(void *arg0, int pending) { struct iwn_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); @@ -8700,8 +8634,7 @@ iwn_panicked(void *arg0, int pending) { struct iwn_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); int error; @@ -8729,7 +8662,7 @@ } /* Only run start once the NIC is in a useful state, like associated */ - iwn_start_locked(sc->sc_ifp); + iwn_start_locked(sc); IWN_UNLOCK(sc); } @@ -8737,13 +8670,14 @@ 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); @@ -8791,38 +8725,33 @@ 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: iwn_stop_locked(sc); +fail: + sc->sc_flags &= ~IWN_FLAG_RUNNING; + iwn_stop_locked(sc); DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__); } static void -iwn_init(void *arg) +iwn_init(struct iwn_softc *sc) { - 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 (ifp->if_drv_flags & IFF_DRV_RUNNING) - ieee80211_start_all(ic); + if (sc->sc_flags & IWN_FLAG_RUNNING) + ieee80211_start_all(&sc->sc_ic); } static void iwn_stop_locked(struct iwn_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; IWN_LOCK_ASSERT(sc); @@ -8830,7 +8759,7 @@ sc->sc_tx_timer = 0; callout_stop(&sc->watchdog_to); callout_stop(&sc->calib_to); - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_flags &= ~IWN_FLAG_RUNNING; /* Power OFF hardware. */ iwn_hw_stop(sc); @@ -8850,8 +8779,7 @@ static void iwn_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct iwn_softc *sc = ifp->if_softc; + struct iwn_softc *sc = ic->ic_softc; IWN_LOCK(sc); /* make the link LED blink while we're scanning */ @@ -8865,8 +8793,7 @@ static void iwn_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct iwn_softc *sc = ifp->if_softc; + struct iwn_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); IWN_LOCK(sc); @@ -8884,8 +8811,7 @@ iwn_set_channel(struct ieee80211com *ic) { const struct ieee80211_channel *c = ic->ic_curchan; - struct ifnet *ifp = ic->ic_ifp; - struct iwn_softc *sc = ifp->if_softc; + struct iwn_softc *sc = ic->ic_softc; int error; DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); @@ -8942,8 +8868,7 @@ iwn_hw_reset(void *arg0, int pending) { struct iwn_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__); Index: sys/dev/iwn/if_iwnvar.h =================================================================== --- sys/dev/iwn/if_iwnvar.h +++ sys/dev/iwn/if_iwnvar.h @@ -228,18 +228,16 @@ 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) @@ -251,6 +249,7 @@ #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 */ @@ -320,7 +319,6 @@ 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; Index: sys/dev/ral/if_ral_pci.c =================================================================== --- sys/dev/ral/if_ral_pci.c +++ sys/dev/ral/if_ral_pci.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include Index: sys/dev/ral/rt2560.c =================================================================== --- sys/dev/ral/rt2560.c +++ sys/dev/ral/rt2560.c @@ -127,10 +127,10 @@ struct ieee80211_node *); static int rt2560_tx_data(struct rt2560_softc *, struct mbuf *, struct ieee80211_node *); -static void rt2560_start_locked(struct ifnet *); -static void rt2560_start(struct ifnet *); +static int rt2560_transmit(struct ieee80211com *, struct mbuf *); +static void rt2560_start(struct rt2560_softc *); static void rt2560_watchdog(void *); -static int rt2560_ioctl(struct ifnet *, u_long, caddr_t); +static void rt2560_parent(struct ieee80211com *); static void rt2560_bbp_write(struct rt2560_softc *, uint8_t, uint8_t); static uint8_t rt2560_bbp_read(struct rt2560_softc *, uint8_t); @@ -149,7 +149,8 @@ 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 *, uint8_t *); +static void rt2560_set_macaddr(struct rt2560_softc *, + const 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); @@ -197,11 +198,9 @@ rt2560_attach(device_t dev, int id) { struct rt2560_softc *sc = device_get_softc(dev); - struct ieee80211com *ic; - struct ifnet *ifp; - int error; + struct ieee80211com *ic = &sc->sc_ic; uint8_t bands; - uint8_t macaddr[IEEE80211_ADDR_LEN]; + int error; sc->sc_dev = dev; @@ -209,6 +208,7 @@ 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,27 +252,9 @@ goto fail5; } - 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); + rt2560_get_macaddr(sc, ic->ic_macaddr); - ic->ic_ifp = ifp; ic->ic_softc = sc; ic->ic_name = device_get_nameunit(dev); ic->ic_opmode = IEEE80211_M_STA; @@ -303,7 +285,7 @@ setbit(&bands, IEEE80211_MODE_11A); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, macaddr); + ieee80211_ifattach(ic); ic->ic_raw_xmit = rt2560_raw_xmit; ic->ic_updateslot = rt2560_update_slot; ic->ic_update_promisc = rt2560_update_promisc; @@ -313,6 +295,8 @@ 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), @@ -341,7 +325,6 @@ 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); @@ -355,12 +338,12 @@ rt2560_detach(void *xsc) { struct rt2560_softc *sc = xsc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; 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); @@ -368,8 +351,6 @@ rt2560_free_tx_ring(sc, &sc->bcnq); rt2560_free_rx_ring(sc, &sc->rxq); - if_free(ifp); - mtx_destroy(&sc->sc_mtx); return 0; @@ -381,7 +362,7 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct ifnet *ifp = ic->ic_ifp; + struct rt2560_softc *sc = ic->ic_softc; struct rt2560_vap *rvp; struct ieee80211vap *vap; @@ -394,7 +375,7 @@ case IEEE80211_M_MBSS: /* XXXRP: TBD */ if (!TAILQ_EMPTY(&ic->ic_vaps)) { - if_printf(ifp, "only 1 vap supported\n"); + device_printf(sc->sc_dev, "only 1 vap supported\n"); return NULL; } if (opmode == IEEE80211_M_STA) @@ -403,7 +384,8 @@ case IEEE80211_M_WDS: if (TAILQ_EMPTY(&ic->ic_vaps) || ic->ic_opmode != IEEE80211_M_HOSTAP) { - if_printf(ifp, "wds only supported in ap mode\n"); + device_printf(sc->sc_dev, + "wds only supported in ap mode\n"); return NULL; } /* @@ -414,15 +396,12 @@ flags &= ~IEEE80211_CLONE_BSSID; break; default: - if_printf(ifp, "unknown opmode %d\n", opmode); + device_printf(sc->sc_dev, "unknown opmode %d\n", opmode); return NULL; } - rvp = (struct rt2560_vap *) malloc(sizeof(struct rt2560_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (rvp == NULL) - return NULL; + rvp = malloc(sizeof(struct rt2560_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &rvp->ral_vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); /* override state transition machine */ rvp->ral_newstate = vap->iv_newstate; @@ -431,7 +410,8 @@ ieee80211_ratectl_init(vap); /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); if (TAILQ_FIRST(&ic->ic_vaps) == vap) ic->ic_opmode = opmode; return vap; @@ -451,9 +431,8 @@ rt2560_resume(void *xsc) { struct rt2560_softc *sc = xsc; - struct ifnet *ifp = sc->sc_ifp; - if (ifp->if_flags & IFF_UP) + if (sc->sc_ic.ic_nrunning > 0) rt2560_init(sc); } @@ -763,8 +742,7 @@ rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct rt2560_vap *rvp = RT2560_VAP(vap); - struct ifnet *ifp = vap->iv_ic->ic_ifp; - struct rt2560_softc *sc = ifp->if_softc; + struct rt2560_softc *sc = vap->iv_ic->ic_softc; int error; if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) { @@ -792,7 +770,8 @@ vap->iv_opmode == IEEE80211_M_MBSS) { m = ieee80211_beacon_alloc(ni, &rvp->ral_bo); if (m == NULL) { - if_printf(ifp, "could not allocate beacon\n"); + device_printf(sc->sc_dev, + "could not allocate beacon\n"); return ENOBUFS; } ieee80211_ref_node(ni); @@ -926,14 +905,13 @@ 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); @@ -961,7 +939,7 @@ ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + status = 0; break; case RT2560_TX_SUCCESS_RETRY: @@ -973,7 +951,7 @@ ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + status = 0; break; case RT2560_TX_FAIL_RETRY: @@ -985,7 +963,7 @@ ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + status = 1; break; case RT2560_TX_FAIL_INVALID: @@ -993,16 +971,16 @@ default: device_printf(sc->sc_dev, "sending data frame failed " "0x%08x\n", flags); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + status = 1; } bus_dmamap_sync(sc->txq.data_dmat, data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->txq.data_dmat, data->map); - m_freem(m); - data->m = NULL; - ieee80211_free_node(data->ni); + + ieee80211_tx_complete(ni, m, status); data->ni = NULL; + data->m = NULL; /* descriptor is no longer valid */ desc->flags &= ~htole32(RT2560_TX_VALID); @@ -1019,19 +997,13 @@ if (sc->prioq.queued == 0 && sc->txq.queued == 0) sc->sc_tx_timer = 0; - 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); - } + if (sc->txq.queued < RT2560_TX_RING_COUNT - 1) + rt2560_start(sc); } 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; @@ -1103,13 +1075,8 @@ if (sc->prioq.queued == 0 && sc->txq.queued == 0) sc->sc_tx_timer = 0; - 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); - } + if (sc->prioq.queued < RT2560_PRIO_RING_COUNT) + rt2560_start(sc); } /* @@ -1119,8 +1086,7 @@ static void rt2560_decryption_intr(struct rt2560_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct rt2560_rx_desc *desc; struct rt2560_rx_data *data; bus_addr_t physaddr; @@ -1146,13 +1112,13 @@ break; if (data->drop) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } if ((le32toh(desc->flags) & RT2560_RX_CIPHER_MASK) != 0 && (le32toh(desc->flags) & RT2560_RX_ICV_ERROR)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } @@ -1165,7 +1131,7 @@ */ mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mnew == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } @@ -1188,7 +1154,7 @@ panic("%s: could not load old rx mbuf", device_get_name(sc->sc_dev)); } - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } @@ -1201,7 +1167,6 @@ desc->physaddr = htole32(physaddr); /* finalize mbuf */ - m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = (le32toh(desc->flags) >> 16) & 0xfff; @@ -1321,8 +1286,7 @@ static void rt2560_beacon_expire(struct rt2560_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct rt2560_vap *rvp = RT2560_VAP(vap); struct rt2560_tx_data *data; @@ -1363,7 +1327,6 @@ rt2560_intr(void *arg) { struct rt2560_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; uint32_t r; RAL_LOCK(sc); @@ -1372,7 +1335,7 @@ RAL_WRITE(sc, RT2560_CSR8, 0xffffffff); /* don't re-enable interrupts if we're shutting down */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!(sc->sc_flags & RT2560_F_RUNNING)) { RAL_UNLOCK(sc); return; } @@ -1440,8 +1403,7 @@ 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 ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint16_t plcp_length; int remainder; @@ -1916,55 +1878,57 @@ 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_locked(struct ifnet *ifp) +rt2560_start(struct rt2560_softc *sc) { - struct rt2560_softc *sc = ifp->if_softc; - struct mbuf *m; struct ieee80211_node *ni; + struct mbuf *m; RAL_LOCK_ASSERT(sc); - 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; - } + 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); - 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(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running")); + KASSERT(sc->sc_flags & RT2560_F_RUNNING, ("not running")); if (sc->sc_invalid) /* card ejected */ return; @@ -1973,51 +1937,33 @@ rt2560_tx_intr(sc); if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { - if_printf(ifp, "device timeout\n"); + device_printf(sc->sc_dev, "device timeout\n"); rt2560_init_locked(sc); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); /* NB: callout is reset in rt2560_init() */ return; } callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc); } -static int -rt2560_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +rt2560_parent(struct ieee80211com *ic) { - struct rt2560_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + struct rt2560_softc *sc = ic->ic_softc; + int startall = 0; - 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; + 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); } static void @@ -2101,8 +2047,7 @@ static void rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint8_t power, tmp; u_int i, chan; @@ -2201,8 +2146,7 @@ static void rt2560_set_channel(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct rt2560_softc *sc = ifp->if_softc; + struct rt2560_softc *sc = ic->ic_softc; RAL_LOCK(sc); rt2560_set_chan(sc, ic->ic_curchan); @@ -2238,8 +2182,7 @@ static void rt2560_enable_tsf_sync(struct rt2560_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint16_t logcwmin, preload; uint32_t tmp; @@ -2280,8 +2223,7 @@ static void rt2560_update_plcp(struct rt2560_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; /* no short preamble for 1Mbps */ RAL_WRITE(sc, RT2560_PLCP1MCSR, 0x00700400); @@ -2360,8 +2302,7 @@ const struct ieee80211_rateset *rs) { #define RV(r) ((r) & IEEE80211_RATE_VAL) - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t mask = 0; uint8_t rate; int i; @@ -2406,7 +2347,7 @@ } static void -rt2560_set_macaddr(struct rt2560_softc *sc, uint8_t *addr) +rt2560_set_macaddr(struct rt2560_softc *sc, const uint8_t *addr) { uint32_t tmp; @@ -2444,13 +2385,13 @@ tmp = RAL_READ(sc, RT2560_RXCSR0); tmp &= ~RT2560_DROP_NOT_TO_ME; - if (!(ic->ic_ifp->if_flags & IFF_PROMISC)) + if (ic->ic_promisc == 0) tmp |= RT2560_DROP_NOT_TO_ME; RAL_WRITE(sc, RT2560_RXCSR0, tmp); DPRINTF(sc, "%s promiscuous mode\n", - (ic->ic_ifp->if_flags & IFF_PROMISC) ? "entering" : "leaving"); + (ic->ic_promisc > 0) ? "entering" : "leaving"); } static const char * @@ -2516,19 +2457,17 @@ static void rt2560_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct rt2560_softc *sc = ifp->if_softc; + struct rt2560_softc *sc = ic->ic_softc; /* abort TSF synchronization */ RAL_WRITE(sc, RT2560_CSR14, 0); - rt2560_set_bssid(sc, ifp->if_broadcastaddr); + rt2560_set_bssid(sc, ieee80211broadcastaddr); } static void rt2560_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct rt2560_softc *sc = ifp->if_softc; + struct rt2560_softc *sc = ic->ic_softc; struct ieee80211vap *vap = ic->ic_scan->ss_vap; rt2560_enable_tsf_sync(sc); @@ -2622,8 +2561,8 @@ rt2560_init_locked(struct rt2560_softc *sc) { #define N(a) (sizeof (a) / sizeof ((a)[0])) - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; int i; @@ -2654,7 +2593,7 @@ 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, IF_LLADDR(ifp)); + rt2560_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); /* set basic rate set (will be updated later) */ RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153); @@ -2684,7 +2623,7 @@ if (ic->ic_opmode != IEEE80211_M_HOSTAP && ic->ic_opmode != IEEE80211_M_MBSS) tmp |= RT2560_DROP_TODS; - if (!(ifp->if_flags & IFF_PROMISC)) + if (ic->ic_promisc == 0) tmp |= RT2560_DROP_NOT_TO_ME; } RAL_WRITE(sc, RT2560_RXCSR0, tmp); @@ -2699,8 +2638,7 @@ /* enable interrupts */ RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_flags |= RT2560_F_RUNNING; callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc); #undef N @@ -2710,21 +2648,19 @@ rt2560_init(void *priv) { struct rt2560_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; RAL_LOCK(sc); rt2560_init_locked(sc); RAL_UNLOCK(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->sc_flags & RT2560_F_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); @@ -2735,8 +2671,8 @@ callout_stop(&sc->watchdog_ch); sc->sc_tx_timer = 0; - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + if (sc->sc_flags & RT2560_F_RUNNING) { + sc->sc_flags &= ~RT2560_F_RUNNING; /* abort Tx */ RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX); @@ -2758,7 +2694,6 @@ 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 @@ -2776,29 +2711,24 @@ const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct rt2560_softc *sc = ifp->if_softc; + struct rt2560_softc *sc = ic->ic_softc; RAL_LOCK(sc); /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!(sc->sc_flags & RT2560_F_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 @@ -2820,7 +2750,6 @@ return 0; bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); ieee80211_free_node(ni); RAL_UNLOCK(sc); return EIO; /* XXX */ Index: sys/dev/ral/rt2560var.h =================================================================== --- sys/dev/ral/rt2560var.h +++ sys/dev/ral/rt2560var.h @@ -105,13 +105,13 @@ #define RT2560_VAP(vap) ((struct rt2560_vap *)(vap)) struct rt2560_softc { - struct ifnet *sc_ifp; + struct ieee80211com sc_ic; + struct mtx sc_mtx; + struct mbufq sc_snd; 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,8 +152,7 @@ struct rt2560_tx_radiotap_header sc_txtap; int sc_txtap_len; #define RT2560_F_INPUT_RUNNING 0x1 -#define RT2560_F_PRIO_OACTIVE 0x2 -#define RT2560_F_DATA_OACTIVE 0x4 +#define RT2560_F_RUNNING 0x2 int sc_flags; }; Index: sys/dev/ral/rt2661.c =================================================================== --- sys/dev/ral/rt2661.c +++ sys/dev/ral/rt2661.c @@ -121,12 +121,12 @@ struct ieee80211_node *, int); static int rt2661_tx_mgt(struct rt2661_softc *, struct mbuf *, struct ieee80211_node *); -static void rt2661_start_locked(struct ifnet *); -static void rt2661_start(struct ifnet *); +static int rt2661_transmit(struct ieee80211com *, struct mbuf *); +static void rt2661_start(struct rt2661_softc *); static int rt2661_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); static void rt2661_watchdog(void *); -static int rt2661_ioctl(struct ifnet *, u_long, caddr_t); +static void rt2661_parent(struct ieee80211com *); static void rt2661_bbp_write(struct rt2661_softc *, uint8_t, uint8_t); static uint8_t rt2661_bbp_read(struct rt2661_softc *, uint8_t); @@ -197,27 +197,19 @@ rt2661_attach(device_t dev, int id) { struct rt2661_softc *sc = device_get_softc(dev); - struct ieee80211com *ic; - struct ifnet *ifp; + struct ieee80211com *ic = &sc->sc_ic; 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++) { @@ -233,7 +225,7 @@ } /* retrieve RF rev. no and various other things from EEPROM */ - rt2661_read_eeprom(sc, macaddr); + rt2661_read_eeprom(sc, ic->ic_macaddr); device_printf(dev, "MAC/BBP RT%X, RF %s\n", val, rt2661_get_rf(sc->rf_rev)); @@ -263,17 +255,6 @@ 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; @@ -305,7 +286,7 @@ setbit(&bands, IEEE80211_MODE_11A); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, macaddr); + ieee80211_ifattach(ic); #if 0 ic->ic_wme.wme_update = rt2661_wme_update; #endif @@ -315,7 +296,8 @@ 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; @@ -339,7 +321,6 @@ fail2: while (--ac >= 0) rt2661_free_tx_ring(sc, &sc->txq[ac]); fail1: mtx_destroy(&sc->sc_mtx); - if_free(ifp); return error; } @@ -347,14 +328,14 @@ rt2661_detach(void *xsc) { struct rt2661_softc *sc = xsc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; 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]); @@ -363,8 +344,6 @@ rt2661_free_tx_ring(sc, &sc->mgtq); rt2661_free_rx_ring(sc, &sc->rxq); - if_free(ifp); - mtx_destroy(&sc->sc_mtx); return 0; @@ -376,7 +355,7 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct ifnet *ifp = ic->ic_ifp; + struct rt2661_softc *sc = ic->ic_softc; struct rt2661_vap *rvp; struct ieee80211vap *vap; @@ -389,7 +368,7 @@ case IEEE80211_M_MBSS: /* XXXRP: TBD */ if (!TAILQ_EMPTY(&ic->ic_vaps)) { - if_printf(ifp, "only 1 vap supported\n"); + device_printf(sc->sc_dev, "only 1 vap supported\n"); return NULL; } if (opmode == IEEE80211_M_STA) @@ -398,7 +377,8 @@ case IEEE80211_M_WDS: if (TAILQ_EMPTY(&ic->ic_vaps) || ic->ic_opmode != IEEE80211_M_HOSTAP) { - if_printf(ifp, "wds only supported in ap mode\n"); + device_printf(sc->sc_dev, + "wds only supported in ap mode\n"); return NULL; } /* @@ -409,15 +389,12 @@ flags &= ~IEEE80211_CLONE_BSSID; break; default: - if_printf(ifp, "unknown opmode %d\n", opmode); + device_printf(sc->sc_dev, "unknown opmode %d\n", opmode); return NULL; } - rvp = (struct rt2661_vap *) malloc(sizeof(struct rt2661_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (rvp == NULL) - return NULL; + rvp = malloc(sizeof(struct rt2661_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &rvp->ral_vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); /* override state transition machine */ rvp->ral_newstate = vap->iv_newstate; @@ -428,7 +405,8 @@ ieee80211_ratectl_init(vap); /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); if (TAILQ_FIRST(&ic->ic_vaps) == vap) ic->ic_opmode = opmode; return vap; @@ -464,9 +442,8 @@ rt2661_resume(void *xsc) { struct rt2661_softc *sc = xsc; - struct ifnet *ifp = sc->sc_ifp; - if (ifp->if_flags & IFF_UP) + if (sc->sc_ic.ic_nrunning > 0) rt2661_init(sc); } @@ -770,7 +747,7 @@ { struct rt2661_vap *rvp = RT2661_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct rt2661_softc *sc = ic->ic_ifp->if_softc; + struct rt2661_softc *sc = ic->ic_softc; int error; if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) { @@ -869,11 +846,10 @@ 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 qid, retrycnt; + int error, qid, retrycnt; struct ieee80211vap *vap; for (;;) { @@ -911,7 +887,7 @@ ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + error = 0; break; case RT2661_TX_RETRY_FAIL: @@ -923,14 +899,14 @@ ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + error = 1; break; default: /* other failure */ device_printf(sc->sc_dev, "sending data frame failed 0x%08x\n", val); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + error = 1; } DPRINTFN(sc, 15, "tx done q=%d idx=%u\n", qid, txq->stat); @@ -939,17 +915,12 @@ if (++txq->stat >= txq->count) /* faster than % count */ txq->stat = 0; - 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); + ieee80211_tx_complete(ni, m, error); } sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - rt2661_start_locked(ifp); + rt2661_start(sc); } static void @@ -987,8 +958,7 @@ static void rt2661_rx_intr(struct rt2661_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct rt2661_rx_desc *desc; struct rt2661_rx_data *data; bus_addr_t physaddr; @@ -1017,12 +987,12 @@ */ DPRINTFN(sc, 5, "PHY or CRC error flags 0x%08x\n", le32toh(desc->flags)); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } if ((le32toh(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } @@ -1035,7 +1005,7 @@ */ mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mnew == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } @@ -1058,7 +1028,7 @@ panic("%s: could not load old rx mbuf", device_get_name(sc->sc_dev)); } - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } @@ -1071,7 +1041,6 @@ desc->physaddr = htole32(physaddr); /* finalize mbuf */ - m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = (le32toh(desc->flags) >> 16) & 0xfff; @@ -1156,7 +1125,6 @@ rt2661_intr(void *arg) { struct rt2661_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; uint32_t r1, r2; RAL_LOCK(sc); @@ -1166,7 +1134,7 @@ RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff); /* don't re-enable interrupts if we're shutting down */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!(sc->sc_flags & RAL_RUNNING)) { RAL_UNLOCK(sc); return; } @@ -1242,8 +1210,7 @@ uint32_t flags, uint16_t xflags, int len, int rate, const bus_dma_segment_t *segs, int nsegs, int ac) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint16_t plcp_length; int i, remainder; @@ -1461,8 +1428,7 @@ struct ieee80211_node *ni, int ac) { struct ieee80211vap *vap = ni->ni_vap; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct rt2661_tx_ring *txq = &sc->txq[ac]; struct rt2661_tx_desc *desc; struct rt2661_tx_data *data; @@ -1604,10 +1570,31 @@ 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_locked(struct ifnet *ifp) +rt2661_start(struct rt2661_softc *sc) { - struct rt2661_softc *sc = ifp->if_softc; struct mbuf *m; struct ieee80211_node *ni; int ac; @@ -1615,69 +1602,50 @@ RAL_LOCK_ASSERT(sc); /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) || sc->sc_invalid) + if (!(sc->sc_flags & RAL_RUNNING) || sc->sc_invalid) return; - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { ac = M_WME_GETAC(m); if (sc->txq[ac].queued >= RT2661_TX_RING_COUNT - 1) { /* there is no place left in this ring */ - IFQ_DRV_PREPEND(&ifp->if_snd, m); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; + mbufq_prepend(&sc->sc_snd, m); 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(ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(ni->ni_vap->iv_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 ifnet *ifp = ic->ic_ifp; - struct rt2661_softc *sc = ifp->if_softc; + struct rt2661_softc *sc = ic->ic_softc; RAL_LOCK(sc); /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!(sc->sc_flags & RAL_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. @@ -1691,7 +1659,6 @@ return 0; bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); ieee80211_free_node(ni); RAL_UNLOCK(sc); return EIO; /* XXX */ @@ -1701,61 +1668,42 @@ rt2661_watchdog(void *arg) { struct rt2661_softc *sc = (struct rt2661_softc *)arg; - struct ifnet *ifp = sc->sc_ifp; RAL_LOCK_ASSERT(sc); - KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running")); + KASSERT(sc->sc_flags & RAL_RUNNING, ("not running")); if (sc->sc_invalid) /* card ejected */ return; if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { - if_printf(ifp, "device timeout\n"); + device_printf(sc->sc_dev, "device timeout\n"); rt2661_init_locked(sc); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); /* NB: callout is reset in rt2661_init() */ return; } callout_reset(&sc->watchdog_ch, hz, rt2661_watchdog, sc); } -static int -rt2661_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +rt2661_parent(struct ieee80211com *ic) { - struct rt2661_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + struct rt2661_softc *sc = ic->ic_softc; + int startall = 0; - 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; + 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); } static void @@ -1879,8 +1827,7 @@ static void rt2661_enable_mrr(struct rt2661_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; tmp = RAL_READ(sc, RT2661_TXRX_CSR4); @@ -1896,8 +1843,7 @@ static void rt2661_set_txpreamble(struct rt2661_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; tmp = RAL_READ(sc, RT2661_TXRX_CSR4); @@ -1914,8 +1860,7 @@ const struct ieee80211_rateset *rs) { #define RV(r) ((r) & IEEE80211_RATE_VAL) - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t mask = 0; uint8_t rate; int i; @@ -1984,8 +1929,7 @@ static void rt2661_set_chan(struct rt2661_softc *sc, struct ieee80211_channel *c) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; const struct rfprog *rfprog; uint8_t bbp3, bbp94 = RT2661_BBPR94_DEFAULT; int8_t power; @@ -2088,13 +2032,13 @@ tmp = RAL_READ(sc, RT2661_TXRX_CSR0); tmp &= ~RT2661_DROP_NOT_TO_ME; - if (!(ic->ic_ifp->if_flags & IFF_PROMISC)) + if (ic->ic_promisc == 0) tmp |= RT2661_DROP_NOT_TO_ME; RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp); DPRINTF(sc, "%s promiscuous mode\n", - (ic->ic_ifp->if_flags & IFF_PROMISC) ? "entering" : "leaving"); + (ic->ic_promisc > 0) ? "entering" : "leaving"); } /* @@ -2103,7 +2047,7 @@ static int rt2661_wme_update(struct ieee80211com *ic) { - struct rt2661_softc *sc = ic->ic_ifp->if_softc; + struct rt2661_softc *sc = ic->ic_softc; const struct wmeParams *wmep; wmep = ic->ic_wme.wme_chanParams.cap_wmeParams; @@ -2301,8 +2245,8 @@ rt2661_init_locked(struct rt2661_softc *sc) { #define N(a) (sizeof (a) / sizeof ((a)[0])) - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp, sta[3]; int i, error, ntries; @@ -2311,7 +2255,7 @@ if ((sc->sc_flags & RAL_FW_LOADED) == 0) { error = rt2661_load_microcode(sc); if (error != 0) { - if_printf(ifp, + device_printf(sc->sc_dev, "%s: could not load 8051 microcode, error %d\n", __func__, error); return; @@ -2364,7 +2308,7 @@ 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, IF_LLADDR(ifp)); + rt2661_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); /* set host ready */ RAL_WRITE(sc, RT2661_MAC_CSR1, 3); @@ -2403,7 +2347,7 @@ if (ic->ic_opmode != IEEE80211_M_HOSTAP && ic->ic_opmode != IEEE80211_M_MBSS) tmp |= RT2661_DROP_TODS; - if (!(ifp->if_flags & IFF_PROMISC)) + if (ic->ic_promisc == 0) tmp |= RT2661_DROP_NOT_TO_ME; } @@ -2425,8 +2369,7 @@ /* kick Rx */ RAL_WRITE(sc, RT2661_RX_CNTL_CSR, 1); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_flags |= RAL_RUNNING; callout_reset(&sc->watchdog_ch, hz, rt2661_watchdog, sc); #undef N @@ -2436,23 +2379,21 @@ rt2661_init(void *priv) { struct rt2661_softc *sc = priv; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; RAL_LOCK(sc); rt2661_init_locked(sc); RAL_UNLOCK(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->sc_flags & RAL_RUNNING) ieee80211_start_all(ic); /* start all vap's */ } void rt2661_stop_locked(struct rt2661_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - uint32_t tmp; volatile int *flags = &sc->sc_flags; + uint32_t tmp; while (*flags & RAL_INPUT_RUNNING) msleep(sc, &sc->sc_mtx, 0, "ralrunning", hz/10); @@ -2460,8 +2401,8 @@ callout_stop(&sc->watchdog_ch); sc->sc_tx_timer = 0; - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + if (sc->sc_flags & RAL_RUNNING) { + sc->sc_flags &= ~RAL_RUNNING; /* abort Tx (for all 5 Tx rings) */ RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 0x1f << 16); @@ -2505,7 +2446,6 @@ 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; @@ -2517,7 +2457,7 @@ case 0x0302: imagename = "rt2561fw"; break; case 0x0401: imagename = "rt2661fw"; break; default: - if_printf(ifp, "%s: unexpected pci device id 0x%x, " + device_printf(sc->sc_dev, "%s: unexpected pci device id 0x%x, " "don't know how to retrieve firmware\n", __func__, sc->sc_id); return EINVAL; @@ -2526,7 +2466,8 @@ fp = firmware_get(imagename); RAL_LOCK(sc); if (fp == NULL) { - if_printf(ifp, "%s: unable to retrieve firmware image %s\n", + device_printf(sc->sc_dev, + "%s: unable to retrieve firmware image %s\n", __func__, imagename); return EINVAL; } @@ -2557,8 +2498,8 @@ DELAY(100); } if (ntries == 500) { - if_printf(ifp, "%s: timeout waiting for MCU to initialize\n", - __func__); + device_printf(sc->sc_dev, + "%s: timeout waiting for MCU to initialize\n", __func__); error = EIO; } else error = 0; @@ -2726,8 +2667,7 @@ static void rt2661_enable_tsf_sync(struct rt2661_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; @@ -2811,21 +2751,19 @@ static void rt2661_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct rt2661_softc *sc = ifp->if_softc; + struct rt2661_softc *sc = ic->ic_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, ifp->if_broadcastaddr); + rt2661_set_bssid(sc, ieee80211broadcastaddr); } static void rt2661_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct rt2661_softc *sc = ifp->if_softc; + struct rt2661_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); rt2661_enable_tsf_sync(sc); @@ -2836,8 +2774,7 @@ static void rt2661_set_channel(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct rt2661_softc *sc = ifp->if_softc; + struct rt2661_softc *sc = ic->ic_softc; RAL_LOCK(sc); rt2661_set_chan(sc, ic->ic_curchan); Index: sys/dev/ral/rt2661var.h =================================================================== --- sys/dev/ral/rt2661var.h +++ sys/dev/ral/rt2661var.h @@ -97,13 +97,13 @@ #define RT2661_VAP(vap) ((struct rt2661_vap *)(vap)) struct rt2661_softc { - struct ifnet *sc_ifp; + struct ieee80211com sc_ic; + struct mtx sc_mtx; + struct mbufq sc_snd; 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,6 +117,7 @@ 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; Index: sys/dev/ral/rt2860.c =================================================================== --- sys/dev/ral/rt2860.c +++ sys/dev/ral/rt2860.c @@ -122,10 +122,10 @@ static int rt2860_tx_raw(struct rt2860_softc *, struct mbuf *, struct ieee80211_node *, const struct ieee80211_bpf_params *params); -static void rt2860_start(struct ifnet *); -static void rt2860_start_locked(struct ifnet *); +static int rt2860_transmit(struct ieee80211com *, struct mbuf *); +static void rt2860_start(struct rt2860_softc *); static void rt2860_watchdog(void *); -static int rt2860_ioctl(struct ifnet *, u_long, caddr_t); +static void rt2860_parent(struct ieee80211com *); static void rt2860_mcu_bbp_write(struct rt2860_softc *, uint8_t, uint8_t); static 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_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 ifnet *); +static void rt2860_updateprot(struct rt2860_softc *); static int rt2860_updateedca(struct ieee80211com *); #ifdef HW_CRYPTO static int rt2860_set_key(struct ieee80211com *, struct ieee80211_node *, @@ -230,27 +230,19 @@ rt2860_attach(device_t dev, int id) { struct rt2860_softc *sc = device_get_softc(dev); - struct ieee80211com *ic; - struct ifnet *ifp; + struct ieee80211com *ic = &sc->sc_ic; 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++) { @@ -273,11 +265,11 @@ sc->sc_flags |= RT2860_ADVANCED_PS; /* retrieve RF rev. no and various other things from EEPROM */ - rt2860_read_eeprom(sc, macaddr); + rt2860_read_eeprom(sc, ic->ic_macaddr); device_printf(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), " "RF %s (MIMO %dT%dR), address %6D\n", sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev), - sc->ntxchains, sc->nrxchains, macaddr, ":"); + sc->ntxchains, sc->nrxchains, ic->ic_macaddr, ":"); /* * Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings. @@ -304,17 +296,6 @@ 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; @@ -345,7 +326,7 @@ setbit(&bands, IEEE80211_MODE_11A); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, macaddr); + ieee80211_ifattach(ic); ic->ic_wme.wme_update = rt2860_updateedca; ic->ic_scan_start = rt2860_scan_start; @@ -357,7 +338,8 @@ 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; @@ -381,7 +363,6 @@ fail2: while (--qid >= 0) rt2860_free_tx_ring(sc, &sc->txq[qid]); fail1: mtx_destroy(&sc->sc_mtx); - if_free(ifp); return error; } @@ -389,8 +370,7 @@ rt2860_detach(void *xsc) { struct rt2860_softc *sc = xsc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; int qid; RAL_LOCK(sc); @@ -398,14 +378,12 @@ 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; @@ -431,9 +409,8 @@ rt2860_resume(void *xsc) { struct rt2860_softc *sc = xsc; - struct ifnet *ifp = sc->sc_ifp; - if (ifp->if_flags & IFF_UP) + if (sc->sc_ic.ic_nrunning > 0) rt2860_init(sc); } @@ -443,7 +420,7 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct ifnet *ifp = ic->ic_ifp; + struct rt2860_softc *sc = ic->ic_softc; struct rt2860_vap *rvp; struct ieee80211vap *vap; @@ -456,7 +433,7 @@ case IEEE80211_M_MBSS: /* XXXRP: TBD */ if (!TAILQ_EMPTY(&ic->ic_vaps)) { - if_printf(ifp, "only 1 vap supported\n"); + device_printf(sc->sc_dev, "only 1 vap supported\n"); return NULL; } if (opmode == IEEE80211_M_STA) @@ -465,7 +442,8 @@ case IEEE80211_M_WDS: if (TAILQ_EMPTY(&ic->ic_vaps) || ic->ic_opmode != IEEE80211_M_HOSTAP) { - if_printf(ifp, "wds only supported in ap mode\n"); + device_printf(sc->sc_dev, + "wds only supported in ap mode\n"); return NULL; } /* @@ -476,14 +454,12 @@ flags &= ~IEEE80211_CLONE_BSSID; break; default: - if_printf(ifp, "unknown opmode %d\n", opmode); + device_printf(sc->sc_dev, "unknown opmode %d\n", opmode); return NULL; } - rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_NOWAIT | M_ZERO); - if (rvp == NULL) - return NULL; + rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &rvp->ral_vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); /* override state transition machine */ rvp->ral_newstate = vap->iv_newstate; @@ -497,7 +473,8 @@ ieee80211_ratectl_init(vap); /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); if (TAILQ_FIRST(&ic->ic_vaps) == vap) ic->ic_opmode = opmode; return vap; @@ -829,7 +806,7 @@ static void rt2860_updatestats(struct rt2860_softc *sc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; /* * In IBSS or HostAP modes (when the hardware sends beacons), the @@ -856,7 +833,7 @@ rt2860_newassoc(struct ieee80211_node *ni, int isnew) { struct ieee80211com *ic = ni->ni_ic; - struct rt2860_softc *sc = ic->ic_ifp->if_softc; + struct rt2860_softc *sc = ic->ic_softc; uint8_t wcid; wcid = IEEE80211_AID(ni->ni_associd); @@ -875,7 +852,7 @@ rt2860_node_free(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; - struct rt2860_softc *sc = ic->ic_ifp->if_softc; + struct rt2860_softc *sc = ic->ic_softc; uint8_t wcid; if (ni->ni_associd != 0) { @@ -923,7 +900,7 @@ { struct rt2860_vap *rvp = RT2860_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct rt2860_softc *sc = ic->ic_ifp->if_softc; + struct rt2860_softc *sc = ic->ic_softc; uint32_t tmp; int error; @@ -1101,7 +1078,6 @@ 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; @@ -1137,7 +1113,8 @@ } else { ieee80211_ratectl_tx_complete(ni->ni_vap, ni, IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); } } } @@ -1145,7 +1122,6 @@ 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; @@ -1163,15 +1139,11 @@ ieee80211_process_callback(data->ni, data->m, 0); } - m_freem(data->m); - ieee80211_free_node(data->ni); - data->m = NULL; + ieee80211_tx_complete(data->ni, data->m, 0); data->ni = NULL; - + data->m = 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; @@ -1180,8 +1152,7 @@ sc->sc_tx_timer = 0; if (ring->queued < RT2860_TX_RING_COUNT) sc->qfullmsk &= ~(1 << qid); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - rt2860_start_locked(ifp); + rt2860_start(sc); } /* @@ -1206,8 +1177,7 @@ rt2860_rx_intr(struct rt2860_softc *sc) { struct rt2860_rx_radiotap_header *tap; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *m, *m1; @@ -1234,7 +1204,7 @@ if (__predict_false(rxd->flags & htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } @@ -1243,14 +1213,14 @@ /* report MIC failures to net80211 for TKIP */ ic->ic_stats.is_rx_locmicfail++; ieee80211_michael_mic_failure(ic, 0/* XXX */); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } #endif m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (__predict_false(m1 == NULL)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } @@ -1274,7 +1244,7 @@ } /* physical address may have changed */ rxd->sdp0 = htole32(physaddr); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto skip; } @@ -1289,7 +1259,6 @@ 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; @@ -1399,7 +1368,7 @@ #endif /* check if protection mode has changed */ if ((sc->sc_ic_flags ^ ic->ic_flags) & IEEE80211_F_USEPROT) { - rt2860_updateprot(ic); + rt2860_updateprot(sc); sc->sc_ic_flags = ic->ic_flags; } #endif @@ -1408,7 +1377,7 @@ static void rt2860_gp_intr(struct rt2860_softc *sc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); DPRINTFN(2, ("GP timeout state=%d\n", vap->iv_state)); @@ -1480,8 +1449,7 @@ static int rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct rt2860_tx_ring *ring; struct rt2860_tx_data *data; @@ -1725,14 +1693,13 @@ const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct rt2860_softc *sc = ifp->if_softc; + struct rt2860_softc *sc = ic->ic_softc; int error; RAL_LOCK(sc); /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!(sc->sc_flags & RT2860_RUNNNING)) { RAL_UNLOCK(sc); m_freem(m); ieee80211_free_node(ni); @@ -1754,7 +1721,6 @@ 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); @@ -1765,8 +1731,7 @@ rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct rt2860_tx_ring *ring; struct rt2860_tx_data *data; @@ -1973,41 +1938,46 @@ return 0; } -static void -rt2860_start(struct ifnet *ifp) +static int +rt2860_transmit(struct ieee80211com *ic, struct mbuf *m) { - struct rt2860_softc *sc = ifp->if_softc; + struct rt2860_softc *sc = ic->ic_softc; + int error; RAL_LOCK(sc); - rt2860_start_locked(ifp); + if ((sc->sc_flags & RT2860_RUNNNING) == 0) { + RAL_UNLOCK(sc); + return (ENXIO); + } + error = mbufq_enqueue(&sc->sc_snd, m); + if (error) { + RAL_UNLOCK(sc); + return (error); + } + rt2860_start(sc); RAL_UNLOCK(sc); + + return (0); } static void -rt2860_start_locked(struct ifnet *ifp) +rt2860_start(struct rt2860_softc *sc) { - struct rt2860_softc *sc = ifp->if_softc; struct ieee80211_node *ni; struct mbuf *m; RAL_LOCK_ASSERT(sc); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || - (ifp->if_drv_flags & IFF_DRV_OACTIVE)) + if ((sc->sc_flags & RT2860_RUNNNING) == 0) return; - 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; + while (!SLIST_EMPTY(&sc->data_pool) && sc->qfullmsk == 0 && + (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { 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; @@ -2018,61 +1988,42 @@ rt2860_watchdog(void *arg) { struct rt2860_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; RAL_LOCK_ASSERT(sc); - KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running")); + KASSERT(sc->sc_flags & RT2860_RUNNNING, ("not running")); if (sc->sc_invalid) /* card ejected */ return; if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { - if_printf(ifp, "device timeout\n"); + device_printf(sc->sc_dev, "device timeout\n"); rt2860_stop_locked(sc); rt2860_init_locked(sc); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); return; } callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); } -static int -rt2860_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +rt2860_parent(struct ieee80211com *ic) { - struct rt2860_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *)data; - int error = 0, startall = 0; + struct rt2860_softc *sc = ic->ic_softc; + int startall = 0; - 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; + 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); } /* @@ -2295,8 +2246,7 @@ static void rt2860_set_txpreamble(struct rt2860_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; tmp = RAL_READ(sc, RT2860_AUTO_RSP_CFG); @@ -2311,8 +2261,7 @@ const struct ieee80211_rateset *rs) { #define RV(r) ((r) & IEEE80211_RATE_VAL) - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t mask = 0; uint8_t rate; int i; @@ -2333,8 +2282,7 @@ static void rt2860_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct rt2860_softc *sc = ifp->if_softc; + struct rt2860_softc *sc = ic->ic_softc; uint32_t tmp; tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); @@ -2347,8 +2295,7 @@ static void rt2860_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct rt2860_softc *sc = ifp->if_softc; + struct rt2860_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); if (vap->iv_state == IEEE80211_S_RUN) { @@ -2360,8 +2307,7 @@ static void rt2860_set_channel(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct rt2860_softc *sc = ifp->if_softc; + struct rt2860_softc *sc = ic->ic_softc; RAL_LOCK(sc); rt2860_switch_chan(sc, ic->ic_curchan); @@ -3113,10 +3059,9 @@ } static void -rt2860_updateprot(struct ifnet *ifp) +rt2860_updateprot(struct rt2860_softc *sc) { - struct rt2860_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; @@ -3145,7 +3090,7 @@ tmp = RAL_READ(sc, RT2860_RX_FILTR_CFG); tmp &= ~RT2860_DROP_NOT_MYBSS; - if (!(ic->ic_ifp->if_flags & IFF_PROMISC)) + if (ic->ic_promisc == 0) tmp |= RT2860_DROP_NOT_MYBSS; RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); } @@ -3153,7 +3098,7 @@ static int rt2860_updateedca(struct ieee80211com *ic) { - struct rt2860_softc *sc = ic->ic_ifp->if_softc; + struct rt2860_softc *sc = ic->ic_softc; const struct wmeParams *wmep; int aci; @@ -3325,8 +3270,7 @@ static int8_t rt2860_rssi2dbm(struct rt2860_softc *sc, uint8_t rssi, uint8_t rxchain) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_channel *c = ic->ic_curchan; int delta; @@ -3801,8 +3745,7 @@ static int rt2860_txrx_enable(struct rt2860_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; int ntries; @@ -3848,22 +3791,21 @@ rt2860_init(void *arg) { struct rt2860_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; RAL_LOCK(sc); rt2860_init_locked(sc); RAL_UNLOCK(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->sc_flags & RT2860_RUNNNING) ieee80211_start_all(ic); } static void rt2860_init_locked(struct rt2860_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; uint8_t bbp1, bbp3; int i, qid, ridx, ntries, error; @@ -3899,7 +3841,7 @@ return; } - rt2860_set_macaddr(sc, IF_LLADDR(ifp)); + rt2860_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); /* init Tx power for all Tx rates (from EEPROM) */ for (ridx = 0; ridx < 5; ridx++) { @@ -4096,7 +4038,7 @@ RAL_WRITE(sc, RT2860_TX_RTS_CFG, tmp); /* setup initial protection mode */ - rt2860_updateprot(ifp); + rt2860_updateprot(sc); /* turn radio LED on */ rt2860_set_leds(sc, RT2860_LED_RADIO); @@ -4115,8 +4057,7 @@ if (sc->sc_flags & RT2860_ADVANCED_PS) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_PSLEVEL, sc->pslevel, 0); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_flags |= RT2860_RUNNNING; callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); } @@ -4134,16 +4075,15 @@ static void rt2860_stop_locked(struct rt2860_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; uint32_t tmp; int qid; - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->sc_flags & RT2860_RUNNNING) rt2860_set_leds(sc, 0); /* turn all LEDs off */ callout_stop(&sc->watchdog_ch); sc->sc_tx_timer = 0; - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_flags &= ~RT2860_RUNNNING; /* disable interrupts */ RAL_WRITE(sc, RT2860_INT_MASK, 0); @@ -4294,8 +4234,7 @@ static void rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; u_int chan, group; chan = ieee80211_chan2ieee(ic, c); @@ -4364,8 +4303,7 @@ static void rt2860_enable_tsf_sync(struct rt2860_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; Index: sys/dev/ral/rt2860var.h =================================================================== --- sys/dev/ral/rt2860var.h +++ sys/dev/ral/rt2860var.h @@ -115,13 +115,13 @@ #define RT2860_VAP(vap) ((struct rt2860_vap *)(vap)) struct rt2860_softc { - struct ifnet *sc_ifp; + struct ieee80211com sc_ic; + struct mbufq sc_snd; + struct mtx sc_mtx; 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,6 +139,7 @@ #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]; Index: sys/dev/usb/wlan/if_rsu.c =================================================================== --- sys/dev/usb/wlan/if_rsu.c +++ sys/dev/usb/wlan/if_rsu.c @@ -187,15 +187,13 @@ 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(void *); -static void rsu_init_locked(struct rsu_softc *); +static void rsu_init(struct rsu_softc *); static int rsu_tx_start(struct rsu_softc *, struct ieee80211_node *, struct mbuf *, struct rsu_data *); -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 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_ms_delay(struct rsu_softc *); static device_method_t rsu_methods[] = { @@ -285,8 +283,7 @@ { struct usb_attach_arg *uaa = device_get_ivars(self); struct rsu_softc *sc = device_get_softc(self); - struct ifnet *ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; int error; uint8_t iface_index, bands; @@ -298,6 +295,7 @@ 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); @@ -333,28 +331,9 @@ device_printf(self, "could not read ROM\n"); goto fail_rom; } - IEEE80211_ADDR_COPY(sc->sc_bssid, &sc->rom[0x12]); + IEEE80211_ADDR_COPY(ic->ic_macaddr, &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. */ @@ -387,7 +366,7 @@ setbit(&bands, IEEE80211_MODE_11G); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, sc->sc_bssid); + ieee80211_ifattach(ic); ic->ic_raw_xmit = rsu_raw_xmit; ic->ic_scan_start = rsu_scan_start; ic->ic_scan_end = rsu_scan_end; @@ -395,6 +374,8 @@ 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, @@ -406,7 +387,6 @@ return (0); -fail_ifalloc: fail_rom: usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER); fail_usb: @@ -418,10 +398,11 @@ rsu_detach(device_t self) { struct rsu_softc *sc = device_get_softc(self); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; - rsu_stop(ifp, 1); + RSU_LOCK(sc); + rsu_stop(sc); + RSU_UNLOCK(sc); usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER); ieee80211_ifdetach(ic); @@ -431,7 +412,7 @@ rsu_free_tx_list(sc); rsu_free_rx_list(sc); - if_free(ifp); + mbufq_drain(&sc->sc_snd); mtx_destroy(&sc->sc_mtx); return (0); @@ -471,14 +452,11 @@ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return (NULL); - uvp = (struct rsu_vap *) malloc(sizeof(struct rsu_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (uvp == NULL) - return (NULL); + uvp = malloc(sizeof(struct rsu_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &uvp->vap; if (ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags, bssid, mac) != 0) { + flags, bssid) != 0) { /* out of memory */ free(uvp, M_80211_VAP); return (NULL); @@ -490,7 +468,7 @@ /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); + ieee80211_media_status, mac); ic->ic_opmode = opmode; return (vap); @@ -508,9 +486,8 @@ 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); @@ -676,11 +653,8 @@ RSU_ASSERT_LOCKED(sc); bf = _rsu_getbuf(sc); - if (bf == NULL) { - struct ifnet *ifp = sc->sc_ifp; + if (bf == NULL) DPRINTF("stop queue\n"); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - } return (bf); } @@ -935,7 +909,7 @@ { struct rsu_vap *uvp = RSU_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct rsu_softc *sc = ic->ic_ifp->if_softc; + struct rsu_softc *sc = ic->ic_softc; struct ieee80211_node *ni; struct ieee80211_rateset *rs; enum ieee80211_state ostate; @@ -1033,29 +1007,27 @@ rsu_site_survey(struct rsu_softc *sc, struct ieee80211vap *vap) { struct r92s_fw_cmd_sitesurvey cmd; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; memset(&cmd, 0, sizeof(cmd)); - if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->scan_pass == 1) + if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->sc_scan_pass == 1) cmd.active = htole32(1); cmd.limit = htole32(48); - if (sc->scan_pass == 1 && vap->iv_des_nssid > 0) { + if (sc->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->scan_pass); + DPRINTF("sending site survey command, pass=%d\n", sc->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 ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct ndis_wlan_bssid_ex *bss; struct ndis_802_11_fixed_ies *fixed; @@ -1133,8 +1105,7 @@ static void rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; struct ieee80211_channel *c; struct ndis_wlan_bssid_ex *bss; @@ -1165,7 +1136,7 @@ IEEE80211_FC0_SUBTYPE_BEACON; wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; USETW(wh->i_dur, 0); - IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr); + IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr); IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr); IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr); *(uint16_t *)wh->i_seq = 0; @@ -1173,7 +1144,6 @@ /* 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), @@ -1191,8 +1161,7 @@ static void rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211_node *ni = vap->iv_bss; struct r92s_event_join_bss *rsp; @@ -1228,8 +1197,7 @@ static void rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); DPRINTFN(4, "Rx event code=%d len=%d\n", code, len); @@ -1240,18 +1208,18 @@ break; case R92S_EVT_SURVEY_DONE: DPRINTF("site survey pass %d done, found %d BSS\n", - sc->scan_pass, le32toh(*(uint32_t *)buf)); + sc->sc_scan_pass, le32toh(*(uint32_t *)buf)); if (vap->iv_state != IEEE80211_S_SCAN) break; /* Ignore if not scanning. */ - if (sc->scan_pass == 0 && vap->iv_des_nssid != 0) { + if (sc->sc_scan_pass == 0 && vap->iv_des_nssid != 0) { /* Schedule a directed scan for hidden APs. */ - sc->scan_pass = 1; + sc->sc_scan_pass = 1; RSU_UNLOCK(sc); ieee80211_new_state(vap, IEEE80211_S_SCAN, -1); RSU_LOCK(sc); break; } - sc->scan_pass = 0; + sc->sc_scan_pass = 0; break; case R92S_EVT_JOIN_BSS: if (vap->iv_state == IEEE80211_S_AUTH) @@ -1274,7 +1242,7 @@ DPRINTF("WPS PBC pushed.\n"); break; case R92S_EVT_FWDBG: - if (ifp->if_flags & IFF_DEBUG) { + if (vap->iv_ifp->if_flags & IFF_DEBUG) { buf[60] = '\0'; printf("FWDBG: %s\n", (char *)buf); } @@ -1341,8 +1309,7 @@ static struct mbuf * rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; struct r92s_rx_stat *stat; uint32_t rxdw0, rxdw3; @@ -1355,11 +1322,11 @@ rxdw3 = le32toh(stat->rxdw3); if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return NULL; } if (__predict_false(pktlen < sizeof(*wh) || pktlen > MCLBYTES)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return NULL; } @@ -1377,11 +1344,9 @@ m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR); if (__predict_false(m == NULL)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_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)) @@ -1479,6 +1444,7 @@ 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; @@ -1486,7 +1452,7 @@ if (__predict_false(len < sizeof(*stat))) { DPRINTF("xfer too short %d\n", len); - if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return (NULL); } /* Determine if it is a firmware C2H event or an 802.11 frame. */ @@ -1503,8 +1469,7 @@ rsu_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) { struct rsu_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *m = NULL, *next; @@ -1564,7 +1529,7 @@ } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto tr_setup; } break; @@ -1572,35 +1537,16 @@ } - 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) { - m = data->m; - if (m->m_flags & M_TXCB) { - /* XXX status? */ - ieee80211_process_callback(data->ni, m, 0); - } - m_freem(m); + /* XXX status? */ + ieee80211_tx_complete(data->ni, data->m, 0); 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 @@ -1608,7 +1554,7 @@ uint8_t which) { struct rsu_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; struct rsu_data *data; RSU_ASSERT_LOCKED(sc); @@ -1643,7 +1589,7 @@ rsu_txeof(xfer, data); STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next); } - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(ic->ic_oerrors, 1); if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); @@ -1669,8 +1615,7 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, struct rsu_data *data) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; @@ -1772,82 +1717,75 @@ return (0); } -static void -rsu_start(struct ifnet *ifp) +static int +rsu_transmit(struct ieee80211com *ic, struct mbuf *m) { - struct rsu_softc *sc = ifp->if_softc; - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; + struct rsu_softc *sc = ic->ic_softc; + int error; RSU_LOCK(sc); - rsu_start_locked(ifp); + 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_UNLOCK(sc); + + return (0); } static void -rsu_start_locked(struct ifnet *ifp) +rsu_start(struct rsu_softc *sc) { - struct rsu_softc *sc = ifp->if_softc; struct ieee80211_node *ni; struct rsu_data *bf; struct mbuf *m; RSU_ASSERT_LOCKED(sc); - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { + bf = rsu_getbuf(sc); + if (bf == NULL) { + mbufq_prepend(&sc->sc_snd, m); break; + } + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; m->m_pkthdr.rcvif = NULL; - 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); + if (rsu_tx_start(sc, ni, m, bf) != 0) { + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); ieee80211_free_node(ni); + break; } } } -static int -rsu_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +rsu_parent(struct ieee80211com *ic) { - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; - - 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); + struct rsu_softc *sc = ic->ic_softc; + int startall = 0; + + RSU_LOCK(sc); + if (ic->ic_nrunning > 0) { + if (!sc->sc_running) { + rsu_init(sc); + startall = 1; } - 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; - } + } else if (sc->sc_running) + rsu_stop(sc); + RSU_UNLOCK(sc); - return (error); + if (startall) + ieee80211_start_all(ic); } /* @@ -2296,12 +2234,11 @@ const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct rsu_softc *sc = ifp->if_softc; + struct rsu_softc *sc = ic->ic_softc; struct rsu_data *bf; /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!sc->sc_running) { m_freem(m); ieee80211_free_node(ni); return (ENETDOWN); @@ -2314,10 +2251,8 @@ 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); @@ -2328,23 +2263,17 @@ } static void -rsu_init(void *arg) -{ - struct rsu_softc *sc = arg; - - RSU_LOCK(sc); - rsu_init_locked(arg); - RSU_UNLOCK(sc); -} - -static void -rsu_init_locked(struct rsu_softc *sc) +rsu_init(struct rsu_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + uint8_t macaddr[IEEE80211_ADDR_LEN]; 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; @@ -2384,14 +2313,14 @@ rsu_read_1(sc, 0xfe5c) | 0x80); /* Set MAC address. */ - rsu_write_region_1(sc, R92S_MACID, IF_LLADDR(ifp), - IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr); + rsu_write_region_1(sc, R92S_MACID, macaddr, 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(IF_LLADDR(ifp))); - error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp), + error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, macaddr, IEEE80211_ADDR_LEN); if (error != 0) { device_printf(sc->sc_dev, "could not set MAC address\n"); @@ -2427,12 +2356,11 @@ /* Set default channel. */ ic->ic_bss->ni_chan = ic->ic_ibss_chan; #endif - sc->scan_pass = 0; + sc->sc_scan_pass = 0; usbd_transfer_start(sc->sc_xfer[RSU_BULK_RX]); /* We're ready to go. */ - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_running = 1; return; fail: /* Need to stop all failed transfers, if any */ @@ -2441,22 +2369,11 @@ } static void -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) +rsu_stop(struct rsu_softc *sc) { - struct rsu_softc *sc = ifp->if_softc; int i; - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_running = 0; sc->sc_calibrating = 0; taskqueue_cancel_timeout(taskqueue_thread, &sc->calib_task, NULL); Index: sys/dev/usb/wlan/if_rsureg.h =================================================================== --- sys/dev/usb/wlan/if_rsureg.h +++ sys/dev/usb/wlan/if_rsureg.h @@ -726,7 +726,8 @@ #define RSU_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) struct rsu_softc { - struct ifnet *sc_ifp; + struct ieee80211com sc_ic; + struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; int (*sc_newstate)(struct ieee80211com *, @@ -736,17 +737,17 @@ 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; Index: sys/dev/usb/wlan/if_rum.c =================================================================== --- sys/dev/usb/wlan/if_rum.c +++ sys/dev/usb/wlan/if_rum.c @@ -175,8 +175,9 @@ const struct ieee80211_bpf_params *); static int rum_tx_data(struct rum_softc *, struct mbuf *, struct ieee80211_node *); -static void rum_start(struct ifnet *); -static int rum_ioctl(struct ifnet *, u_long, caddr_t); +static int rum_transmit(struct ieee80211com *, struct mbuf *); +static void rum_start(struct rum_softc *); +static void rum_parent(struct ieee80211com *); static void rum_eeprom_read(struct rum_softc *, uint16_t, void *, int); static uint32_t rum_read(struct rum_softc *, uint16_t); @@ -198,7 +199,7 @@ 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 ifnet *); +static void rum_update_slot(struct rum_softc *); 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 *); @@ -207,8 +208,7 @@ 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_locked(struct rum_softc *); -static void rum_init(void *); +static void rum_init(struct rum_softc *); static void rum_stop(struct rum_softc *); static void rum_load_microcode(struct rum_softc *, const uint8_t *, size_t); @@ -425,8 +425,7 @@ { struct usb_attach_arg *uaa = device_get_ivars(self); struct rum_softc *sc = device_get_softc(self); - struct ieee80211com *ic; - struct ifnet *ifp; + struct ieee80211com *ic = &sc->sc_ic; uint8_t iface_index, bands; uint32_t tmp; int error, ntries; @@ -437,6 +436,7 @@ 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,24 +470,6 @@ 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 */ @@ -512,13 +494,14 @@ setbit(&bands, IEEE80211_MODE_11A); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, sc->sc_bssid); + ieee80211_ifattach(ic); 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; @@ -543,8 +526,6 @@ 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); @@ -559,11 +540,9 @@ rum_unsetup_tx_list(sc); RUM_UNLOCK(sc); - if (ifp) { - ic = ifp->if_l2com; - ieee80211_ifdetach(ic); - if_free(ifp); - } + if (sc->sc_ic.ic_softc == sc) + ieee80211_ifdetach(&sc->sc_ic); + mbufq_drain(&sc->sc_snd); mtx_destroy(&sc->sc_mtx); return (0); } @@ -595,21 +574,18 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct rum_softc *sc = ic->ic_ifp->if_softc; + struct rum_softc *sc = ic->ic_softc; struct rum_vap *rvp; struct ieee80211vap *vap; if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return NULL; - rvp = (struct rum_vap *) malloc(sizeof(struct rum_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (rvp == NULL) - return NULL; + rvp = malloc(sizeof(struct rum_vap), M_80211_VAP, M_WAITOK | M_ZERO); 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, mac) != 0) { + flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) { /* out of memory */ free(rvp, M_80211_VAP); return (NULL); @@ -624,7 +600,8 @@ ieee80211_ratectl_init(vap); ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); ic->ic_opmode = opmode; return vap; } @@ -648,13 +625,8 @@ struct rum_softc *sc = data->sc; if (data->m != NULL) { - if (data->m->m_flags & M_TXCB) - ieee80211_process_callback(data->ni, data->m, - txerr ? ETIMEDOUT : 0); - m_freem(data->m); + ieee80211_tx_complete(data->ni, data->m, txerr); data->m = NULL; - - ieee80211_free_node(data->ni); data->ni = NULL; } STAILQ_INSERT_TAIL(&sc->tx_free, data, next); @@ -711,7 +683,7 @@ { struct rum_vap *rvp = RUM_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct rum_softc *sc = ic->ic_ifp->if_softc; + struct rum_softc *sc = ic->ic_softc; const struct ieee80211_txparam *tp; enum ieee80211_state ostate; struct ieee80211_node *ni; @@ -745,12 +717,12 @@ ieee80211_free_node(ni); return (-1); } - rum_update_slot(ic->ic_ifp); + rum_update_slot(sc); rum_enable_mrr(sc); rum_set_txpreamble(sc); rum_set_basicrates(sc); - IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); - rum_set_bssid(sc, sc->sc_bssid); + IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid); + rum_set_bssid(sc, ic->ic_macaddr); } if (vap->iv_opmode == IEEE80211_M_HOSTAP || @@ -780,7 +752,6 @@ 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; @@ -799,9 +770,6 @@ 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: @@ -844,16 +812,14 @@ usbd_transfer_submit(xfer); } - RUM_UNLOCK(sc); - rum_start(ifp); - RUM_LOCK(sc); + rum_start(sc); break; default: /* Error */ DPRINTFN(11, "transfer error, %s\n", usbd_errstr(error)); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); data = usbd_xfer_get_priv(xfer); if (data != NULL) { rum_tx_free(data, error); @@ -880,8 +846,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) { struct rum_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; struct mbuf *m = NULL; struct usb_page_cache *pc; @@ -899,7 +864,7 @@ if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) { DPRINTF("%s: xfer too short %d\n", device_get_nameunit(sc->sc_dev), len); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto tr_setup; } @@ -916,21 +881,20 @@ * filled RUM_TXRX_CSR2: */ DPRINTFN(5, "PHY or CRC error\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto tr_setup; } m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (m == NULL) { DPRINTF("could not allocate mbuf\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_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)) { @@ -968,10 +932,8 @@ (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 */ @@ -1011,8 +973,7 @@ rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc, uint32_t flags, uint16_t xflags, int len, int rate) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint16_t plcp_length; int remainder; @@ -1109,8 +1070,7 @@ rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct rum_tx_data *data; struct ieee80211_frame *wh; const struct ieee80211_txparam *tp; @@ -1221,8 +1181,7 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni) { struct ieee80211vap *vap = ni->ni_vap; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct rum_tx_data *data; struct ieee80211_frame *wh; const struct ieee80211_txparam *tp; @@ -1299,80 +1258,73 @@ 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 ifnet *ifp) +rum_start(struct rum_softc *sc) { - struct rum_softc *sc = ifp->if_softc; struct ieee80211_node *ni; struct mbuf *m; - RUM_LOCK(sc); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - RUM_UNLOCK(sc); + RUM_LOCK_ASSERT(sc, MA_OWNED); + + if (!sc->sc_running) return; - } - 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; - } + + 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); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); break; } } - RUM_UNLOCK(sc); } -static int -rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +rum_parent(struct ieee80211com *ic) { - struct rum_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error; + struct rum_softc *sc = ic->ic_softc; 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); - } + if (sc->sc_detached) { 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; } - return error; + 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); + RUM_UNLOCK(sc); + if (startall) + ieee80211_start_all(ic); } static void @@ -1572,8 +1524,7 @@ static void rum_enable_mrr(struct rum_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; tmp = rum_read(sc, RT2573_TXRX_CSR4); @@ -1589,8 +1540,7 @@ static void rum_set_txpreamble(struct rum_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; tmp = rum_read(sc, RT2573_TXRX_CSR4); @@ -1605,8 +1555,7 @@ static void rum_set_basicrates(struct rum_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; /* update basic rate set */ if (ic->ic_curmode == IEEE80211_MODE_11B) { @@ -1671,8 +1620,7 @@ static void rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; const struct rfprog *rfprog; uint8_t bbp3, bbp94 = RT2573_BBPR94_DEFAULT; int8_t power; @@ -1748,8 +1696,7 @@ static void rum_enable_tsf_sync(struct rum_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; @@ -1784,10 +1731,9 @@ } static void -rum_update_slot(struct ifnet *ifp) +rum_update_slot(struct rum_softc *sc) { - struct rum_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint8_t slottime; uint32_t tmp; @@ -1827,18 +1773,17 @@ 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 (!(ifp->if_flags & IFF_PROMISC)) + if (sc->sc_ic.ic_promisc == 0) tmp |= RT2573_DROP_NOT_TO_ME; rum_write(sc, RT2573_TXRX_CSR0, tmp); - DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? + DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc > 0 ? "entering" : "leaving"); } @@ -1847,10 +1792,11 @@ { struct rum_softc *sc = ic->ic_softc; - if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - RUM_LOCK(sc); + if (!sc->sc_running) { + RUM_UNLOCK(sc); + return; + } rum_setpromisc(sc); RUM_UNLOCK(sc); } @@ -1887,7 +1833,7 @@ #endif /* read MAC address */ - rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_bssid, 6); + rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_ic.ic_macaddr, 6); rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2); val = le16toh(val); @@ -1994,10 +1940,10 @@ } static void -rum_init_locked(struct rum_softc *sc) +rum_init(struct rum_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; usb_error_t error; int i, ntries; @@ -2039,7 +1985,7 @@ /* clear STA registers */ rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta); - rum_set_macaddr(sc, IF_LLADDR(ifp)); + rum_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); /* initialize ASIC */ rum_write(sc, RT2573_MAC_CSR1, 4); @@ -2058,13 +2004,12 @@ RT2573_DROP_ACKCTS; if (ic->ic_opmode != IEEE80211_M_HOSTAP) tmp |= RT2573_DROP_TODS; - if (!(ifp->if_flags & IFF_PROMISC)) + if (ic->ic_promisc == 0) tmp |= RT2573_DROP_NOT_TO_ME; } rum_write(sc, RT2573_TXRX_CSR0, tmp); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_running = 1; usbd_xfer_set_stall(sc->sc_xfer[RUM_BULK_WR]); usbd_transfer_start(sc->sc_xfer[RUM_BULK_RD]); return; @@ -2074,29 +2019,13 @@ } 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); - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_running = 0; RUM_UNLOCK(sc); @@ -2188,27 +2117,23 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params) { - struct ifnet *ifp = ni->ni_ic->ic_ifp; - struct rum_softc *sc = ifp->if_softc; + struct rum_softc *sc = ni->ni_ic->ic_softc; RUM_LOCK(sc); /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!sc->sc_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 @@ -2228,7 +2153,6 @@ return 0; bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); RUM_UNLOCK(sc); ieee80211_free_node(ni); return EIO; @@ -2262,8 +2186,7 @@ struct rum_vap *rvp = arg; struct ieee80211vap *vap = &rvp->vap; struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct rum_softc *sc = ifp->if_softc; + struct rum_softc *sc = ic->ic_softc; struct ieee80211_node *ni; int ok, fail; int sum, retrycnt; @@ -2283,7 +2206,8 @@ (void) ieee80211_ratectl_rate(ni, NULL, 0); ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */ + /* count TX retry-fail as Tx errors */ + if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail); usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp); RUM_UNLOCK(sc); @@ -2292,15 +2216,14 @@ static void rum_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct rum_softc *sc = ifp->if_softc; + struct rum_softc *sc = ic->ic_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, ifp->if_broadcastaddr); + rum_set_bssid(sc, ieee80211broadcastaddr); RUM_UNLOCK(sc); } @@ -2308,11 +2231,11 @@ static void rum_scan_end(struct ieee80211com *ic) { - struct rum_softc *sc = ic->ic_ifp->if_softc; + struct rum_softc *sc = ic->ic_softc; RUM_LOCK(sc); rum_enable_tsf_sync(sc); - rum_set_bssid(sc, sc->sc_bssid); + rum_set_bssid(sc, ic->ic_macaddr); RUM_UNLOCK(sc); } @@ -2320,7 +2243,7 @@ static void rum_set_channel(struct ieee80211com *ic) { - struct rum_softc *sc = ic->ic_ifp->if_softc; + struct rum_softc *sc = ic->ic_softc; RUM_LOCK(sc); rum_set_chan(sc, ic->ic_curchan); @@ -2330,8 +2253,7 @@ static int rum_get_rssi(struct rum_softc *sc, uint8_t raw) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; int lna, agc, rssi; lna = (raw >> 5) & 0x3; Index: sys/dev/usb/wlan/if_rumvar.h =================================================================== --- sys/dev/usb/wlan/if_rumvar.h +++ sys/dev/usb/wlan/if_rumvar.h @@ -85,7 +85,8 @@ }; struct rum_softc { - struct ifnet *sc_ifp; + struct ieee80211com sc_ic; + struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; @@ -105,8 +106,8 @@ uint32_t sta[6]; uint32_t rf_regs[4]; uint8_t txpow[44]; - uint8_t sc_bssid[6]; - uint8_t sc_detached; + u_int sc_detached:1, + sc_running:1; struct { uint8_t val; Index: sys/dev/usb/wlan/if_run.c =================================================================== --- sys/dev/usb/wlan/if_run.c +++ sys/dev/usb/wlan/if_run.c @@ -410,8 +410,9 @@ const struct ieee80211_bpf_params *); static int run_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); -static void run_start(struct ifnet *); -static int run_ioctl(struct ifnet *, u_long, caddr_t); +static int run_transmit(struct ieee80211com *, struct mbuf *); +static void run_start(struct run_softc *); +static void run_parent(struct ieee80211com *); 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); @@ -457,7 +458,6 @@ 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,8 +702,7 @@ { struct run_softc *sc = device_get_softc(self); struct usb_attach_arg *uaa = device_get_ivars(self); - struct ieee80211com *ic; - struct ifnet *ifp; + struct ieee80211com *ic = &sc->sc_ic; uint32_t ver; int ntries, error; uint8_t iface_index, bands; @@ -716,6 +715,7 @@ 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,28 +754,10 @@ 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(sc->sc_bssid)); + sc->ntxchains, sc->nrxchains, ether_sprintf(ic->ic_macaddr)); 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 */ @@ -812,7 +794,7 @@ setbit(&bands, IEEE80211_MODE_11A); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, sc->sc_bssid); + ieee80211_ifattach(ic); ic->ic_scan_start = run_scan_start; ic->ic_scan_end = run_scan_end; @@ -824,9 +806,10 @@ 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), @@ -852,8 +835,7 @@ run_detach(device_t self) { struct run_softc *sc = device_get_softc(self); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; int i; RUN_LOCK(sc); @@ -872,16 +854,15 @@ run_unsetup_tx_list(sc, &sc->sc_epq[i]); RUN_UNLOCK(sc); - if (ifp) { - ic = ifp->if_l2com; + if (sc->sc_ic.ic_softc == sc) { /* 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); @@ -893,14 +874,13 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct ifnet *ifp = ic->ic_ifp; - struct run_softc *sc = ifp->if_softc; + struct run_softc *sc = ic->ic_softc; struct run_vap *rvp; struct ieee80211vap *vap; int i; if (sc->rvp_cnt >= RUN_VAP_MAX) { - if_printf(ifp, "number of VAPs maxed out\n"); + device_printf(sc->sc_dev, "number of VAPs maxed out\n"); return (NULL); } @@ -926,23 +906,21 @@ break; } if (vap == NULL) { - if_printf(ifp, "wds only supported in ap mode\n"); + device_printf(sc->sc_dev, + "wds only supported in ap mode\n"); return (NULL); } break; default: - if_printf(ifp, "unknown opmode %d\n", opmode); + device_printf(sc->sc_dev, "unknown opmode %d\n", opmode); return (NULL); } - rvp = (struct run_vap *) malloc(sizeof(struct run_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (rvp == NULL) - return (NULL); + rvp = malloc(sizeof(struct run_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &rvp->vap; - if (ieee80211_vap_setup(ic, vap, name, unit, - opmode, flags, bssid, mac) != 0) { + if (ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, + bssid) != 0) { /* out of memory */ free(rvp, M_80211_VAP); return (NULL); @@ -969,7 +947,8 @@ ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); /* complete setup */ - ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status); + ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status, + mac); /* make sure id is always unique */ for (i = 0; i < RUN_VAP_MAX; i++) { @@ -995,7 +974,6 @@ 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; @@ -1004,9 +982,7 @@ return; ic = vap->iv_ic; - ifp = ic->ic_ifp; - - sc = ifp->if_softc; + sc = ic->ic_softc; RUN_LOCK(sc); @@ -1740,6 +1716,7 @@ 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; @@ -1760,14 +1737,14 @@ /* read MAC address */ run_srom_read(sc, RT2860_EEPROM_MAC01, &val); - sc->sc_bssid[0] = val & 0xff; - sc->sc_bssid[1] = val >> 8; + ic->ic_macaddr[0] = val & 0xff; + ic->ic_macaddr[1] = val >> 8; run_srom_read(sc, RT2860_EEPROM_MAC23, &val); - sc->sc_bssid[2] = val & 0xff; - sc->sc_bssid[3] = val >> 8; + ic->ic_macaddr[2] = val & 0xff; + ic->ic_macaddr[3] = val >> 8; run_srom_read(sc, RT2860_EEPROM_MAC45, &val); - sc->sc_bssid[4] = val & 0xff; - sc->sc_bssid[5] = val >> 8; + ic->ic_macaddr[4] = val & 0xff; + ic->ic_macaddr[5] = val >> 8; if (sc->mac_ver < 0x3593) { /* read vender BBP settings */ @@ -2002,7 +1979,7 @@ struct ieee80211vap *vap = ifp->if_softc; struct ieee80211com *ic = vap->iv_ic; const struct ieee80211_txparam *tp; - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; uint8_t rate, ridx; int error; @@ -2033,7 +2010,7 @@ #if 0 if ((ifp->if_flags & IFF_UP) && - (ifp->if_drv_flags & IFF_DRV_RUNNING)){ + (ifp->if_drv_flags & RUN_RUNNING)){ run_init_locked(sc); } #endif @@ -2048,7 +2025,7 @@ { const struct ieee80211_txparam *tp; struct ieee80211com *ic = vap->iv_ic; - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; struct run_vap *rvp = RUN_VAP(vap); enum ieee80211_state ostate; uint32_t sta[3]; @@ -2144,7 +2121,7 @@ run_set_txpreamble(sc); run_set_basicrates(sc); ni = ieee80211_ref_node(vap->iv_bss); - IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); + IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid); run_set_bssid(sc, ni->ni_bssid); ieee80211_free_node(ni); run_enable_tsf_sync(sc); @@ -2181,7 +2158,7 @@ run_wme_update_cb(void *arg) { struct ieee80211com *ic = arg; - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; struct ieee80211_wme_state *wmesp = &ic->ic_wme; int aci, error = 0; @@ -2234,7 +2211,7 @@ static int run_wme_update(struct ieee80211com *ic) { - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; /* sometime called wothout lock */ if (mtx_owned(&ic->ic_comlock.mtx)) { @@ -2277,7 +2254,7 @@ struct ieee80211vap *vap = cmdq->arg1; struct ieee80211_key *k = cmdq->k; struct ieee80211com *ic = vap->iv_ic; - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; struct ieee80211_node *ni; uint32_t attr; uint16_t base, associd; @@ -2399,7 +2376,7 @@ const uint8_t mac[IEEE80211_ADDR_LEN]) { struct ieee80211com *ic = vap->iv_ic; - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; uint32_t i; i = RUN_CMDQ_GET(&sc->cmdq_store); @@ -2467,7 +2444,7 @@ run_key_delete(struct ieee80211vap *vap, struct ieee80211_key *k) { struct ieee80211com *ic = vap->iv_ic; - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; struct ieee80211_key *k0; uint32_t i; @@ -2498,7 +2475,7 @@ struct run_softc *sc = arg; /* do it in a process context, so it can go sleep */ - ieee80211_runtask(sc->sc_ifp->if_l2com, &sc->ratectl_task); + ieee80211_runtask(&sc->sc_ic, &sc->ratectl_task); /* next timeout will be rescheduled in the callback task */ } @@ -2507,7 +2484,7 @@ run_ratectl_cb(void *arg, int pending) { struct run_softc *sc = arg; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); if (vap == NULL) @@ -2540,7 +2517,6 @@ 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; @@ -2577,7 +2553,7 @@ if (stat & RT2860_TXQ_OK) (*wstat)[RUN_SUCCESS]++; else - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); /* * Check if there were retries, ie if the Tx success rate is * different from the requested rate. Note that it works only @@ -2600,8 +2576,6 @@ { 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]; @@ -2623,7 +2597,8 @@ goto fail; /* count failed TX as errors */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, le16toh(sta[0].error.fail)); + if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, + le16toh(sta[0].error.fail)); retrycnt = le16toh(sta[1].tx.retry); success = le16toh(sta[1].tx.success); @@ -2661,7 +2636,7 @@ { struct run_cmdq *cmdq = arg; struct ieee80211_node *ni = cmdq->arg1; - struct run_softc *sc = ni->ni_vap->iv_ic->ic_ifp->if_softc; + struct run_softc *sc = ni->ni_vap->iv_ic->ic_softc; uint8_t wcid = cmdq->wcid; RUN_LOCK_ASSERT(sc, MA_OWNED); @@ -2679,7 +2654,7 @@ 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_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; uint8_t rate; uint8_t ridx; uint8_t wcid; @@ -2769,8 +2744,7 @@ static void run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; struct ieee80211_node *ni; struct rt2870_rxd *rxd; @@ -2789,7 +2763,7 @@ rxwisize += sizeof(uint32_t); if (__predict_false(len > dmalen)) { m_freem(m); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); DPRINTF("bad RXWI length %u > %u\n", len, dmalen); return; } @@ -2799,7 +2773,7 @@ if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { m_freem(m); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); DPRINTF("%s error.\n", (flags & RT2860_RX_CRCERR)?"CRC":"ICV"); return; } @@ -2828,7 +2802,7 @@ ieee80211_notify_michael_failure(ni->ni_vap, wh, rxwi->keyidx); m_freem(m); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); DPRINTF("MIC error. Someone is lying.\n"); return; } @@ -2837,7 +2811,6 @@ 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) { @@ -2890,7 +2863,7 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) { struct run_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; struct mbuf *m = NULL; struct mbuf *m0; uint32_t dmalen; @@ -2928,7 +2901,7 @@ } if (sc->rx_m == NULL) { DPRINTF("could not allocate mbuf - idle with stall\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); usbd_xfer_set_stall(xfer); usbd_xfer_set_frames(xfer, 0); } else { @@ -2948,12 +2921,9 @@ 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"); - - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - + counter_u64_add(ic->ic_ierrors, 1); goto tr_setup; } if (sc->rx_m != NULL) { @@ -3001,7 +2971,7 @@ m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (__predict_false(m0 == NULL)) { DPRINTF("could not allocate mbuf\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); break; } m_copydata(m, 4 /* skip 32-bit DMA-len header */, @@ -3048,8 +3018,7 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index) { struct run_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct run_tx_data *data; struct ieee80211vap *vap = NULL; struct usb_page_cache *pc; @@ -3067,14 +3036,9 @@ "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: @@ -3091,11 +3055,7 @@ 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; } @@ -3132,12 +3092,8 @@ usbd_xfer_set_frame_len(xfer, 0, size); usbd_xfer_set_priv(xfer, data); - usbd_transfer_submit(xfer); - - RUN_UNLOCK(sc); - run_start(ifp); - RUN_LOCK(sc); + run_start(sc); break; @@ -3147,14 +3103,13 @@ 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); @@ -3220,7 +3175,7 @@ run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data) { struct mbuf *m = data->m; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = data->ni->ni_vap; struct ieee80211_frame *wh; struct rt2870_txd *txd; @@ -3283,7 +3238,7 @@ static int run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh; struct ieee80211_channel *chan; @@ -3451,8 +3406,7 @@ static int run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct run_node *rn = (void *)ni; struct run_tx_data *data; struct ieee80211_frame *wh; @@ -3483,11 +3437,9 @@ 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--; @@ -3555,11 +3507,9 @@ 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 */ @@ -3570,7 +3520,7 @@ mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); } if (mprot == NULL) { - if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); DPRINTF("could not allocate mbuf\n"); return (ENOBUFS); } @@ -3652,7 +3602,6 @@ 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); } @@ -3691,36 +3640,31 @@ run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params) { - struct ifnet *ifp = ni->ni_ic->ic_ifp; - struct run_softc *sc = ifp->if_softc; + struct run_softc *sc = ni->ni_ic->ic_softc; int error = 0; RUN_LOCK(sc); /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { - error = ENETDOWN; + if (!(sc->sc_flags & RUN_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); @@ -3733,83 +3677,71 @@ 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 ifnet *ifp) +run_start(struct run_softc *sc) { - struct run_softc *sc = ifp->if_softc; struct ieee80211_node *ni; struct mbuf *m; - RUN_LOCK(sc); + RUN_LOCK_ASSERT(sc, MA_OWNED); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - RUN_UNLOCK(sc); + if ((sc->sc_flags & RUN_RUNNING) == 0) return; - } - - for (;;) { - /* send data frames */ - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { 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; + mbufq_prepend(&sc->sc_snd, m); break; } } - - RUN_UNLOCK(sc); } -static int -run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +run_parent(struct ieee80211com *ic) { - struct run_softc *sc = ifp->if_softc; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; + struct run_softc *sc = ic->ic_softc; 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); - } - } + if (sc->sc_detached) { 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; } - return (error); + 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); + RUN_UNLOCK(sc); + if (startall) + ieee80211_start_all(ic); } static void @@ -4796,7 +4728,7 @@ static int run_set_chan(struct run_softc *sc, struct ieee80211_channel *c) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; u_int chan, group; chan = ieee80211_chan2ieee(ic, c); @@ -4841,7 +4773,7 @@ static void run_set_channel(struct ieee80211com *ic) { - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; RUN_LOCK(sc); run_set_chan(sc, ic->ic_curchan); @@ -4853,7 +4785,7 @@ static void run_scan_start(struct ieee80211com *ic) { - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; uint32_t tmp; RUN_LOCK(sc); @@ -4863,7 +4795,7 @@ run_write(sc, RT2860_BCN_TIME_CFG, tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN)); - run_set_bssid(sc, sc->sc_ifp->if_broadcastaddr); + run_set_bssid(sc, ieee80211broadcastaddr); RUN_UNLOCK(sc); @@ -4873,13 +4805,13 @@ static void run_scan_end(struct ieee80211com *ic) { - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; RUN_LOCK(sc); run_enable_tsf_sync(sc); /* XXX keep local copy */ - run_set_bssid(sc, sc->sc_bssid); + run_set_bssid(sc, ic->ic_macaddr); RUN_UNLOCK(sc); @@ -4894,7 +4826,7 @@ run_update_beacon(struct ieee80211vap *vap, int item) { struct ieee80211com *ic = vap->iv_ic; - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; struct run_vap *rvp = RUN_VAP(vap); int mcast = 0; uint32_t i; @@ -4939,7 +4871,7 @@ struct ieee80211vap *vap = arg; struct run_vap *rvp = RUN_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; struct rt2860_txwi txwi; struct mbuf *m; uint16_t txwisize; @@ -4987,7 +4919,7 @@ static void run_updateprot(struct ieee80211com *ic) { - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; uint32_t i; i = RUN_CMDQ_GET(&sc->cmdq_store); @@ -5001,7 +4933,7 @@ run_updateprot_cb(void *arg) { struct ieee80211com *ic = arg; - struct run_softc *sc = ic->ic_ifp->if_softc; + struct run_softc *sc = ic->ic_softc; uint32_t tmp; tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; @@ -5025,7 +4957,7 @@ run_usb_timeout_cb(void *arg) { struct ieee80211vap *vap = arg; - struct run_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct run_softc *sc = vap->iv_ic->ic_softc; RUN_LOCK_ASSERT(sc, MA_OWNED); @@ -5071,12 +5003,12 @@ run_read(sc, RT2860_RX_FILTR_CFG, &tmp); tmp |= RT2860_DROP_UC_NOME; - if (sc->sc_ifp->if_flags & IFF_PROMISC) + if (sc->sc_ic.ic_promisc > 0) tmp &= ~RT2860_DROP_UC_NOME; run_write(sc, RT2860_RX_FILTR_CFG, tmp); - DPRINTF("%s promiscuous mode\n", (sc->sc_ifp->if_flags & IFF_PROMISC) ? + DPRINTF("%s promiscuous mode\n", (sc->sc_ic.ic_promisc > 0) ? "entering" : "leaving"); } @@ -5085,7 +5017,7 @@ { struct run_softc *sc = ic->ic_softc; - if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + if ((sc->sc_flags & RUN_RUNNING) == 0) return; RUN_LOCK(sc); @@ -5096,7 +5028,7 @@ static void run_enable_tsf_sync(struct run_softc *sc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; @@ -5161,7 +5093,7 @@ static void run_set_txpreamble(struct run_softc *sc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; run_read(sc, RT2860_AUTO_RSP_CFG, &tmp); @@ -5175,7 +5107,7 @@ static void run_set_basicrates(struct run_softc *sc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; /* set basic rates mask */ if (ic->ic_curmode == IEEE80211_MODE_11B) @@ -5220,7 +5152,7 @@ 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->ic_ifp; + sc->cmdq[i].arg0 = ic; ieee80211_runtask(ic, &sc->cmdq_task); return; @@ -5230,9 +5162,8 @@ static void run_updateslot_cb(void *arg) { - struct ifnet *ifp = arg; - struct run_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = arg; + struct run_softc *sc = ic->ic_softc; uint32_t tmp; run_read(sc, RT2860_BKOFF_SLOT_CFG, &tmp); @@ -5244,15 +5175,12 @@ 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_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_channel *c = ic->ic_curchan; int delta; @@ -5902,7 +5830,7 @@ static int run_txrx_enable(struct run_softc *sc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; int error, ntries; @@ -5962,8 +5890,8 @@ static void run_init_locked(struct run_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; uint8_t bbp1, bbp3; int i; @@ -5993,7 +5921,7 @@ for (i = 0; i != RUN_EP_QUEUES; i++) run_setup_tx_list(sc, &sc->sc_epq[i]); - run_set_macaddr(sc, IF_LLADDR(ifp)); + run_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); for (ntries = 0; ntries < 100; ntries++) { if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0) @@ -6166,8 +6094,7 @@ /* turn radio LED on */ run_set_leds(sc, RT2860_LED_RADIO); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_flags |= RUN_RUNNING; sc->cmdq_run = RUN_CMDQ_GO; for (i = 0; i != RUN_N_XFER; i++) @@ -6185,35 +6112,19 @@ } 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 (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->sc_flags & RUN_RUNNING) run_set_leds(sc, 0); /* turn all LEDs off */ - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_flags &= ~RUN_RUNNING; sc->ratectl_run = RUN_RATECTL_OFF; sc->cmdq_run = sc->cmdq_key_set; Index: sys/dev/usb/wlan/if_runvar.h =================================================================== --- sys/dev/usb/wlan/if_runvar.h +++ sys/dev/usb/wlan/if_runvar.h @@ -151,13 +151,16 @@ }; 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 @@ -203,10 +206,6 @@ 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; Index: sys/dev/usb/wlan/if_ural.c =================================================================== --- sys/dev/usb/wlan/if_ural.c +++ sys/dev/usb/wlan/if_ural.c @@ -149,8 +149,9 @@ struct ieee80211_node *); static int ural_tx_data(struct ural_softc *, struct mbuf *, struct ieee80211_node *); -static void ural_start(struct ifnet *); -static int ural_ioctl(struct ifnet *, u_long, caddr_t); +static int ural_transmit(struct ieee80211com *, struct mbuf *); +static void ural_start(struct ural_softc *); +static void ural_parent(struct ieee80211com *); static void ural_set_testmode(struct ural_softc *); static void ural_eeprom_read(struct ural_softc *, uint16_t, void *, int); @@ -171,12 +172,12 @@ 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 ifnet *); +static void ural_update_slot(struct ural_softc *); 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 *, uint8_t *); +static void ural_set_macaddr(struct ural_softc *, const uint8_t *); static void ural_update_promisc(struct ieee80211com *); static void ural_setpromisc(struct ural_softc *); static const char *ural_get_rf(int); @@ -184,8 +185,7 @@ 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_locked(struct ural_softc *); -static void ural_init(void *); +static void ural_init(struct ural_softc *); static void ural_stop(struct ural_softc *); static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); @@ -422,8 +422,7 @@ { struct usb_attach_arg *uaa = device_get_ivars(self); struct ural_softc *sc = device_get_softc(self); - struct ifnet *ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; uint8_t iface_index, bands; int error; @@ -433,6 +432,7 @@ 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,24 +455,6 @@ 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 */ @@ -497,13 +479,14 @@ setbit(&bands, IEEE80211_MODE_11A); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, sc->sc_bssid); + ieee80211_ifattach(ic); 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; @@ -527,8 +510,7 @@ ural_detach(device_t self) { struct ural_softc *sc = device_get_softc(self); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; /* prevent further ioctls */ RAL_LOCK(sc); @@ -543,11 +525,9 @@ ural_unsetup_tx_list(sc); RAL_UNLOCK(sc); - if (ifp) { - ic = ifp->if_l2com; + if (ic->ic_softc == sc) ieee80211_ifdetach(ic); - if_free(ifp); - } + mbufq_drain(&sc->sc_snd); mtx_destroy(&sc->sc_mtx); return (0); @@ -580,7 +560,7 @@ const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct ural_softc *sc = ic->ic_ifp->if_softc; + struct ural_softc *sc = ic->ic_softc; struct ural_vap *uvp; struct ieee80211vap *vap; @@ -594,7 +574,7 @@ /* enable s/w bmiss handling for sta mode */ if (ieee80211_vap_setup(ic, vap, name, unit, opmode, - flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) { + flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) { /* out of memory */ free(uvp, M_80211_VAP); return (NULL); @@ -610,7 +590,8 @@ ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */); /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); + ieee80211_vap_attach(vap, ieee80211_media_change, + ieee80211_media_status, mac); ic->ic_opmode = opmode; return vap; } @@ -634,13 +615,8 @@ struct ural_softc *sc = data->sc; if (data->m != NULL) { - if (data->m->m_flags & M_TXCB) - ieee80211_process_callback(data->ni, data->m, - txerr ? ETIMEDOUT : 0); - m_freem(data->m); + ieee80211_tx_complete(data->ni, data->m, txerr); data->m = NULL; - - ieee80211_free_node(data->ni); data->ni = NULL; } STAILQ_INSERT_TAIL(&sc->tx_free, data, next); @@ -697,7 +673,7 @@ { struct ural_vap *uvp = URAL_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct ural_softc *sc = ic->ic_ifp->if_softc; + struct ural_softc *sc = ic->ic_softc; const struct ieee80211_txparam *tp; struct ieee80211_node *ni; struct mbuf *m; @@ -731,11 +707,11 @@ ieee80211_free_node(ni); return (-1); } - ural_update_slot(ic->ic_ifp); + ural_update_slot(sc); ural_set_txpreamble(sc); ural_set_basicrates(sc, ic->ic_bsschan); - IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid); - ural_set_bssid(sc, sc->sc_bssid); + IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid); + ural_set_bssid(sc, ic->ic_macaddr); } if (vap->iv_opmode == IEEE80211_M_HOSTAP || @@ -789,7 +765,6 @@ 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; @@ -807,9 +782,6 @@ 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: @@ -852,16 +824,13 @@ usbd_transfer_submit(xfer); } - RAL_UNLOCK(sc); - ural_start(ifp); - RAL_LOCK(sc); + ural_start(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); @@ -883,8 +852,7 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) { struct ural_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; struct mbuf *m = NULL; struct usb_page_cache *pc; @@ -902,7 +870,7 @@ if (len < (int)(RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN)) { DPRINTF("%s: xfer too short %d\n", device_get_nameunit(sc->sc_dev), len); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto tr_setup; } @@ -921,20 +889,19 @@ * filled RAL_TXRX_CSR2: */ DPRINTFN(5, "PHY or CRC error\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto tr_setup; } m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (m == NULL) { DPRINTF("could not allocate mbuf\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_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)) { @@ -973,10 +940,8 @@ } 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 */ @@ -1016,8 +981,7 @@ ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc, uint32_t flags, int len, int rate) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint16_t plcp_length; int remainder; @@ -1066,12 +1030,10 @@ { 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); @@ -1348,78 +1310,73 @@ 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 ifnet *ifp) +ural_start(struct ural_softc *sc) { - struct ural_softc *sc = ifp->if_softc; struct ieee80211_node *ni; struct mbuf *m; - RAL_LOCK(sc); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - RAL_UNLOCK(sc); + RAL_LOCK_ASSERT(sc, MA_OWNED); + + if (sc->sc_running == 0) return; - } - 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; - } + + 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); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); break; } } - RAL_UNLOCK(sc); } -static int -ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +ural_parent(struct ieee80211com *ic) { - struct ural_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error; + struct ural_softc *sc = ic->ic_softc; 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); - } + if (sc->sc_detached) { 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; } - return error; + 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); + RAL_UNLOCK(sc); + if (startall) + ieee80211_start_all(ic); } static void @@ -1614,23 +1571,22 @@ static void ural_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct ural_softc *sc = ifp->if_softc; + struct ural_softc *sc = ic->ic_softc; RAL_LOCK(sc); ural_write(sc, RAL_TXRX_CSR19, 0); - ural_set_bssid(sc, ifp->if_broadcastaddr); + ural_set_bssid(sc, ieee80211broadcastaddr); RAL_UNLOCK(sc); } static void ural_scan_end(struct ieee80211com *ic) { - struct ural_softc *sc = ic->ic_ifp->if_softc; + struct ural_softc *sc = ic->ic_softc; RAL_LOCK(sc); ural_enable_tsf_sync(sc); - ural_set_bssid(sc, sc->sc_bssid); + ural_set_bssid(sc, ic->ic_macaddr); RAL_UNLOCK(sc); } @@ -1638,7 +1594,7 @@ static void ural_set_channel(struct ieee80211com *ic) { - struct ural_softc *sc = ic->ic_ifp->if_softc; + struct ural_softc *sc = ic->ic_softc; RAL_LOCK(sc); ural_set_chan(sc, ic->ic_curchan); @@ -1648,8 +1604,7 @@ static void ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint8_t power, tmp; int i, chan; @@ -1780,8 +1735,7 @@ static void ural_enable_tsf_sync(struct ural_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint16_t logcwmin, preload, tmp; @@ -1817,10 +1771,9 @@ #define RAL_RXTX_TURNAROUND 5 /* us */ static void -ural_update_slot(struct ifnet *ifp) +ural_update_slot(struct ural_softc *sc) { - struct ural_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint16_t slottime, sifs, eifs; slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; @@ -1845,8 +1798,7 @@ static void ural_set_txpreamble(struct ural_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint16_t tmp; tmp = ural_read(sc, RAL_TXRX_CSR10); @@ -1893,7 +1845,7 @@ } static void -ural_set_macaddr(struct ural_softc *sc, uint8_t *addr) +ural_set_macaddr(struct ural_softc *sc, const uint8_t *addr) { uint16_t tmp; @@ -1912,18 +1864,17 @@ 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 (!(ifp->if_flags & IFF_PROMISC)) + if (sc->sc_ic.ic_promisc == 0) tmp |= RAL_DROP_NOT_TO_ME; ural_write(sc, RAL_TXRX_CSR2, tmp); - DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? + DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc ? "entering" : "leaving"); } @@ -1932,11 +1883,9 @@ { struct ural_softc *sc = ic->ic_softc; - if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - RAL_LOCK(sc); - ural_setpromisc(sc); + if (sc->sc_running) + ural_setpromisc(sc); RAL_UNLOCK(sc); } @@ -1958,6 +1907,7 @@ 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); @@ -1970,7 +1920,7 @@ sc->nb_ant = val & 0x3; /* read MAC address */ - ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6); + ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_macaddr, 6); /* read default values for BBP registers */ ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16); @@ -2064,11 +2014,11 @@ } static void -ural_init_locked(struct ural_softc *sc) +ural_init(struct ural_softc *sc) { #define N(a) ((int)(sizeof (a) / sizeof ((a)[0]))) - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint16_t tmp; int i, ntries; @@ -2115,7 +2065,7 @@ ural_set_txantenna(sc, sc->tx_ant); ural_set_rxantenna(sc, sc->rx_ant); - ural_set_macaddr(sc, IF_LLADDR(ifp)); + ural_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); /* * Allocate Tx and Rx xfer queues. @@ -2128,13 +2078,12 @@ tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION; if (ic->ic_opmode != IEEE80211_M_HOSTAP) tmp |= RAL_DROP_TODS; - if (!(ifp->if_flags & IFF_PROMISC)) + if (ic->ic_promisc == 0) tmp |= RAL_DROP_NOT_TO_ME; } ural_write(sc, RAL_TXRX_CSR2, tmp); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_running = 1; usbd_xfer_set_stall(sc->sc_xfer[URAL_BULK_WR]); usbd_transfer_start(sc->sc_xfer[URAL_BULK_RD]); return; @@ -2144,28 +2093,12 @@ } 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); - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_running = 0; /* * Drain all the transfers, if not already drained: @@ -2193,27 +2126,23 @@ const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ural_softc *sc = ifp->if_softc; + struct ural_softc *sc = ic->ic_softc; RAL_LOCK(sc); /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!sc->sc_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 @@ -2232,7 +2161,6 @@ RAL_UNLOCK(sc); return 0; bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); RAL_UNLOCK(sc); ieee80211_free_node(ni); return EIO; /* XXX */ @@ -2266,8 +2194,7 @@ struct ural_vap *uvp = arg; struct ieee80211vap *vap = &uvp->vap; struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct ural_softc *sc = ifp->if_softc; + struct ural_softc *sc = ic->ic_softc; struct ieee80211_node *ni; int ok, fail; int sum, retrycnt; @@ -2286,7 +2213,8 @@ ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt); (void) ieee80211_ratectl_rate(ni, NULL, 0); - if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */ + /* count TX retry-fail as Tx errors */ + if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail); usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp); RAL_UNLOCK(sc); Index: sys/dev/usb/wlan/if_uralvar.h =================================================================== --- sys/dev/usb/wlan/if_uralvar.h +++ sys/dev/usb/wlan/if_uralvar.h @@ -89,7 +89,8 @@ }; struct ural_softc { - struct ifnet *sc_ifp; + struct ieee80211com sc_ic; + struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; @@ -109,8 +110,8 @@ uint16_t sta[11]; uint32_t rf_regs[4]; uint8_t txpow[14]; - uint8_t sc_bssid[6]; - uint8_t sc_detached; + u_int sc_detached:1, + sc_running:1; struct { uint8_t val; Index: sys/dev/usb/wlan/if_urtw.c =================================================================== --- sys/dev/usb/wlan/if_urtw.c +++ sys/dev/usb/wlan/if_urtw.c @@ -651,11 +651,11 @@ int, const uint8_t [IEEE80211_ADDR_LEN], const uint8_t [IEEE80211_ADDR_LEN]); static void urtw_vap_delete(struct ieee80211vap *); -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 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 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,8 +784,7 @@ int ret = ENXIO; struct urtw_softc *sc = device_get_softc(dev); struct usb_attach_arg *uaa = device_get_ivars(dev); - struct ieee80211com *ic; - struct ifnet *ifp; + struct ieee80211com *ic = &sc->sc_ic; uint8_t bands, iface_index = URTW_IFACE_INDEX; /* XXX */ uint16_t n_setup; uint32_t data; @@ -807,6 +806,7 @@ 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,26 +861,6 @@ 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 */ @@ -901,7 +881,7 @@ setbit(&bands, IEEE80211_MODE_11G); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, sc->sc_bssid); + ieee80211_ifattach(ic); ic->ic_raw_xmit = urtw_raw_xmit; ic->ic_scan_start = urtw_scan_start; ic->ic_scan_end = urtw_scan_end; @@ -910,6 +890,8 @@ 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), @@ -923,8 +905,9 @@ ieee80211_announce(ic); return (0); -fail: URTW_UNLOCK(sc); -fail1: usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ? +fail: + URTW_UNLOCK(sc); + usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ? URTW_8187B_N_XFERS : URTW_8187L_N_XFERS); fail0: return (ret); @@ -934,18 +917,16 @@ urtw_detach(device_t dev) { struct urtw_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; 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); @@ -979,7 +960,7 @@ usbd_transfer_unsetup(sc->sc_xfer, n_xfers); ieee80211_ifdetach(ic); - if_free(ifp); + mbufq_drain(&sc->sc_snd); mtx_destroy(&sc->sc_mtx); return (0); } @@ -1032,15 +1013,12 @@ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return (NULL); - uvp = (struct urtw_vap *) malloc(sizeof(struct urtw_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (uvp == NULL) - return (NULL); + uvp = malloc(sizeof(struct urtw_vap), M_80211_VAP, M_WAITOK | M_ZERO); 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, mac) != 0) { + flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) { /* out of memory */ free(uvp, M_80211_VAP); return (NULL); @@ -1052,7 +1030,7 @@ /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); + ieee80211_media_status, mac); ic->ic_opmode = opmode; return (vap); } @@ -1067,15 +1045,15 @@ } static void -urtw_init_locked(void *arg) +urtw_init(struct urtw_softc *sc) { - int ret; - struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; usb_error_t error; + int ret; + + URTW_ASSERT_LOCKED(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - urtw_stop_locked(ifp); + if (sc->sc_flags & URTW_RUNNING) + urtw_stop(sc); error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) : urtw_adapter_start(sc); @@ -1105,24 +1083,13 @@ if (sc->sc_flags & URTW_RTL8187B) usbd_transfer_start(sc->sc_xfer[URTW_8187B_BULK_TX_STATUS]); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_flags |= URTW_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) { @@ -1215,6 +1182,7 @@ 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); @@ -1234,8 +1202,8 @@ if (error) goto fail; /* applying MAC address again. */ - 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); + 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); error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); if (error) goto fail; @@ -1338,13 +1306,14 @@ } static void -urtw_stop_locked(struct ifnet *ifp) +urtw_stop(struct urtw_softc *sc) { - struct urtw_softc *sc = ifp->if_softc; uint8_t data8; usb_error_t error; - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + URTW_ASSERT_LOCKED(sc); + + sc->sc_flags &= ~URTW_RUNNING; error = urtw_intr_disable(sc); if (error) @@ -1377,16 +1346,6 @@ } 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) { int i, max; @@ -1401,72 +1360,71 @@ usbd_transfer_stop(sc->sc_xfer[i]); } -static int -urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +urtw_parent(struct ieee80211com *ic) { - struct urtw_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error; + struct urtw_softc *sc = ic->ic_softc; int startall = 0; URTW_LOCK(sc); - error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0; - URTW_UNLOCK(sc); - if (error) - return (error); + if (sc->sc_flags & URTW_DETACHED) { + URTW_UNLOCK(sc); + return; + } - 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; - } + 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 { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - urtw_stop(ifp); + urtw_init(sc); + startall = 1; } - 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; + } else if (sc->sc_flags & URTW_RUNNING) + urtw_stop(sc); + 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); } - return (error); + error = mbufq_enqueue(&sc->sc_snd, m); + if (error) { + URTW_UNLOCK(sc); + return (error); + } + urtw_start(sc); + URTW_UNLOCK(sc); + + return (0); } static void -urtw_start(struct ifnet *ifp) +urtw_start(struct urtw_softc *sc) { struct urtw_data *bf; - struct urtw_softc *sc = ifp->if_softc; struct ieee80211_node *ni; struct mbuf *m; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + URTW_ASSERT_LOCKED(sc); + + if ((sc->sc_flags & URTW_RUNNING) == 0) return; - URTW_LOCK(sc); - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { bf = urtw_getbuf(sc); if (bf == NULL) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); + mbufq_prepend(&sc->sc_snd, m); break; } @@ -1474,7 +1432,8 @@ m->m_pkthdr.rcvif = NULL; if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_NORMAL) != 0) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next); ieee80211_free_node(ni); break; @@ -1483,7 +1442,6 @@ sc->sc_txtimer = 5; callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); } - URTW_UNLOCK(sc); } static int @@ -1565,12 +1523,11 @@ const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; + struct urtw_softc *sc = ic->ic_softc; struct urtw_data *bf; - struct urtw_softc *sc = ifp->if_softc; /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!(sc->sc_flags & URTW_RUNNING)) { m_freem(m); ieee80211_free_node(ni); return ENETDOWN; @@ -1584,10 +1541,8 @@ 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); @@ -1615,8 +1570,7 @@ static void urtw_set_channel(struct ieee80211com *ic) { - struct urtw_softc *sc = ic->ic_ifp->if_softc; - struct ifnet *ifp = sc->sc_ifp; + struct urtw_softc *sc = ic->ic_softc; uint32_t data, orig; usb_error_t error; @@ -1626,7 +1580,7 @@ * initialization would be failed if setting a channel is called before * the init have done. */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) + if (!(sc->sc_flags & URTW_RUNNING)) return; if (sc->sc_curchan != NULL && sc->sc_curchan == ic->ic_curchan) @@ -1673,11 +1627,10 @@ 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 = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct usb_xfer *rtl8187b_pipes[URTW_8187B_TXPIPE_MAX] = { sc->sc_xfer[URTW_8187B_BULK_TX_BE], @@ -1862,7 +1815,7 @@ urtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct ieee80211com *ic = vap->iv_ic; - struct urtw_softc *sc = ic->ic_ifp->if_softc; + struct urtw_softc *sc = ic->ic_softc; struct urtw_vap *uvp = URTW_VAP(vap); struct ieee80211_node *ni; usb_error_t error = 0; @@ -1905,7 +1858,6 @@ default: break; } -fail: URTW_UNLOCK(sc); IEEE80211_LOCK(ic); return (uvp->newstate(vap, nstate, arg)); @@ -1915,12 +1867,11 @@ 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"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); return; } callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); @@ -1930,17 +1881,7 @@ static void urtw_set_multi(void *arg) { - 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; + /* XXX don't know how to set a device. Lack of docs. */ } static usb_error_t @@ -2002,8 +1943,7 @@ static usb_error_t urtw_update_msr(struct urtw_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint8_t data; usb_error_t error; @@ -2144,24 +2084,25 @@ 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; - sc->sc_bssid[0] = data & 0xff; - sc->sc_bssid[1] = (data & 0xff00) >> 8; + ic->ic_macaddr[0] = data & 0xff; + ic->ic_macaddr[1] = (data & 0xff00) >> 8; error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data); if (error != 0) goto fail; - sc->sc_bssid[2] = data & 0xff; - sc->sc_bssid[3] = (data & 0xff00) >> 8; + ic->ic_macaddr[2] = data & 0xff; + ic->ic_macaddr[3] = (data & 0xff00) >> 8; error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data); if (error != 0) goto fail; - sc->sc_bssid[4] = data & 0xff; - sc->sc_bssid[5] = (data & 0xff00) >> 8; + ic->ic_macaddr[4] = data & 0xff; + ic->ic_macaddr[5] = (data & 0xff00) >> 8; fail: return (error); } @@ -3233,7 +3174,7 @@ static usb_error_t urtw_8225v2b_rf_init(struct urtw_softc *sc) { -#define N(a) ((int)(sizeof(a) / sizeof((a)[0]))) + struct ieee80211com *ic = &sc->sc_ic; int i; uint8_t data8; usb_error_t error; @@ -3281,8 +3222,8 @@ urtw_write8_m(sc, URTW_CONFIG1, data8); /* applying MAC address again. */ - 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); + 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); error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); if (error) @@ -3293,7 +3234,7 @@ /* * MAC configuration */ - for (i = 0; i < N(urtw_8225v2b_rf_part1); i++) + for (i = 0; i < nitems(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); @@ -3326,7 +3267,7 @@ urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1fff); usb_pause_mtx(&sc->sc_mtx, 1100); - for (i = 0; i < N(urtw_8225v2b_rf_part0); i++) { + for (i = 0; i < nitems(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); @@ -3372,7 +3313,7 @@ } urtw_8187_write_phy_ofdm(sc, 0x80, 0x10); - for (i = 0; i < N(urtw_8225v2b_rf_part2); i++) + for (i = 0; i < nitems(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); @@ -3787,8 +3728,7 @@ urtw_led_ch(void *arg) { struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; ieee80211_runtask(ic, &sc->sc_led_task); } @@ -3935,8 +3875,7 @@ static usb_error_t urtw_rx_setconf(struct urtw_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t data; usb_error_t error; @@ -3961,7 +3900,7 @@ data = data | URTW_RX_FILTER_CRCERR; if (ic->ic_opmode == IEEE80211_M_MONITOR || - (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { + ic->ic_promisc > 0 || ic->ic_allmulti > 0) { data = data | URTW_RX_FILTER_ALLMAC; } else { data = data | URTW_RX_FILTER_NICMAC; @@ -3988,14 +3927,13 @@ struct ieee80211_frame *wh; struct mbuf *m, *mnew; struct urtw_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint8_t noise = 0, rate; usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); if (actlen < (int)URTW_MIN_RXBUFSZ) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return (NULL); } @@ -4006,7 +3944,7 @@ (actlen - (sizeof(struct urtw_8187b_rxhdr)))); flen = le32toh(rx->flag) & 0xfff; if (flen > actlen) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return (NULL); } rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf; @@ -4020,7 +3958,7 @@ (actlen - (sizeof(struct urtw_8187l_rxhdr)))); flen = le32toh(rx->flag) & 0xfff; if (flen > actlen) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return (NULL); } @@ -4032,7 +3970,7 @@ mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (mnew == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return (NULL); } @@ -4041,7 +3979,6 @@ 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)) { @@ -4067,8 +4004,7 @@ urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) { struct urtw_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *m = NULL; @@ -4129,7 +4065,7 @@ } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto setup; } break; @@ -4143,7 +4079,7 @@ urtw_txstatus_eof(struct usb_xfer *xfer) { struct urtw_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; int actlen, type, pktretry, seq; uint64_t val; @@ -4158,7 +4094,7 @@ pktretry = val & 0xff; seq = (val >> 16) & 0xff; if (pktretry == URTW_TX_MAXRETRY) - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(ic->ic_oerrors, 1); DPRINTF(sc, URTW_DEBUG_TXSTATUS, "pktretry %d seq %#x\n", pktretry, seq); } @@ -4168,7 +4104,7 @@ urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error) { struct urtw_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0); URTW_ASSERT_LOCKED(sc); @@ -4186,7 +4122,7 @@ default: if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto setup; } break; @@ -4197,38 +4133,22 @@ 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) { - m = data->m; - if (m->m_flags & M_TXCB) { - /* XXX status? */ - ieee80211_process_callback(data->ni, m, 0); - } - m_freem(m); + /* XXX status? */ + ieee80211_tx_complete(data->ni, data->m, 0); 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); @@ -4256,18 +4176,17 @@ usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen); usbd_transfer_submit(xfer); - URTW_UNLOCK(sc); - urtw_start(ifp); - URTW_LOCK(sc); + urtw_start(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); @@ -4301,12 +4220,8 @@ URTW_ASSERT_LOCKED(sc); bf = _urtw_getbuf(sc); - if (bf == NULL) { - struct ifnet *ifp = sc->sc_ifp; - + if (bf == NULL) DPRINTF(sc, URTW_DEBUG_XMIT, "%s: stop queue\n", __func__); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - } return (bf); } @@ -4378,14 +4293,14 @@ urtw_updateslottask(void *arg, int pending) { struct urtw_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; int error; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; - URTW_LOCK(sc); + if ((sc->sc_flags & URTW_RUNNING) == 0) { + URTW_UNLOCK(sc); + return; + } if (sc->sc_flags & URTW_RTL8187B) { urtw_write8_m(sc, URTW_SIFS, 0x22); if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) Index: sys/dev/usb/wlan/if_urtwn.c =================================================================== --- sys/dev/usb/wlan/if_urtwn.c +++ sys/dev/usb/wlan/if_urtwn.c @@ -169,8 +169,8 @@ 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 *sc, - struct usb_device_request *req, void *data); +static usb_error_t urtwn_do_request(struct urtwn_softc *, + struct usb_device_request *, void *); static struct ieee80211vap *urtwn_vap_create(struct ieee80211com *, const char [IFNAMSIZ], int, enum ieee80211_opmode, int, const uint8_t [IEEE80211_ADDR_LEN], @@ -228,10 +228,9 @@ static int urtwn_tx_start(struct urtwn_softc *, struct ieee80211_node *, struct mbuf *, struct urtwn_data *); -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_transmit(struct ieee80211com *, struct mbuf *); +static void urtwn_start(struct urtwn_softc *); +static void urtwn_parent(struct ieee80211com *); 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 *); @@ -269,10 +268,8 @@ 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(void *); -static void urtwn_init_locked(void *); -static void urtwn_stop(struct ifnet *); -static void urtwn_stop_locked(struct ifnet *); +static void urtwn_init(struct urtwn_softc *); +static void urtwn_stop(struct urtwn_softc *); static void urtwn_abort_xfers(struct urtwn_softc *); static int urtwn_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); @@ -368,8 +365,7 @@ { struct usb_attach_arg *uaa = device_get_ivars(self); struct urtwn_softc *sc = device_get_softc(self); - struct ifnet *ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; uint8_t iface_index, bands; int error; @@ -382,6 +378,7 @@ 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, @@ -424,24 +421,6 @@ 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 */ @@ -462,12 +441,13 @@ setbit(&bands, IEEE80211_MODE_11G); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, sc->sc_bssid); + ieee80211_ifattach(ic); 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; @@ -491,17 +471,15 @@ urtwn_detach(device_t self) { struct urtwn_softc *sc = device_get_softc(self); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; 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. */ @@ -527,8 +505,7 @@ /* stop all USB transfers */ usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER); ieee80211_ifdetach(ic); - - if_free(ifp); + mbufq_drain(&sc->sc_snd); mtx_destroy(&sc->sc_mtx); return (0); @@ -599,15 +576,12 @@ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return (NULL); - uvp = (struct urtwn_vap *) malloc(sizeof(struct urtwn_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (uvp == NULL) - return (NULL); + uvp = malloc(sizeof(struct urtwn_vap), M_80211_VAP, M_WAITOK | M_ZERO); 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, mac) != 0) { + flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) { /* out of memory */ free(uvp, M_80211_VAP); return (NULL); @@ -619,7 +593,7 @@ /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); + ieee80211_media_status, mac); ic->ic_opmode = opmode; return (vap); } @@ -636,8 +610,7 @@ static struct mbuf * urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; struct mbuf *m; struct r92c_rx_stat *stat; @@ -650,7 +623,7 @@ * don't pass packets to the ieee80211 framework if the driver isn't * RUNNING. */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) + if (!(sc->sc_flags & URTWN_RUNNING)) return (NULL); stat = (struct r92c_rx_stat *)buf; @@ -662,11 +635,11 @@ * This should not happen since we setup our Rx filter * to not receive these frames. */ - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return (NULL); } if (pktlen < sizeof(*wh) || pktlen > MCLBYTES) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return (NULL); } @@ -695,7 +668,6 @@ } /* 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; @@ -741,7 +713,7 @@ int8_t *nf) { struct urtwn_softc *sc = data->sc; - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; struct r92c_rx_stat *stat; struct mbuf *m, *m0 = NULL, *prevm = NULL; uint32_t rxdw0; @@ -751,7 +723,7 @@ usbd_xfer_status(xfer, &len, NULL, NULL, NULL); if (len < sizeof(*stat)) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return (NULL); } @@ -802,8 +774,7 @@ urtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) { struct urtwn_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *m = NULL, *next; @@ -866,7 +837,7 @@ } if (error != USB_ERR_CANCELLED) { usbd_xfer_set_stall(xfer); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto tr_setup; } break; @@ -877,38 +848,19 @@ 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); - - /* - * 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; - } + /* XXX status? */ + ieee80211_tx_complete(data->ni, data->m, 0); + data->ni = NULL; + data->m = 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); @@ -933,16 +885,17 @@ 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_locked(ifp, sc); + urtwn_start(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); @@ -975,11 +928,8 @@ URTWN_ASSERT_LOCKED(sc); bf = _urtwn_getbuf(sc); - if (bf == NULL) { - struct ifnet *ifp = sc->sc_ifp; + if (bf == NULL) DPRINTF("%s: stop queue\n", __func__); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - } return (bf); } @@ -1302,7 +1252,7 @@ sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY); DPRINTF("regulatory type=%d\n", sc->regulatory); - IEEE80211_ADDR_COPY(sc->sc_bssid, rom->macaddr); + IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr); sc->sc_rf_write = urtwn_r92c_rf_write; sc->sc_power_on = urtwn_r92c_power_on; @@ -1363,7 +1313,7 @@ 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_bssid, &sc->r88e_rom[0xd7]); + IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, &sc->r88e_rom[0xd7]); sc->sc_rf_write = urtwn_r88e_rf_write; sc->sc_power_on = urtwn_r88e_power_on; @@ -1378,7 +1328,7 @@ { static const uint8_t map[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211_node *ni; struct ieee80211_rateset *rs; @@ -1455,8 +1405,7 @@ void urtwn_tsf_sync_enable(struct urtwn_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211_node *ni = vap->iv_bss; @@ -1513,7 +1462,7 @@ { struct urtwn_vap *uvp = URTWN_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct urtwn_softc *sc = ic->ic_ifp->if_softc; + struct urtwn_softc *sc = ic->ic_softc; struct ieee80211_node *ni; enum ieee80211_state ostate; uint32_t reg; @@ -1669,12 +1618,11 @@ 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"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); return; } callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc); @@ -1800,10 +1748,9 @@ 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 = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct usb_xfer *xfer; struct r92c_tx_desc *txd; @@ -1942,89 +1889,78 @@ return (0); } -static void -urtwn_start(struct ifnet *ifp) +static int +urtwn_transmit(struct ieee80211com *ic, struct mbuf *m) { - struct urtwn_softc *sc = ifp->if_softc; + struct urtwn_softc *sc = ic->ic_softc; + int error; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - return; URTWN_LOCK(sc); - urtwn_start_locked(ifp, 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_UNLOCK(sc); + + return (0); } static void -urtwn_start_locked(struct ifnet *ifp, struct urtwn_softc *sc) +urtwn_start(struct urtwn_softc *sc) { struct ieee80211_node *ni; struct mbuf *m; struct urtwn_data *bf; URTWN_ASSERT_LOCKED(sc); - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { bf = urtwn_getbuf(sc); if (bf == NULL) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); + mbufq_prepend(&sc->sc_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(ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(ni->ni_vap->iv_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 int -urtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +urtwn_parent(struct ieee80211com *ic) { - struct urtwn_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + struct urtwn_softc *sc = ic->ic_softc; + int startall = 0; URTWN_LOCK(sc); - error = (sc->sc_flags & URTWN_DETACHED) ? ENXIO : 0; + 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); URTWN_UNLOCK(sc); - if (error != 0) - return (error); - 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); + if (startall) + ieee80211_start_all(ic); } static int @@ -2938,7 +2874,7 @@ struct ieee80211_channel *c, struct ieee80211_channel *extc, uint16_t power[URTWN_RIDX_COUNT]) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct r92c_rom *rom = &sc->rom; uint16_t cckpow, ofdmpow, htpow, diff, max; const struct urtwn_txpwr *base; @@ -3037,7 +2973,7 @@ struct ieee80211_channel *c, struct ieee80211_channel *extc, uint16_t power[URTWN_RIDX_COUNT]) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint16_t cckpow, ofdmpow, bw20pow, htpow; const struct urtwn_r88e_txpwr *base; int ridx, chan, group; @@ -3134,7 +3070,7 @@ static void urtwn_set_channel(struct ieee80211com *ic) { - struct urtwn_softc *sc = ic->ic_ifp->if_softc; + struct urtwn_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); URTWN_LOCK(sc); @@ -3156,7 +3092,7 @@ urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c, struct ieee80211_channel *extc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t reg; u_int chan; int i; @@ -3287,17 +3223,18 @@ } static void -urtwn_init_locked(void *arg) +urtwn_init(struct urtwn_softc *sc) { - struct urtwn_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + uint8_t macaddr[IEEE80211_ADDR_LEN]; uint32_t reg; int error; URTWN_ASSERT_LOCKED(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - urtwn_stop_locked(ifp); + if (sc->sc_flags & URTWN_RUNNING) + urtwn_stop(sc); /* Init firmware commands ring. */ sc->fwcur = 0; @@ -3340,8 +3277,8 @@ } /* Set MAC address. */ - urtwn_write_region_1(sc, R92C_MACID, IF_LLADDR(ifp), - IEEE80211_ADDR_LEN); + IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr); + urtwn_write_region_1(sc, R92C_MACID, macaddr, IEEE80211_ADDR_LEN); /* Set initial network type. */ reg = urtwn_read_4(sc, R92C_CR); @@ -3465,8 +3402,7 @@ usbd_transfer_start(sc->sc_xfer[URTWN_BULK_RX]); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_flags |= URTWN_RUNNING; callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc); fail: @@ -3474,39 +3410,16 @@ } static void -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) +urtwn_stop(struct urtwn_softc *sc) { - struct urtwn_softc *sc = ifp->if_softc; URTWN_ASSERT_LOCKED(sc); - - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - + sc->sc_flags &= ~URTWN_RUNNING; 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) { int i; @@ -3523,12 +3436,11 @@ const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct urtwn_softc *sc = ifp->if_softc; + struct urtwn_softc *sc = ic->ic_softc; struct urtwn_data *bf; /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!(sc->sc_flags & URTWN_RUNNING)) { m_freem(m); ieee80211_free_node(ni); return (ENETDOWN); @@ -3542,10 +3454,8 @@ 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); Index: sys/dev/usb/wlan/if_urtwnreg.h =================================================================== --- sys/dev/usb/wlan/if_urtwnreg.h +++ sys/dev/usb/wlan/if_urtwnreg.h @@ -1172,7 +1172,8 @@ #define URTWN_EP_QUEUES URTWN_BULK_RX struct urtwn_softc { - struct ifnet *sc_ifp; + struct ieee80211com sc_ic; + struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; @@ -1180,6 +1181,7 @@ 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 @@ -1224,7 +1226,6 @@ 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; Index: sys/dev/usb/wlan/if_urtwvar.h =================================================================== --- sys/dev/usb/wlan/if_urtwvar.h +++ sys/dev/usb/wlan/if_urtwvar.h @@ -93,14 +93,14 @@ #define URTW_VAP(vap) ((struct urtw_vap *)(vap)) struct urtw_softc { - struct ifnet *sc_ifp; + struct ieee80211com sc_ic; + struct mbufq sc_snd; 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 @@ #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; Index: sys/dev/usb/wlan/if_zyd.c =================================================================== --- sys/dev/usb/wlan/if_zyd.c +++ sys/dev/usb/wlan/if_zyd.c @@ -154,12 +154,12 @@ 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 void zyd_start(struct ifnet *); +static int zyd_transmit(struct ieee80211com *, struct mbuf *); +static void zyd_start(struct zyd_softc *); static int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); -static int zyd_ioctl(struct ifnet *, u_long, caddr_t); +static void zyd_parent(struct ieee80211com *); 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,8 +333,7 @@ { struct usb_attach_arg *uaa = device_get_ivars(dev); struct zyd_softc *sc = device_get_softc(dev); - struct ifnet *ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; uint8_t iface_index, bands; int error; @@ -353,6 +352,7 @@ 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,22 +372,6 @@ } 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 */ @@ -408,16 +392,17 @@ setbit(&bands, IEEE80211_MODE_11G); ieee80211_init_channels(ic, NULL, &bands); - ieee80211_ifattach(ic, sc->sc_bssid); + ieee80211_ifattach(ic); 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), @@ -439,8 +424,7 @@ zyd_detach(device_t dev) { struct zyd_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; unsigned int x; /* @@ -465,11 +449,9 @@ /* free USB transfers and some data buffers */ usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER); - if (ifp) { - ic = ifp->if_l2com; + if (ic->ic_softc == sc) ieee80211_ifdetach(ic); - if_free(ifp); - } + mbufq_drain(&sc->sc_snd); mtx_destroy(&sc->sc_mtx); return (0); @@ -486,15 +468,12 @@ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return (NULL); - zvp = (struct zyd_vap *) malloc(sizeof(struct zyd_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (zvp == NULL) - return (NULL); + zvp = malloc(sizeof(struct zyd_vap), M_80211_VAP, M_WAITOK | M_ZERO); 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, mac) != 0) { + flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) { /* out of memory */ free(zvp, M_80211_VAP); return (NULL); @@ -509,7 +488,7 @@ /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); + ieee80211_media_status, mac); ic->ic_opmode = opmode; return (vap); } @@ -530,13 +509,8 @@ struct zyd_softc *sc = data->sc; if (data->m != NULL) { - if (data->m->m_flags & M_TXCB) - ieee80211_process_callback(data->ni, data->m, - txerr ? ETIMEDOUT : 0); - m_freem(data->m); + ieee80211_tx_complete(data->ni, data->m, txerr); data->m = NULL; - - ieee80211_free_node(data->ni); data->ni = NULL; } STAILQ_INSERT_TAIL(&sc->tx_free, data, next); @@ -593,7 +567,7 @@ { struct zyd_vap *zvp = ZYD_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct zyd_softc *sc = ic->ic_ifp->if_softc; + struct zyd_softc *sc = ic->ic_softc; int error; DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__, @@ -618,8 +592,8 @@ /* make data LED blink upon Tx */ zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1); - IEEE80211_ADDR_COPY(sc->sc_bssid, vap->iv_bss->ni_bssid); - zyd_set_bssid(sc, sc->sc_bssid); + IEEE80211_ADDR_COPY(ic->ic_macaddr, vap->iv_bss->ni_bssid); + zyd_set_bssid(sc, ic->ic_macaddr); break; default: break; @@ -637,8 +611,7 @@ zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error) { struct zyd_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211_node *ni; struct zyd_cmd *cmd = &sc->sc_ibuf; @@ -681,7 +654,9 @@ ieee80211_free_node(ni); } if (le16toh(retry->count) & 0x100) - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); /* too many retries */ + /* too many retries */ + if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, + 1); break; } case ZYD_NOTIF_IORD: @@ -1243,8 +1218,7 @@ #define N(a) ((int)(sizeof(a) / sizeof((a)[0]))) int error = 0, i; struct zyd_softc *sc = rf->rf_sc; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6; int chan = ieee80211_chan2ieee(ic, c); @@ -1932,7 +1906,7 @@ USETW(req.wIndex, 0); USETW(req.wLength, IEEE80211_ADDR_LEN); - error = zyd_do_request(sc, &req, sc->sc_bssid); + error = zyd_do_request(sc, &req, sc->sc_ic.ic_macaddr); if (error != 0) { device_printf(sc->sc_dev, "could not read EEPROM: %s\n", usbd_errstr(error)); @@ -2004,36 +1978,41 @@ static void zyd_set_multi(struct zyd_softc *sc) { - int error; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ifmultiaddr *ifma; + struct ieee80211com *ic = &sc->sc_ic; uint32_t low, high; - uint8_t v; + int error; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0) return; low = 0x00000000; high = 0x80000000; - if (ic->ic_opmode == IEEE80211_M_MONITOR || - (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) { + if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 || + ic->ic_promisc > 0) { low = 0xffffffff; high = 0xffffffff; } else { - 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); + 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_runlock(ifp); } /* reprogram multicast global hash table */ @@ -2050,9 +2029,6 @@ { 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); @@ -2061,8 +2037,7 @@ static int zyd_set_rxfilter(struct zyd_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; uint32_t rxfilter; switch (ic->ic_opmode) { @@ -2087,8 +2062,7 @@ zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c) { int error; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct zyd_rf *rf = &sc->sc_rf; uint32_t tmp; int chan; @@ -2179,8 +2153,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len) { struct zyd_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct zyd_plcphdr plcp; struct zyd_rx_stat stat; struct usb_page_cache *pc; @@ -2190,7 +2163,7 @@ if (len < ZYD_MIN_FRAGSZ) { DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too short (length=%d)\n", device_get_nameunit(sc->sc_dev), len); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return; } pc = usbd_xfer_get_frame(xfer, 0); @@ -2201,7 +2174,7 @@ DPRINTF(sc, ZYD_DEBUG_RECV, "%s: RX status indicated error (%x)\n", device_get_nameunit(sc->sc_dev), stat.flags); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return; } @@ -2213,7 +2186,7 @@ if (rlen > (int)MCLBYTES) { DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too long (length=%d)\n", device_get_nameunit(sc->sc_dev), rlen); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); return; } else if (rlen > (int)MHLEN) m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); @@ -2222,10 +2195,9 @@ if (m == NULL) { DPRINTF(sc, ZYD_DEBUG_RECV, "%s: could not allocate rx mbuf\n", device_get_nameunit(sc->sc_dev)); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_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); @@ -2255,8 +2227,7 @@ zyd_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) { struct zyd_softc *sc = usbd_xfer_softc(xfer); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; struct zyd_rx_desc desc; struct mbuf *m; @@ -2328,10 +2299,8 @@ } 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 */ @@ -2386,7 +2355,6 @@ 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; @@ -2405,9 +2373,6 @@ 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: @@ -2440,16 +2405,14 @@ usbd_xfer_set_priv(xfer, data); usbd_transfer_submit(xfer); } - ZYD_UNLOCK(sc); - zyd_start(ifp); - ZYD_LOCK(sc); + zyd_start(sc); break; default: /* Error */ DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n", usbd_errstr(error)); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); data = usbd_xfer_get_priv(xfer); usbd_xfer_set_priv(xfer, NULL); if (data != NULL) @@ -2590,31 +2553,45 @@ 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 ifnet *ifp) +zyd_start(struct zyd_softc *sc) { - struct zyd_softc *sc = ifp->if_softc; struct ieee80211_node *ni; struct mbuf *m; - 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; - } + ZYD_LOCK_ASSERT(sc, MA_LOCKED); + + while (sc->tx_nfree > 0 && (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; if (zyd_tx_start(sc, m, ni) != 0) { ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); break; } } - ZYD_UNLOCK(sc); } static int @@ -2622,19 +2599,17 @@ const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; - struct zyd_softc *sc = ifp->if_softc; + struct zyd_softc *sc = ic->ic_softc; ZYD_LOCK(sc); /* prevent management frames from being sent if we're not ready */ - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + if (!(sc->sc_flags & ZYD_FLAG_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); @@ -2648,7 +2623,6 @@ */ if (zyd_tx_start(sc, m, ni) != 0) { ZYD_UNLOCK(sc); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); ieee80211_free_node(ni); return (EIO); } @@ -2656,56 +2630,35 @@ return (0); } -static int -zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +zyd_parent(struct ieee80211com *ic) { - struct zyd_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error; + struct zyd_softc *sc = ic->ic_softc; int startall = 0; ZYD_LOCK(sc); - error = (sc->sc_flags & ZYD_FLAG_DETACHED) ? ENXIO : 0; - ZYD_UNLOCK(sc); - 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); - } + if (sc->sc_flags & ZYD_FLAG_DETACHED) { 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; } - return (error); + 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); + ZYD_UNLOCK(sc); + if (startall) + ieee80211_start_all(ic); } static void zyd_init_locked(struct zyd_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct usb_config_descriptor *cd; int error; uint32_t val; @@ -2757,12 +2710,12 @@ sc->sc_flags |= ZYD_FLAG_INITONCE; } - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->sc_flags & ZYD_FLAG_RUNNING) zyd_stop(sc); DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %6D\n", IF_LLADDR(ifp), ":"); - error = zyd_set_macaddr(sc, IF_LLADDR(ifp)); + error = zyd_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); if (error != 0) return; @@ -2798,8 +2751,7 @@ /* enable interrupts */ zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->sc_flags |= ZYD_FLAG_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]); @@ -2811,29 +2763,13 @@ } 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); - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + sc->sc_flags &= ~ZYD_FLAG_RUNNING; /* * Drain all the transfers, if not already drained: @@ -2925,30 +2861,29 @@ static void zyd_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct zyd_softc *sc = ifp->if_softc; + struct zyd_softc *sc = ic->ic_softc; ZYD_LOCK(sc); /* want broadcast address while scanning */ - zyd_set_bssid(sc, ifp->if_broadcastaddr); + zyd_set_bssid(sc, ieee80211broadcastaddr); ZYD_UNLOCK(sc); } static void zyd_scan_end(struct ieee80211com *ic) { - struct zyd_softc *sc = ic->ic_ifp->if_softc; + struct zyd_softc *sc = ic->ic_softc; ZYD_LOCK(sc); /* restore previous bssid */ - zyd_set_bssid(sc, sc->sc_bssid); + zyd_set_bssid(sc, ic->ic_macaddr); ZYD_UNLOCK(sc); } static void zyd_set_channel(struct ieee80211com *ic) { - struct zyd_softc *sc = ic->ic_ifp->if_softc; + struct zyd_softc *sc = ic->ic_softc; ZYD_LOCK(sc); zyd_set_chan(sc, ic->ic_curchan); Index: sys/dev/usb/wlan/if_zydreg.h =================================================================== --- sys/dev/usb/wlan/if_zydreg.h +++ sys/dev/usb/wlan/if_zydreg.h @@ -1249,7 +1249,8 @@ }; struct zyd_softc { - struct ifnet *sc_ifp; + struct ieee80211com sc_ic; + struct mbufq sc_snd; device_t sc_dev; struct usb_device *sc_udev; @@ -1260,13 +1261,13 @@ #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; Index: sys/dev/wpi/if_wpi.c =================================================================== --- sys/dev/wpi/if_wpi.c +++ sys/dev/wpi/if_wpi.c @@ -205,12 +205,12 @@ const struct ieee80211_bpf_params *); static int wpi_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); -static void wpi_start(struct ifnet *); -static void wpi_start_task(void *, int); +static int wpi_transmit(struct ieee80211com *, struct mbuf *); +static void wpi_start(void *, int); static void wpi_watchdog_rfkill(void *); static void wpi_scan_timeout(void *); static void wpi_tx_timeout(void *); -static int wpi_ioctl(struct ifnet *, u_long, caddr_t); +static void wpi_parent(struct ieee80211com *); static int wpi_cmd(struct wpi_softc *, int, const void *, size_t, int); static int wpi_mrr_setup(struct wpi_softc *); static int wpi_add_node(struct wpi_softc *, struct ieee80211_node *); @@ -272,7 +272,7 @@ static void wpi_hw_stop(struct wpi_softc *); static void wpi_radio_on(void *, int); static void wpi_radio_off(void *, int); -static void wpi_init(void *); +static int wpi_init(struct wpi_softc *); static void wpi_stop_locked(struct wpi_softc *); static void wpi_stop(struct wpi_softc *); static void wpi_scan_start(struct ieee80211com *); @@ -329,13 +329,11 @@ { struct wpi_softc *sc = (struct wpi_softc *)device_get_softc(dev); struct ieee80211com *ic; - struct ifnet *ifp; int i, error, rid; #ifdef WPI_DEBUG int supportsa = 1; const struct wpi_ident *ident; #endif - uint8_t macaddr[IEEE80211_ADDR_LEN]; sc->sc_dev = dev; @@ -445,14 +443,7 @@ /* Clear pending interrupts. */ WPI_WRITE(sc, WPI_INT, 0xffffffff); - 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 = &sc->sc_ic; ic->ic_softc = sc; ic->ic_name = device_get_nameunit(dev); ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ @@ -481,7 +472,7 @@ * Read in the eeprom and also setup the channels for * net80211. We don't set the rates as net80211 does this for us */ - if ((error = wpi_read_eeprom(sc, macaddr)) != 0) { + if ((error = wpi_read_eeprom(sc, ic->ic_macaddr)) != 0) { device_printf(dev, "could not read EEPROM, error %d\n", error); goto fail; @@ -503,20 +494,12 @@ } #endif - 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 = wpi_init; - ifp->if_ioctl = wpi_ioctl; - ifp->if_start = wpi_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); + ieee80211_ifattach(ic); ic->ic_vap_create = wpi_vap_create; ic->ic_vap_delete = wpi_vap_delete; + ic->ic_parent = wpi_parent; ic->ic_raw_xmit = wpi_raw_xmit; + ic->ic_transmit = wpi_transmit; ic->ic_node_alloc = wpi_node_alloc; sc->sc_node_free = ic->ic_node_free; ic->ic_node_free = wpi_node_free; @@ -543,7 +526,7 @@ TASK_INIT(&sc->sc_reinittask, 0, wpi_hw_reset, sc); TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc); TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc); - TASK_INIT(&sc->sc_start_task, 0, wpi_start_task, sc); + TASK_INIT(&sc->sc_start_task, 0, wpi_start, sc); sc->sc_tq = taskqueue_create("wpi_taskq", M_WAITOK, taskqueue_thread_enqueue, &sc->sc_tq); @@ -588,14 +571,13 @@ static void wpi_radiotap_attach(struct wpi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct wpi_rx_radiotap_header *rxtap = &sc->sc_rxtap; + struct wpi_tx_radiotap_header *txtap = &sc->sc_txtap; + DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - ieee80211_radiotap_attach(ic, - &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), - WPI_TX_RADIOTAP_PRESENT, - &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), - WPI_RX_RADIOTAP_PRESENT); + ieee80211_radiotap_attach(&sc->sc_ic, + &txtap->wt_ihdr, sizeof(*txtap), WPI_TX_RADIOTAP_PRESENT, + &rxtap->wr_ihdr, sizeof(*rxtap), WPI_RX_RADIOTAP_PRESENT); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); } @@ -646,12 +628,9 @@ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return NULL; - wvp = (struct wpi_vap *) malloc(sizeof(struct wpi_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (wvp == NULL) - return NULL; + wvp = malloc(sizeof(struct wpi_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &wvp->wv_vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); if (opmode == IEEE80211_M_IBSS || opmode == IEEE80211_M_HOSTAP) { WPI_VAP_LOCK_INIT(wvp); @@ -671,7 +650,7 @@ ieee80211_ratectl_init(vap); /* Complete setup. */ ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); + ieee80211_media_status, mac); ic->ic_opmode = opmode; return vap; } @@ -700,22 +679,21 @@ wpi_detach(device_t dev) { struct wpi_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; int qid; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if (ifp != NULL) { - ic = ifp->if_l2com; - + if (ic->ic_vap_create == wpi_vap_create) { ieee80211_draintask(ic, &sc->sc_radioon_task); ieee80211_draintask(ic, &sc->sc_start_task); wpi_stop(sc); - taskqueue_drain_all(sc->sc_tq); - taskqueue_free(sc->sc_tq); + if (sc->sc_tq != NULL) { + taskqueue_drain_all(sc->sc_tq); + taskqueue_free(sc->sc_tq); + } callout_drain(&sc->watchdog_rfkill); callout_drain(&sc->tx_timeout); @@ -748,9 +726,6 @@ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem), sc->mem); - if (ifp != NULL) - if_free(ifp); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); WPI_TXQ_STATE_LOCK_DESTROY(sc); WPI_TXQ_LOCK_DESTROY(sc); @@ -774,7 +749,7 @@ wpi_suspend(device_t dev) { struct wpi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; ieee80211_suspend_all(ic); return 0; @@ -784,7 +759,7 @@ wpi_resume(device_t dev) { struct wpi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; /* Clear device-specific "PCI retry timeout" register (41h). */ pci_write_config(dev, 0x41, 0, 1); @@ -1191,6 +1166,7 @@ ring->queued = 0; ring->cur = 0; ring->update = 0; + mbufq_init(&ring->snd, ifqmaxlen); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); @@ -1318,6 +1294,7 @@ memset(ring->desc, 0, ring->desc_dma.size); bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, BUS_DMASYNC_PREWRITE); + mbufq_drain(&ring->snd); sc->qfullmsk &= ~(1 << ring->qid); ring->queued = 0; ring->cur = 0; @@ -1448,8 +1425,7 @@ static void wpi_read_eeprom_band(struct wpi_softc *sc, int n) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct wpi_eeprom_chan *channels = sc->eeprom_channels[n]; const struct wpi_chan_band *band = &wpi_bands[n]; struct ieee80211_channel *c; @@ -1506,8 +1482,7 @@ static int wpi_read_eeprom_channels(struct wpi_softc *sc, int n) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; const struct wpi_chan_band *band = &wpi_bands[n]; int error; @@ -1549,8 +1524,7 @@ wpi_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd, int nchan, struct ieee80211_channel chans[]) { - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; int i; for (i = 0; i < nchan; i++) { @@ -1559,8 +1533,7 @@ channel = wpi_find_eeprom_channel(sc, c); if (channel == NULL) { - if_printf(ic->ic_ifp, - "%s: invalid channel %u freq %u/0x%x\n", + ic_printf(ic, "%s: invalid channel %u freq %u/0x%x\n", __func__, c->ic_ieee, c->ic_freq, c->ic_flags); return EINVAL; } @@ -1672,8 +1645,7 @@ static void wpi_node_free(struct ieee80211_node *ni) { - struct ieee80211com *ic = ni->ni_ic; - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); if (wn->id != WPI_ID_UNDEFINED) { @@ -1700,7 +1672,7 @@ int rssi, int nf) { struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct wpi_softc *sc = vap->iv_ic->ic_softc; struct wpi_vap *wvp = WPI_VAP(vap); uint64_t ni_tstamp, rx_tstamp; @@ -1744,7 +1716,7 @@ static void wpi_restore_node_table(struct wpi_softc *sc, struct wpi_vap *wvp) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; /* Set group keys once. */ WPI_NT_LOCK(sc); @@ -1763,12 +1735,20 @@ { struct wpi_vap *wvp = WPI_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; int error = 0; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); + WPI_TXQ_LOCK(sc); + if (nstate > IEEE80211_S_INIT && sc->sc_running == 0) { + DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); + WPI_TXQ_UNLOCK(sc); + + return ENXIO; + } + WPI_TXQ_UNLOCK(sc); + DPRINTF(sc, WPI_DEBUG_STATE, "%s: %s -> %s\n", __func__, ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]); @@ -1937,8 +1917,7 @@ wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc, struct wpi_rx_data *data) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct wpi_rx_ring *ring = &sc->rxq; struct wpi_rx_stat *stat; struct wpi_rx_head *head; @@ -2019,7 +1998,6 @@ BUS_DMASYNC_PREWRITE); /* Finalize mbuf. */ - m->m_pkthdr.rcvif = ifp; m->m_data = (caddr_t)(head + 1); m->m_pkthdr.len = m->m_len = len; @@ -2073,7 +2051,7 @@ fail2: m_freem(m); -fail1: if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); +fail1: counter_u64_add(ic->ic_ierrors, 1); } static void @@ -2086,7 +2064,6 @@ static void wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc) { - struct ifnet *ifp = sc->sc_ifp; struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3]; struct wpi_tx_data *data = &ring->data[desc->idx]; struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1); @@ -2119,14 +2096,11 @@ * Update rate control statistics for the node. */ if (status & WPI_TX_STATUS_FAIL) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); - } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + } else ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); - } ieee80211_tx_complete(ni, m, (status & WPI_TX_STATUS_FAIL) != 0); @@ -2135,17 +2109,10 @@ if (ring->queued > 0) { callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc); - if (sc->qfullmsk != 0 && - ring->queued < WPI_TX_RING_LOMARK) { + if ((sc->qfullmsk & (1 << ring->qid)) != 0 && + ring->queued < WPI_TX_RING_LOMARK) { sc->qfullmsk &= ~(1 << ring->qid); - IF_LOCK(&ifp->if_snd); - if (sc->qfullmsk == 0 && - (ifp->if_drv_flags & IFF_DRV_OACTIVE)) { - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - ieee80211_runtask(ic, &sc->sc_start_task); - } else - IF_UNLOCK(&ifp->if_snd); + ieee80211_runtask(ic, &sc->sc_start_task); } } else callout_stop(&sc->tx_timeout); @@ -2203,8 +2170,7 @@ static void wpi_notif_intr(struct wpi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t hw; @@ -2239,7 +2205,7 @@ /* An 802.11 frame has been received. */ wpi_rx_done(sc, desc, data); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { + if (sc->sc_running == 0) { /* wpi_stop() was called. */ return; } @@ -2328,6 +2294,7 @@ device_printf(sc->sc_dev, "microcontroller initialization failed\n"); wpi_stop_locked(sc); + return; } /* Save the address of the error log in SRAM. */ sc->errptr = le32toh(uc->errptr); @@ -2558,7 +2525,6 @@ wpi_intr(void *arg) { struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; uint32_t r1, r2; WPI_LOCK(sc); @@ -2608,7 +2574,7 @@ done: /* Re-enable interrupts. */ - if (ifp->if_flags & IFF_UP) + if (sc->sc_running) WPI_WRITE(sc, WPI_INT_MASK, WPI_INT_MASK_DEF); end: WPI_UNLOCK(sc); @@ -2617,7 +2583,6 @@ static int wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) { - struct ifnet *ifp = sc->sc_ifp; struct ieee80211_frame *wh; struct wpi_tx_cmd *cmd; struct wpi_tx_data *data; @@ -2633,7 +2598,7 @@ DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if (sc->txq_active == 0) { + if (sc->sc_running == 0) { /* wpi_stop() was called */ error = ENETDOWN; goto fail; @@ -2730,14 +2695,8 @@ if (ring->qid < WPI_CMD_QUEUE_NUM) { /* Mark TX ring as full if we reach a certain threshold. */ WPI_TXQ_STATE_LOCK(sc); - if (++ring->queued > WPI_TX_RING_HIMARK) { + if (++ring->queued > WPI_TX_RING_HIMARK) sc->qfullmsk |= 1 << ring->qid; - - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - } - callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc); WPI_TXQ_STATE_UNLOCK(sc); } @@ -3031,24 +2990,47 @@ return wpi_cmd2(sc, &tx_data); } +static __inline int +wpi_tx_ring_is_full(struct wpi_softc *sc, int ac) +{ + struct wpi_tx_ring *ring = &sc->txq[ac]; + int retval; + + WPI_TXQ_STATE_LOCK(sc); + retval = (ring->queued > WPI_TX_RING_HIMARK); + WPI_TXQ_STATE_UNLOCK(sc); + + return retval; +} + +static __inline void +wpi_handle_tx_failure(struct ieee80211_node *ni) +{ + /* NB: m is reclaimed on tx failure */ + if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); + ieee80211_free_node(ni); +} + static int wpi_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 wpi_softc *sc = ifp->if_softc; - int error = 0; + struct wpi_softc *sc = ic->ic_softc; + int ac, error = 0; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - ieee80211_free_node(ni); + ac = M_WME_GETAC(m); + + WPI_TX_LOCK(sc); + + if (sc->sc_running == 0 || wpi_tx_ring_is_full(sc, ac)) { m_freem(m); - return ENETDOWN; + error = sc->sc_running ? ENOBUFS : ENETDOWN; + goto unlock; } - WPI_TX_LOCK(sc); if (params == NULL) { /* * Legacy path; interpret frame contents to decide @@ -3062,13 +3044,11 @@ */ error = wpi_tx_data_raw(sc, m, ni, params); } - WPI_TX_UNLOCK(sc); - if (error != 0) { - /* NB: m is reclaimed on tx failure */ - ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); +unlock: WPI_TX_UNLOCK(sc); + if (error != 0) { + wpi_handle_tx_failure(ni); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); return error; @@ -3079,57 +3059,88 @@ return 0; } -/** - * Process data waiting to be sent on the IFNET output queue - */ -static void -wpi_start(struct ifnet *ifp) +static int +wpi_transmit(struct ieee80211com *ic, struct mbuf *m) { - struct wpi_softc *sc = ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; struct ieee80211_node *ni; - struct mbuf *m; + struct mbufq *sndq; + int ac, error; WPI_TX_LOCK(sc); DPRINTF(sc, WPI_DEBUG_XMIT, "%s: called\n", __func__); - for (;;) { - IF_LOCK(&ifp->if_snd); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || - (ifp->if_drv_flags & IFF_DRV_OACTIVE)) { - IF_UNLOCK(&ifp->if_snd); - break; - } - IF_UNLOCK(&ifp->if_snd); + /* Check if interface is up & running. */ + if (sc->sc_running == 0) { + error = ENXIO; + goto unlock; + } - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - if (wpi_tx_data(sc, m, ni) != 0) { - ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } + /* Check for available space. */ + ac = M_WME_GETAC(m); + sndq = &sc->txq[ac].snd; + if (wpi_tx_ring_is_full(sc, ac) || mbufq_len(sndq) != 0) { + /* wpi_tx_done() will dequeue it. */ + error = mbufq_enqueue(sndq, m); + goto unlock; + } + + error = 0; + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + if (wpi_tx_data(sc, m, ni) != 0) { + wpi_handle_tx_failure(ni); } DPRINTF(sc, WPI_DEBUG_XMIT, "%s: done\n", __func__); - WPI_TX_UNLOCK(sc); + +unlock: WPI_TX_UNLOCK(sc); + + return (error); } +/** + * Process data waiting to be sent on the output queue + */ static void -wpi_start_task(void *arg0, int pending) +wpi_start(void *arg0, int pending) { struct wpi_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211_node *ni; + struct mbuf *m; + uint8_t i; + + WPI_TX_LOCK(sc); + if (sc->sc_running == 0) + goto unlock; - wpi_start(ifp); + DPRINTF(sc, WPI_DEBUG_XMIT, "%s: called\n", __func__); + + for (i = 0; i < WPI_CMD_QUEUE_NUM; i++) { + struct mbufq *sndq = &sc->txq[i].snd; + + for (;;) { + if (wpi_tx_ring_is_full(sc, i)) + break; + + if ((m = mbufq_dequeue(sndq)) == NULL) + break; + + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + if (wpi_tx_data(sc, m, ni) != 0) { + wpi_handle_tx_failure(ni); + } + } + } + + DPRINTF(sc, WPI_DEBUG_XMIT, "%s: done\n", __func__); +unlock: WPI_TX_UNLOCK(sc); } static void wpi_watchdog_rfkill(void *arg) { struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; DPRINTF(sc, WPI_DEBUG_WATCHDOG, "RFkill Watchdog: tick\n"); @@ -3146,9 +3157,9 @@ wpi_scan_timeout(void *arg) { struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; - if_printf(ifp, "scan timeout\n"); + ic_printf(ic, "scan timeout\n"); taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask); } @@ -3156,44 +3167,28 @@ wpi_tx_timeout(void *arg) { struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; - if_printf(ifp, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ic_printf(ic, "device timeout\n"); taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask); } -static int -wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +wpi_parent(struct ieee80211com *ic) { - struct wpi_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; + struct wpi_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ifreq *ifr = (struct ifreq *) data; - int error = 0; - switch (cmd) { - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - wpi_init(sc); - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 && - vap != NULL) - ieee80211_stop(vap); - } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) - wpi_stop(sc); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - default: - error = EINVAL; - break; - } - return error; + if (ic->ic_nrunning > 0) { + if (wpi_init(sc) == 0) { + ieee80211_notify_radio(ic, 1); + ieee80211_start_all(ic); + } else { + ieee80211_notify_radio(ic, 0); + ieee80211_stop(vap); + } + } else + wpi_stop(sc); } /* @@ -3215,9 +3210,13 @@ DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if (sc->txq_active == 0) { + if (sc->sc_running == 0) { /* wpi_stop() was called */ - error = 0; + if (code == WPI_CMD_SCAN) + error = ENETDOWN; + else + error = 0; + goto fail; } @@ -3283,10 +3282,7 @@ WPI_TXQ_UNLOCK(sc); - if (async) - return 0; - - return mtx_sleep(cmd, &sc->sc_mtx, PCATCH, "wpicmd", hz); + return async ? 0 : mtx_sleep(cmd, &sc->sc_mtx, PCATCH, "wpicmd", hz); fail: DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); @@ -3301,8 +3297,7 @@ static int wpi_mrr_setup(struct wpi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct wpi_mrr_setup mrr; int i, error; @@ -3399,14 +3394,13 @@ static int wpi_add_broadcast_node(struct wpi_softc *sc, int async) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct wpi_node_info node; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.macaddr, ifp->if_broadcastaddr); + IEEE80211_ADDR_COPY(node.macaddr, ieee80211broadcastaddr); node.id = WPI_ID_BROADCAST; node.plcp = (ic->ic_curmode == IEEE80211_MODE_11A) ? wpi_ridx_to_plcp[WPI_RIDX_OFDM6] : wpi_ridx_to_plcp[WPI_RIDX_CCK1]; @@ -3492,7 +3486,7 @@ wpi_updateedca(struct ieee80211com *ic) { #define WPI_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */ - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; struct wpi_edca_params cmd; int aci, error; @@ -3526,8 +3520,7 @@ static void wpi_set_promisc(struct wpi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t promisc_filter; @@ -3535,7 +3528,7 @@ if (vap != NULL && vap->iv_opmode != IEEE80211_M_HOSTAP) promisc_filter |= WPI_FILTER_PROMISC; - if (ifp->if_flags & IFF_PROMISC) + if (ic->ic_promisc > 0) sc->rxon.filter |= htole32(promisc_filter); else sc->rxon.filter &= ~htole32(promisc_filter); @@ -3900,8 +3893,7 @@ static int wpi_config(struct wpi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211_channel *c = ic->ic_curchan; int error; @@ -4011,7 +4003,7 @@ static uint16_t wpi_limit_dwell(struct wpi_softc *sc, uint16_t dwell_time) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); int bintval = 0; @@ -4068,8 +4060,7 @@ static int wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_scan_state *ss = ic->ic_scan; struct ieee80211vap *vap = ss->ss_vap; struct wpi_scan_hdr *hdr; @@ -4171,11 +4162,9 @@ 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, ifp->if_broadcastaddr); + IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr); IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr); - IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr); - *(uint16_t *)&wh->i_dur[0] = 0; /* filled by h/w */ - *(uint16_t *)&wh->i_seq[0] = 0; /* filled by h/w */ + IEEE80211_ADDR_COPY(wh->i_addr3, ieee80211broadcastaddr); frm = (uint8_t *)(wh + 1); frm = ieee80211_add_ssid(frm, NULL, 0); @@ -4206,7 +4195,6 @@ /* * Calculate the active/passive dwell times. */ - dwell_active = wpi_get_active_dwell_time(sc, c, nssid); dwell_passive = wpi_get_passive_dwell_time(sc, c); @@ -4324,7 +4312,7 @@ struct ieee80211com *ic = wvp->wv_vap.iv_ic; struct ieee80211_beacon_offsets *bo = &wvp->wv_boff; struct wpi_buf *bcn = &wvp->wv_bcbuf; - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; struct wpi_cmd_beacon *cmd = (struct wpi_cmd_beacon *)&bcn->data; struct ieee80211_tim_ie *tie; struct mbuf *m; @@ -4406,7 +4394,7 @@ static void wpi_update_beacon(struct ieee80211vap *vap, int item) { - struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct wpi_softc *sc = vap->iv_ic->ic_softc; struct wpi_vap *wvp = WPI_VAP(vap); struct wpi_buf *bcn = &wvp->wv_bcbuf; struct ieee80211_beacon_offsets *bo = &wvp->wv_boff; @@ -4448,7 +4436,7 @@ wpi_newassoc(struct ieee80211_node *ni, int isnew) { struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); int error; @@ -4575,7 +4563,7 @@ { const struct ieee80211_cipher *cip = k->wk_cipher; struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); struct wpi_node_info node; uint16_t kflags; @@ -4639,7 +4627,7 @@ { const struct ieee80211_key *k = arg; struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); int error; @@ -4674,7 +4662,7 @@ wpi_del_key(struct ieee80211_node *ni, const struct ieee80211_key *k) { struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); struct wpi_node_info node; uint16_t kflags; @@ -4724,7 +4712,7 @@ { const struct ieee80211_key *k = arg; struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); int error; @@ -4746,7 +4734,7 @@ int set) { struct ieee80211com *ic = vap->iv_ic; - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; struct wpi_vap *wvp = WPI_VAP(vap); struct ieee80211_node *ni; int error, ni_ref = 0; @@ -5396,34 +5384,29 @@ wpi_radio_on(void *arg0, int pending) { struct wpi_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); device_printf(sc->sc_dev, "RF switch: radio enabled\n"); - if (vap != NULL) { - wpi_init(sc); - ieee80211_init(vap); - } + WPI_LOCK(sc); + callout_stop(&sc->watchdog_rfkill); + WPI_UNLOCK(sc); - if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_RFKILL) { - WPI_LOCK(sc); - callout_stop(&sc->watchdog_rfkill); - WPI_UNLOCK(sc); - } + if (vap != NULL) + ieee80211_init(vap); } static void wpi_radio_off(void *arg0, int pending) { struct wpi_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); device_printf(sc->sc_dev, "RF switch: radio disabled\n"); + ieee80211_notify_radio(ic, 0); wpi_stop(sc); if (vap != NULL) ieee80211_stop(vap); @@ -5433,19 +5416,16 @@ WPI_UNLOCK(sc); } -static void -wpi_init(void *arg) +static int +wpi_init(struct wpi_softc *sc) { - struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - int error; + int error = 0; WPI_LOCK(sc); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + if (sc->sc_running != 0) goto end; /* Check that the radio is not disabled by hardware switch. */ @@ -5454,6 +5434,7 @@ "RF switch: radio disabled (%s)\n", __func__); callout_reset(&sc->watchdog_rfkill, hz, wpi_watchdog_rfkill, sc); + error = EINPROGRESS; goto end; } @@ -5462,9 +5443,11 @@ device_printf(sc->sc_dev, "%s: could not read firmware, error %d\n", __func__, error); - goto fail; + goto end; } + sc->sc_running = 1; + /* Initialize hardware and upload firmware. */ error = wpi_hw_init(sc); wpi_unload_firmware(sc); @@ -5476,7 +5459,6 @@ } /* Configure adapter now that it is ready. */ - sc->txq_active = 1; if ((error = wpi_config(sc)) != 0) { device_printf(sc->sc_dev, "%s: could not configure device, error %d\n", __func__, @@ -5484,34 +5466,34 @@ goto fail; } - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - IF_UNLOCK(&ifp->if_snd); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); WPI_UNLOCK(sc); - ieee80211_start_all(ic); - - return; + return 0; fail: wpi_stop_locked(sc); + end: DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); WPI_UNLOCK(sc); + + return error; } static void wpi_stop_locked(struct wpi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; WPI_LOCK_ASSERT(sc); + if (sc->sc_running == 0) + return; + + WPI_TX_LOCK(sc); WPI_TXQ_LOCK(sc); - sc->txq_active = 0; + sc->sc_running = 0; WPI_TXQ_UNLOCK(sc); + WPI_TX_UNLOCK(sc); WPI_TXQ_STATE_LOCK(sc); callout_stop(&sc->tx_timeout); @@ -5522,10 +5504,6 @@ callout_stop(&sc->calib_to); WPI_RXON_UNLOCK(sc); - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - IF_UNLOCK(&ifp->if_snd); - /* Power OFF hardware. */ wpi_hw_stop(sc); } @@ -5544,7 +5522,7 @@ static void wpi_scan_start(struct ieee80211com *ic) { - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; wpi_set_led(sc, WPI_LED_LINK, 20, 2); } @@ -5555,8 +5533,7 @@ static void wpi_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); if (vap->iv_state == IEEE80211_S_RUN) @@ -5571,8 +5548,7 @@ wpi_set_channel(struct ieee80211com *ic) { const struct ieee80211_channel *c = ic->ic_curchan; - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; int error; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); @@ -5618,7 +5594,7 @@ { struct ieee80211vap *vap = ss->ss_vap; struct ieee80211com *ic = vap->iv_ic; - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; int error; WPI_RXON_LOCK(sc); @@ -5644,19 +5620,18 @@ wpi_hw_reset(void *arg, int pending) { struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + ieee80211_notify_radio(ic, 0); if (vap != NULL && (ic->ic_flags & IEEE80211_F_SCAN)) ieee80211_cancel_scan(vap); wpi_stop(sc); - if (vap != NULL) + if (vap != NULL) { ieee80211_stop(vap); - wpi_init(sc); - if (vap != NULL) ieee80211_init(vap); + } } Index: sys/dev/wpi/if_wpivar.h =================================================================== --- sys/dev/wpi/if_wpivar.h +++ sys/dev/wpi/if_wpivar.h @@ -72,6 +72,7 @@ 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; @@ -164,14 +165,15 @@ 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. */ @@ -181,7 +183,6 @@ 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; Index: sys/net80211/ieee80211.c =================================================================== --- sys/net80211/ieee80211.c +++ sys/net80211/ieee80211.c @@ -91,8 +91,6 @@ 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); @@ -121,7 +119,7 @@ * all available channels as active, and pick * a default channel if not already specified. */ -static void +void ieee80211_chan_init(struct ieee80211com *ic) { #define DEFAULTRATES(m, def) do { \ @@ -238,29 +236,6 @@ 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) { @@ -268,6 +243,8 @@ ic_printf(ic, "%s: need callback\n", __func__); } +static LIST_HEAD(, ieee80211com) ic_head = LIST_HEAD_INITIALIZER(ic_head); + int ic_printf(struct ieee80211com *ic, const char * fmt, ...) { @@ -286,14 +263,8 @@ * the driver on attach to prior to creating any vap's. */ void -ieee80211_ifattach(struct ieee80211com *ic, - const uint8_t macaddr[IEEE80211_ADDR_LEN]) +ieee80211_ifattach(struct ieee80211com *ic) { - 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 +282,7 @@ * available channels as active, and pick a default * channel if not already specified. */ - ieee80211_media_init(ic); + ieee80211_chan_init(ic); ic->ic_update_mcast = null_update_mcast; ic->ic_update_promisc = null_update_promisc; @@ -336,28 +307,7 @@ ieee80211_sysctl_attach(ic); - 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(); + LIST_INSERT_HEAD(&ic_head, ic, ic_next); } /* @@ -369,16 +319,9 @@ void ieee80211_ifdetach(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; struct ieee80211vap *vap; - /* - * 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(); + LIST_REMOVE(ic, ic_next); /* * The VAP is responsible for setting and clearing @@ -402,8 +345,6 @@ 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); @@ -412,6 +353,17 @@ IEEE80211_LOCK_DESTROY(ic); } +struct ieee80211com * +ieee80211_find_com(const char *name) +{ + struct ieee80211com *ic; + + LIST_FOREACH(ic, &ic_head, ic_next) + if (strcmp(ic->ic_name, name) == 0) + break; + return (ic); +} + /* * Default reset method for use with the ioctl support. This * method is invoked after any state change in the 802.11 @@ -460,8 +412,7 @@ 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], - const uint8_t macaddr[IEEE80211_ADDR_LEN]) + int flags, const uint8_t bssid[IEEE80211_ADDR_LEN]) { struct ifnet *ifp; @@ -490,6 +441,7 @@ 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: /* @@ -556,8 +508,6 @@ */ vap->iv_reset = default_reset; - IEEE80211_ADDR_COPY(vap->iv_myaddr, macaddr); - ieee80211_sysctl_vattach(vap); ieee80211_crypto_vattach(vap); ieee80211_node_vattach(vap); @@ -581,8 +531,8 @@ * 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) +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]) { struct ifnet *ifp = vap->iv_ifp; struct ieee80211com *ic = vap->iv_ic; @@ -610,7 +560,8 @@ if (maxrate) ifp->if_baudrate = IF_Mbps(maxrate); - ether_ifattach(ifp, vap->iv_myaddr); + ether_ifattach(ifp, macaddr); + vap->iv_myaddr = IF_LLADDR(ifp); /* hook output method setup by ether_ifattach */ vap->iv_output = ifp->if_output; ifp->if_output = ieee80211_output; @@ -626,8 +577,6 @@ 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; @@ -677,8 +626,10 @@ ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40); /* NB: this handles the bpfdetach done below */ ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_BPF); - ieee80211_syncifflag_locked(ic, IFF_PROMISC); - ieee80211_syncifflag_locked(ic, IFF_ALLMULTI); + if (vap->iv_ifflags & IFF_PROMISC) + ieee80211_promisc(vap, false); + if (vap->iv_ifflags & IFF_ALLMULTI) + ieee80211_allmulti(vap, false); IEEE80211_UNLOCK(ic); ifmedia_removeall(&vap->iv_media); @@ -703,49 +654,57 @@ } /* - * 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. + * Count number of vaps in promisc, and issue promisc on + * parent respectively. */ void -ieee80211_syncifflag_locked(struct ieee80211com *ic, int flag) +ieee80211_promisc(struct ieee80211vap *vap, bool on) { - struct ifnet *ifp = ic->ic_ifp; - struct ieee80211vap *vap; - int bit, oflags; + struct ieee80211com *ic = vap->iv_ic; - IEEE80211_LOCK_ASSERT(ic); + /* + * 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; - 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_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); } + 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); } /* @@ -1234,39 +1193,6 @@ 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) @@ -1395,15 +1321,6 @@ } /* - * 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. */ int @@ -1480,23 +1397,6 @@ 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) { Index: sys/net80211/ieee80211_ddb.c =================================================================== --- sys/net80211/ieee80211_ddb.c +++ sys/net80211/ieee80211_ddb.c @@ -520,7 +520,7 @@ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) db_printf(" %s(%p)", vap->iv_ifp->if_xname, vap); db_printf("\n"); - db_printf("\tifp %p(%s)", ic->ic_ifp, ic->ic_ifp->if_xname); + db_printf("\tsoftc %p", ic->ic_softc); db_printf("\tname %s", ic->ic_name); db_printf(" comlock %p", &ic->ic_comlock); db_printf("\n"); @@ -528,7 +528,6 @@ 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"); Index: sys/net80211/ieee80211_freebsd.c =================================================================== --- sys/net80211/ieee80211_freebsd.c +++ sys/net80211/ieee80211_freebsd.c @@ -69,58 +69,27 @@ 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; - ifp = ifunit(cp.icp_parent); - if (ifp == NULL) + ic = ieee80211_find_com(cp.icp_parent); + if (ic == 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) { - if_printf(ifp, "%s: invalid opmode %d\n", - __func__, cp.icp_opmode); + ic_printf(ic, "%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) { - if_printf(ifp, "%s mode not supported\n", + ic_printf(ic, "%s mode not supported\n", ieee80211_opmode_name[cp.icp_opmode]); return EOPNOTSUPP; } @@ -131,13 +100,13 @@ (1) #endif ) { - if_printf(ifp, "TDMA not supported\n"); + ic_printf(ic, "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 : (const uint8_t *)IF_LLADDR(ifp)); + cp.icp_macaddr : ic->ic_macaddr); return (vap == NULL ? EIO : 0); } @@ -528,17 +497,19 @@ * (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) { - struct ifnet *parent = ic->ic_ifp; + int error; + /* * Assert the IC TX lock is held - this enforces the * processing -> queuing order is maintained */ IEEE80211_TX_LOCK_ASSERT(ic); - - return (parent->if_transmit(parent, m)); + error = ic->ic_transmit(ic, m); + if (error) + m_freem(m); + return (error); } /* @@ -836,7 +807,6 @@ } static eventhandler_tag wlan_bpfevent; -static eventhandler_tag wlan_ifllevent; static void bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach) @@ -864,33 +834,6 @@ } } -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. * @@ -905,17 +848,12 @@ 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; Index: sys/net80211/ieee80211_ioctl.c =================================================================== --- sys/net80211/ieee80211_ioctl.c +++ sys/net80211/ieee80211_ioctl.c @@ -1329,13 +1329,12 @@ setmlme_dropsta(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop) { - struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_node_table *nt = &ic->ic_sta; + struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta; struct ieee80211_node *ni; int error = 0; /* NB: the broadcast address means do 'em all */ - if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) { + if (!IEEE80211_ADDR_EQ(mac, vap->iv_ifp->if_broadcastaddr)) { IEEE80211_NODE_LOCK(nt); ni = ieee80211_find_node_locked(nt, mac); IEEE80211_NODE_UNLOCK(nt); @@ -2529,14 +2528,9 @@ 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)); @@ -3300,41 +3294,6 @@ 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) { @@ -3347,8 +3306,11 @@ switch (cmd) { case SIOCSIFFLAGS: IEEE80211_LOCK(ic); - ieee80211_syncifflag_locked(ic, IFF_PROMISC); - ieee80211_syncifflag_locked(ic, IFF_ALLMULTI); + 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; if (ifp->if_flags & IFF_UP) { /* * Bring ourself up unless we're already operational. @@ -3371,7 +3333,7 @@ break; case SIOCADDMULTI: case SIOCDELMULTI: - ieee80211_ioctl_updatemulti(ic); + ieee80211_runtask(ic, &ic->ic_mcast_task); break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: @@ -3427,17 +3389,16 @@ 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); } Index: sys/net80211/ieee80211_output.c =================================================================== --- sys/net80211/ieee80211_output.c +++ sys/net80211/ieee80211_output.c @@ -254,10 +254,6 @@ /* 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; @@ -430,17 +426,6 @@ { 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. @@ -507,6 +492,7 @@ 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 @@ -528,7 +514,10 @@ if (params) (void) ieee80211_add_xmit_params(m, params); - return (ic->ic_raw_xmit(ni, m, params)); + error = ic->ic_raw_xmit(ni, m, params); + if (error) + if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1); + return (error); } /* @@ -3457,6 +3446,15 @@ { 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); Index: sys/net80211/ieee80211_power.c =================================================================== --- sys/net80211/ieee80211_power.c +++ sys/net80211/ieee80211_power.c @@ -418,7 +418,6 @@ 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; @@ -429,59 +428,51 @@ 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 */ - 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); - } + 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 */ - 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); - } + 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); } } Index: sys/net80211/ieee80211_proto.h =================================================================== --- sys/net80211/ieee80211_proto.h +++ sys/net80211/ieee80211_proto.h @@ -56,7 +56,8 @@ void ieee80211_proto_vattach(struct ieee80211vap *); void ieee80211_proto_vdetach(struct ieee80211vap *); -void ieee80211_syncifflag_locked(struct ieee80211com *, int flag); +void ieee80211_promisc(struct ieee80211vap *, bool); +void ieee80211_allmulti(struct ieee80211vap *, bool); void ieee80211_syncflag(struct ieee80211vap *, int flag); void ieee80211_syncflag_ht(struct ieee80211vap *, int flag); void ieee80211_syncflag_ext(struct ieee80211vap *, int flag); Index: sys/net80211/ieee80211_proto.c =================================================================== --- sys/net80211/ieee80211_proto.c +++ sys/net80211/ieee80211_proto.c @@ -122,23 +122,23 @@ void ieee80211_proto_attach(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; + uint8_t hdrlen; /* override the 802.3 setting */ - ifp->if_hdrlen = ic->ic_headroom + 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(ifp->if_hdrlen) > max_linkhdr) { + if (ALIGN(hdrlen) > max_linkhdr) { /* XXX sanity check... */ - max_linkhdr = ALIGN(ifp->if_hdrlen); + max_linkhdr = ALIGN(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, ifp); + TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ic); 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,7 +188,10 @@ int i; /* override the 802.3 setting */ - ifp->if_hdrlen = ic->ic_ifp->if_hdrlen; + ifp->if_hdrlen = ic->ic_headroom + + sizeof(struct ieee80211_qosframe_addr4) + + IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + + IEEE80211_WEP_EXTIVLEN; vap->iv_rtsthreshold = IEEE80211_RTS_DEFAULT; vap->iv_fragthreshold = IEEE80211_FRAG_DEFAULT; @@ -1155,9 +1158,9 @@ static void parent_updown(void *arg, int npending) { - struct ifnet *parent = arg; + struct ieee80211com *ic = arg; - parent->if_ioctl(parent, SIOCSIFFLAGS, NULL); + ic->ic_parent(ic); } static void @@ -1224,7 +1227,6 @@ { struct ifnet *ifp = vap->iv_ifp; struct ieee80211com *ic = vap->iv_ic; - struct ifnet *parent = ic->ic_ifp; IEEE80211_LOCK_ASSERT(ic); @@ -1246,12 +1248,10 @@ * 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 && - (parent->if_drv_flags & IFF_DRV_RUNNING) == 0) { + if (ic->ic_nrunning++ == 0) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, - "%s: up parent %s\n", __func__, parent->if_xname); - parent->if_flags |= IFF_UP; + "%s: up parent %s\n", __func__, ic->ic_name); ieee80211_runtask(ic, &ic->ic_parent_task); return; } @@ -1260,8 +1260,7 @@ * If the parent is up and running, then kick the * 802.11 state machine as appropriate. */ - if ((parent->if_drv_flags & IFF_DRV_RUNNING) && - vap->iv_roaming != IEEE80211_ROAMING_MANUAL) { + if (vap->iv_roaming != IEEE80211_ROAMING_MANUAL) { if (vap->iv_opmode == IEEE80211_M_STA) { #if 0 /* XXX bypasses scan too easily; disable for now */ @@ -1344,7 +1343,6 @@ { struct ieee80211com *ic = vap->iv_ic; struct ifnet *ifp = vap->iv_ifp; - struct ifnet *parent = ic->ic_ifp; IEEE80211_LOCK_ASSERT(ic); @@ -1354,12 +1352,10 @@ 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 && - (parent->if_drv_flags & IFF_DRV_RUNNING)) { + if (--ic->ic_nrunning == 0) { IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG, - "down parent %s\n", parent->if_xname); - parent->if_flags &= ~IFF_UP; + "down parent %s\n", ic->ic_name); ieee80211_runtask(ic, &ic->ic_parent_task); } } Index: sys/net80211/ieee80211_regdomain.c =================================================================== --- sys/net80211/ieee80211_regdomain.c +++ sys/net80211/ieee80211_regdomain.c @@ -35,7 +35,6 @@ #include #include #include - #include #include @@ -487,7 +486,7 @@ memset(&ic->ic_channels[ic->ic_nchans], 0, (IEEE80211_CHAN_MAX - ic->ic_nchans) * sizeof(struct ieee80211_channel)); - ieee80211_media_init(ic); + ieee80211_chan_init(ic); /* * Invalidate channel-related state. Index: sys/net80211/ieee80211_scan_sta.c =================================================================== --- sys/net80211/ieee80211_scan_sta.c +++ sys/net80211/ieee80211_scan_sta.c @@ -1706,26 +1706,6 @@ 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) { @@ -1741,7 +1721,7 @@ st->st_scangen++; st->st_newscan = 1; - ap_force_promisc(vap->iv_ic); + ieee80211_promisc(vap, true); return 0; } @@ -1751,7 +1731,7 @@ static int ap_cancel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap) { - ap_reset_promisc(vap->iv_ic); + ieee80211_promisc(vap, false); return 0; } @@ -1825,7 +1805,7 @@ return 0; } } - ap_reset_promisc(ic); + ieee80211_promisc(vap, false); if (ss->ss_flags & (IEEE80211_SCAN_NOPICK | IEEE80211_SCAN_NOJOIN)) { /* * Manual/background scan, don't select+join the Index: sys/net80211/ieee80211_var.h =================================================================== --- sys/net80211/ieee80211_var.h +++ sys/net80211/ieee80211_var.h @@ -116,16 +116,15 @@ 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 */ @@ -151,6 +150,7 @@ 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,6 +241,11 @@ 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 */ @@ -254,6 +259,9 @@ 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); @@ -351,14 +359,15 @@ 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 */ @@ -681,24 +690,24 @@ "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS" int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3); -void ieee80211_ifattach(struct ieee80211com *, - const uint8_t macaddr[IEEE80211_ADDR_LEN]); +void ieee80211_ifattach(struct ieee80211com *); 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], - const uint8_t macaddr[IEEE80211_ADDR_LEN]); + const uint8_t bssid[IEEE80211_ADDR_LEN]); int ieee80211_vap_attach(struct ieee80211vap *, - ifm_change_cb_t, ifm_stat_cb_t); + ifm_change_cb_t, ifm_stat_cb_t, + const uint8_t macaddr[IEEE80211_ADDR_LEN]); 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_media_init(struct ieee80211com *); +void ieee80211_chan_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); Index: tools/tools/iwn/iwnstats/main.c =================================================================== --- tools/tools/iwn/iwnstats/main.c +++ tools/tools/iwn/iwnstats/main.c @@ -50,7 +50,7 @@ #include "iwnstats.h" #include "iwn_ioctl.h" -#define IWN_DEFAULT_IF "iwn0" +#define IWN_DEFAULT_IF "wlan0" static struct iwnstats * iwnstats_new(const char *ifname) @@ -290,19 +290,6 @@ if (ifname) free(ifname); ifname = strdup(optarg); - if (strncmp(ifname, "wlan", 4) == 0) { - free(ifname); - len = 0; - asprintf(&sysctlname, "net.wlan.%s.%%parent", ifname + 4); - ret = sysctlbyname(sysctlname, NULL, &len, NULL, 0); - if (ret != 0) - err(1, "sysctl failed"); - ifname = calloc(len, 1); - ret = sysctlbyname(sysctlname, ifname, &len, NULL, 0); - if (ret != 0) - err(1, "sysctl failed"); - free(sysctlname); - } break; default: case '?':