summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/wlan/if_uath.c
diff options
context:
space:
mode:
authorbapt <bapt@FreeBSD.org>2015-08-09 00:15:17 +0000
committerbapt <bapt@FreeBSD.org>2015-08-09 00:15:17 +0000
commit2c81d1658920f732f451e9edffa48cf9b90607b1 (patch)
tree20549ce39ea8b5a45adaa22dbf88f3cba90d926d /sys/dev/usb/wlan/if_uath.c
parentee75e8628c34502fa04b16cab8adb0a4ab24a2fc (diff)
parent9e0d1c3e199cfcd8480d2e892da387ebb1bbde8b (diff)
downloadFreeBSD-src-2c81d1658920f732f451e9edffa48cf9b90607b1.zip
FreeBSD-src-2c81d1658920f732f451e9edffa48cf9b90607b1.tar.gz
Merge from HEAD
Diffstat (limited to 'sys/dev/usb/wlan/if_uath.c')
-rw-r--r--sys/dev/usb/wlan/if_uath.c308
1 files changed, 196 insertions, 112 deletions
diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c
index 04e09204..fca9e39 100644
--- a/sys/dev/usb/wlan/if_uath.c
+++ b/sys/dev/usb/wlan/if_uath.c
@@ -279,11 +279,12 @@ static int uath_alloc_rx_data_list(struct uath_softc *);
static int uath_alloc_tx_data_list(struct uath_softc *);
static void uath_free_rx_data_list(struct uath_softc *);
static void uath_free_tx_data_list(struct uath_softc *);
-static int uath_init(struct uath_softc *);
-static void uath_stop(struct uath_softc *);
-static void uath_parent(struct ieee80211com *);
-static int uath_transmit(struct ieee80211com *, struct mbuf *);
-static void uath_start(struct uath_softc *);
+static int uath_init_locked(void *);
+static void uath_init(void *);
+static void uath_stop_locked(struct ifnet *);
+static void uath_stop(struct ifnet *);
+static int uath_ioctl(struct ifnet *, u_long, caddr_t);
+static void uath_start(struct ifnet *);
static int uath_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void uath_scan_start(struct ieee80211com *);
@@ -335,9 +336,11 @@ uath_attach(device_t dev)
{
struct uath_softc *sc = device_get_softc(dev);
struct usb_attach_arg *uaa = device_get_ivars(dev);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic;
+ struct ifnet *ifp;
uint8_t bands, iface_index = UATH_IFACE_INDEX; /* XXX */
usb_error_t error;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
sc->sc_udev = uaa->device;
@@ -353,7 +356,6 @@ uath_attach(device_t dev)
MTX_DEF);
callout_init(&sc->stat_ch, 0);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
- mbufq_init(&sc->sc_snd, ifqmaxlen);
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
@@ -385,24 +387,31 @@ uath_attach(device_t dev)
error = uath_host_available(sc);
if (error != 0) {
device_printf(sc->sc_dev, "could not initialize adapter\n");
- goto fail2;
+ goto fail3;
}
error = uath_get_devcap(sc);
if (error != 0) {
device_printf(sc->sc_dev,
"could not get device capabilities\n");
- goto fail2;
+ goto fail3;
}
UATH_UNLOCK(sc);
/* Create device sysctl node. */
uath_sysctl_node(sc);
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(sc->sc_dev, "can not allocate ifnet\n");
+ error = ENXIO;
+ goto fail2;
+ }
+
UATH_LOCK(sc);
- error = uath_get_devstatus(sc, ic->ic_macaddr);
+ error = uath_get_devstatus(sc, macaddr);
if (error != 0) {
device_printf(sc->sc_dev, "could not get device status\n");
- goto fail2;
+ goto fail4;
}
/*
@@ -411,15 +420,28 @@ uath_attach(device_t dev)
error = uath_alloc_rx_data_list(sc);
if (error != 0) {
device_printf(sc->sc_dev, "could not allocate Rx data list\n");
- goto fail2;
+ goto fail4;
}
error = uath_alloc_tx_data_list(sc);
if (error != 0) {
device_printf(sc->sc_dev, "could not allocate Tx data list\n");
- goto fail2;
+ goto fail4;
}
UATH_UNLOCK(sc);
+ ifp->if_softc = sc;
+ if_initname(ifp, "uath", device_get_unit(sc->sc_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = uath_init;
+ ifp->if_ioctl = uath_ioctl;
+ ifp->if_start = uath_start;
+ /* XXX UATH_TX_DATA_LIST_COUNT */
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ic = ifp->if_l2com;
+ ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -447,17 +469,16 @@ uath_attach(device_t dev)
/* XXX turbo */
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, macaddr);
ic->ic_raw_xmit = uath_raw_xmit;
ic->ic_scan_start = uath_scan_start;
ic->ic_scan_end = uath_scan_end;
ic->ic_set_channel = uath_set_channel;
+
ic->ic_vap_create = uath_vap_create;
ic->ic_vap_delete = uath_vap_delete;
ic->ic_update_mcast = uath_update_mcast;
ic->ic_update_promisc = uath_update_promisc;
- ic->ic_transmit = uath_transmit;
- ic->ic_parent = uath_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -470,8 +491,9 @@ uath_attach(device_t dev)
return (0);
-fail2: UATH_UNLOCK(sc);
- uath_free_cmd_list(sc, sc->sc_cmd);
+fail4: if_free(ifp);
+fail3: UATH_UNLOCK(sc);
+fail2: uath_free_cmd_list(sc, sc->sc_cmd);
fail1: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
fail:
return (error);
@@ -481,7 +503,8 @@ static int
uath_detach(device_t dev)
{
struct uath_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
unsigned int x;
/*
@@ -502,10 +525,10 @@ uath_detach(device_t dev)
STAILQ_INIT(&sc->sc_cmd_pending);
STAILQ_INIT(&sc->sc_cmd_waiting);
STAILQ_INIT(&sc->sc_cmd_inactive);
-
- uath_stop(sc);
UATH_UNLOCK(sc);
+ uath_stop(ifp);
+
callout_drain(&sc->stat_ch);
callout_drain(&sc->watchdog_ch);
@@ -524,7 +547,7 @@ uath_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
ieee80211_ifdetach(ic);
- mbufq_drain(&sc->sc_snd);
+ if_free(ifp);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@@ -1044,12 +1067,15 @@ uath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
- uvp = malloc(sizeof(struct uath_vap), M_80211_VAP, M_WAITOK | M_ZERO);
+ uvp = (struct uath_vap *) malloc(sizeof(struct uath_vap),
+ M_80211_VAP, M_NOWAIT | M_ZERO);
+ if (uvp == NULL)
+ return (NULL);
vap = &uvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
+ flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@@ -1061,7 +1087,7 @@ uath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status, mac);
+ ieee80211_media_status);
ic->ic_opmode = opmode;
return (vap);
}
@@ -1076,17 +1102,18 @@ uath_vap_delete(struct ieee80211vap *vap)
}
static int
-uath_init(struct uath_softc *sc)
+uath_init_locked(void *arg)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct uath_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint32_t val;
int error;
UATH_ASSERT_LOCKED(sc);
- if (sc->sc_flags & UATH_FLAG_INITDONE)
- uath_stop(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ uath_stop_locked(ifp);
/* reset variables */
sc->sc_intrx_nextnum = sc->sc_msgid = 0;
@@ -1095,8 +1122,7 @@ uath_init(struct uath_softc *sc)
uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof val, 0);
/* set MAC address */
- uath_config_multi(sc, CFG_MAC_ADDR,
- vap ? vap->iv_myaddr : ic->ic_macaddr, IEEE80211_ADDR_LEN);
+ uath_config_multi(sc, CFG_MAC_ADDR, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
/* XXX honor net80211 state */
uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001);
@@ -1145,6 +1171,8 @@ uath_init(struct uath_softc *sc)
UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON,
UATH_FILTER_OP_SET);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= UATH_FLAG_INITDONE;
callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
@@ -1152,16 +1180,28 @@ uath_init(struct uath_softc *sc)
return (0);
fail:
- uath_stop(sc);
+ uath_stop_locked(ifp);
return (error);
}
static void
-uath_stop(struct uath_softc *sc)
+uath_init(void *arg)
+{
+ struct uath_softc *sc = arg;
+
+ UATH_LOCK(sc);
+ (void)uath_init_locked(sc);
+ UATH_UNLOCK(sc);
+}
+
+static void
+uath_stop_locked(struct ifnet *ifp)
{
+ struct uath_softc *sc = ifp->if_softc;
UATH_ASSERT_LOCKED(sc);
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~UATH_FLAG_INITDONE;
callout_stop(&sc->stat_ch);
@@ -1177,6 +1217,16 @@ uath_stop(struct uath_softc *sc)
uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0);
}
+static void
+uath_stop(struct ifnet *ifp)
+{
+ struct uath_softc *sc = ifp->if_softc;
+
+ UATH_LOCK(sc);
+ uath_stop_locked(ifp);
+ UATH_UNLOCK(sc);
+}
+
static int
uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val)
{
@@ -1279,13 +1329,13 @@ static void
uath_watchdog(void *arg)
{
struct uath_softc *sc = arg;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
- /*uath_init(sc); XXX needs a process context! */
- counter_u64_add(ic->ic_oerrors, 1);
+ /*uath_init(ifp); XXX needs a process context! */
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return;
}
callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
@@ -1400,8 +1450,12 @@ uath_getbuf(struct uath_softc *sc)
UATH_ASSERT_LOCKED(sc);
bf = _uath_getbuf(sc);
- if (bf == NULL)
+ if (bf == NULL) {
+ struct ifnet *ifp = sc->sc_ifp;
+
DPRINTF(sc, UATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ }
return (bf);
}
@@ -1420,7 +1474,8 @@ static int
uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
{
#ifdef UATH_DEBUG
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
#endif
struct uath_cmd_reset reset;
@@ -1499,28 +1554,47 @@ uath_wme_init(struct uath_softc *sc)
return (error);
}
-static void
-uath_parent(struct ieee80211com *ic)
+static int
+uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct uath_softc *sc = ic->ic_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ struct uath_softc *sc = ifp->if_softc;
+ int error;
int startall = 0;
UATH_LOCK(sc);
- if (sc->sc_flags & UATH_FLAG_INVALID) {
- UATH_UNLOCK(sc);
- return;
- }
+ error = (sc->sc_flags & UATH_FLAG_INVALID) ? ENXIO : 0;
+ UATH_UNLOCK(sc);
+ if (error)
+ return (error);
- if (ic->ic_nrunning > 0) {
- if (!(sc->sc_flags & UATH_FLAG_INITDONE)) {
- uath_init(sc);
- startall = 1;
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ uath_init(ifp->if_softc);
+ startall = 1;
+ }
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ uath_stop(ifp);
}
- } else if (sc->sc_flags & UATH_FLAG_INITDONE)
- uath_stop(sc);
- UATH_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
+ if (startall)
+ ieee80211_start_all(ic);
+ break;
+ case SIOCGIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
+ break;
+ case SIOCGIFADDR:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
}
static int
@@ -1689,49 +1763,31 @@ uath_freetx(struct mbuf *m)
} while ((m = next) != NULL);
}
-static int
-uath_transmit(struct ieee80211com *ic, struct mbuf *m)
-{
- struct uath_softc *sc = ic->ic_softc;
- int error;
-
- UATH_LOCK(sc);
- if ((sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
- UATH_UNLOCK(sc);
- return (ENXIO);
- }
- error = mbufq_enqueue(&sc->sc_snd, m);
- if (error) {
- UATH_UNLOCK(sc);
- return (error);
- }
- uath_start(sc);
- UATH_UNLOCK(sc);
-
- return (0);
-}
-
static void
-uath_start(struct uath_softc *sc)
+uath_start(struct ifnet *ifp)
{
struct uath_data *bf;
+ struct uath_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m, *next;
uath_datahead frags;
- UATH_ASSERT_LOCKED(sc);
-
- if ((sc->sc_flags & UATH_FLAG_INITDONE) == 0 ||
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
(sc->sc_flags & UATH_FLAG_INVALID))
return;
- while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ UATH_LOCK(sc);
+ for (;;) {
bf = uath_getbuf(sc);
- if (bf == NULL) {
- mbufq_prepend(&sc->sc_snd, m);
+ if (bf == NULL)
break;
- }
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL) {
+ STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
+ UATH_STAT_INC(sc, st_tx_inactive);
+ break;
+ }
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
@@ -1760,8 +1816,7 @@ uath_start(struct uath_softc *sc)
next = m->m_nextpkt;
if (uath_tx_start(sc, m, ni, bf) != 0) {
bad:
- if_inc_counter(ni->ni_vap->iv_ifp,
- IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
reclaim:
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
UATH_STAT_INC(sc, st_tx_inactive);
@@ -1792,6 +1847,7 @@ uath_start(struct uath_softc *sc)
sc->sc_tx_timer = 5;
}
+ UATH_UNLOCK(sc);
}
static int
@@ -1799,19 +1855,19 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
+ struct ifnet *ifp = ic->ic_ifp;
struct uath_data *bf;
- struct uath_softc *sc = ic->ic_softc;
+ struct uath_softc *sc = ifp->if_softc;
- UATH_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
- !(sc->sc_flags & UATH_FLAG_INITDONE)) {
+ !(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
m_freem(m);
ieee80211_free_node(ni);
- UATH_UNLOCK(sc);
return (ENETDOWN);
}
+ UATH_LOCK(sc);
/* grab a TX buffer */
bf = uath_getbuf(sc);
if (bf == NULL) {
@@ -1824,6 +1880,7 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
sc->sc_seqnum = 0;
if (uath_tx_start(sc, m, ni, bf) != 0) {
ieee80211_free_node(ni);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
UATH_STAT_INC(sc, st_tx_inactive);
UATH_UNLOCK(sc);
@@ -1850,11 +1907,12 @@ uath_scan_end(struct ieee80211com *ic)
static void
uath_set_channel(struct ieee80211com *ic)
{
- struct uath_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct uath_softc *sc = ifp->if_softc;
UATH_LOCK(sc);
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
- (sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
UATH_UNLOCK(sc);
return;
}
@@ -1875,7 +1933,7 @@ uath_update_mcast(struct ieee80211com *ic)
UATH_LOCK(sc);
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
- (sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
+ (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
UATH_UNLOCK(sc);
return;
}
@@ -1895,7 +1953,7 @@ uath_update_promisc(struct ieee80211com *ic)
UATH_LOCK(sc);
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
- (sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
+ (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
UATH_UNLOCK(sc);
return;
}
@@ -1912,7 +1970,7 @@ static int
uath_create_connection(struct uath_softc *sc, uint32_t connid)
{
const struct ieee80211_rateset *rs;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct uath_cmd_create_connection create;
@@ -1963,7 +2021,7 @@ uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
static int
uath_write_associd(struct uath_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct uath_cmd_set_associd associd;
@@ -2017,7 +2075,7 @@ uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
int error;
struct ieee80211_node *ni;
struct ieee80211com *ic = vap->iv_ic;
- struct uath_softc *sc = ic->ic_softc;
+ struct uath_softc *sc = ic->ic_ifp->if_softc;
struct uath_vap *uvp = UATH_VAP(vap);
DPRINTF(sc, UATH_DEBUG_STATE,
@@ -2484,7 +2542,8 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
struct uath_rx_desc **pdesc)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct uath_chunk *chunk;
struct uath_rx_desc *desc;
struct mbuf *m = data->m, *mnew, *mp;
@@ -2496,14 +2555,14 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
if (actlen < (int)UATH_MIN_RXBUFSZ) {
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
"%s: wrong xfer size (len=%d)\n", __func__, actlen);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return (NULL);
}
chunk = (struct uath_chunk *)data->buf;
if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
device_printf(sc->sc_dev, "%s: strange response\n", __func__);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
UATH_RESET_INTRX(sc);
return (NULL);
}
@@ -2536,7 +2595,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
if ((sc->sc_intrx_len + sizeof(struct uath_rx_desc) +
chunklen) > UATH_MAX_INTRX_SIZE) {
UATH_STAT_INC(sc, st_invalidlen);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
UATH_RESET_INTRX(sc);
@@ -2561,7 +2620,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
if (mnew == NULL) {
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
"%s: can't get new mbuf, drop frame\n", __func__);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
UATH_RESET_INTRX(sc);
@@ -2602,7 +2661,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
"%s: bad descriptor (len=%d)\n", __func__,
be32toh(desc->len));
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
UATH_STAT_INC(sc, st_toobigrxpkt);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
@@ -2614,11 +2673,13 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
/* finalize mbuf */
if (sc->sc_intrx_head == NULL) {
+ m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len =
be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
m->m_data += sizeof(struct uath_chunk);
} else {
mp = sc->sc_intrx_head;
+ mp->m_pkthdr.rcvif = ifp;
mp->m_flags |= M_PKTHDR;
mp->m_pkthdr.len = sc->sc_intrx_len;
m = mp;
@@ -2644,6 +2705,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
tap->wr_antnoise = -95;
}
+ if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
UATH_RESET_INTRX(sc);
return (m);
@@ -2653,7 +2715,8 @@ static void
uath_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
@@ -2713,8 +2776,10 @@ setup:
m = NULL;
desc = NULL;
}
+ if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
+ !IFQ_IS_EMPTY(&ifp->if_snd))
+ uath_start(ifp);
UATH_LOCK(sc);
- uath_start(sc);
break;
default:
/* needs it to the inactive queue due to a error. */
@@ -2727,7 +2792,7 @@ setup:
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
goto setup;
}
break;
@@ -2738,22 +2803,40 @@ static void
uath_data_txeof(struct usb_xfer *xfer, struct uath_data *data)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct mbuf *m;
UATH_ASSERT_LOCKED(sc);
+ /*
+ * Do any tx complete callback. Note this must be done before releasing
+ * the node reference.
+ */
if (data->m) {
- /* XXX status? */
- ieee80211_tx_complete(data->ni, data->m, 0);
+ m = data->m;
+ if (m->m_flags & M_TXCB &&
+ (sc->sc_flags & UATH_FLAG_INVALID) == 0) {
+ /* XXX status? */
+ ieee80211_process_callback(data->ni, m, 0);
+ }
+ m_freem(m);
data->m = NULL;
+ }
+ if (data->ni) {
+ if ((sc->sc_flags & UATH_FLAG_INVALID) == 0)
+ ieee80211_free_node(data->ni);
data->ni = NULL;
}
sc->sc_tx_timer = 0;
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
uath_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
struct uath_data *data;
UATH_ASSERT_LOCKED(sc);
@@ -2785,18 +2868,19 @@ setup:
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
- uath_start(sc);
+ UATH_UNLOCK(sc);
+ uath_start(ifp);
+ UATH_LOCK(sc);
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
if (data == NULL)
goto setup;
if (data->ni != NULL) {
- if_inc_counter(data->ni->ni_vap->iv_ifp,
- IFCOUNTER_OERRORS, 1);
if ((sc->sc_flags & UATH_FLAG_INVALID) == 0)
ieee80211_free_node(data->ni);
data->ni = NULL;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
OpenPOWER on IntegriCloud