summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/wlan/if_upgt.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/wlan/if_upgt.c')
-rw-r--r--sys/dev/usb/wlan/if_upgt.c323
1 files changed, 211 insertions, 112 deletions
diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c
index b882fe3..a2e493e 100644
--- a/sys/dev/usb/wlan/if_upgt.c
+++ b/sys/dev/usb/wlan/if_upgt.c
@@ -128,10 +128,10 @@ static void upgt_eeprom_parse_freq4(struct upgt_softc *, uint8_t *, int);
static void upgt_eeprom_parse_freq6(struct upgt_softc *, uint8_t *, int);
static uint32_t upgt_chksum_le(const uint32_t *, size_t);
static void upgt_tx_done(struct upgt_softc *, uint8_t *);
-static void upgt_init(struct upgt_softc *);
-static void upgt_parent(struct ieee80211com *);
-static int upgt_transmit(struct ieee80211com *, struct mbuf *);
-static void upgt_start(struct upgt_softc *);
+static void upgt_init(void *);
+static void upgt_init_locked(struct upgt_softc *);
+static int upgt_ioctl(struct ifnet *, u_long, caddr_t);
+static void upgt_start(struct ifnet *);
static int upgt_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void upgt_scan_start(struct ieee80211com *);
@@ -240,11 +240,12 @@ upgt_match(device_t dev)
static int
upgt_attach(device_t dev)
{
+ int error;
+ struct ieee80211com *ic;
+ struct ifnet *ifp;
struct upgt_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = &sc->sc_ic;
struct usb_attach_arg *uaa = device_get_ivars(dev);
uint8_t bands, iface_index = UPGT_IFACE_INDEX;
- int error;
sc->sc_dev = dev;
sc->sc_udev = uaa->device;
@@ -257,7 +258,6 @@ upgt_attach(device_t dev)
MTX_DEF);
callout_init(&sc->sc_led_ch, 0);
callout_init(&sc->sc_watchdog_ch, 0);
- mbufq_init(&sc->sc_snd, ifqmaxlen);
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
upgt_config, UPGT_N_XFERS, sc, &sc->sc_mtx);
@@ -280,20 +280,26 @@ upgt_attach(device_t dev)
if (error)
goto fail3;
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(dev, "can not if_alloc()\n");
+ goto fail4;
+ }
+
/* Initialize the device. */
error = upgt_device_reset(sc);
if (error)
- goto fail4;
+ goto fail5;
/* Verify the firmware. */
error = upgt_fw_verify(sc);
if (error)
- goto fail4;
+ goto fail5;
/* Calculate device memory space. */
if (sc->sc_memaddr_frame_start == 0 || sc->sc_memaddr_frame_end == 0) {
device_printf(dev,
"could not find memory space addresses on FW\n");
error = EIO;
- goto fail4;
+ goto fail5;
}
sc->sc_memaddr_frame_end -= UPGT_MEMSIZE_RX + 1;
sc->sc_memaddr_rx_start = sc->sc_memaddr_frame_end + 1;
@@ -310,19 +316,31 @@ upgt_attach(device_t dev)
/* Load the firmware. */
error = upgt_fw_load(sc);
if (error)
- goto fail4;
+ goto fail5;
/* Read the whole EEPROM content and parse it. */
error = upgt_eeprom_read(sc);
if (error)
- goto fail4;
+ goto fail5;
error = upgt_eeprom_parse(sc);
if (error)
- goto fail4;
+ goto fail5;
/* all works related with the device have done here. */
upgt_abort_xfers(sc);
+ /* Setup the 802.11 device. */
+ ifp->if_softc = sc;
+ if_initname(ifp, "upgt", device_get_unit(sc->sc_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = upgt_init;
+ ifp->if_ioctl = upgt_ioctl;
+ ifp->if_start = upgt_start;
+ IFQ_SET_MAXLEN(&ifp->if_snd, 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 */
@@ -342,16 +360,15 @@ upgt_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->sc_myaddr);
ic->ic_raw_xmit = upgt_raw_xmit;
ic->ic_scan_start = upgt_scan_start;
ic->ic_scan_end = upgt_scan_end;
ic->ic_set_channel = upgt_set_channel;
+
ic->ic_vap_create = upgt_vap_create;
ic->ic_vap_delete = upgt_vap_delete;
ic->ic_update_mcast = upgt_update_mcast;
- ic->ic_transmit = upgt_transmit;
- ic->ic_parent = upgt_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -366,6 +383,7 @@ upgt_attach(device_t dev)
return (0);
+fail5: if_free(ifp);
fail4: upgt_free_rx(sc);
fail3: upgt_free_tx(sc);
fail2: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
@@ -377,13 +395,30 @@ fail1: mtx_destroy(&sc->sc_mtx);
static void
upgt_txeof(struct usb_xfer *xfer, struct upgt_data *data)
{
+ struct upgt_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct mbuf *m;
+
+ UPGT_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;
}
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
}
static void
@@ -427,43 +462,77 @@ upgt_get_stats(struct upgt_softc *sc)
upgt_bulk_tx(sc, data_cmd);
}
-static void
-upgt_parent(struct ieee80211com *ic)
+static int
+upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct upgt_softc *sc = ic->ic_softc;
+ struct upgt_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error;
int startall = 0;
UPGT_LOCK(sc);
- if (sc->sc_flags & UPGT_FLAG_DETACHED) {
- UPGT_UNLOCK(sc);
- return;
- }
- if (ic->ic_nrunning > 0) {
- if (sc->sc_flags & UPGT_FLAG_INITDONE) {
- if (ic->ic_allmulti > 0 || ic->ic_promisc > 0)
- upgt_set_multi(sc);
+ error = (sc->sc_flags & UPGT_FLAG_DETACHED) ? ENXIO : 0;
+ UPGT_UNLOCK(sc);
+ if (error)
+ return (error);
+
+ 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))
+ upgt_set_multi(sc);
+ } else {
+ upgt_init(sc);
+ startall = 1;
+ }
} else {
- upgt_init(sc);
- startall = 1;
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ upgt_stop(sc);
}
- } else if (sc->sc_flags & UPGT_FLAG_INITDONE)
- upgt_stop(sc);
- UPGT_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
+ 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;
+ }
+ return error;
}
static void
-upgt_stop(struct upgt_softc *sc)
+upgt_stop_locked(struct upgt_softc *sc)
{
+ struct ifnet *ifp = sc->sc_ifp;
UPGT_ASSERT_LOCKED(sc);
- if (sc->sc_flags & UPGT_FLAG_INITDONE)
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
upgt_set_macfilter(sc, IEEE80211_S_INIT);
upgt_abort_xfers_locked(sc);
+}
+
+static void
+upgt_stop(struct upgt_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+
+ UPGT_LOCK(sc);
+ upgt_stop_locked(sc);
+ UPGT_UNLOCK(sc);
+
/* device down */
sc->sc_tx_timer = 0;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~UPGT_FLAG_INITDONE;
}
@@ -555,18 +624,36 @@ upgt_set_led_blink(void *arg)
}
static void
-upgt_init(struct upgt_softc *sc)
+upgt_init(void *priv)
+{
+ struct upgt_softc *sc = priv;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ UPGT_LOCK(sc);
+ upgt_init_locked(sc);
+ UPGT_UNLOCK(sc);
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ieee80211_start_all(ic); /* start all vap's */
+}
+
+static void
+upgt_init_locked(struct upgt_softc *sc)
{
+ struct ifnet *ifp = sc->sc_ifp;
UPGT_ASSERT_LOCKED(sc);
- if (sc->sc_flags & UPGT_FLAG_INITDONE)
- upgt_stop(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ upgt_stop_locked(sc);
usbd_transfer_start(sc->sc_xfer[UPGT_BULK_RX]);
(void)upgt_set_macfilter(sc, IEEE80211_S_SCAN);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= UPGT_FLAG_INITDONE;
callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc);
@@ -575,12 +662,14 @@ upgt_init(struct upgt_softc *sc)
static int
upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct upgt_data *data_cmd;
struct upgt_lmac_mem *mem;
struct upgt_lmac_filter *filter;
+ uint8_t broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
UPGT_ASSERT_LOCKED(sc);
@@ -620,11 +709,10 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
case IEEE80211_S_SCAN:
DPRINTF(sc, UPGT_DEBUG_STATE,
"set MAC filter to SCAN (bssid %s)\n",
- ether_sprintf(ieee80211broadcastaddr));
+ ether_sprintf(broadcast));
filter->type = htole16(UPGT_FILTER_TYPE_NONE);
- IEEE80211_ADDR_COPY(filter->dst,
- vap ? vap->iv_myaddr : ic->ic_macaddr);
- IEEE80211_ADDR_COPY(filter->src, ieee80211broadcastaddr);
+ IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
+ IEEE80211_ADDR_COPY(filter->src, broadcast);
filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1);
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
filter->unknown2 = htole16(UPGT_FILTER_UNKNOWN2);
@@ -636,8 +724,7 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
/* XXX monitor mode isn't tested yet. */
if (vap->iv_opmode == IEEE80211_M_MONITOR) {
filter->type = htole16(UPGT_FILTER_TYPE_MONITOR);
- IEEE80211_ADDR_COPY(filter->dst,
- vap ? vap->iv_myaddr : ic->ic_macaddr);
+ IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid);
filter->unknown1 = htole16(UPGT_FILTER_MONITOR_UNKNOWN1);
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
@@ -649,8 +736,7 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
"set MAC filter to RUN (bssid %s)\n",
ether_sprintf(ni->ni_bssid));
filter->type = htole16(UPGT_FILTER_TYPE_STA);
- IEEE80211_ADDR_COPY(filter->dst,
- vap ? vap->iv_myaddr : ic->ic_macaddr);
+ IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid);
filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1);
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
@@ -679,7 +765,8 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
static void
upgt_setup_rates(struct ieee80211vap *vap, struct ieee80211com *ic)
{
- struct upgt_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct upgt_softc *sc = ifp->if_softc;
const struct ieee80211_txparam *tp;
/*
@@ -726,48 +813,39 @@ upgt_setup_rates(struct ieee80211vap *vap, struct ieee80211com *ic)
static void
upgt_set_multi(void *arg)
{
+ struct upgt_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
- /* XXX don't know how to set a device. Lack of docs. */
-}
-
-static int
-upgt_transmit(struct ieee80211com *ic, struct mbuf *m)
-{
- struct upgt_softc *sc = ic->ic_softc;
- int error;
-
- UPGT_LOCK(sc);
- if ((sc->sc_flags & UPGT_FLAG_INITDONE) == 0) {
- UPGT_UNLOCK(sc);
- return (ENXIO);
- }
- error = mbufq_enqueue(&sc->sc_snd, m);
- if (error) {
- UPGT_UNLOCK(sc);
- return (error);
- }
- upgt_start(sc);
- UPGT_UNLOCK(sc);
+ if (!(ifp->if_flags & IFF_UP))
+ return;
- return (0);
+ /*
+ * 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 void
-upgt_start(struct upgt_softc *sc)
+upgt_start(struct ifnet *ifp)
{
+ struct upgt_softc *sc = ifp->if_softc;
struct upgt_data *data_tx;
struct ieee80211_node *ni;
struct mbuf *m;
- UPGT_ASSERT_LOCKED(sc);
-
- if ((sc->sc_flags & UPGT_FLAG_INITDONE) == 0)
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
- while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ UPGT_LOCK(sc);
+ for (;;) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+
data_tx = upgt_gettxbuf(sc);
if (data_tx == NULL) {
- mbufq_prepend(&sc->sc_snd, m);
+ IFQ_DRV_PREPEND(&ifp->if_snd, m);
break;
}
@@ -775,15 +853,15 @@ upgt_start(struct upgt_softc *sc)
m->m_pkthdr.rcvif = NULL;
if (upgt_tx_start(sc, m, ni, data_tx) != 0) {
- if_inc_counter(ni->ni_vap->iv_ifp,
- IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next);
UPGT_STAT_INC(sc, st_tx_inactive);
ieee80211_free_node(ni);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
continue;
}
sc->sc_tx_timer = 5;
}
+ UPGT_UNLOCK(sc);
}
static int
@@ -791,18 +869,18 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct upgt_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct upgt_softc *sc = ifp->if_softc;
struct upgt_data *data_tx = NULL;
- UPGT_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(sc->sc_flags & UPGT_FLAG_INITDONE)) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
m_freem(m);
ieee80211_free_node(ni);
- UPGT_UNLOCK(sc);
return ENETDOWN;
}
+ UPGT_LOCK(sc);
data_tx = upgt_gettxbuf(sc);
if (data_tx == NULL) {
ieee80211_free_node(ni);
@@ -815,6 +893,7 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next);
UPGT_STAT_INC(sc, st_tx_inactive);
ieee80211_free_node(ni);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
UPGT_UNLOCK(sc);
return (EIO);
}
@@ -828,13 +907,13 @@ static void
upgt_watchdog(void *arg)
{
struct upgt_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, "watchdog timeout\n");
- /* upgt_init(sc); XXX needs a process context ? */
- counter_u64_add(ic->ic_oerrors, 1);
+ /* upgt_init(ifp); XXX needs a process context ? */
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc);
@@ -871,7 +950,7 @@ upgt_scan_end(struct ieee80211com *ic)
static void
upgt_set_channel(struct ieee80211com *ic)
{
- struct upgt_softc *sc = ic->ic_softc;
+ struct upgt_softc *sc = ic->ic_ifp->if_softc;
UPGT_LOCK(sc);
upgt_set_chan(sc, ic->ic_curchan);
@@ -881,7 +960,8 @@ upgt_set_channel(struct ieee80211com *ic)
static void
upgt_set_chan(struct upgt_softc *sc, struct ieee80211_channel *c)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct upgt_data *data_cmd;
struct upgt_lmac_mem *mem;
struct upgt_lmac_channel *chan;
@@ -964,7 +1044,7 @@ upgt_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* 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);
@@ -979,7 +1059,7 @@ upgt_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;
}
@@ -989,7 +1069,7 @@ upgt_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct upgt_vap *uvp = UPGT_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct upgt_softc *sc = ic->ic_softc;
+ struct upgt_softc *sc = ic->ic_ifp->if_softc;
/* do it in a process context */
sc->sc_state = nstate;
@@ -1045,7 +1125,6 @@ upgt_update_mcast(struct ieee80211com *ic)
static int
upgt_eeprom_parse(struct upgt_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
struct upgt_eeprom_header *eeprom_header;
struct upgt_eeprom_option *eeprom_option;
uint16_t option_len;
@@ -1090,8 +1169,7 @@ upgt_eeprom_parse(struct upgt_softc *sc)
DPRINTF(sc, UPGT_DEBUG_FW,
"EEPROM mac len=%d\n", option_len);
- IEEE80211_ADDR_COPY(ic->ic_macaddr,
- eeprom_option->data);
+ IEEE80211_ADDR_COPY(sc->sc_myaddr, eeprom_option->data);
break;
case UPGT_EEPROM_TYPE_HWRX:
DPRINTF(sc, UPGT_DEBUG_FW,
@@ -1440,7 +1518,8 @@ upgt_chksum_le(const uint32_t *buf, size_t size)
static struct mbuf *
upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct upgt_lmac_rx_desc *rxdesc;
struct mbuf *m;
@@ -1448,7 +1527,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
* don't pass packets to the ieee80211 framework if the driver isn't
* RUNNING.
*/
- if (!(sc->sc_flags & UPGT_FLAG_INITDONE))
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
return (NULL);
/* access RX packet descriptor */
@@ -1466,6 +1545,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
memcpy(mtod(m, char *), rxdesc->data, pkglen);
/* trim FCS */
m->m_len = m->m_pkthdr.len = pkglen - IEEE80211_CRC_LEN;
+ m->m_pkthdr.rcvif = ifp;
if (ieee80211_radiotap_active(ic)) {
struct upgt_rx_radiotap_header *tap = &sc->sc_rxtap;
@@ -1474,6 +1554,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
tap->wr_rate = upgt_rx_rate(sc, rxdesc->rate);
tap->wr_antsignal = rxdesc->rssi;
}
+ if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
DPRINTF(sc, UPGT_DEBUG_RX_PROC, "%s: RX done\n", __func__);
*rssi = rxdesc->rssi;
@@ -1483,7 +1564,8 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
static uint8_t
upgt_rx_rate(struct upgt_softc *sc, const int rate)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
static const uint8_t cck_upgt2rate[4] = { 2, 4, 11, 22 };
static const uint8_t ofdm_upgt2rate[12] =
{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
@@ -1502,6 +1584,7 @@ upgt_rx_rate(struct upgt_softc *sc, const int rate)
static void
upgt_tx_done(struct upgt_softc *sc, uint8_t *data)
{
+ struct ifnet *ifp = sc->sc_ifp;
struct upgt_lmac_tx_done_desc *desc;
int i, freed = 0;
@@ -1530,9 +1613,10 @@ upgt_tx_done(struct upgt_softc *sc, uint8_t *data)
}
if (freed != 0) {
- UPGT_UNLOCK(sc);
sc->sc_tx_timer = 0;
- upgt_start(sc);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ UPGT_UNLOCK(sc);
+ upgt_start(ifp);
UPGT_LOCK(sc);
}
}
@@ -1938,7 +2022,8 @@ static int
upgt_detach(device_t dev)
{
struct upgt_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;
/*
@@ -1954,9 +2039,9 @@ upgt_detach(device_t dev)
STAILQ_INIT(&sc->sc_rx_active);
STAILQ_INIT(&sc->sc_rx_inactive);
+ UPGT_UNLOCK(sc);
upgt_stop(sc);
- UPGT_UNLOCK(sc);
callout_drain(&sc->sc_led_ch);
callout_drain(&sc->sc_watchdog_ch);
@@ -1975,7 +2060,7 @@ upgt_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
ieee80211_ifdetach(ic);
- mbufq_drain(&sc->sc_snd);
+ if_free(ifp);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -2083,8 +2168,12 @@ upgt_getbuf(struct upgt_softc *sc)
UPGT_ASSERT_LOCKED(sc);
bf = _upgt_getbuf(sc);
- if (bf == NULL)
+ if (bf == NULL) {
+ struct ifnet *ifp = sc->sc_ifp;
+
DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: stop queue\n", __func__);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ }
return (bf);
}
@@ -2102,10 +2191,14 @@ upgt_gettxbuf(struct upgt_softc *sc)
bf->addr = upgt_mem_alloc(sc);
if (bf->addr == 0) {
+ struct ifnet *ifp = sc->sc_ifp;
+
DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: no free prism memory!\n",
__func__);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
UPGT_STAT_INC(sc, st_tx_inactive);
+ if (!(ifp->if_drv_flags & IFF_DRV_OACTIVE))
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
return (NULL);
}
return (bf);
@@ -2119,6 +2212,7 @@ upgt_tx_start(struct upgt_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
int error = 0, len;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
+ struct ifnet *ifp = sc->sc_ifp;
struct upgt_lmac_mem *mem;
struct upgt_lmac_tx_desc *txdesc;
@@ -2201,7 +2295,7 @@ done:
* will stall. It's strange, but it works, so we keep reading
* the statistics here. *shrug*
*/
- if (!(vap->iv_ifp->if_get_counter(vap->iv_ifp, IFCOUNTER_OPACKETS) %
+ if (!(ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS) %
UPGT_TX_STAT_INTERVAL))
upgt_get_stats(sc);
@@ -2212,7 +2306,8 @@ static void
upgt_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct upgt_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;
@@ -2260,8 +2355,10 @@ setup:
(void) ieee80211_input_all(ic, m, rssi, nf);
m = NULL;
}
+ if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
+ !IFQ_IS_EMPTY(&ifp->if_snd))
+ upgt_start(ifp);
UPGT_LOCK(sc);
- upgt_start(sc);
break;
default:
/* needs it to the inactive queue due to a error. */
@@ -2272,7 +2369,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;
@@ -2283,6 +2380,7 @@ static void
upgt_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct upgt_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
struct upgt_data *data;
UPGT_ASSERT_LOCKED(sc);
@@ -2312,17 +2410,18 @@ setup:
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
- upgt_start(sc);
+ UPGT_UNLOCK(sc);
+ upgt_start(ifp);
+ UPGT_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);
OpenPOWER on IntegriCloud