summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath/if_ath.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r--sys/dev/ath/if_ath.c498
1 files changed, 316 insertions, 182 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index f40f4fa..2c935a2b 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -151,15 +151,15 @@ static struct ieee80211vap *ath_vap_create(struct ieee80211com *,
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, uint8_t *macaddr)
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_softc *sc)
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_softc *sc)
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_softc *sc)
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_softc *sc)
/* 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 char name[IFNAMSIZ], int unit,
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, const char name[IFNAMSIZ], int unit,
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, const char name[IFNAMSIZ], int unit,
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;
- sc->sc_resume_up = ic->ic_nrunning != 0;
+ DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
+ __func__, ifp->if_flags);
+
+ 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 *sc, struct ieee80211_channel *chan)
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;
- ath_stop(sc);
+ DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
+ __func__, ifp->if_flags);
+
+ 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, int dowait)
*/
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_RESET_TYPE reset_type)
}
}
+ /*
+ * 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, u_long cmd)
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_type_t btype)
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_type_t btype)
* 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, struct mbuf *m)
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, struct mbuf *m)
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, struct mbuf *m)
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, struct mbuf *m)
* 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, struct mbuf *m)
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, struct mbuf *m)
}
}
+ /*
+ * 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 *vap)
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 *ic)
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 ac)
{
#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 ac)
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_tx_status *ts,
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 npending)
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, struct ath_txq *txq)
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_RESET_TYPE reset_type)
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, struct ieee80211_channel *chan)
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
ath_scan_start(struct ieee80211com *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;
u_int32_t rfilt;
/* XXX calibration timer? */
- /* XXXGL: is constant ieee80211broadcastaddr a correct choice? */
ATH_LOCK(sc);
sc->sc_scanning = 1;
@@ -5682,17 +5811,18 @@ ath_scan_start(struct ieee80211com *ic)
ATH_PCU_LOCK(sc);
ath_hal_setrxfilter(ah, rfilt);
- ath_hal_setassocid(ah, ieee80211broadcastaddr, 0);
+ ath_hal_setassocid(ah, ifp->if_broadcastaddr, 0);
ATH_PCU_UNLOCK(sc);
DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0\n",
- __func__, rfilt, ether_sprintf(ieee80211broadcastaddr));
+ __func__, rfilt, ether_sprintf(ifp->if_broadcastaddr));
}
static void
ath_scan_end(struct ieee80211com *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;
u_int32_t rfilt;
@@ -5732,7 +5862,8 @@ ath_scan_end(struct ieee80211com *ic)
static void
ath_update_chw(struct ieee80211com *ic)
{
- struct ath_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct ath_softc *sc = ifp->if_softc;
DPRINTF(sc, ATH_DEBUG_STATE, "%s: called\n", __func__);
ath_set_channel(ic);
@@ -5742,7 +5873,8 @@ ath_update_chw(struct ieee80211com *ic)
static void
ath_set_channel(struct ieee80211com *ic)
{
- struct ath_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct ath_softc *sc = ifp->if_softc;
ATH_LOCK(sc);
ath_power_set_power_state(sc, HAL_PM_AWAKE);
@@ -5784,7 +5916,7 @@ static int
ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ath_softc *sc = ic->ic_softc;
+ struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ath_vap *avp = ATH_VAP(vap);
struct ath_hal *ah = sc->sc_ah;
struct ieee80211_node *ni = NULL;
@@ -6120,7 +6252,7 @@ static void
ath_setup_stationkey(struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ath_softc *sc = vap->iv_ic->ic_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
ieee80211_keyix keyix, rxkeyix;
/* XXX should take a locked ref to vap->iv_bss */
@@ -6153,7 +6285,7 @@ ath_newassoc(struct ieee80211_node *ni, int isnew)
{
struct ath_node *an = ATH_NODE(ni);
struct ieee80211vap *vap = ni->ni_vap;
- struct ath_softc *sc = vap->iv_ic->ic_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
const struct ieee80211_txparam *tp = ni->ni_txparms;
an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate);
@@ -6205,7 +6337,7 @@ static int
ath_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *reg,
int nchans, struct ieee80211_channel chans[])
{
- struct ath_softc *sc = ic->ic_softc;
+ struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ath_hal *ah = sc->sc_ah;
HAL_STATUS status;
@@ -6229,7 +6361,7 @@ static void
ath_getradiocaps(struct ieee80211com *ic,
int maxchans, int *nchans, struct ieee80211_channel chans[])
{
- struct ath_softc *sc = ic->ic_softc;
+ struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ath_hal *ah = sc->sc_ah;
DPRINTF(sc, ATH_DEBUG_REGDOMAIN, "%s: use rd %u cc %d\n",
@@ -6244,7 +6376,8 @@ ath_getradiocaps(struct ieee80211com *ic,
static int
ath_getchannels(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;
@@ -6406,12 +6539,12 @@ static void
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);
@@ -6423,7 +6556,7 @@ ath_watchdog(void *arg)
} else
device_printf(sc->sc_dev, "device timeout\n");
do_reset = 1;
- counter_u64_add(ic->ic_oerrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
sc->sc_stats.ast_watchdog++;
ath_power_restore_power_state(sc);
@@ -6449,7 +6582,7 @@ static int
ath_ioctl_ratestats(struct ath_softc *sc, struct ath_rateioctl *rs)
{
struct ath_node *an;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211_node *ni;
int error = 0;
@@ -6555,23 +6688,31 @@ bad:
}
#endif /* ATH_DIAGAPI */
-static void
-ath_parent(struct ieee80211com *ic)
+static int
+ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct ath_softc *sc = ic->ic_softc;
+#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;
- 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) {
+ 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_power_set_power_state(sc, HAL_PM_AWAKE);
ath_mode_init(sc);
ath_power_restore_power_state(sc);
- } else if (!sc->sc_invalid) {
+ ATH_UNLOCK(sc);
+ } else if (ifp->if_flags & IFF_UP) {
/*
* Beware of being called during attach/detach
* to reset promiscuous mode. In that case we
@@ -6581,40 +6722,26 @@ ath_parent(struct ieee80211com *ic)
* 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;
}
- } 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;
-
+ break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
+ break;
+ case SIOCGATHSTATS:
/* NB: embed these numbers to get a consistent view */
- 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_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
@@ -6628,13 +6755,10 @@ ath_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
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: {
- int error;
-
+ case SIOCZATHSTATS:
error = priv_check(curthread, PRIV_DRIVER);
if (error == 0) {
memset(&sc->sc_stats, 0, sizeof(sc->sc_stats));
@@ -6643,21 +6767,30 @@ ath_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
memset(&sc->sc_intr_stats, 0,
sizeof(sc->sc_intr_stats));
}
- return (error);
- }
+ break;
#ifdef ATH_DIAGAPI
case SIOCGATHDIAG:
- return (ath_ioctl_diag(sc, data));
+ error = ath_ioctl_diag(sc, (struct ath_diag *) ifr);
+ break;
case SIOCGATHPHYERR:
- return (ath_ioctl_phyerr(sc, data));
+ error = ath_ioctl_phyerr(sc,(struct ath_diag*) ifr);
+ break;
#endif
case SIOCGATHSPECTRAL:
- return (ath_ioctl_spectral(sc, data));
+ error = ath_ioctl_spectral(sc,(struct ath_diag*) ifr);
+ break;
case SIOCGATHNODERATESTATS:
- return (ath_ioctl_ratestats(sc, data));
+ error = ath_ioctl_ratestats(sc, (struct ath_rateioctl *) ifr);
+ break;
+ case SIOCGIFADDR:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
default:
- return (ENOTTY);
+ error = EINVAL;
+ break;
}
+ return error;
+#undef IS_RUNNING
}
/*
@@ -6698,7 +6831,8 @@ static void
ath_dfs_tasklet(void *p, int npending)
{
struct ath_softc *sc = (struct ath_softc *) p;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
/*
* If previous processing has found a radar event,
@@ -6730,7 +6864,7 @@ ath_node_powersave(struct ieee80211_node *ni, int enable)
#ifdef ATH_SW_PSQ
struct ath_node *an = ATH_NODE(ni);
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_softc;
+ struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
/* XXX and no TXQ locks should be held here */
@@ -6797,7 +6931,7 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
{
#ifdef ATH_SW_PSQ
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_softc;
+ struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ath_node *an = ATH_NODE(ni);
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
int changed = 0;
@@ -7002,7 +7136,7 @@ ath_node_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m)
struct ath_node *an;
struct ath_vap *avp;
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_softc;
+ struct ath_softc *sc = ic->ic_ifp->if_softc;
int tid;
/* Just paranoia */
OpenPOWER on IntegriCloud