summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/wlan/if_urtw.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/wlan/if_urtw.c')
-rw-r--r--sys/dev/usb/wlan/if_urtw.c338
1 files changed, 211 insertions, 127 deletions
diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c
index f0d2674..f8b77d4 100644
--- a/sys/dev/usb/wlan/if_urtw.c
+++ b/sys/dev/usb/wlan/if_urtw.c
@@ -651,11 +651,11 @@ static struct ieee80211vap *urtw_vap_create(struct ieee80211com *,
int, const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void urtw_vap_delete(struct ieee80211vap *);
-static void urtw_init(struct urtw_softc *);
-static void urtw_stop(struct urtw_softc *);
-static void urtw_parent(struct ieee80211com *);
-static int urtw_transmit(struct ieee80211com *, struct mbuf *);
-static void urtw_start(struct urtw_softc *);
+static void urtw_init(void *);
+static void urtw_stop(struct ifnet *);
+static void urtw_stop_locked(struct ifnet *);
+static int urtw_ioctl(struct ifnet *, u_long, caddr_t);
+static void urtw_start(struct ifnet *);
static int urtw_alloc_rx_data_list(struct urtw_softc *);
static int urtw_alloc_tx_data_list(struct urtw_softc *);
static int urtw_raw_xmit(struct ieee80211_node *, struct mbuf *,
@@ -784,7 +784,8 @@ urtw_attach(device_t dev)
int ret = ENXIO;
struct urtw_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 = URTW_IFACE_INDEX; /* XXX */
uint16_t n_setup;
uint32_t data;
@@ -806,7 +807,6 @@ urtw_attach(device_t dev)
TASK_INIT(&sc->sc_led_task, 0, urtw_ledtask, sc);
TASK_INIT(&sc->sc_updateslot_task, 0, urtw_updateslottask, sc);
callout_init(&sc->sc_watchdog_ch, 0);
- mbufq_init(&sc->sc_snd, ifqmaxlen);
if (sc->sc_flags & URTW_RTL8187B) {
setup_start = urtw_8187b_usbconfig;
@@ -861,6 +861,26 @@ urtw_attach(device_t dev)
sc->sc_currate = 3;
sc->sc_preamble_mode = urtw_preamble_mode;
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(sc->sc_dev, "can not allocate ifnet\n");
+ ret = ENOMEM;
+ goto fail1;
+ }
+
+ ifp->if_softc = sc;
+ if_initname(ifp, "urtw", device_get_unit(sc->sc_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = urtw_init;
+ ifp->if_ioctl = urtw_ioctl;
+ ifp->if_start = urtw_start;
+ /* XXX URTW_TX_DATA_LIST_COUNT */
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ic = ifp->if_l2com;
+ ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -881,7 +901,7 @@ urtw_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->sc_bssid);
ic->ic_raw_xmit = urtw_raw_xmit;
ic->ic_scan_start = urtw_scan_start;
ic->ic_scan_end = urtw_scan_end;
@@ -890,8 +910,6 @@ urtw_attach(device_t dev)
ic->ic_vap_create = urtw_vap_create;
ic->ic_vap_delete = urtw_vap_delete;
ic->ic_update_mcast = urtw_update_mcast;
- ic->ic_parent = urtw_parent;
- ic->ic_transmit = urtw_transmit;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -905,9 +923,8 @@ urtw_attach(device_t dev)
ieee80211_announce(ic);
return (0);
-fail:
- URTW_UNLOCK(sc);
- usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
+fail: URTW_UNLOCK(sc);
+fail1: usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
fail0:
return (ret);
@@ -917,16 +934,18 @@ static int
urtw_detach(device_t dev)
{
struct urtw_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;
unsigned int n_xfers;
/* Prevent further ioctls */
URTW_LOCK(sc);
sc->sc_flags |= URTW_DETACHED;
- urtw_stop(sc);
URTW_UNLOCK(sc);
+ urtw_stop(ifp);
+
ieee80211_draintask(ic, &sc->sc_updateslot_task);
ieee80211_draintask(ic, &sc->sc_led_task);
@@ -960,7 +979,7 @@ urtw_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, n_xfers);
ieee80211_ifdetach(ic);
- mbufq_drain(&sc->sc_snd);
+ if_free(ifp);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@@ -1013,12 +1032,15 @@ urtw_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 urtw_vap), M_80211_VAP, M_WAITOK | M_ZERO);
+ uvp = (struct urtw_vap *) malloc(sizeof(struct urtw_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);
@@ -1030,7 +1052,7 @@ urtw_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);
}
@@ -1045,15 +1067,15 @@ urtw_vap_delete(struct ieee80211vap *vap)
}
static void
-urtw_init(struct urtw_softc *sc)
+urtw_init_locked(void *arg)
{
- usb_error_t error;
int ret;
+ struct urtw_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
+ usb_error_t error;
- URTW_ASSERT_LOCKED(sc);
-
- if (sc->sc_flags & URTW_RUNNING)
- urtw_stop(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ urtw_stop_locked(ifp);
error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) :
urtw_adapter_start(sc);
@@ -1083,13 +1105,24 @@ urtw_init(struct urtw_softc *sc)
if (sc->sc_flags & URTW_RTL8187B)
usbd_transfer_start(sc->sc_xfer[URTW_8187B_BULK_TX_STATUS]);
- sc->sc_flags |= URTW_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
fail:
return;
}
+static void
+urtw_init(void *arg)
+{
+ struct urtw_softc *sc = arg;
+
+ URTW_LOCK(sc);
+ urtw_init_locked(arg);
+ URTW_UNLOCK(sc);
+}
+
static usb_error_t
urtw_adapter_start_b(struct urtw_softc *sc)
{
@@ -1182,7 +1215,6 @@ fail:
static usb_error_t
urtw_adapter_start(struct urtw_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
usb_error_t error;
error = urtw_reset(sc);
@@ -1202,8 +1234,8 @@ urtw_adapter_start(struct urtw_softc *sc)
if (error)
goto fail;
/* applying MAC address again. */
- urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
- urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
+ urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]);
+ urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff);
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
goto fail;
@@ -1306,14 +1338,13 @@ urtw_do_request(struct urtw_softc *sc,
}
static void
-urtw_stop(struct urtw_softc *sc)
+urtw_stop_locked(struct ifnet *ifp)
{
+ struct urtw_softc *sc = ifp->if_softc;
uint8_t data8;
usb_error_t error;
- URTW_ASSERT_LOCKED(sc);
-
- sc->sc_flags &= ~URTW_RUNNING;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
error = urtw_intr_disable(sc);
if (error)
@@ -1346,6 +1377,16 @@ fail:
}
static void
+urtw_stop(struct ifnet *ifp)
+{
+ struct urtw_softc *sc = ifp->if_softc;
+
+ URTW_LOCK(sc);
+ urtw_stop_locked(ifp);
+ URTW_UNLOCK(sc);
+}
+
+static void
urtw_abort_xfers(struct urtw_softc *sc)
{
int i, max;
@@ -1360,71 +1401,72 @@ urtw_abort_xfers(struct urtw_softc *sc)
usbd_transfer_stop(sc->sc_xfer[i]);
}
-static void
-urtw_parent(struct ieee80211com *ic)
+static int
+urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct urtw_softc *sc = ic->ic_softc;
+ struct urtw_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error;
int startall = 0;
URTW_LOCK(sc);
- if (sc->sc_flags & URTW_DETACHED) {
- URTW_UNLOCK(sc);
- return;
- }
+ error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0;
+ URTW_UNLOCK(sc);
+ if (error)
+ return (error);
- if (ic->ic_nrunning > 0) {
- if (sc->sc_flags & URTW_RUNNING) {
- if (ic->ic_promisc > 0 || ic->ic_allmulti > 0)
- urtw_set_multi(sc);
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if ((ifp->if_flags ^ sc->sc_if_flags) &
+ (IFF_ALLMULTI | IFF_PROMISC))
+ urtw_set_multi(sc);
+ } else {
+ urtw_init(ifp->if_softc);
+ startall = 1;
+ }
} else {
- urtw_init(sc);
- startall = 1;
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ urtw_stop(ifp);
}
- } else if (sc->sc_flags & URTW_RUNNING)
- urtw_stop(sc);
- URTW_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
-}
-
-static int
-urtw_transmit(struct ieee80211com *ic, struct mbuf *m)
-{
- struct urtw_softc *sc = ic->ic_softc;
- int error;
-
- URTW_LOCK(sc);
- if ((sc->sc_flags & URTW_RUNNING) == 0) {
- URTW_UNLOCK(sc);
- return (ENXIO);
- }
- error = mbufq_enqueue(&sc->sc_snd, m);
- if (error) {
- URTW_UNLOCK(sc);
- return (error);
+ sc->sc_if_flags = ifp->if_flags;
+ if (startall)
+ ieee80211_start_all(ic);
+ break;
+ case SIOCGIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
+ break;
+ case SIOCGIFADDR:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
+ default:
+ error = EINVAL;
+ break;
}
- urtw_start(sc);
- URTW_UNLOCK(sc);
-
- return (0);
+ return (error);
}
static void
-urtw_start(struct urtw_softc *sc)
+urtw_start(struct ifnet *ifp)
{
struct urtw_data *bf;
+ struct urtw_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
- URTW_ASSERT_LOCKED(sc);
-
- if ((sc->sc_flags & URTW_RUNNING) == 0)
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
- while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ URTW_LOCK(sc);
+ for (;;) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
bf = urtw_getbuf(sc);
if (bf == NULL) {
- mbufq_prepend(&sc->sc_snd, m);
+ IFQ_DRV_PREPEND(&ifp->if_snd, m);
break;
}
@@ -1432,8 +1474,7 @@ urtw_start(struct urtw_softc *sc)
m->m_pkthdr.rcvif = NULL;
if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_NORMAL) != 0) {
- if_inc_counter(ni->ni_vap->iv_ifp,
- IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
ieee80211_free_node(ni);
break;
@@ -1442,6 +1483,7 @@ urtw_start(struct urtw_softc *sc)
sc->sc_txtimer = 5;
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
}
+ URTW_UNLOCK(sc);
}
static int
@@ -1523,11 +1565,12 @@ urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct urtw_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
struct urtw_data *bf;
+ struct urtw_softc *sc = ifp->if_softc;
/* prevent management frames from being sent if we're not ready */
- if (!(sc->sc_flags & URTW_RUNNING)) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
@@ -1541,8 +1584,10 @@ urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return (ENOBUFS); /* XXX */
}
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_LOW) != 0) {
ieee80211_free_node(ni);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
URTW_UNLOCK(sc);
return (EIO);
@@ -1570,7 +1615,8 @@ urtw_scan_end(struct ieee80211com *ic)
static void
urtw_set_channel(struct ieee80211com *ic)
{
- struct urtw_softc *sc = ic->ic_softc;
+ struct urtw_softc *sc = ic->ic_ifp->if_softc;
+ struct ifnet *ifp = sc->sc_ifp;
uint32_t data, orig;
usb_error_t error;
@@ -1580,7 +1626,7 @@ urtw_set_channel(struct ieee80211com *ic)
* initialization would be failed if setting a channel is called before
* the init have done.
*/
- if (!(sc->sc_flags & URTW_RUNNING))
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
return;
if (sc->sc_curchan != NULL && sc->sc_curchan == ic->ic_curchan)
@@ -1627,10 +1673,11 @@ static int
urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0,
struct urtw_data *data, int prior)
{
+ struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *);
struct ieee80211_key *k;
const struct ieee80211_txparam *tp;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = ni->ni_vap;
struct usb_xfer *rtl8187b_pipes[URTW_8187B_TXPIPE_MAX] = {
sc->sc_xfer[URTW_8187B_BULK_TX_BE],
@@ -1815,7 +1862,7 @@ static int
urtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct urtw_softc *sc = ic->ic_softc;
+ struct urtw_softc *sc = ic->ic_ifp->if_softc;
struct urtw_vap *uvp = URTW_VAP(vap);
struct ieee80211_node *ni;
usb_error_t error = 0;
@@ -1868,11 +1915,12 @@ static void
urtw_watchdog(void *arg)
{
struct urtw_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
if (sc->sc_txtimer > 0) {
if (--sc->sc_txtimer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
- counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
@@ -1882,7 +1930,17 @@ urtw_watchdog(void *arg)
static void
urtw_set_multi(void *arg)
{
- /* XXX don't know how to set a device. Lack of docs. */
+ struct urtw_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
+
+ if (!(ifp->if_flags & IFF_UP))
+ return;
+
+ /*
+ * XXX don't know how to set a device. Lack of docs. Just try to set
+ * IFF_ALLMULTI flag here.
+ */
+ ifp->if_flags |= IFF_ALLMULTI;
}
static usb_error_t
@@ -1944,7 +2002,8 @@ urtw_rtl2rate(uint32_t rate)
static usb_error_t
urtw_update_msr(struct urtw_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint8_t data;
usb_error_t error;
@@ -2085,25 +2144,24 @@ urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data)
static usb_error_t
urtw_get_macaddr(struct urtw_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
uint32_t data;
usb_error_t error;
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data);
if (error != 0)
goto fail;
- ic->ic_macaddr[0] = data & 0xff;
- ic->ic_macaddr[1] = (data & 0xff00) >> 8;
+ sc->sc_bssid[0] = data & 0xff;
+ sc->sc_bssid[1] = (data & 0xff00) >> 8;
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data);
if (error != 0)
goto fail;
- ic->ic_macaddr[2] = data & 0xff;
- ic->ic_macaddr[3] = (data & 0xff00) >> 8;
+ sc->sc_bssid[2] = data & 0xff;
+ sc->sc_bssid[3] = (data & 0xff00) >> 8;
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data);
if (error != 0)
goto fail;
- ic->ic_macaddr[4] = data & 0xff;
- ic->ic_macaddr[5] = (data & 0xff00) >> 8;
+ sc->sc_bssid[4] = data & 0xff;
+ sc->sc_bssid[5] = (data & 0xff00) >> 8;
fail:
return (error);
}
@@ -3175,7 +3233,7 @@ fail:
static usb_error_t
urtw_8225v2b_rf_init(struct urtw_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+#define N(a) ((int)(sizeof(a) / sizeof((a)[0])))
int i;
uint8_t data8;
usb_error_t error;
@@ -3223,8 +3281,8 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
urtw_write8_m(sc, URTW_CONFIG1, data8);
/* applying MAC address again. */
- urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
- urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
+ urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]);
+ urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff);
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
@@ -3235,7 +3293,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
/*
* MAC configuration
*/
- for (i = 0; i < nitems(urtw_8225v2b_rf_part1); i++)
+ for (i = 0; i < N(urtw_8225v2b_rf_part1); i++)
urtw_write8_m(sc, urtw_8225v2b_rf_part1[i].reg,
urtw_8225v2b_rf_part1[i].val);
urtw_write16_m(sc, URTW_TID_AC_MAP, 0xfa50);
@@ -3268,7 +3326,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1fff);
usb_pause_mtx(&sc->sc_mtx, 1100);
- for (i = 0; i < nitems(urtw_8225v2b_rf_part0); i++) {
+ for (i = 0; i < N(urtw_8225v2b_rf_part0); i++) {
urtw_8225_write(sc, urtw_8225v2b_rf_part0[i].reg,
urtw_8225v2b_rf_part0[i].val);
usb_pause_mtx(&sc->sc_mtx, 1);
@@ -3314,7 +3372,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
}
urtw_8187_write_phy_ofdm(sc, 0x80, 0x10);
- for (i = 0; i < nitems(urtw_8225v2b_rf_part2); i++)
+ for (i = 0; i < N(urtw_8225v2b_rf_part2); i++)
urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val);
urtw_write32_m(sc, URTW_8187B_AC_VO, (7 << 12) | (3 << 8) | 0x1c);
@@ -3729,7 +3787,8 @@ static void
urtw_led_ch(void *arg)
{
struct urtw_softc *sc = arg;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
ieee80211_runtask(ic, &sc->sc_led_task);
}
@@ -3876,7 +3935,8 @@ fail:
static usb_error_t
urtw_rx_setconf(struct urtw_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint32_t data;
usb_error_t error;
@@ -3901,7 +3961,7 @@ urtw_rx_setconf(struct urtw_softc *sc)
data = data | URTW_RX_FILTER_CRCERR;
if (ic->ic_opmode == IEEE80211_M_MONITOR ||
- ic->ic_promisc > 0 || ic->ic_allmulti > 0) {
+ (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
data = data | URTW_RX_FILTER_ALLMAC;
} else {
data = data | URTW_RX_FILTER_NICMAC;
@@ -3928,13 +3988,14 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
struct ieee80211_frame *wh;
struct mbuf *m, *mnew;
struct urtw_softc *sc = data->sc;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint8_t noise = 0, rate;
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
if (actlen < (int)URTW_MIN_RXBUFSZ) {
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return (NULL);
}
@@ -3945,7 +4006,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
(actlen - (sizeof(struct urtw_8187b_rxhdr))));
flen = le32toh(rx->flag) & 0xfff;
if (flen > actlen) {
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return (NULL);
}
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
@@ -3959,7 +4020,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
(actlen - (sizeof(struct urtw_8187l_rxhdr))));
flen = le32toh(rx->flag) & 0xfff;
if (flen > actlen) {
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return (NULL);
}
@@ -3971,7 +4032,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return (NULL);
}
@@ -3980,6 +4041,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
data->buf = mtod(mnew, uint8_t *);
/* finalize mbuf */
+ m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = flen - IEEE80211_CRC_LEN;
if (ieee80211_radiotap_active(ic)) {
@@ -4005,7 +4067,8 @@ static void
urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_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;
@@ -4066,7 +4129,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;
@@ -4080,7 +4143,7 @@ static void
urtw_txstatus_eof(struct usb_xfer *xfer)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
int actlen, type, pktretry, seq;
uint64_t val;
@@ -4095,7 +4158,7 @@ urtw_txstatus_eof(struct usb_xfer *xfer)
pktretry = val & 0xff;
seq = (val >> 16) & 0xff;
if (pktretry == URTW_TX_MAXRETRY)
- counter_u64_add(ic->ic_oerrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
DPRINTF(sc, URTW_DEBUG_TXSTATUS, "pktretry %d seq %#x\n",
pktretry, seq);
}
@@ -4105,7 +4168,7 @@ static void
urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0);
URTW_ASSERT_LOCKED(sc);
@@ -4123,7 +4186,7 @@ setup:
default:
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;
@@ -4134,22 +4197,38 @@ static void
urtw_txeof(struct usb_xfer *xfer, struct urtw_data *data)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct mbuf *m;
URTW_ASSERT_LOCKED(sc);
+ /*
+ * Do any tx complete callback. Note this must be done before releasing
+ * the node reference.
+ */
if (data->m) {
- /* XXX status? */
- ieee80211_tx_complete(data->ni, data->m, 0);
+ m = data->m;
+ if (m->m_flags & M_TXCB) {
+ /* XXX status? */
+ ieee80211_process_callback(data->ni, m, 0);
+ }
+ m_freem(m);
data->m = NULL;
+ }
+ if (data->ni) {
+ ieee80211_free_node(data->ni);
data->ni = NULL;
}
sc->sc_txtimer = 0;
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
urtw_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
struct urtw_data *data;
URTW_ASSERT_LOCKED(sc);
@@ -4177,17 +4256,18 @@ setup:
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
- urtw_start(sc);
+ URTW_UNLOCK(sc);
+ urtw_start(ifp);
+ URTW_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);
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);
@@ -4221,8 +4301,12 @@ urtw_getbuf(struct urtw_softc *sc)
URTW_ASSERT_LOCKED(sc);
bf = _urtw_getbuf(sc);
- if (bf == NULL)
+ if (bf == NULL) {
+ struct ifnet *ifp = sc->sc_ifp;
+
DPRINTF(sc, URTW_DEBUG_XMIT, "%s: stop queue\n", __func__);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ }
return (bf);
}
@@ -4294,14 +4378,14 @@ static void
urtw_updateslottask(void *arg, int pending)
{
struct urtw_softc *sc = arg;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
int error;
- URTW_LOCK(sc);
- if ((sc->sc_flags & URTW_RUNNING) == 0) {
- URTW_UNLOCK(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
- }
+
+ URTW_LOCK(sc);
if (sc->sc_flags & URTW_RTL8187B) {
urtw_write8_m(sc, URTW_SIFS, 0x22);
if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan))
OpenPOWER on IntegriCloud