Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 Aug 2015 01:10:19 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r286437 - in head/sys: dev/ath dev/ath/ath_rate/sample dev/bwi dev/bwn dev/if_ndis dev/ipw dev/iwi dev/iwn dev/malo dev/mwl dev/ral dev/usb/wlan dev/wi dev/wpi dev/wtap net80211
Message-ID:  <201508080110.t781AJUf044737@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Sat Aug  8 01:10:17 2015
New Revision: 286437
URL: https://svnweb.freebsd.org/changeset/base/286437

Log:
  Revert the wifi ifnet changes until things are more baked and tested.
  
  * 286410
  * 286413
  * 286416
  
  The initial commit broke a variety of debug and features that aren't
  in the GENERIC kernels but are enabled in other platforms.

Modified:
  head/sys/dev/ath/ath_rate/sample/sample.c
  head/sys/dev/ath/ath_rate/sample/sample.h
  head/sys/dev/ath/if_ath.c
  head/sys/dev/ath/if_ath_beacon.c
  head/sys/dev/ath/if_ath_debug.h
  head/sys/dev/ath/if_ath_keycache.c
  head/sys/dev/ath/if_ath_misc.h
  head/sys/dev/ath/if_ath_rx.c
  head/sys/dev/ath/if_ath_rx_edma.c
  head/sys/dev/ath/if_ath_sysctl.c
  head/sys/dev/ath/if_ath_tdma.c
  head/sys/dev/ath/if_ath_tx.c
  head/sys/dev/ath/if_ath_tx_edma.c
  head/sys/dev/ath/if_athvar.h
  head/sys/dev/bwi/bwimac.c
  head/sys/dev/bwi/bwiphy.c
  head/sys/dev/bwi/bwirf.c
  head/sys/dev/bwi/if_bwi.c
  head/sys/dev/bwi/if_bwivar.h
  head/sys/dev/bwn/if_bwn.c
  head/sys/dev/bwn/if_bwnvar.h
  head/sys/dev/if_ndis/if_ndis.c
  head/sys/dev/if_ndis/if_ndisvar.h
  head/sys/dev/ipw/if_ipw.c
  head/sys/dev/ipw/if_ipwvar.h
  head/sys/dev/iwi/if_iwi.c
  head/sys/dev/iwi/if_iwivar.h
  head/sys/dev/iwn/if_iwn.c
  head/sys/dev/iwn/if_iwnvar.h
  head/sys/dev/malo/if_malo.c
  head/sys/dev/malo/if_malo.h
  head/sys/dev/mwl/if_mwl.c
  head/sys/dev/mwl/if_mwl_pci.c
  head/sys/dev/mwl/if_mwlvar.h
  head/sys/dev/ral/if_ral_pci.c
  head/sys/dev/ral/rt2560.c
  head/sys/dev/ral/rt2560var.h
  head/sys/dev/ral/rt2661.c
  head/sys/dev/ral/rt2661var.h
  head/sys/dev/ral/rt2860.c
  head/sys/dev/ral/rt2860var.h
  head/sys/dev/usb/wlan/if_rsu.c
  head/sys/dev/usb/wlan/if_rsureg.h
  head/sys/dev/usb/wlan/if_rum.c
  head/sys/dev/usb/wlan/if_rumvar.h
  head/sys/dev/usb/wlan/if_run.c
  head/sys/dev/usb/wlan/if_runvar.h
  head/sys/dev/usb/wlan/if_uath.c
  head/sys/dev/usb/wlan/if_uathvar.h
  head/sys/dev/usb/wlan/if_upgt.c
  head/sys/dev/usb/wlan/if_upgtvar.h
  head/sys/dev/usb/wlan/if_ural.c
  head/sys/dev/usb/wlan/if_uralvar.h
  head/sys/dev/usb/wlan/if_urtw.c
  head/sys/dev/usb/wlan/if_urtwn.c
  head/sys/dev/usb/wlan/if_urtwnreg.h
  head/sys/dev/usb/wlan/if_urtwvar.h
  head/sys/dev/usb/wlan/if_zyd.c
  head/sys/dev/usb/wlan/if_zydreg.h
  head/sys/dev/wi/if_wi.c
  head/sys/dev/wi/if_wi_pccard.c
  head/sys/dev/wi/if_wi_pci.c
  head/sys/dev/wi/if_wivar.h
  head/sys/dev/wpi/if_wpi.c
  head/sys/dev/wpi/if_wpivar.h
  head/sys/dev/wtap/if_wtap.c
  head/sys/dev/wtap/if_wtapvar.h
  head/sys/net80211/ieee80211.c
  head/sys/net80211/ieee80211_ddb.c
  head/sys/net80211/ieee80211_freebsd.c
  head/sys/net80211/ieee80211_ioctl.c
  head/sys/net80211/ieee80211_output.c
  head/sys/net80211/ieee80211_power.c
  head/sys/net80211/ieee80211_proto.c
  head/sys/net80211/ieee80211_proto.h
  head/sys/net80211/ieee80211_regdomain.c
  head/sys/net80211/ieee80211_scan_sta.c
  head/sys/net80211/ieee80211_var.h

Modified: head/sys/dev/ath/ath_rate/sample/sample.c
==============================================================================
--- head/sys/dev/ath/ath_rate/sample/sample.c	Sat Aug  8 00:57:27 2015	(r286436)
+++ head/sys/dev/ath/ath_rate/sample/sample.c	Sat Aug  8 01:10:17 2015	(r286437)
@@ -488,7 +488,8 @@ ath_rate_findrate(struct ath_softc *sc, 
 #define	RATE(ix)	(DOT11RATE(ix) / 2)
 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
 	struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	const HAL_RATE_TABLE *rt = sc->sc_currates;
 	const int size_bin = size_to_bin(frameLen);
 	int rix, mrr, best_rix, change_rates;
@@ -855,7 +856,8 @@ ath_rate_tx_complete(struct ath_softc *s
 	const struct ath_rc_series *rc, const struct ath_tx_status *ts,
 	int frame_size, int nframes, int nbad)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
 	int final_rix, short_tries, long_tries;
 	const HAL_RATE_TABLE *rt = sc->sc_currates;
@@ -1301,7 +1303,8 @@ static int
 ath_rate_sysctl_stats(SYSCTL_HANDLER_ARGS)
 {
 	struct ath_softc *sc = arg1;
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	int error, v;
 
 	v = 0;

Modified: head/sys/dev/ath/ath_rate/sample/sample.h
==============================================================================
--- head/sys/dev/ath/ath_rate/sample/sample.h	Sat Aug  8 00:57:27 2015	(r286436)
+++ head/sys/dev/ath/ath_rate/sample/sample.h	Sat Aug  8 01:10:17 2015	(r286437)
@@ -134,7 +134,8 @@ static unsigned calc_usecs_unicast_packe
 				int long_retries, int is_ht40)
 {
 	const HAL_RATE_TABLE *rt = sc->sc_currates;
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	int rts, cts;
 	
 	unsigned t_slot = 20;

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Sat Aug  8 00:57:27 2015	(r286436)
+++ head/sys/dev/ath/if_ath.c	Sat Aug  8 01:10:17 2015	(r286437)
@@ -151,15 +151,15 @@ static struct ieee80211vap *ath_vap_crea
 		    const uint8_t [IEEE80211_ADDR_LEN],
 		    const uint8_t [IEEE80211_ADDR_LEN]);
 static void	ath_vap_delete(struct ieee80211vap *);
-static void	ath_init(struct ath_softc *);
-static void	ath_stop_locked(struct ath_softc *);
-static void	ath_stop(struct ath_softc *);
+static void	ath_init(void *);
+static void	ath_stop_locked(struct ifnet *);
+static void	ath_stop(struct ifnet *);
 static int	ath_reset_vap(struct ieee80211vap *, u_long);
-static int	ath_transmit(struct ieee80211com *, struct mbuf *);
+static int	ath_transmit(struct ifnet *ifp, struct mbuf *m);
+static void	ath_qflush(struct ifnet *ifp);
 static int	ath_media_change(struct ifnet *);
 static void	ath_watchdog(void *);
-static int	ath_ioctl(struct ieee80211com *, u_long, void *);
-static void	ath_parent(struct ieee80211com *);
+static int	ath_ioctl(struct ifnet *, u_long, caddr_t);
 static void	ath_fatal_proc(void *, int);
 static void	ath_bmiss_vap(struct ieee80211vap *);
 static void	ath_bmiss_proc(void *, int);
@@ -571,19 +571,34 @@ ath_fetch_mac_kenv(struct ath_softc *sc,
 int
 ath_attach(u_int16_t devid, struct ath_softc *sc)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp;
+	struct ieee80211com *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.
 	 *
@@ -717,8 +732,8 @@ ath_attach(u_int16_t devid, struct ath_s
 
 	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",
-	    device_get_nameunit(sc->sc_dev));
+	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
+		"%s taskq", ifp->if_xname);
 
 	TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc);
 	TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc);
@@ -861,6 +876,17 @@ ath_attach(u_int16_t devid, struct ath_s
 	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;
@@ -1182,11 +1208,11 @@ ath_attach(u_int16_t devid, struct ath_s
 	sc->sc_hasveol = ath_hal_hasveol(ah);
 
 	/* get mac address from kenv first, then hardware */
-	if (ath_fetch_mac_kenv(sc, ic->ic_macaddr) == 0) {
+	if (ath_fetch_mac_kenv(sc, macaddr) == 0) {
 		/* Tell the HAL now about the new MAC */
-		ath_hal_setmac(ah, ic->ic_macaddr);
+		ath_hal_setmac(ah, macaddr);
 	} else {
-		ath_hal_getmac(ah, ic->ic_macaddr);
+		ath_hal_getmac(ah, macaddr);
 	}
 
 	if (sc->sc_hasbmask)
@@ -1195,15 +1221,12 @@ ath_attach(u_int16_t devid, struct ath_s
 	/* NB: used to size node table key mapping array */
 	ic->ic_max_keyix = sc->sc_keymax;
 	/* call MI attach routine. */
-	ieee80211_ifattach(ic);
+	ieee80211_ifattach(ic, macaddr);
 	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;
@@ -1299,6 +1322,16 @@ bad2:
 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;
 }
@@ -1306,6 +1339,10 @@ bad:
 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:
@@ -1330,14 +1367,14 @@ ath_detach(struct ath_softc *sc)
 	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_locked(sc);
-	ATH_UNLOCK(sc);
+	ath_stop(ifp);
 
-	ieee80211_ifdetach(&sc->sc_ic);
+	ieee80211_ifdetach(ifp->if_l2com);
 	taskqueue_free(sc->sc_tq);
 #ifdef ATH_TX99_DIAG
 	if (sc->sc_tx99 != NULL)
@@ -1357,6 +1394,10 @@ ath_detach(struct ath_softc *sc)
 	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;
 }
 
@@ -1432,7 +1473,7 @@ ath_vap_create(struct ieee80211com *ic, 
     const uint8_t bssid[IEEE80211_ADDR_LEN],
     const uint8_t mac0[IEEE80211_ADDR_LEN])
 {
-	struct ath_softc *sc = ic->ic_softc;
+	struct ath_softc *sc = ic->ic_ifp->if_softc;
 	struct ath_vap *avp;
 	struct ieee80211vap *vap;
 	uint8_t mac[IEEE80211_ADDR_LEN];
@@ -1540,7 +1581,8 @@ ath_vap_create(struct ieee80211com *ic, 
 	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);
+	error = ieee80211_vap_setup(ic, vap, name, unit, opmode, flags,
+	    bssid, mac);
 	ATH_LOCK(sc);
 	if (error != 0) {
 		device_printf(sc->sc_dev, "%s: error %d creating vap\n",
@@ -1674,8 +1716,7 @@ ath_vap_create(struct ieee80211com *ic, 
 	ATH_UNLOCK(sc);
 
 	/* complete setup */
-	ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status,
-	    mac);
+	ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status);
 	return vap;
 bad2:
 	reclaim_address(sc, mac);
@@ -1690,7 +1731,8 @@ static void
 ath_vap_delete(struct ieee80211vap *vap)
 {
 	struct ieee80211com *ic = vap->iv_ic;
-	struct ath_softc *sc = ic->ic_softc;
+	struct ifnet *ifp = ic->ic_ifp;
+	struct ath_softc *sc = ifp->if_softc;
 	struct ath_hal *ah = sc->sc_ah;
 	struct ath_vap *avp = ATH_VAP(vap);
 
@@ -1699,7 +1741,7 @@ ath_vap_delete(struct ieee80211vap *vap)
 	ATH_UNLOCK(sc);
 
 	DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__);
-	if (sc->sc_running) {
+	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 		/*
 		 * Quiesce the hardware while we remove the vap.  In
 		 * particular we need to reclaim all references to
@@ -1782,7 +1824,7 @@ ath_vap_delete(struct ieee80211vap *vap)
 #endif
 	free(avp, M_80211_VAP);
 
-	if (sc->sc_running) {
+	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 		/*
 		 * Restart rx+tx machines if still running (RUNNING will
 		 * be reset if we just destroyed the last vap).
@@ -1809,9 +1851,13 @@ ath_vap_delete(struct ieee80211vap *vap)
 void
 ath_suspend(struct ath_softc *sc)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	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);
 
-	sc->sc_resume_up = ic->ic_nrunning != 0;
+	sc->sc_resume_up = (ifp->if_flags & IFF_UP) != 0;
 
 	ieee80211_suspend_all(ic);
 	/*
@@ -1852,7 +1898,8 @@ ath_suspend(struct ath_softc *sc)
 static void
 ath_reset_keycache(struct ath_softc *sc)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct ath_hal *ah = sc->sc_ah;
 	int i;
 
@@ -1894,7 +1941,8 @@ ath_update_chainmasks(struct ath_softc *
 void
 ath_resume(struct ath_softc *sc)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct ath_hal *ah = sc->sc_ah;
 	HAL_STATUS status;
 
@@ -1967,8 +2015,12 @@ ath_resume(struct ath_softc *sc)
 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(sc);
+	ath_stop(ifp);
 	/* NB: no point powering down chip as we're about to reboot */
 }
 
@@ -1979,6 +2031,7 @@ void
 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;
@@ -2017,11 +2070,12 @@ ath_intr(void *arg)
 	ath_power_set_power_state(sc, HAL_PM_AWAKE);
 	ATH_UNLOCK(sc);
 
-	if (sc->sc_ic.ic_nrunning == 0 && sc->sc_running == 0) {
+	if ((ifp->if_flags & IFF_UP) == 0 ||
+	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
 		HAL_INT status;
 
-		DPRINTF(sc, ATH_DEBUG_ANY, "%s: ic_nrunning %d sc_running %d\n",
-		    __func__, sc->sc_ic.ic_nrunning, sc->sc_running);
+		DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags 0x%x\n",
+			__func__, ifp->if_flags);
 		ath_hal_getisr(ah, &status);	/* clear ISR */
 		ath_hal_intrset(ah, 0);		/* disable further intr's */
 		ATH_PCU_UNLOCK(sc);
@@ -2259,6 +2313,7 @@ static void
 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;
@@ -2279,13 +2334,13 @@ ath_fatal_proc(void *arg, int pending)
 		    "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(sc, ATH_RESET_NOLOSS);
+	ath_reset(ifp, ATH_RESET_NOLOSS);
 }
 
 static void
 ath_bmiss_vap(struct ieee80211vap *vap)
 {
-	struct ath_softc *sc = vap->iv_ic->ic_softc;
+	struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
 
 	/*
 	 * Workaround phantom bmiss interrupts by sanity-checking
@@ -2306,6 +2361,8 @@ ath_bmiss_vap(struct ieee80211vap *vap)
 	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 */
@@ -2363,6 +2420,7 @@ static void
 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);
@@ -2380,12 +2438,12 @@ ath_bmiss_proc(void *arg, int pending)
 	 * to clear.
 	 */
 	if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) {
-		ath_reset(sc, ATH_RESET_NOLOSS);
+		ath_reset(ifp, ATH_RESET_NOLOSS);
 		device_printf(sc->sc_dev,
 		    "bb hang detected (0x%x), resetting\n", hangs);
 	} else {
-		ath_reset(sc, ATH_RESET_NOLOSS);
-		ieee80211_beacon_miss(&sc->sc_ic);
+		ath_reset(ifp, ATH_RESET_NOLOSS);
+		ieee80211_beacon_miss(ifp->if_l2com);
 	}
 
 	/* Force a beacon resync, in case they've drifted */
@@ -2405,7 +2463,8 @@ ath_bmiss_proc(void *arg, int pending)
 static void
 ath_settkipmic(struct ath_softc *sc)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 
 	if ((ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP) && !sc->sc_wmetkipmic) {
 		if (ic->ic_flags & IEEE80211_F_WME) {
@@ -2419,9 +2478,11 @@ ath_settkipmic(struct ath_softc *sc)
 }
 
 static void
-ath_init(struct ath_softc *sc)
+ath_init(void *arg)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ath_softc *sc = (struct ath_softc *) arg;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct ath_hal *ah = sc->sc_ah;
 	HAL_STATUS status;
 
@@ -2440,7 +2501,7 @@ ath_init(struct ath_softc *sc)
 	 * Stop anything previously setup.  This is safe
 	 * whether this is the first time through or not.
 	 */
-	ath_stop_locked(sc);
+	ath_stop_locked(ifp);
 
 	/*
 	 * The basic interface to setting the hardware in a good
@@ -2566,7 +2627,7 @@ ath_init(struct ath_softc *sc)
 	DPRINTF(sc, ATH_DEBUG_RESET, "%s: imask=0x%x\n",
 		__func__, sc->sc_imask);
 
-	sc->sc_running = 1;
+	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	callout_reset(&sc->sc_wd_ch, hz, ath_watchdog, sc);
 	ath_hal_intrset(ah, sc->sc_imask);
 
@@ -2582,10 +2643,14 @@ ath_init(struct ath_softc *sc)
 }
 
 static void
-ath_stop_locked(struct ath_softc *sc)
+ath_stop_locked(struct ifnet *ifp)
 {
+	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);
 
 	/*
@@ -2593,7 +2658,7 @@ ath_stop_locked(struct ath_softc *sc)
 	 */
 	ath_power_set_power_state(sc, HAL_PM_AWAKE);
 
-	if (sc->sc_running) {
+	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 		/*
 		 * Shutdown the hardware and driver:
 		 *    reset 802.11 state machine
@@ -2615,7 +2680,7 @@ ath_stop_locked(struct ath_softc *sc)
 #endif
 		callout_stop(&sc->sc_wd_ch);
 		sc->sc_wd_timer = 0;
-		sc->sc_running = 0;
+		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
 		if (!sc->sc_invalid) {
 			if (sc->sc_softled) {
 				callout_stop(&sc->sc_ledtimer);
@@ -2767,11 +2832,12 @@ ath_reset_grablock(struct ath_softc *sc,
  */
 
 static void
-ath_stop(struct ath_softc *sc)
+ath_stop(struct ifnet *ifp)
 {
-	
+	struct ath_softc *sc = ifp->if_softc;
+
 	ATH_LOCK(sc);
-	ath_stop_locked(sc);
+	ath_stop_locked(ifp);
 	ATH_UNLOCK(sc);
 }
 
@@ -2783,9 +2849,10 @@ ath_stop(struct ath_softc *sc)
  * to reset or reload hardware state.
  */
 int
-ath_reset(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
+ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ath_softc *sc = ifp->if_softc;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct ath_hal *ah = sc->sc_ah;
 	HAL_STATUS status;
 	int i;
@@ -2947,6 +3014,15 @@ ath_reset(struct ath_softc *sc, ATH_RESE
 		}
 	}
 
+	/*
+	 * 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);
@@ -2968,7 +3044,8 @@ static int
 ath_reset_vap(struct ieee80211vap *vap, u_long cmd)
 {
 	struct ieee80211com *ic = vap->iv_ic;
-	struct ath_softc *sc = ic->ic_softc;
+	struct ifnet *ifp = ic->ic_ifp;
+	struct ath_softc *sc = ifp->if_softc;
 	struct ath_hal *ah = sc->sc_ah;
 
 	switch (cmd) {
@@ -2983,7 +3060,7 @@ ath_reset_vap(struct ieee80211vap *vap, 
 		return 0;
 	}
 	/* XXX? Full or NOLOSS? */
-	return ath_reset(sc, ATH_RESET_FULL);
+	return ath_reset(ifp, ATH_RESET_FULL);
 }
 
 struct ath_buf *
@@ -3143,12 +3220,24 @@ ath_getbuf(struct ath_softc *sc, ath_buf
 		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.
  *
@@ -3156,9 +3245,10 @@ ath_getbuf(struct ath_softc *sc, ath_buf
  * fails, so don't free the node reference here.
  */
 static int
-ath_transmit(struct ieee80211com *ic, struct mbuf *m)
+ath_transmit(struct ifnet *ifp, struct mbuf *m)
 {
-	struct ath_softc *sc = ic->ic_softc;
+	struct ieee80211com *ic = ifp->if_l2com;
+	struct ath_softc *sc = ic->ic_ifp->if_softc;
 	struct ieee80211_node *ni;
 	struct mbuf *next;
 	struct ath_buf *bf;
@@ -3173,7 +3263,10 @@ ath_transmit(struct ieee80211com *ic, st
 		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? */
 	}
@@ -3213,6 +3306,8 @@ ath_transmit(struct ieee80211com *ic, st
 	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;
 	}
@@ -3236,6 +3331,8 @@ ath_transmit(struct ieee80211com *ic, st
 	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;
 	}
@@ -3263,6 +3360,11 @@ ath_transmit(struct ieee80211com *ic, st
 		 * 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;
 	}
@@ -3284,13 +3386,8 @@ ath_transmit(struct ieee80211com *ic, st
 		DPRINTF(sc, ATH_DEBUG_XMIT,
 		    "%s: out of txfrag buffers\n", __func__);
 		sc->sc_stats.ast_tx_nofrag++;
-		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.
-		 */
+		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 		ath_freetx(m);
-		m = NULL;
 		goto bad;
 	}
 
@@ -3332,6 +3429,12 @@ ath_transmit(struct ieee80211com *ic, st
 		}
 	}
 
+	/*
+	 * 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.
@@ -3351,7 +3454,7 @@ nextfrag:
 	next = m->m_nextpkt;
 	if (ath_tx_start(sc, ni, bf, m)) {
 bad:
-		if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
+		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 reclaim:
 		bf->bf_m = NULL;
 		bf->bf_node = NULL;
@@ -3435,7 +3538,8 @@ ath_media_change(struct ifnet *ifp)
 static void
 ath_key_update_begin(struct ieee80211vap *vap)
 {
-	struct ath_softc *sc =  vap->iv_ic->ic_softc;
+	struct ifnet *ifp = vap->iv_ic->ic_ifp;
+	struct ath_softc *sc = ifp->if_softc;
 
 	DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
 	taskqueue_block(sc->sc_tq);
@@ -3444,7 +3548,8 @@ ath_key_update_begin(struct ieee80211vap
 static void
 ath_key_update_end(struct ieee80211vap *vap)
 {
-	struct ath_softc *sc =  vap->iv_ic->ic_softc;
+	struct ifnet *ifp = vap->iv_ic->ic_ifp;
+	struct ath_softc *sc = ifp->if_softc;
 
 	DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
 	taskqueue_unblock(sc->sc_tq);
@@ -3475,41 +3580,32 @@ ath_update_promisc(struct ieee80211com *
 static void
 ath_update_mcast_hw(struct ath_softc *sc)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
 	u_int32_t mfilt[2];
 
 	/* calculate and install multicast filter */
-	if (ic->ic_allmulti == 0) {
-		struct ieee80211vap *vap;
-		struct ifnet *ifp;
+	if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
 		struct ifmultiaddr *ifma;
-
 		/*
 		 * Merge multicast addresses to form the hardware filter.
 		 */
 		mfilt[0] = mfilt[1] = 0;
-		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_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));
 		}
+		if_maddr_runlock(ifp);
 	} else
 		mfilt[0] = mfilt[1] = ~0;
 
@@ -3542,7 +3638,7 @@ ath_update_mcast(struct ieee80211com *ic
 void
 ath_mode_init(struct ath_softc *sc)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
 	struct ath_hal *ah = sc->sc_ah;
 	u_int32_t rfilt;
 
@@ -3553,8 +3649,15 @@ ath_mode_init(struct ath_softc *sc)
 	/* 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, ic->ic_macaddr);
+	ath_hal_setmac(ah, IF_LLADDR(ifp));
 
 	/* calculate and install multicast filter */
 	ath_update_mcast_hw(sc);
@@ -3566,7 +3669,7 @@ ath_mode_init(struct ath_softc *sc)
 void
 ath_setslottime(struct ath_softc *sc)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 	struct ath_hal *ah = sc->sc_ah;
 	u_int usec;
 
@@ -3650,11 +3753,12 @@ static void
 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(sc, ATH_RESET_NOLOSS);
+	ath_reset(ifp, ATH_RESET_NOLOSS);
 }
 
 /*
@@ -3664,6 +3768,7 @@ static void
 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)
@@ -3681,7 +3786,7 @@ ath_bstuck_proc(void *arg, int pending)
 	 * This assumes that there's no simultaneous channel mode change
 	 * occuring.
 	 */
-	ath_reset(sc, ATH_RESET_NOLOSS);
+	ath_reset(ifp, ATH_RESET_NOLOSS);
 }
 
 static void
@@ -4051,7 +4156,7 @@ static struct ieee80211_node *
 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_softc;
+	struct ath_softc *sc = ic->ic_ifp->if_softc;
 	const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space;
 	struct ath_node *an;
 
@@ -4078,7 +4183,7 @@ static void
 ath_node_cleanup(struct ieee80211_node *ni)
 {
 	struct ieee80211com *ic = ni->ni_ic;
-	struct ath_softc *sc = ic->ic_softc;
+	struct ath_softc *sc = ic->ic_ifp->if_softc;
 
 	DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__,
 	    ni->ni_macaddr, ":", ATH_NODE(ni));
@@ -4093,7 +4198,7 @@ static void
 ath_node_free(struct ieee80211_node *ni)
 {
 	struct ieee80211com *ic = ni->ni_ic;
-	struct ath_softc *sc = ic->ic_softc;
+	struct ath_softc *sc = ic->ic_ifp->if_softc;
 
 	DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__,
 	    ni->ni_macaddr, ":", ATH_NODE(ni));
@@ -4105,7 +4210,7 @@ static void
 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_softc;
+	struct ath_softc *sc = ic->ic_ifp->if_softc;
 	struct ath_hal *ah = sc->sc_ah;
 
 	*rssi = ic->ic_node_getrssi(ni);
@@ -4243,7 +4348,8 @@ ath_txq_update(struct ath_softc *sc, int
 {
 #define	ATH_EXPONENT_TO_VALUE(v)	((1<<v)-1)
 #define	ATH_TXOP_TO_US(v)		(v<<5)
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	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;
@@ -4316,7 +4422,7 @@ ath_txq_update(struct ath_softc *sc, int
 int
 ath_wme_update(struct ieee80211com *ic)
 {
-	struct ath_softc *sc = ic->ic_softc;
+	struct ath_softc *sc = ic->ic_ifp->if_softc;
 
 	return !ath_txq_update(sc, WME_AC_BE) ||
 	    !ath_txq_update(sc, WME_AC_BK) ||
@@ -4367,7 +4473,8 @@ ath_tx_update_stats(struct ath_softc *sc
     struct ath_buf *bf)
 {
 	struct ieee80211_node *ni = bf->bf_node;
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	int sr, lr, pri;
 
 	if (ts->ts_status == 0) {
@@ -4722,6 +4829,7 @@ static void
 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);
@@ -4742,6 +4850,9 @@ ath_tx_proc_q0(void *arg, int npending)
 		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)
@@ -4766,6 +4877,7 @@ static void
 ath_tx_proc_q0123(void *arg, int npending)
 {
 	struct ath_softc *sc = arg;
+	struct ifnet *ifp = sc->sc_ifp;
 	int nacked;
 	uint32_t txqs;
 
@@ -4799,6 +4911,9 @@ ath_tx_proc_q0123(void *arg, int npendin
 	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)
@@ -4822,6 +4937,7 @@ static void
 ath_tx_proc(void *arg, int npending)
 {
 	struct ath_softc *sc = arg;
+	struct ifnet *ifp = sc->sc_ifp;
 	int i, nacked;
 	uint32_t txqs;
 
@@ -4847,6 +4963,10 @@ ath_tx_proc(void *arg, int npending)
 	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)
@@ -5157,7 +5277,7 @@ ath_tx_draintxq(struct ath_softc *sc, st
 			txq->axq_aggr_depth--;
 #ifdef ATH_DEBUG
 		if (sc->sc_debug & ATH_DEBUG_RESET) {
-			struct ieee80211com *ic = &sc->sc_ic;
+			struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 			int status = 0;
 
 			/*
@@ -5302,8 +5422,9 @@ void
 ath_legacy_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
 {
 	struct ath_hal *ah = sc->sc_ah;
-	struct ath_buf *bf_last;
+	struct ifnet *ifp = sc->sc_ifp;
 	int i;
+	struct ath_buf *bf_last;
 
 	(void) ath_stoptxdma(sc);
 
@@ -5355,12 +5476,15 @@ ath_legacy_tx_drain(struct ath_softc *sc
 			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(&sc->sc_ic,
+			ieee80211_dump_pkt(ifp->if_l2com,
 			    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;
 }
 
@@ -5391,7 +5515,8 @@ ath_chan_change(struct ath_softc *sc, st
 static int
 ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
 {
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	struct ath_hal *ah = sc->sc_ah;
 	int ret = 0;
 
@@ -5526,6 +5651,9 @@ finish:
 	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? */
 
@@ -5541,7 +5669,8 @@ ath_calibrate(void *arg)
 {
 	struct ath_softc *sc = arg;
 	struct ath_hal *ah = sc->sc_ah;
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
 	HAL_BOOL longCal, isCalDone = AH_TRUE;
 	HAL_BOOL aniCal, shortCal = AH_FALSE;
 	int nextcal;
@@ -5667,12 +5796,12 @@ restart:
 static void

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508080110.t781AJUf044737>