summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath/if_ath.c
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2015-08-07 11:43:14 +0000
committerglebius <glebius@FreeBSD.org>2015-08-07 11:43:14 +0000
commiteb8a90b8596b58df12c5e12dd059fe3c40dad08e (patch)
tree6454e7be9c51af111875a842eec79f4a2ddb1d23 /sys/dev/ath/if_ath.c
parent94936bfa1d0fc354e859129a11266bc6dac1f589 (diff)
downloadFreeBSD-src-eb8a90b8596b58df12c5e12dd059fe3c40dad08e.zip
FreeBSD-src-eb8a90b8596b58df12c5e12dd059fe3c40dad08e.tar.gz
Change KPI of how device drivers that provide wireless connectivity interact
with the net80211 stack. Historical background: originally wireless devices created an interface, just like Ethernet devices do. Name of an interface matched the name of the driver that created. Later, wlan(4) layer was introduced, and the wlanX interfaces become the actual interface, leaving original ones as "a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer and a driver became a mix of methods that pass a pointer to struct ifnet as identifier and methods that pass pointer to struct ieee80211com. From user point of view, the parent interface just hangs on in the ifconfig list, and user can't do anything useful with it. Now, the struct ifnet goes away. The struct ieee80211com is the only KPI between a device driver and net80211. Details: - The struct ieee80211com is embedded into drivers softc. - Packets are sent via new ic_transmit method, which is very much like the previous if_transmit. - Bringing parent up/down is done via new ic_parent method, which notifies driver about any changes: number of wlan(4) interfaces, number of them in promisc or allmulti state. - Device specific ioctls (if any) are received on new ic_ioctl method. - Packets/errors accounting are done by the stack. In certain cases, when driver experiences errors and can not attribute them to any specific interface, driver updates ic_oerrors or ic_ierrors counters. Details on interface configuration with new world order: - A sequence of commands needed to bring up wireless DOESN"T change. - /etc/rc.conf parameters DON'T change. - List of devices that can be used to create wlan(4) interfaces is now provided by net.wlan.devices sysctl. Most drivers in this change were converted by me, except of wpi(4), that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing changes to at least 8 drivers. Thanks to Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in testing. Details here: https://wiki.freebsd.org/projects/ifnet/net80211 Still, drivers: ndis, wtap, mwl, ipw, bwn, wi, upgt, uath were not tested. Changes to mwl, ipw, bwn, wi, upgt are trivial and chances of problems are low. The wtap wasn't compilable even before this change. But the ndis driver is complex, and it is likely to be broken with this commit. Help with testing and debugging it is appreciated. Differential Revision: D2655, D2740 Sponsored by: Nginx, Inc. Sponsored by: Netflix
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r--sys/dev/ath/if_ath.c498
1 files changed, 182 insertions, 316 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 2c935a2b..f40f4fa 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(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 @@ ath_fetch_mac_kenv(struct ath_softc *sc, uint8_t *macaddr)
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 @@ 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", 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_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;
@@ -1208,11 +1182,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, 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 @@ 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, 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 @@ 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;
}
@@ -1339,10 +1306,6 @@ 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:
@@ -1367,14 +1330,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(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_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;
}
@@ -1473,7 +1432,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_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 @@ 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, 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_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);
+ ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status,
+ mac);
return vap;
bad2:
reclaim_address(sc, mac);
@@ -1731,8 +1690,7 @@ static void
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_vap_delete(struct ieee80211vap *vap)
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 @@ ath_vap_delete(struct ieee80211vap *vap)
#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 @@ ath_vap_delete(struct ieee80211vap *vap)
void
ath_suspend(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
- DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
- __func__, ifp->if_flags);
-
- 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 @@ ath_suspend(struct ath_softc *sc)
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 @@ ath_update_chainmasks(struct ath_softc *sc, struct ieee80211_channel *chan)
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 @@ 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(ifp);
+ ath_stop(sc);
/* NB: no point powering down chip as we're about to reboot */
}
@@ -2031,7 +1979,6 @@ 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;
@@ -2070,12 +2017,11 @@ ath_intr(void *arg)
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 @@ 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;
@@ -2334,13 +2279,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(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
@@ -2361,8 +2306,6 @@ 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 */
@@ -2420,7 +2363,6 @@ 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);
@@ -2438,12 +2380,12 @@ ath_bmiss_proc(void *arg, int pending)
* 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 */
@@ -2463,8 +2405,7 @@ ath_bmiss_proc(void *arg, int pending)
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) {
@@ -2478,11 +2419,9 @@ ath_settkipmic(struct ath_softc *sc)
}
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;
@@ -2501,7 +2440,7 @@ ath_init(void *arg)
* 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
@@ -2627,7 +2566,7 @@ ath_init(void *arg)
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);
@@ -2643,14 +2582,10 @@ ath_init(void *arg)
}
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);
/*
@@ -2658,7 +2593,7 @@ ath_stop_locked(struct ifnet *ifp)
*/
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
@@ -2680,7 +2615,7 @@ ath_stop_locked(struct ifnet *ifp)
#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);
@@ -2832,12 +2767,11 @@ ath_reset_grablock(struct ath_softc *sc, int dowait)
*/
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);
}
@@ -2849,10 +2783,9 @@ ath_stop(struct ifnet *ifp)
* 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;
@@ -3014,15 +2947,6 @@ ath_reset(struct ifnet *ifp, 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);
@@ -3044,8 +2968,7 @@ static int
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) {
@@ -3060,7 +2983,7 @@ ath_reset_vap(struct ieee80211vap *vap, u_long cmd)
return 0;
}
/* XXX? Full or NOLOSS? */
- return ath_reset(ifp, ATH_RESET_FULL);
+ return ath_reset(sc, ATH_RESET_FULL);
}
struct ath_buf *
@@ -3220,24 +3143,12 @@ 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.
*
@@ -3245,10 +3156,9 @@ ath_qflush(struct ifnet *ifp)
* 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;
@@ -3263,10 +3173,7 @@ ath_transmit(struct ifnet *ifp, 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? */
}
@@ -3306,8 +3213,6 @@ ath_transmit(struct ifnet *ifp, 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;
}
@@ -3331,8 +3236,6 @@ ath_transmit(struct ifnet *ifp, 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;
}
@@ -3360,11 +3263,6 @@ ath_transmit(struct ifnet *ifp, 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;
}
@@ -3386,8 +3284,13 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
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;
}
@@ -3429,12 +3332,6 @@ ath_transmit(struct ifnet *ifp, 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.
@@ -3454,7 +3351,7 @@ nextfrag:
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;
@@ -3538,8 +3435,7 @@ ath_media_change(struct ifnet *ifp)
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);
@@ -3548,8 +3444,7 @@ ath_key_update_begin(struct ieee80211vap *vap)
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);
@@ -3580,32 +3475,41 @@ ath_update_promisc(struct ieee80211com *ic)
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;
@@ -3638,7 +3542,7 @@ ath_update_mcast(struct ieee80211com *ic)
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;
@@ -3649,15 +3553,8 @@ 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, IF_LLADDR(ifp));
+ ath_hal_setmac(ah, ic->ic_macaddr);
/* calculate and install multicast filter */
ath_update_mcast_hw(sc);
@@ -3669,7 +3566,7 @@ ath_mode_init(struct ath_softc *sc)
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;
@@ -3753,12 +3650,11 @@ 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(ifp, ATH_RESET_NOLOSS);
+ ath_reset(sc, ATH_RESET_NOLOSS);
}
/*
@@ -3768,7 +3664,6 @@ 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)
@@ -3786,7 +3681,7 @@ ath_bstuck_proc(void *arg, int pending)
* 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
@@ -4156,7 +4051,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_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;
@@ -4183,7 +4078,7 @@ static void
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));
@@ -4198,7 +4093,7 @@ static void
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));
@@ -4210,7 +4105,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_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
*rssi = ic->ic_node_getrssi(ni);
@@ -4348,8 +4243,7 @@ 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 ifnet *ifp = sc->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;
@@ -4422,7 +4316,7 @@ ath_txq_update(struct ath_softc *sc, int ac)
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) ||
@@ -4473,8 +4367,7 @@ 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 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) {
@@ -4829,7 +4722,6 @@ 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);
@@ -4850,9 +4742,6 @@ 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)
@@ -4877,7 +4766,6 @@ 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;
@@ -4911,9 +4799,6 @@ 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)
@@ -4937,7 +4822,6 @@ 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;
@@ -4963,10 +4847,6 @@ 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)
@@ -5277,7 +5157,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_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int status = 0;
/*
@@ -5422,9 +5302,8 @@ void
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);
@@ -5476,15 +5355,12 @@ 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(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;
}
@@ -5515,8 +5391,7 @@ 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 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;
@@ -5651,9 +5526,6 @@ 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? */
@@ -5669,8 +5541,7 @@ ath_calibrate(void *arg)
{
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;
@@ -5796,12 +5667,12 @@ restart:
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;
@@ -5811,18 +5682,17 @@ ath_scan_start(struct ieee80211com *ic)
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;
@@ -5862,8 +5732,7 @@ ath_scan_end(struct ieee80211com *ic)
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);
@@ -5873,8 +5742,7 @@ ath_update_chw(struct ieee80211com *ic)
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);
@@ -5916,7 +5784,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_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;
@@ -6252,7 +6120,7 @@ static void
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 */
@@ -6285,7 +6153,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_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);
@@ -6337,7 +6205,7 @@ static int
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;
@@ -6361,7 +6229,7 @@ static void
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",
@@ -6376,8 +6244,7 @@ ath_getradiocaps(struct ieee80211com *ic,
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;
@@ -6539,12 +6406,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);
@@ -6556,7 +6423,7 @@ ath_watchdog(void *arg)
} 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);
@@ -6582,7 +6449,7 @@ static int
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;
@@ -6688,31 +6555,23 @@ bad:
}
#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
@@ -6722,26 +6581,40 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
* 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
@@ -6755,10 +6628,13 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t 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:
+ case SIOCZATHSTATS: {
+ int error;
+
error = priv_check(curthread, PRIV_DRIVER);
if (error == 0) {
memset(&sc->sc_stats, 0, sizeof(sc->sc_stats));
@@ -6767,30 +6643,21 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
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
}
/*
@@ -6831,8 +6698,7 @@ static void
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,
@@ -6864,7 +6730,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_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 */
@@ -6931,7 +6797,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_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;
@@ -7136,7 +7002,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_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
int tid;
/* Just paranoia */
OpenPOWER on IntegriCloud