summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/wlan
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2015-08-08 01:10:17 +0000
committeradrian <adrian@FreeBSD.org>2015-08-08 01:10:17 +0000
commitbad6d5c89b6ffd35818850d95cb88e218dee73b3 (patch)
tree5973a9059f73ed5abf84d6d98e44f1953e764064 /sys/dev/usb/wlan
parent33a3844dbf69152b9d47f6fa1ac1c2d5b1d502e4 (diff)
downloadFreeBSD-src-bad6d5c89b6ffd35818850d95cb88e218dee73b3.zip
FreeBSD-src-bad6d5c89b6ffd35818850d95cb88e218dee73b3.tar.gz
Revert the wifi ifnet changes until things are more baked and tested.
* 286410 * 286413 * 286416 The initial commit broke a variety of debug and features that aren't in the GENERIC kernels but are enabled in other platforms.
Diffstat (limited to 'sys/dev/usb/wlan')
-rw-r--r--sys/dev/usb/wlan/if_rsu.c299
-rw-r--r--sys/dev/usb/wlan/if_rsureg.h9
-rw-r--r--sys/dev/usb/wlan/if_rum.c302
-rw-r--r--sys/dev/usb/wlan/if_rumvar.h7
-rw-r--r--sys/dev/usb/wlan/if_run.c363
-rw-r--r--sys/dev/usb/wlan/if_runvar.h9
-rw-r--r--sys/dev/usb/wlan/if_uath.c308
-rw-r--r--sys/dev/usb/wlan/if_uathvar.h3
-rw-r--r--sys/dev/usb/wlan/if_upgt.c323
-rw-r--r--sys/dev/usb/wlan/if_upgtvar.h6
-rw-r--r--sys/dev/usb/wlan/if_ural.c284
-rw-r--r--sys/dev/usb/wlan/if_uralvar.h7
-rw-r--r--sys/dev/usb/wlan/if_urtw.c338
-rw-r--r--sys/dev/usb/wlan/if_urtwn.c282
-rw-r--r--sys/dev/usb/wlan/if_urtwnreg.h5
-rw-r--r--sys/dev/usb/wlan/if_urtwvar.h6
-rw-r--r--sys/dev/usb/wlan/if_zyd.c299
-rw-r--r--sys/dev/usb/wlan/if_zydreg.h5
18 files changed, 1798 insertions, 1057 deletions
diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c
index 463a9bd..89b8c00 100644
--- a/sys/dev/usb/wlan/if_rsu.c
+++ b/sys/dev/usb/wlan/if_rsu.c
@@ -187,13 +187,15 @@ static struct mbuf *
static void rsu_txeof(struct usb_xfer *, struct rsu_data *);
static int rsu_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static void rsu_init(struct rsu_softc *);
+static void rsu_init(void *);
+static void rsu_init_locked(struct rsu_softc *);
static int rsu_tx_start(struct rsu_softc *, struct ieee80211_node *,
struct mbuf *, struct rsu_data *);
-static int rsu_transmit(struct ieee80211com *, struct mbuf *);
-static void rsu_start(struct rsu_softc *);
-static void rsu_parent(struct ieee80211com *);
-static void rsu_stop(struct rsu_softc *);
+static void rsu_start(struct ifnet *);
+static void rsu_start_locked(struct ifnet *);
+static int rsu_ioctl(struct ifnet *, u_long, caddr_t);
+static void rsu_stop(struct ifnet *, int);
+static void rsu_stop_locked(struct ifnet *, int);
static void rsu_ms_delay(struct rsu_softc *);
static device_method_t rsu_methods[] = {
@@ -283,7 +285,8 @@ rsu_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct rsu_softc *sc = device_get_softc(self);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp;
+ struct ieee80211com *ic;
int error;
uint8_t iface_index, bands;
@@ -295,7 +298,6 @@ rsu_attach(device_t self)
MTX_DEF);
TIMEOUT_TASK_INIT(taskqueue_thread, &sc->calib_task, 0,
rsu_calib_task, sc);
- mbufq_init(&sc->sc_snd, ifqmaxlen);
/* Allocate Tx/Rx buffers. */
error = rsu_alloc_rx_list(sc);
@@ -331,9 +333,28 @@ rsu_attach(device_t self)
device_printf(self, "could not read ROM\n");
goto fail_rom;
}
- IEEE80211_ADDR_COPY(ic->ic_macaddr, &sc->rom[0x12]);
+ IEEE80211_ADDR_COPY(sc->sc_bssid, &sc->rom[0x12]);
device_printf(self, "MAC/BB RTL8712 cut %d\n", sc->cut);
-
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(self, "cannot allocate interface\n");
+ goto fail_ifalloc;
+ }
+ ic = ifp->if_l2com;
+ ifp->if_softc = sc;
+ if_initname(ifp, "rsu", device_get_unit(self));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = rsu_init;
+ ifp->if_ioctl = rsu_ioctl;
+ ifp->if_start = rsu_start;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+ ifp->if_capabilities |= IFCAP_RXCSUM;
+ ifp->if_capenable |= IFCAP_RXCSUM;
+ ifp->if_hwassist = CSUM_TCP;
+
+ ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */
@@ -366,7 +387,7 @@ rsu_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->sc_bssid);
ic->ic_raw_xmit = rsu_raw_xmit;
ic->ic_scan_start = rsu_scan_start;
ic->ic_scan_end = rsu_scan_end;
@@ -374,8 +395,6 @@ rsu_attach(device_t self)
ic->ic_vap_create = rsu_vap_create;
ic->ic_vap_delete = rsu_vap_delete;
ic->ic_update_mcast = rsu_update_mcast;
- ic->ic_parent = rsu_parent;
- ic->ic_transmit = rsu_transmit;
ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr,
sizeof(sc->sc_txtap), RSU_TX_RADIOTAP_PRESENT,
@@ -387,6 +406,7 @@ rsu_attach(device_t self)
return (0);
+fail_ifalloc:
fail_rom:
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
fail_usb:
@@ -398,11 +418,10 @@ static int
rsu_detach(device_t self)
{
struct rsu_softc *sc = device_get_softc(self);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
- RSU_LOCK(sc);
- rsu_stop(sc);
- RSU_UNLOCK(sc);
+ rsu_stop(ifp, 1);
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
ieee80211_ifdetach(ic);
@@ -412,7 +431,7 @@ rsu_detach(device_t self)
rsu_free_tx_list(sc);
rsu_free_rx_list(sc);
- mbufq_drain(&sc->sc_snd);
+ if_free(ifp);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -452,11 +471,14 @@ rsu_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 rsu_vap), M_80211_VAP, M_WAITOK | M_ZERO);
+ uvp = (struct rsu_vap *) malloc(sizeof(struct rsu_vap),
+ M_80211_VAP, M_NOWAIT | M_ZERO);
+ if (uvp == NULL)
+ return (NULL);
vap = &uvp->vap;
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags, bssid) != 0) {
+ flags, bssid, mac) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@@ -468,7 +490,7 @@ rsu_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);
@@ -486,8 +508,9 @@ rsu_vap_delete(struct ieee80211vap *vap)
static void
rsu_scan_start(struct ieee80211com *ic)
{
- struct rsu_softc *sc = ic->ic_softc;
int error;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct rsu_softc *sc = ifp->if_softc;
/* Scanning is done by the firmware. */
RSU_LOCK(sc);
@@ -653,8 +676,11 @@ rsu_getbuf(struct rsu_softc *sc)
RSU_ASSERT_LOCKED(sc);
bf = _rsu_getbuf(sc);
- if (bf == NULL)
+ if (bf == NULL) {
+ struct ifnet *ifp = sc->sc_ifp;
DPRINTF("stop queue\n");
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ }
return (bf);
}
@@ -909,7 +935,7 @@ rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rsu_vap *uvp = RSU_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct rsu_softc *sc = ic->ic_softc;
+ struct rsu_softc *sc = ic->ic_ifp->if_softc;
struct ieee80211_node *ni;
struct ieee80211_rateset *rs;
enum ieee80211_state ostate;
@@ -1007,27 +1033,29 @@ static int
rsu_site_survey(struct rsu_softc *sc, struct ieee80211vap *vap)
{
struct r92s_fw_cmd_sitesurvey cmd;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
memset(&cmd, 0, sizeof(cmd));
- if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->sc_scan_pass == 1)
+ if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->scan_pass == 1)
cmd.active = htole32(1);
cmd.limit = htole32(48);
- if (sc->sc_scan_pass == 1 && vap->iv_des_nssid > 0) {
+ if (sc->scan_pass == 1 && vap->iv_des_nssid > 0) {
/* Do a directed scan for second pass. */
cmd.ssidlen = htole32(vap->iv_des_ssid[0].len);
memcpy(cmd.ssid, vap->iv_des_ssid[0].ssid,
vap->iv_des_ssid[0].len);
}
- DPRINTF("sending site survey command, pass=%d\n", sc->sc_scan_pass);
+ DPRINTF("sending site survey command, pass=%d\n", sc->scan_pass);
return (rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY, &cmd, sizeof(cmd)));
}
static int
rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = ni->ni_vap;
struct ndis_wlan_bssid_ex *bss;
struct ndis_802_11_fixed_ies *fixed;
@@ -1105,7 +1133,8 @@ rsu_disconnect(struct rsu_softc *sc)
static void
rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211_frame *wh;
struct ieee80211_channel *c;
struct ndis_wlan_bssid_ex *bss;
@@ -1136,7 +1165,7 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
IEEE80211_FC0_SUBTYPE_BEACON;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
USETW(wh->i_dur, 0);
- IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr);
IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr);
*(uint16_t *)wh->i_seq = 0;
@@ -1144,6 +1173,7 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
/* Finalize mbuf. */
m->m_pkthdr.len = m->m_len = pktlen;
+ m->m_pkthdr.rcvif = ifp;
/* Fix the channel. */
c = ieee80211_find_channel_byieee(ic,
le32toh(bss->config.dsconfig),
@@ -1161,7 +1191,8 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
static void
rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
{
- 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 = vap->iv_bss;
struct r92s_event_join_bss *rsp;
@@ -1197,7 +1228,8 @@ rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
static void
rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
{
- 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);
DPRINTFN(4, "Rx event code=%d len=%d\n", code, len);
@@ -1208,18 +1240,18 @@ rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
break;
case R92S_EVT_SURVEY_DONE:
DPRINTF("site survey pass %d done, found %d BSS\n",
- sc->sc_scan_pass, le32toh(*(uint32_t *)buf));
+ sc->scan_pass, le32toh(*(uint32_t *)buf));
if (vap->iv_state != IEEE80211_S_SCAN)
break; /* Ignore if not scanning. */
- if (sc->sc_scan_pass == 0 && vap->iv_des_nssid != 0) {
+ if (sc->scan_pass == 0 && vap->iv_des_nssid != 0) {
/* Schedule a directed scan for hidden APs. */
- sc->sc_scan_pass = 1;
+ sc->scan_pass = 1;
RSU_UNLOCK(sc);
ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
RSU_LOCK(sc);
break;
}
- sc->sc_scan_pass = 0;
+ sc->scan_pass = 0;
break;
case R92S_EVT_JOIN_BSS:
if (vap->iv_state == IEEE80211_S_AUTH)
@@ -1242,7 +1274,7 @@ XXX and disrupts the WLAN traffic. Disable for now.
DPRINTF("WPS PBC pushed.\n");
break;
case R92S_EVT_FWDBG:
- if (vap->iv_ifp->if_flags & IFF_DEBUG) {
+ if (ifp->if_flags & IFF_DEBUG) {
buf[60] = '\0';
printf("FWDBG: %s\n", (char *)buf);
}
@@ -1309,7 +1341,8 @@ rsu_get_rssi(struct rsu_softc *sc, int rate, void *physt)
static struct mbuf *
rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211_frame *wh;
struct r92s_rx_stat *stat;
uint32_t rxdw0, rxdw3;
@@ -1322,11 +1355,11 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
rxdw3 = le32toh(stat->rxdw3);
if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)) {
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return NULL;
}
if (__predict_false(pktlen < sizeof(*wh) || pktlen > MCLBYTES)) {
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return NULL;
}
@@ -1344,9 +1377,11 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m == NULL)) {
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return NULL;
}
+ /* Finalize mbuf. */
+ m->m_pkthdr.rcvif = ifp;
/* Hardware does Rx TCP checksum offload. */
if (rxdw3 & R92S_RXDW3_TCPCHKVALID) {
if (__predict_true(rxdw3 & R92S_RXDW3_TCPCHKRPT))
@@ -1444,7 +1479,6 @@ static struct mbuf *
rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi)
{
struct rsu_softc *sc = data->sc;
- struct ieee80211com *ic = &sc->sc_ic;
struct r92s_rx_stat *stat;
int len;
@@ -1452,7 +1486,7 @@ rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi)
if (__predict_false(len < sizeof(*stat))) {
DPRINTF("xfer too short %d\n", len);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1);
return (NULL);
}
/* Determine if it is a firmware C2H event or an 802.11 frame. */
@@ -1469,7 +1503,8 @@ static void
rsu_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct rsu_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, *next;
@@ -1529,7 +1564,7 @@ tr_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 tr_setup;
}
break;
@@ -1537,16 +1572,35 @@ tr_setup:
}
+
static void
rsu_txeof(struct usb_xfer *xfer, struct rsu_data *data)
{
+ struct rsu_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct mbuf *m;
+
+ RSU_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);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
@@ -1554,7 +1608,7 @@ rsu_bulk_tx_callback_sub(struct usb_xfer *xfer, usb_error_t error,
uint8_t which)
{
struct rsu_softc *sc = usbd_xfer_softc(xfer);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
struct rsu_data *data;
RSU_ASSERT_LOCKED(sc);
@@ -1589,7 +1643,7 @@ tr_setup:
rsu_txeof(xfer, data);
STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
}
- counter_u64_add(ic->ic_oerrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
@@ -1615,7 +1669,8 @@ static int
rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
struct mbuf *m0, struct rsu_data *data)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ieee80211_key *k = NULL;
@@ -1717,75 +1772,82 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
return (0);
}
-static int
-rsu_transmit(struct ieee80211com *ic, struct mbuf *m)
+static void
+rsu_start(struct ifnet *ifp)
{
- struct rsu_softc *sc = ic->ic_softc;
- int error;
+ struct rsu_softc *sc = ifp->if_softc;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
RSU_LOCK(sc);
- if (!sc->sc_running) {
- RSU_UNLOCK(sc);
- return (ENXIO);
- }
- error = mbufq_enqueue(&sc->sc_snd, m);
- if (error) {
- RSU_UNLOCK(sc);
- return (error);
- }
- rsu_start(sc);
+ rsu_start_locked(ifp);
RSU_UNLOCK(sc);
-
- return (0);
}
static void
-rsu_start(struct rsu_softc *sc)
+rsu_start_locked(struct ifnet *ifp)
{
+ struct rsu_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct rsu_data *bf;
struct mbuf *m;
RSU_ASSERT_LOCKED(sc);
- while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
- bf = rsu_getbuf(sc);
- if (bf == NULL) {
- mbufq_prepend(&sc->sc_snd, m);
+ for (;;) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
break;
- }
-
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
- if (rsu_tx_start(sc, ni, m, bf) != 0) {
- if_inc_counter(ni->ni_vap->iv_ifp,
- IFCOUNTER_OERRORS, 1);
+ bf = rsu_getbuf(sc);
+ if (bf == NULL) {
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
+ m_freem(m);
+ ieee80211_free_node(ni);
+ } else if (rsu_tx_start(sc, ni, m, bf) != 0) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
ieee80211_free_node(ni);
- break;
}
}
}
-static void
-rsu_parent(struct ieee80211com *ic)
+static int
+rsu_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct rsu_softc *sc = ic->ic_softc;
- int startall = 0;
-
- RSU_LOCK(sc);
- if (ic->ic_nrunning > 0) {
- if (!sc->sc_running) {
- rsu_init(sc);
- startall = 1;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error = 0, startall = 0;
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ rsu_init(ifp->if_softc);
+ startall = 1;
+ }
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ rsu_stop(ifp, 1);
}
- } else if (sc->sc_running)
- rsu_stop(sc);
- RSU_UNLOCK(sc);
+ 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;
+ }
- if (startall)
- ieee80211_start_all(ic);
+ return (error);
}
/*
@@ -2234,11 +2296,12 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct rsu_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct rsu_softc *sc = ifp->if_softc;
struct rsu_data *bf;
/* prevent management frames from being sent if we're not ready */
- if (!sc->sc_running) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
m_freem(m);
ieee80211_free_node(ni);
return (ENETDOWN);
@@ -2251,8 +2314,10 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
RSU_UNLOCK(sc);
return (ENOBUFS);
}
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (rsu_tx_start(sc, ni, m, bf) != 0) {
ieee80211_free_node(ni);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
RSU_UNLOCK(sc);
return (EIO);
@@ -2263,17 +2328,23 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
}
static void
-rsu_init(struct rsu_softc *sc)
+rsu_init(void *arg)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- uint8_t macaddr[IEEE80211_ADDR_LEN];
+ struct rsu_softc *sc = arg;
+
+ RSU_LOCK(sc);
+ rsu_init_locked(arg);
+ RSU_UNLOCK(sc);
+}
+
+static void
+rsu_init_locked(struct rsu_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
struct r92s_set_pwr_mode cmd;
int error;
int i;
- RSU_ASSERT_LOCKED(sc);
-
/* Init host async commands ring. */
sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
@@ -2313,14 +2384,14 @@ rsu_init(struct rsu_softc *sc)
rsu_read_1(sc, 0xfe5c) | 0x80);
/* Set MAC address. */
- IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr);
- rsu_write_region_1(sc, R92S_MACID, macaddr, IEEE80211_ADDR_LEN);
+ rsu_write_region_1(sc, R92S_MACID, IF_LLADDR(ifp),
+ IEEE80211_ADDR_LEN);
/* It really takes 1.5 seconds for the firmware to boot: */
usb_pause_mtx(&sc->sc_mtx, (3 * hz) / 2);
- DPRINTF("setting MAC address to %s\n", ether_sprintf(macaddr));
- error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, macaddr,
+ DPRINTF("setting MAC address to %s\n", ether_sprintf(IF_LLADDR(ifp)));
+ error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp),
IEEE80211_ADDR_LEN);
if (error != 0) {
device_printf(sc->sc_dev, "could not set MAC address\n");
@@ -2356,11 +2427,12 @@ rsu_init(struct rsu_softc *sc)
/* Set default channel. */
ic->ic_bss->ni_chan = ic->ic_ibss_chan;
#endif
- sc->sc_scan_pass = 0;
+ sc->scan_pass = 0;
usbd_transfer_start(sc->sc_xfer[RSU_BULK_RX]);
/* We're ready to go. */
- sc->sc_running = 1;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
return;
fail:
/* Need to stop all failed transfers, if any */
@@ -2369,11 +2441,22 @@ fail:
}
static void
-rsu_stop(struct rsu_softc *sc)
+rsu_stop(struct ifnet *ifp, int disable)
+{
+ struct rsu_softc *sc = ifp->if_softc;
+
+ RSU_LOCK(sc);
+ rsu_stop_locked(ifp, disable);
+ RSU_UNLOCK(sc);
+}
+
+static void
+rsu_stop_locked(struct ifnet *ifp, int disable __unused)
{
+ struct rsu_softc *sc = ifp->if_softc;
int i;
- sc->sc_running = 0;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_calibrating = 0;
taskqueue_cancel_timeout(taskqueue_thread, &sc->calib_task, NULL);
diff --git a/sys/dev/usb/wlan/if_rsureg.h b/sys/dev/usb/wlan/if_rsureg.h
index 4e6cd88..db0751d 100644
--- a/sys/dev/usb/wlan/if_rsureg.h
+++ b/sys/dev/usb/wlan/if_rsureg.h
@@ -726,8 +726,7 @@ struct rsu_vap {
#define RSU_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
struct rsu_softc {
- struct ieee80211com sc_ic;
- struct mbufq sc_snd;
+ struct ifnet *sc_ifp;
device_t sc_dev;
struct usb_device *sc_udev;
int (*sc_newstate)(struct ieee80211com *,
@@ -737,17 +736,17 @@ struct rsu_softc {
const uint8_t *qid2idx;
struct mtx sc_mtx;
- u_int sc_running:1,
- sc_calibrating:1,
- sc_scan_pass:1;
u_int cut;
+ int scan_pass;
struct rsu_host_cmd_ring cmdq;
struct rsu_data sc_rx[RSU_RX_LIST_COUNT];
struct rsu_data sc_tx[RSU_TX_LIST_COUNT];
struct rsu_data *fwcmd_data;
uint8_t cmd_seq;
uint8_t rom[128];
+ uint8_t sc_bssid[IEEE80211_ADDR_LEN];
struct usb_xfer *sc_xfer[RSU_N_TRANSFER];
+ uint8_t sc_calibrating;
STAILQ_HEAD(, rsu_data) sc_rx_active;
STAILQ_HEAD(, rsu_data) sc_rx_inactive;
diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
index 6a558f6..d5142ea 100644
--- a/sys/dev/usb/wlan/if_rum.c
+++ b/sys/dev/usb/wlan/if_rum.c
@@ -175,9 +175,8 @@ static int rum_tx_raw(struct rum_softc *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int rum_tx_data(struct rum_softc *, struct mbuf *,
struct ieee80211_node *);
-static int rum_transmit(struct ieee80211com *, struct mbuf *);
-static void rum_start(struct rum_softc *);
-static void rum_parent(struct ieee80211com *);
+static void rum_start(struct ifnet *);
+static int rum_ioctl(struct ifnet *, u_long, caddr_t);
static void rum_eeprom_read(struct rum_softc *, uint16_t, void *,
int);
static uint32_t rum_read(struct rum_softc *, uint16_t);
@@ -199,7 +198,7 @@ static void rum_set_chan(struct rum_softc *,
struct ieee80211_channel *);
static void rum_enable_tsf_sync(struct rum_softc *);
static void rum_enable_tsf(struct rum_softc *);
-static void rum_update_slot(struct rum_softc *);
+static void rum_update_slot(struct ifnet *);
static void rum_set_bssid(struct rum_softc *, const uint8_t *);
static void rum_set_macaddr(struct rum_softc *, const uint8_t *);
static void rum_update_mcast(struct ieee80211com *);
@@ -208,7 +207,8 @@ static void rum_setpromisc(struct rum_softc *);
static const char *rum_get_rf(int);
static void rum_read_eeprom(struct rum_softc *);
static int rum_bbp_init(struct rum_softc *);
-static void rum_init(struct rum_softc *);
+static void rum_init_locked(struct rum_softc *);
+static void rum_init(void *);
static void rum_stop(struct rum_softc *);
static void rum_load_microcode(struct rum_softc *, const uint8_t *,
size_t);
@@ -425,7 +425,8 @@ rum_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct rum_softc *sc = device_get_softc(self);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic;
+ struct ifnet *ifp;
uint8_t iface_index, bands;
uint32_t tmp;
int error, ntries;
@@ -436,7 +437,6 @@ rum_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
- mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = RT2573_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device, &iface_index,
@@ -470,6 +470,24 @@ rum_attach(device_t self)
rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode));
RUM_UNLOCK(sc);
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(sc->sc_dev, "can not if_alloc()\n");
+ goto detach;
+ }
+ ic = ifp->if_l2com;
+
+ ifp->if_softc = sc;
+ if_initname(ifp, "rum", device_get_unit(sc->sc_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = rum_init;
+ ifp->if_ioctl = rum_ioctl;
+ ifp->if_start = rum_start;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -494,14 +512,13 @@ rum_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->sc_bssid);
ic->ic_update_promisc = rum_update_promisc;
ic->ic_raw_xmit = rum_raw_xmit;
ic->ic_scan_start = rum_scan_start;
ic->ic_scan_end = rum_scan_end;
ic->ic_set_channel = rum_set_channel;
- ic->ic_transmit = rum_transmit;
- ic->ic_parent = rum_parent;
+
ic->ic_vap_create = rum_vap_create;
ic->ic_vap_delete = rum_vap_delete;
ic->ic_update_mcast = rum_update_mcast;
@@ -526,6 +543,8 @@ static int
rum_detach(device_t self)
{
struct rum_softc *sc = device_get_softc(self);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic;
/* Prevent further ioctls */
RUM_LOCK(sc);
@@ -540,9 +559,11 @@ rum_detach(device_t self)
rum_unsetup_tx_list(sc);
RUM_UNLOCK(sc);
- if (sc->sc_ic.ic_softc == sc)
- ieee80211_ifdetach(&sc->sc_ic);
- mbufq_drain(&sc->sc_snd);
+ if (ifp) {
+ ic = ifp->if_l2com;
+ ieee80211_ifdetach(ic);
+ if_free(ifp);
+ }
mtx_destroy(&sc->sc_mtx);
return (0);
}
@@ -574,18 +595,21 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct rum_softc *sc = ic->ic_softc;
+ struct rum_softc *sc = ic->ic_ifp->if_softc;
struct rum_vap *rvp;
struct ieee80211vap *vap;
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
- rvp = malloc(sizeof(struct rum_vap), M_80211_VAP, M_WAITOK | M_ZERO);
+ rvp = (struct rum_vap *) malloc(sizeof(struct rum_vap),
+ M_80211_VAP, M_NOWAIT | M_ZERO);
+ if (rvp == NULL)
+ return NULL;
vap = &rvp->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(rvp, M_80211_VAP);
return (NULL);
@@ -600,8 +624,7 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status, mac);
+ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
ic->ic_opmode = opmode;
return vap;
}
@@ -625,8 +648,13 @@ rum_tx_free(struct rum_tx_data *data, int txerr)
struct rum_softc *sc = data->sc;
if (data->m != NULL) {
- ieee80211_tx_complete(data->ni, data->m, txerr);
+ if (data->m->m_flags & M_TXCB)
+ ieee80211_process_callback(data->ni, data->m,
+ txerr ? ETIMEDOUT : 0);
+ m_freem(data->m);
data->m = NULL;
+
+ ieee80211_free_node(data->ni);
data->ni = NULL;
}
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
@@ -683,7 +711,7 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rum_vap *rvp = RUM_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct rum_softc *sc = ic->ic_softc;
+ struct rum_softc *sc = ic->ic_ifp->if_softc;
const struct ieee80211_txparam *tp;
enum ieee80211_state ostate;
struct ieee80211_node *ni;
@@ -717,12 +745,12 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_free_node(ni);
return (-1);
}
- rum_update_slot(sc);
+ rum_update_slot(ic->ic_ifp);
rum_enable_mrr(sc);
rum_set_txpreamble(sc);
rum_set_basicrates(sc);
- IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
- rum_set_bssid(sc, ic->ic_macaddr);
+ IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
+ rum_set_bssid(sc, sc->sc_bssid);
}
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
@@ -752,6 +780,7 @@ static void
rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct rum_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap;
struct rum_tx_data *data;
struct mbuf *m;
@@ -770,6 +799,9 @@ rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
rum_tx_free(data, 0);
usbd_xfer_set_priv(xfer, NULL);
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@@ -812,14 +844,16 @@ tr_setup:
usbd_transfer_submit(xfer);
}
- rum_start(sc);
+ RUM_UNLOCK(sc);
+ rum_start(ifp);
+ RUM_LOCK(sc);
break;
default: /* Error */
DPRINTFN(11, "transfer error, %s\n",
usbd_errstr(error));
- counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
data = usbd_xfer_get_priv(xfer);
if (data != NULL) {
rum_tx_free(data, error);
@@ -846,7 +880,8 @@ static void
rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct rum_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_node *ni;
struct mbuf *m = NULL;
struct usb_page_cache *pc;
@@ -864,7 +899,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) {
DPRINTF("%s: xfer too short %d\n",
device_get_nameunit(sc->sc_dev), len);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
goto tr_setup;
}
@@ -881,20 +916,21 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
* filled RUM_TXRX_CSR2:
*/
DPRINTFN(5, "PHY or CRC error\n");
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
goto tr_setup;
}
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
DPRINTF("could not allocate mbuf\n");
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
goto tr_setup;
}
usbd_copy_out(pc, RT2573_RX_DESC_SIZE,
mtod(m, uint8_t *), len);
/* finalize mbuf */
+ m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
if (ieee80211_radiotap_active(ic)) {
@@ -932,8 +968,10 @@ tr_setup:
(void) ieee80211_input_all(ic, m, rssi,
RT2573_NOISE_FLOOR);
}
+ if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
+ !IFQ_IS_EMPTY(&ifp->if_snd))
+ rum_start(ifp);
RUM_LOCK(sc);
- rum_start(sc);
return;
default: /* Error */
@@ -973,7 +1011,8 @@ static void
rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
uint32_t flags, uint16_t xflags, int len, int rate)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint16_t plcp_length;
int remainder;
@@ -1070,7 +1109,8 @@ static int
rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct rum_tx_data *data;
struct ieee80211_frame *wh;
const struct ieee80211_txparam *tp;
@@ -1181,7 +1221,8 @@ static int
rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct rum_tx_data *data;
struct ieee80211_frame *wh;
const struct ieee80211_txparam *tp;
@@ -1258,73 +1299,80 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
return 0;
}
-static int
-rum_transmit(struct ieee80211com *ic, struct mbuf *m)
-{
- struct rum_softc *sc = ic->ic_softc;
- int error;
-
- RUM_LOCK(sc);
- if (!sc->sc_running) {
- RUM_UNLOCK(sc);
- return (ENXIO);
- }
- error = mbufq_enqueue(&sc->sc_snd, m);
- if (error) {
- RUM_UNLOCK(sc);
- return (error);
- }
- rum_start(sc);
- RUM_UNLOCK(sc);
-
- return (0);
-}
-
static void
-rum_start(struct rum_softc *sc)
+rum_start(struct ifnet *ifp)
{
+ struct rum_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
- RUM_LOCK_ASSERT(sc, MA_OWNED);
-
- if (!sc->sc_running)
+ RUM_LOCK(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ RUM_UNLOCK(sc);
return;
-
- while (sc->tx_nfree >= RUM_TX_MINFREE &&
- (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ }
+ for (;;) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+ if (sc->tx_nfree < RUM_TX_MINFREE) {
+ IFQ_DRV_PREPEND(&ifp->if_snd, m);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (rum_tx_data(sc, m, ni) != 0) {
- if_inc_counter(ni->ni_vap->iv_ifp,
- IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
}
+ RUM_UNLOCK(sc);
}
-static void
-rum_parent(struct ieee80211com *ic)
+static int
+rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct rum_softc *sc = ic->ic_softc;
+ struct rum_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error;
int startall = 0;
RUM_LOCK(sc);
- if (sc->sc_detached) {
+ error = sc->sc_detached ? ENXIO : 0;
+ RUM_UNLOCK(sc);
+ if (error)
+ return (error);
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ RUM_LOCK(sc);
+ if (ifp->if_flags & IFF_UP) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ rum_init_locked(sc);
+ startall = 1;
+ } else
+ rum_setpromisc(sc);
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ rum_stop(sc);
+ }
RUM_UNLOCK(sc);
- return;
+ 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;
}
- if (ic->ic_nrunning > 0) {
- if (!sc->sc_running) {
- rum_init(sc);
- startall = 1;
- } else
- rum_setpromisc(sc);
- } else if (sc->sc_running)
- rum_stop(sc);
- RUM_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
+ return error;
}
static void
@@ -1524,7 +1572,8 @@ rum_select_antenna(struct rum_softc *sc)
static void
rum_enable_mrr(struct rum_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint32_t tmp;
tmp = rum_read(sc, RT2573_TXRX_CSR4);
@@ -1540,7 +1589,8 @@ rum_enable_mrr(struct rum_softc *sc)
static void
rum_set_txpreamble(struct rum_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint32_t tmp;
tmp = rum_read(sc, RT2573_TXRX_CSR4);
@@ -1555,7 +1605,8 @@ rum_set_txpreamble(struct rum_softc *sc)
static void
rum_set_basicrates(struct rum_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
/* update basic rate set */
if (ic->ic_curmode == IEEE80211_MODE_11B) {
@@ -1620,7 +1671,8 @@ rum_select_band(struct rum_softc *sc, struct ieee80211_channel *c)
static void
rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
const struct rfprog *rfprog;
uint8_t bbp3, bbp94 = RT2573_BBPR94_DEFAULT;
int8_t power;
@@ -1696,7 +1748,8 @@ rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
static void
rum_enable_tsf_sync(struct rum_softc *sc)
{
- 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);
uint32_t tmp;
@@ -1731,9 +1784,10 @@ rum_enable_tsf(struct rum_softc *sc)
}
static void
-rum_update_slot(struct rum_softc *sc)
+rum_update_slot(struct ifnet *ifp)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct rum_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
uint8_t slottime;
uint32_t tmp;
@@ -1773,17 +1827,18 @@ rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr)
static void
rum_setpromisc(struct rum_softc *sc)
{
+ struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
tmp = rum_read(sc, RT2573_TXRX_CSR0);
tmp &= ~RT2573_DROP_NOT_TO_ME;
- if (sc->sc_ic.ic_promisc == 0)
+ if (!(ifp->if_flags & IFF_PROMISC))
tmp |= RT2573_DROP_NOT_TO_ME;
rum_write(sc, RT2573_TXRX_CSR0, tmp);
- DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc > 0 ?
+ DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
"entering" : "leaving");
}
@@ -1792,11 +1847,10 @@ rum_update_promisc(struct ieee80211com *ic)
{
struct rum_softc *sc = ic->ic_softc;
- RUM_LOCK(sc);
- if (!sc->sc_running) {
- RUM_UNLOCK(sc);
+ if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
- }
+
+ RUM_LOCK(sc);
rum_setpromisc(sc);
RUM_UNLOCK(sc);
}
@@ -1833,7 +1887,7 @@ rum_read_eeprom(struct rum_softc *sc)
#endif
/* read MAC address */
- rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_ic.ic_macaddr, 6);
+ rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_bssid, 6);
rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2);
val = le16toh(val);
@@ -1940,10 +1994,10 @@ rum_bbp_init(struct rum_softc *sc)
}
static void
-rum_init(struct rum_softc *sc)
+rum_init_locked(struct rum_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint32_t tmp;
usb_error_t error;
int i, ntries;
@@ -1985,7 +2039,7 @@ rum_init(struct rum_softc *sc)
/* clear STA registers */
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
- rum_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
+ rum_set_macaddr(sc, IF_LLADDR(ifp));
/* initialize ASIC */
rum_write(sc, RT2573_MAC_CSR1, 4);
@@ -2004,12 +2058,13 @@ rum_init(struct rum_softc *sc)
RT2573_DROP_ACKCTS;
if (ic->ic_opmode != IEEE80211_M_HOSTAP)
tmp |= RT2573_DROP_TODS;
- if (ic->ic_promisc == 0)
+ if (!(ifp->if_flags & IFF_PROMISC))
tmp |= RT2573_DROP_NOT_TO_ME;
}
rum_write(sc, RT2573_TXRX_CSR0, tmp);
- sc->sc_running = 1;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
usbd_xfer_set_stall(sc->sc_xfer[RUM_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[RUM_BULK_RD]);
return;
@@ -2019,13 +2074,29 @@ fail: rum_stop(sc);
}
static void
+rum_init(void *priv)
+{
+ struct rum_softc *sc = priv;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ RUM_LOCK(sc);
+ rum_init_locked(sc);
+ RUM_UNLOCK(sc);
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ieee80211_start_all(ic); /* start all vap's */
+}
+
+static void
rum_stop(struct rum_softc *sc)
{
+ struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
RUM_LOCK_ASSERT(sc, MA_OWNED);
- sc->sc_running = 0;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
RUM_UNLOCK(sc);
@@ -2117,23 +2188,27 @@ static int
rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
- struct rum_softc *sc = ni->ni_ic->ic_softc;
+ struct ifnet *ifp = ni->ni_ic->ic_ifp;
+ struct rum_softc *sc = ifp->if_softc;
RUM_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!sc->sc_running) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
RUM_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->tx_nfree < RUM_TX_MINFREE) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
RUM_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return EIO;
}
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
@@ -2153,6 +2228,7 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
bad:
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
RUM_UNLOCK(sc);
ieee80211_free_node(ni);
return EIO;
@@ -2186,7 +2262,8 @@ rum_ratectl_task(void *arg, int pending)
struct rum_vap *rvp = arg;
struct ieee80211vap *vap = &rvp->vap;
struct ieee80211com *ic = vap->iv_ic;
- struct rum_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct rum_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
int ok, fail;
int sum, retrycnt;
@@ -2206,8 +2283,7 @@ rum_ratectl_task(void *arg, int pending)
(void) ieee80211_ratectl_rate(ni, NULL, 0);
ieee80211_free_node(ni);
- /* count TX retry-fail as Tx errors */
- if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */
usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp);
RUM_UNLOCK(sc);
@@ -2216,14 +2292,15 @@ rum_ratectl_task(void *arg, int pending)
static void
rum_scan_start(struct ieee80211com *ic)
{
- struct rum_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct rum_softc *sc = ifp->if_softc;
uint32_t tmp;
RUM_LOCK(sc);
/* abort TSF synchronization */
tmp = rum_read(sc, RT2573_TXRX_CSR9);
rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
- rum_set_bssid(sc, ieee80211broadcastaddr);
+ rum_set_bssid(sc, ifp->if_broadcastaddr);
RUM_UNLOCK(sc);
}
@@ -2231,11 +2308,11 @@ rum_scan_start(struct ieee80211com *ic)
static void
rum_scan_end(struct ieee80211com *ic)
{
- struct rum_softc *sc = ic->ic_softc;
+ struct rum_softc *sc = ic->ic_ifp->if_softc;
RUM_LOCK(sc);
rum_enable_tsf_sync(sc);
- rum_set_bssid(sc, ic->ic_macaddr);
+ rum_set_bssid(sc, sc->sc_bssid);
RUM_UNLOCK(sc);
}
@@ -2243,7 +2320,7 @@ rum_scan_end(struct ieee80211com *ic)
static void
rum_set_channel(struct ieee80211com *ic)
{
- struct rum_softc *sc = ic->ic_softc;
+ struct rum_softc *sc = ic->ic_ifp->if_softc;
RUM_LOCK(sc);
rum_set_chan(sc, ic->ic_curchan);
@@ -2253,7 +2330,8 @@ rum_set_channel(struct ieee80211com *ic)
static int
rum_get_rssi(struct rum_softc *sc, uint8_t raw)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
int lna, agc, rssi;
lna = (raw >> 5) & 0x3;
diff --git a/sys/dev/usb/wlan/if_rumvar.h b/sys/dev/usb/wlan/if_rumvar.h
index 35da6d3..17944aa 100644
--- a/sys/dev/usb/wlan/if_rumvar.h
+++ b/sys/dev/usb/wlan/if_rumvar.h
@@ -85,8 +85,7 @@ enum {
};
struct rum_softc {
- struct ieee80211com sc_ic;
- struct mbufq sc_snd;
+ struct ifnet *sc_ifp;
device_t sc_dev;
struct usb_device *sc_udev;
@@ -106,8 +105,8 @@ struct rum_softc {
uint32_t sta[6];
uint32_t rf_regs[4];
uint8_t txpow[44];
- u_int sc_detached:1,
- sc_running:1;
+ uint8_t sc_bssid[6];
+ uint8_t sc_detached;
struct {
uint8_t val;
diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c
index 193b9ad..ac14178 100644
--- a/sys/dev/usb/wlan/if_run.c
+++ b/sys/dev/usb/wlan/if_run.c
@@ -410,9 +410,8 @@ static int run_tx_param(struct run_softc *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int run_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static int run_transmit(struct ieee80211com *, struct mbuf *);
-static void run_start(struct run_softc *);
-static void run_parent(struct ieee80211com *);
+static void run_start(struct ifnet *);
+static int run_ioctl(struct ifnet *, u_long, caddr_t);
static void run_iq_calib(struct run_softc *, u_int);
static void run_set_agc(struct run_softc *, uint8_t);
static void run_select_chan_group(struct run_softc *, int);
@@ -458,6 +457,7 @@ static void run_rt3593_rf_setup(struct run_softc *);
static void run_rt5390_rf_setup(struct run_softc *);
static int run_txrx_enable(struct run_softc *);
static void run_adjust_freq_offset(struct run_softc *);
+static void run_init(void *);
static void run_init_locked(struct run_softc *);
static void run_stop(void *);
static void run_delay(struct run_softc *, u_int);
@@ -702,7 +702,8 @@ run_attach(device_t self)
{
struct run_softc *sc = device_get_softc(self);
struct usb_attach_arg *uaa = device_get_ivars(self);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic;
+ struct ifnet *ifp;
uint32_t ver;
int ntries, error;
uint8_t iface_index, bands;
@@ -715,7 +716,6 @@ run_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
MTX_NETWORK_LOCK, MTX_DEF);
- mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = RT2860_IFACE_INDEX;
@@ -754,10 +754,28 @@ run_attach(device_t self)
device_printf(sc->sc_dev,
"MAC/BBP RT%04X (rev 0x%04X), RF %s (MIMO %dT%dR), address %s\n",
sc->mac_ver, sc->mac_rev, run_get_rf(sc->rf_rev),
- sc->ntxchains, sc->nrxchains, ether_sprintf(ic->ic_macaddr));
+ sc->ntxchains, sc->nrxchains, ether_sprintf(sc->sc_bssid));
RUN_UNLOCK(sc);
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(sc->sc_dev, "can not if_alloc()\n");
+ goto detach;
+ }
+ ic = ifp->if_l2com;
+
+ ifp->if_softc = sc;
+ if_initname(ifp, "run", device_get_unit(sc->sc_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = run_init;
+ ifp->if_ioctl = run_ioctl;
+ ifp->if_start = run_start;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -794,7 +812,7 @@ run_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->sc_bssid);
ic->ic_scan_start = run_scan_start;
ic->ic_scan_end = run_scan_end;
@@ -806,10 +824,9 @@ run_attach(device_t self)
ic->ic_wme.wme_update = run_wme_update;
ic->ic_raw_xmit = run_raw_xmit;
ic->ic_update_promisc = run_update_promisc;
+
ic->ic_vap_create = run_vap_create;
ic->ic_vap_delete = run_vap_delete;
- ic->ic_transmit = run_transmit;
- ic->ic_parent = run_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -835,7 +852,8 @@ static int
run_detach(device_t self)
{
struct run_softc *sc = device_get_softc(self);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic;
int i;
RUN_LOCK(sc);
@@ -854,15 +872,16 @@ run_detach(device_t self)
run_unsetup_tx_list(sc, &sc->sc_epq[i]);
RUN_UNLOCK(sc);
- if (sc->sc_ic.ic_softc == sc) {
+ if (ifp) {
+ ic = ifp->if_l2com;
/* drain tasks */
usb_callout_drain(&sc->ratectl_ch);
ieee80211_draintask(ic, &sc->cmdq_task);
ieee80211_draintask(ic, &sc->ratectl_task);
ieee80211_ifdetach(ic);
+ if_free(ifp);
}
- mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -874,13 +893,14 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct run_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct run_softc *sc = ifp->if_softc;
struct run_vap *rvp;
struct ieee80211vap *vap;
int i;
if (sc->rvp_cnt >= RUN_VAP_MAX) {
- device_printf(sc->sc_dev, "number of VAPs maxed out\n");
+ if_printf(ifp, "number of VAPs maxed out\n");
return (NULL);
}
@@ -906,21 +926,23 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
break;
}
if (vap == NULL) {
- device_printf(sc->sc_dev,
- "wds only supported in ap mode\n");
+ if_printf(ifp, "wds only supported in ap mode\n");
return (NULL);
}
break;
default:
- device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
+ if_printf(ifp, "unknown opmode %d\n", opmode);
return (NULL);
}
- rvp = malloc(sizeof(struct run_vap), M_80211_VAP, M_WAITOK | M_ZERO);
+ rvp = (struct run_vap *) malloc(sizeof(struct run_vap),
+ M_80211_VAP, M_NOWAIT | M_ZERO);
+ if (rvp == NULL)
+ return (NULL);
vap = &rvp->vap;
- if (ieee80211_vap_setup(ic, vap, name, unit, opmode, flags,
- bssid) != 0) {
+ if (ieee80211_vap_setup(ic, vap, name, unit,
+ opmode, flags, bssid, mac) != 0) {
/* out of memory */
free(rvp, M_80211_VAP);
return (NULL);
@@ -947,8 +969,7 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
/* complete setup */
- ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status,
- mac);
+ ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status);
/* make sure id is always unique */
for (i = 0; i < RUN_VAP_MAX; i++) {
@@ -974,6 +995,7 @@ static void
run_vap_delete(struct ieee80211vap *vap)
{
struct run_vap *rvp = RUN_VAP(vap);
+ struct ifnet *ifp;
struct ieee80211com *ic;
struct run_softc *sc;
uint8_t rvp_id;
@@ -982,7 +1004,9 @@ run_vap_delete(struct ieee80211vap *vap)
return;
ic = vap->iv_ic;
- sc = ic->ic_softc;
+ ifp = ic->ic_ifp;
+
+ sc = ifp->if_softc;
RUN_LOCK(sc);
@@ -1716,7 +1740,6 @@ run_get_txpower(struct run_softc *sc)
static int
run_read_eeprom(struct run_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
int8_t delta_2ghz, delta_5ghz;
uint32_t tmp;
uint16_t val;
@@ -1737,14 +1760,14 @@ run_read_eeprom(struct run_softc *sc)
/* read MAC address */
run_srom_read(sc, RT2860_EEPROM_MAC01, &val);
- ic->ic_macaddr[0] = val & 0xff;
- ic->ic_macaddr[1] = val >> 8;
+ sc->sc_bssid[0] = val & 0xff;
+ sc->sc_bssid[1] = val >> 8;
run_srom_read(sc, RT2860_EEPROM_MAC23, &val);
- ic->ic_macaddr[2] = val & 0xff;
- ic->ic_macaddr[3] = val >> 8;
+ sc->sc_bssid[2] = val & 0xff;
+ sc->sc_bssid[3] = val >> 8;
run_srom_read(sc, RT2860_EEPROM_MAC45, &val);
- ic->ic_macaddr[4] = val & 0xff;
- ic->ic_macaddr[5] = val >> 8;
+ sc->sc_bssid[4] = val & 0xff;
+ sc->sc_bssid[5] = val >> 8;
if (sc->mac_ver < 0x3593) {
/* read vender BBP settings */
@@ -1979,7 +2002,7 @@ run_media_change(struct ifnet *ifp)
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
const struct ieee80211_txparam *tp;
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
uint8_t rate, ridx;
int error;
@@ -2010,7 +2033,7 @@ run_media_change(struct ifnet *ifp)
#if 0
if ((ifp->if_flags & IFF_UP) &&
- (ifp->if_drv_flags & RUN_RUNNING)){
+ (ifp->if_drv_flags & IFF_DRV_RUNNING)){
run_init_locked(sc);
}
#endif
@@ -2025,7 +2048,7 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
const struct ieee80211_txparam *tp;
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_vap *rvp = RUN_VAP(vap);
enum ieee80211_state ostate;
uint32_t sta[3];
@@ -2121,7 +2144,7 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
run_set_txpreamble(sc);
run_set_basicrates(sc);
ni = ieee80211_ref_node(vap->iv_bss);
- IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
+ IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
run_set_bssid(sc, ni->ni_bssid);
ieee80211_free_node(ni);
run_enable_tsf_sync(sc);
@@ -2158,7 +2181,7 @@ static void
run_wme_update_cb(void *arg)
{
struct ieee80211com *ic = arg;
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
struct ieee80211_wme_state *wmesp = &ic->ic_wme;
int aci, error = 0;
@@ -2211,7 +2234,7 @@ err:
static int
run_wme_update(struct ieee80211com *ic)
{
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
/* sometime called wothout lock */
if (mtx_owned(&ic->ic_comlock.mtx)) {
@@ -2254,7 +2277,7 @@ run_key_set_cb(void *arg)
struct ieee80211vap *vap = cmdq->arg1;
struct ieee80211_key *k = cmdq->k;
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
struct ieee80211_node *ni;
uint32_t attr;
uint16_t base, associd;
@@ -2376,7 +2399,7 @@ run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k,
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
uint32_t i;
i = RUN_CMDQ_GET(&sc->cmdq_store);
@@ -2444,7 +2467,7 @@ static int
run_key_delete(struct ieee80211vap *vap, struct ieee80211_key *k)
{
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
struct ieee80211_key *k0;
uint32_t i;
@@ -2475,7 +2498,7 @@ run_ratectl_to(void *arg)
struct run_softc *sc = arg;
/* do it in a process context, so it can go sleep */
- ieee80211_runtask(&sc->sc_ic, &sc->ratectl_task);
+ ieee80211_runtask(sc->sc_ifp->if_l2com, &sc->ratectl_task);
/* next timeout will be rescheduled in the callback task */
}
@@ -2484,7 +2507,7 @@ static void
run_ratectl_cb(void *arg, int pending)
{
struct run_softc *sc = arg;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
if (vap == NULL)
@@ -2517,6 +2540,7 @@ static void
run_drain_fifo(void *arg)
{
struct run_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
uint32_t stat;
uint16_t (*wstat)[3];
uint8_t wcid, mcs, pid;
@@ -2553,7 +2577,7 @@ run_drain_fifo(void *arg)
if (stat & RT2860_TXQ_OK)
(*wstat)[RUN_SUCCESS]++;
else
- counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
/*
* Check if there were retries, ie if the Tx success rate is
* different from the requested rate. Note that it works only
@@ -2576,6 +2600,8 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
{
struct run_softc *sc = arg;
struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ifnet *ifp = ic->ic_ifp;
struct run_node *rn = (void *)ni;
union run_stats sta[2];
uint16_t (*wstat)[3];
@@ -2597,8 +2623,7 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
goto fail;
/* count failed TX as errors */
- if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS,
- le16toh(sta[0].error.fail));
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, le16toh(sta[0].error.fail));
retrycnt = le16toh(sta[1].tx.retry);
success = le16toh(sta[1].tx.success);
@@ -2636,7 +2661,7 @@ run_newassoc_cb(void *arg)
{
struct run_cmdq *cmdq = arg;
struct ieee80211_node *ni = cmdq->arg1;
- struct run_softc *sc = ni->ni_vap->iv_ic->ic_softc;
+ struct run_softc *sc = ni->ni_vap->iv_ic->ic_ifp->if_softc;
uint8_t wcid = cmdq->wcid;
RUN_LOCK_ASSERT(sc, MA_OWNED);
@@ -2654,7 +2679,7 @@ run_newassoc(struct ieee80211_node *ni, int isnew)
struct ieee80211_rateset *rs = &ni->ni_rates;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
uint8_t rate;
uint8_t ridx;
uint8_t wcid;
@@ -2744,7 +2769,8 @@ run_maxrssi_chain(struct run_softc *sc, const struct rt2860_rxwi *rxwi)
static void
run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
{
- 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 rt2870_rxd *rxd;
@@ -2763,7 +2789,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
rxwisize += sizeof(uint32_t);
if (__predict_false(len > dmalen)) {
m_freem(m);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF("bad RXWI length %u > %u\n", len, dmalen);
return;
}
@@ -2773,7 +2799,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
m_freem(m);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF("%s error.\n", (flags & RT2860_RX_CRCERR)?"CRC":"ICV");
return;
}
@@ -2802,7 +2828,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
ieee80211_notify_michael_failure(ni->ni_vap, wh,
rxwi->keyidx);
m_freem(m);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF("MIC error. Someone is lying.\n");
return;
}
@@ -2811,6 +2837,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
rssi = rxwi->rssi[ant];
nf = run_rssi2dbm(sc, rssi, ant);
+ m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = len;
if (ni != NULL) {
@@ -2863,7 +2890,7 @@ static void
run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct run_softc *sc = usbd_xfer_softc(xfer);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m = NULL;
struct mbuf *m0;
uint32_t dmalen;
@@ -2901,7 +2928,7 @@ tr_setup:
}
if (sc->rx_m == NULL) {
DPRINTF("could not allocate mbuf - idle with stall\n");
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
usbd_xfer_set_stall(xfer);
usbd_xfer_set_frames(xfer, 0);
} else {
@@ -2921,9 +2948,12 @@ tr_setup:
if (error != USB_ERR_CANCELLED) {
/* try to clear stall first */
usbd_xfer_set_stall(xfer);
+
if (error == USB_ERR_TIMEOUT)
device_printf(sc->sc_dev, "device timeout\n");
- counter_u64_add(ic->ic_ierrors, 1);
+
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+
goto tr_setup;
}
if (sc->rx_m != NULL) {
@@ -2971,7 +3001,7 @@ tr_setup:
m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m0 == NULL)) {
DPRINTF("could not allocate mbuf\n");
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
break;
}
m_copydata(m, 4 /* skip 32-bit DMA-len header */,
@@ -3018,7 +3048,8 @@ static void
run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
{
struct run_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 run_tx_data *data;
struct ieee80211vap *vap = NULL;
struct usb_page_cache *pc;
@@ -3036,9 +3067,14 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
"bytes @ index %d\n", actlen, index);
data = usbd_xfer_get_priv(xfer);
+
run_tx_free(pq, data, 0);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
usbd_xfer_set_priv(xfer, NULL);
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@@ -3055,7 +3091,11 @@ tr_setup:
size + 3 + 8) > RUN_MAX_TXSZ) {
DPRINTF("data overflow, %u bytes\n",
m->m_pkthdr.len);
+
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+
run_tx_free(pq, data, 1);
+
goto tr_setup;
}
@@ -3092,8 +3132,12 @@ tr_setup:
usbd_xfer_set_frame_len(xfer, 0, size);
usbd_xfer_set_priv(xfer, data);
+
usbd_transfer_submit(xfer);
- run_start(sc);
+
+ RUN_UNLOCK(sc);
+ run_start(ifp);
+ RUN_LOCK(sc);
break;
@@ -3103,13 +3147,14 @@ tr_setup:
data = usbd_xfer_get_priv(xfer);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+
if (data != NULL) {
if(data->ni != NULL)
vap = data->ni->ni_vap;
run_tx_free(pq, data, error);
usbd_xfer_set_priv(xfer, NULL);
}
-
if (vap == NULL)
vap = TAILQ_FIRST(&ic->ic_vaps);
@@ -3175,7 +3220,7 @@ static void
run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data)
{
struct mbuf *m = data->m;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211vap *vap = data->ni->ni_vap;
struct ieee80211_frame *wh;
struct rt2870_txd *txd;
@@ -3238,7 +3283,7 @@ run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data)
static int
run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ieee80211_channel *chan;
@@ -3406,7 +3451,8 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
static int
run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct run_node *rn = (void *)ni;
struct run_tx_data *data;
struct ieee80211_frame *wh;
@@ -3437,9 +3483,11 @@ run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
USETW(wh->i_dur, dur);
}
- if (sc->sc_epq[0].tx_nfree == 0)
+ if (sc->sc_epq[0].tx_nfree == 0) {
/* let caller free mbuf */
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
return (EIO);
+ }
data = STAILQ_FIRST(&sc->sc_epq[0].tx_fh);
STAILQ_REMOVE_HEAD(&sc->sc_epq[0].tx_fh, next);
sc->sc_epq[0].tx_nfree--;
@@ -3507,9 +3555,11 @@ run_sendprot(struct run_softc *sc,
wflags = RT2860_TX_FRAG;
/* check that there are free slots before allocating the mbuf */
- if (sc->sc_epq[0].tx_nfree == 0)
+ if (sc->sc_epq[0].tx_nfree == 0) {
/* let caller free mbuf */
+ sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE;
return (ENOBUFS);
+ }
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
@@ -3520,7 +3570,7 @@ run_sendprot(struct run_softc *sc,
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
}
if (mprot == NULL) {
- if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
DPRINTF("could not allocate mbuf\n");
return (ENOBUFS);
}
@@ -3602,6 +3652,7 @@ run_tx_param(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
if (sc->sc_epq[0].tx_nfree == 0) {
/* let caller free mbuf */
+ sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE;
DPRINTF("sending raw frame, but tx ring is full\n");
return (EIO);
}
@@ -3640,31 +3691,36 @@ static int
run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
- struct run_softc *sc = ni->ni_ic->ic_softc;
+ struct ifnet *ifp = ni->ni_ic->ic_ifp;
+ struct run_softc *sc = ifp->if_softc;
int error = 0;
RUN_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(sc->sc_flags & RUN_RUNNING)) {
- error = ENETDOWN;
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ error = ENETDOWN;
goto done;
}
if (params == NULL) {
/* tx mgt packet */
if ((error = run_tx_mgt(sc, m, ni)) != 0) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
DPRINTF("mgt tx failed\n");
goto done;
}
} else {
/* tx raw packet with param */
if ((error = run_tx_param(sc, m, ni, params)) != 0) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
DPRINTF("tx with param failed\n");
goto done;
}
}
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+
done:
RUN_UNLOCK(sc);
@@ -3677,71 +3733,83 @@ done:
return (error);
}
-static int
-run_transmit(struct ieee80211com *ic, struct mbuf *m)
-{
- struct run_softc *sc = ic->ic_softc;
- int error;
-
- RUN_LOCK(sc);
- if ((sc->sc_flags & RUN_RUNNING) == 0) {
- RUN_UNLOCK(sc);
- return (ENXIO);
- }
- error = mbufq_enqueue(&sc->sc_snd, m);
- if (error) {
- RUN_UNLOCK(sc);
- return (error);
- }
- run_start(sc);
- RUN_UNLOCK(sc);
-
- return (0);
-}
-
static void
-run_start(struct run_softc *sc)
+run_start(struct ifnet *ifp)
{
+ struct run_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
- RUN_LOCK_ASSERT(sc, MA_OWNED);
+ RUN_LOCK(sc);
- if ((sc->sc_flags & RUN_RUNNING) == 0)
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ RUN_UNLOCK(sc);
return;
+ }
+
+ for (;;) {
+ /* send data frames */
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
- while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (run_tx(sc, m, ni) != 0) {
- mbufq_prepend(&sc->sc_snd, m);
+ IFQ_DRV_PREPEND(&ifp->if_snd, m);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
}
+
+ RUN_UNLOCK(sc);
}
-static void
-run_parent(struct ieee80211com *ic)
+static int
+run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
int startall = 0;
+ int error;
RUN_LOCK(sc);
- if (sc->sc_detached) {
+ error = sc->sc_detached ? ENXIO : 0;
+ RUN_UNLOCK(sc);
+ if (error)
+ return (error);
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ RUN_LOCK(sc);
+ if (ifp->if_flags & IFF_UP) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)){
+ startall = 1;
+ run_init_locked(sc);
+ } else
+ run_update_promisc_locked(sc);
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
+ (ic->ic_nrunning == 0 || sc->rvp_cnt <= 1)) {
+ run_stop(sc);
+ }
+ }
RUN_UNLOCK(sc);
- return;
+ 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;
}
- if (ic->ic_nrunning > 0) {
- if (!(sc->sc_flags & RUN_RUNNING)) {
- startall = 1;
- run_init_locked(sc);
- } else
- run_update_promisc_locked(sc);
- } else if ((sc->sc_flags & RUN_RUNNING) && sc->rvp_cnt <= 1)
- run_stop(sc);
- RUN_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
+ return (error);
}
static void
@@ -4728,7 +4796,7 @@ run_set_rx_antenna(struct run_softc *sc, int aux)
static int
run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
u_int chan, group;
chan = ieee80211_chan2ieee(ic, c);
@@ -4773,7 +4841,7 @@ run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
static void
run_set_channel(struct ieee80211com *ic)
{
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
RUN_LOCK(sc);
run_set_chan(sc, ic->ic_curchan);
@@ -4785,7 +4853,7 @@ run_set_channel(struct ieee80211com *ic)
static void
run_scan_start(struct ieee80211com *ic)
{
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
uint32_t tmp;
RUN_LOCK(sc);
@@ -4795,7 +4863,7 @@ run_scan_start(struct ieee80211com *ic)
run_write(sc, RT2860_BCN_TIME_CFG,
tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
RT2860_TBTT_TIMER_EN));
- run_set_bssid(sc, ieee80211broadcastaddr);
+ run_set_bssid(sc, sc->sc_ifp->if_broadcastaddr);
RUN_UNLOCK(sc);
@@ -4805,13 +4873,13 @@ run_scan_start(struct ieee80211com *ic)
static void
run_scan_end(struct ieee80211com *ic)
{
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
RUN_LOCK(sc);
run_enable_tsf_sync(sc);
/* XXX keep local copy */
- run_set_bssid(sc, ic->ic_macaddr);
+ run_set_bssid(sc, sc->sc_bssid);
RUN_UNLOCK(sc);
@@ -4826,7 +4894,7 @@ static void
run_update_beacon(struct ieee80211vap *vap, int item)
{
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
struct run_vap *rvp = RUN_VAP(vap);
int mcast = 0;
uint32_t i;
@@ -4871,7 +4939,7 @@ run_update_beacon_cb(void *arg)
struct ieee80211vap *vap = arg;
struct run_vap *rvp = RUN_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
struct rt2860_txwi txwi;
struct mbuf *m;
uint16_t txwisize;
@@ -4919,7 +4987,7 @@ run_update_beacon_cb(void *arg)
static void
run_updateprot(struct ieee80211com *ic)
{
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
uint32_t i;
i = RUN_CMDQ_GET(&sc->cmdq_store);
@@ -4933,7 +5001,7 @@ static void
run_updateprot_cb(void *arg)
{
struct ieee80211com *ic = arg;
- struct run_softc *sc = ic->ic_softc;
+ struct run_softc *sc = ic->ic_ifp->if_softc;
uint32_t tmp;
tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL;
@@ -4957,7 +5025,7 @@ static void
run_usb_timeout_cb(void *arg)
{
struct ieee80211vap *vap = arg;
- struct run_softc *sc = vap->iv_ic->ic_softc;
+ struct run_softc *sc = vap->iv_ic->ic_ifp->if_softc;
RUN_LOCK_ASSERT(sc, MA_OWNED);
@@ -5003,12 +5071,12 @@ run_update_promisc_locked(struct run_softc *sc)
run_read(sc, RT2860_RX_FILTR_CFG, &tmp);
tmp |= RT2860_DROP_UC_NOME;
- if (sc->sc_ic.ic_promisc > 0)
+ if (sc->sc_ifp->if_flags & IFF_PROMISC)
tmp &= ~RT2860_DROP_UC_NOME;
run_write(sc, RT2860_RX_FILTR_CFG, tmp);
- DPRINTF("%s promiscuous mode\n", (sc->sc_ic.ic_promisc > 0) ?
+ DPRINTF("%s promiscuous mode\n", (sc->sc_ifp->if_flags & IFF_PROMISC) ?
"entering" : "leaving");
}
@@ -5017,7 +5085,7 @@ run_update_promisc(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_softc;
- if ((sc->sc_flags & RUN_RUNNING) == 0)
+ if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
RUN_LOCK(sc);
@@ -5028,7 +5096,7 @@ run_update_promisc(struct ieee80211com *ic)
static void
run_enable_tsf_sync(struct run_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
@@ -5093,7 +5161,7 @@ run_enable_mrr(struct run_softc *sc)
static void
run_set_txpreamble(struct run_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
uint32_t tmp;
run_read(sc, RT2860_AUTO_RSP_CFG, &tmp);
@@ -5107,7 +5175,7 @@ run_set_txpreamble(struct run_softc *sc)
static void
run_set_basicrates(struct run_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
/* set basic rates mask */
if (ic->ic_curmode == IEEE80211_MODE_11B)
@@ -5152,7 +5220,7 @@ run_updateslot(struct ieee80211com *ic)
i = RUN_CMDQ_GET(&sc->cmdq_store);
DPRINTF("cmdq_store=%d\n", i);
sc->cmdq[i].func = run_updateslot_cb;
- sc->cmdq[i].arg0 = ic;
+ sc->cmdq[i].arg0 = ic->ic_ifp;
ieee80211_runtask(ic, &sc->cmdq_task);
return;
@@ -5162,8 +5230,9 @@ run_updateslot(struct ieee80211com *ic)
static void
run_updateslot_cb(void *arg)
{
- struct ieee80211com *ic = arg;
- struct run_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = arg;
+ struct run_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
uint32_t tmp;
run_read(sc, RT2860_BKOFF_SLOT_CFG, &tmp);
@@ -5175,12 +5244,15 @@ run_updateslot_cb(void *arg)
static void
run_update_mcast(struct ieee80211com *ic)
{
+
+ /* h/w filter supports getting everything or nothing */
+ ic->ic_ifp->if_flags |= IFF_ALLMULTI;
}
static int8_t
run_rssi2dbm(struct run_softc *sc, uint8_t rssi, uint8_t rxchain)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211_channel *c = ic->ic_curchan;
int delta;
@@ -5830,7 +5902,7 @@ run_rt5390_rf_setup(struct run_softc *sc)
static int
run_txrx_enable(struct run_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
uint32_t tmp;
int error, ntries;
@@ -5890,8 +5962,8 @@ run_adjust_freq_offset(struct run_softc *sc)
static void
run_init_locked(struct run_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint32_t tmp;
uint8_t bbp1, bbp3;
int i;
@@ -5921,7 +5993,7 @@ run_init_locked(struct run_softc *sc)
for (i = 0; i != RUN_EP_QUEUES; i++)
run_setup_tx_list(sc, &sc->sc_epq[i]);
- run_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
+ run_set_macaddr(sc, IF_LLADDR(ifp));
for (ntries = 0; ntries < 100; ntries++) {
if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0)
@@ -6094,7 +6166,8 @@ run_init_locked(struct run_softc *sc)
/* turn radio LED on */
run_set_leds(sc, RT2860_LED_RADIO);
- sc->sc_flags |= RUN_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->cmdq_run = RUN_CMDQ_GO;
for (i = 0; i != RUN_N_XFER; i++)
@@ -6112,19 +6185,35 @@ fail:
}
static void
+run_init(void *arg)
+{
+ struct run_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ RUN_LOCK(sc);
+ run_init_locked(sc);
+ RUN_UNLOCK(sc);
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ieee80211_start_all(ic);
+}
+
+static void
run_stop(void *arg)
{
struct run_softc *sc = (struct run_softc *)arg;
+ struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
int i;
int ntries;
RUN_LOCK_ASSERT(sc, MA_OWNED);
- if (sc->sc_flags & RUN_RUNNING)
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
run_set_leds(sc, 0); /* turn all LEDs off */
- sc->sc_flags &= ~RUN_RUNNING;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->ratectl_run = RUN_RATECTL_OFF;
sc->cmdq_run = sc->cmdq_key_set;
diff --git a/sys/dev/usb/wlan/if_runvar.h b/sys/dev/usb/wlan/if_runvar.h
index b8cb12f..ad0fc30 100644
--- a/sys/dev/usb/wlan/if_runvar.h
+++ b/sys/dev/usb/wlan/if_runvar.h
@@ -151,16 +151,13 @@ struct run_endpoint_queue {
};
struct run_softc {
- struct mtx sc_mtx;
- struct ieee80211com sc_ic;
- struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
+ struct ifnet *sc_ifp;
int sc_need_fwload;
int sc_flags;
#define RUN_FLAG_FWLOAD_NEEDED 0x01
-#define RUN_RUNNING 0x02
uint16_t wcid_stats[RT2870_WCID_MAX + 1][3];
#define RUN_TXCNT 0
@@ -206,6 +203,10 @@ struct run_softc {
uint32_t txpow40mhz_2ghz[5];
uint32_t txpow40mhz_5ghz[5];
+ uint8_t sc_bssid[6];
+
+ struct mtx sc_mtx;
+
struct run_endpoint_queue sc_epq[RUN_EP_QUEUES];
struct task ratectl_task;
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);
diff --git a/sys/dev/usb/wlan/if_uathvar.h b/sys/dev/usb/wlan/if_uathvar.h
index 56b5ba3..fae3604 100644
--- a/sys/dev/usb/wlan/if_uathvar.h
+++ b/sys/dev/usb/wlan/if_uathvar.h
@@ -183,8 +183,7 @@ struct uath_vap {
#define UATH_VAP(vap) ((struct uath_vap *)(vap))
struct uath_softc {
- struct ieee80211com sc_ic;
- struct mbufq sc_snd;
+ struct ifnet *sc_ifp;
device_t sc_dev;
struct usb_device *sc_udev;
void *sc_cmd_dma_buf;
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);
diff --git a/sys/dev/usb/wlan/if_upgtvar.h b/sys/dev/usb/wlan/if_upgtvar.h
index 3dcd335..c50276b 100644
--- a/sys/dev/usb/wlan/if_upgtvar.h
+++ b/sys/dev/usb/wlan/if_upgtvar.h
@@ -418,9 +418,8 @@ struct upgt_vap {
#define UPGT_VAP(vap) ((struct upgt_vap *)(vap))
struct upgt_softc {
- struct ieee80211com sc_ic;
- struct mbufq sc_snd;
device_t sc_dev;
+ struct ifnet *sc_ifp;
struct usb_device *sc_udev;
void *sc_rx_dma_buf;
void *sc_tx_dma_buf;
@@ -430,8 +429,11 @@ struct upgt_softc {
#define UPGT_FLAG_FWLOADED (1 << 0)
#define UPGT_FLAG_INITDONE (1 << 1)
#define UPGT_FLAG_DETACHED (1 << 2)
+ int sc_if_flags;
int sc_debug;
+ uint8_t sc_myaddr[IEEE80211_ADDR_LEN];
+
enum ieee80211_state sc_state;
int sc_arg;
int sc_led_blink;
diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c
index e8224ba..79a5be0 100644
--- a/sys/dev/usb/wlan/if_ural.c
+++ b/sys/dev/usb/wlan/if_ural.c
@@ -149,9 +149,8 @@ static int ural_tx_mgt(struct ural_softc *, struct mbuf *,
struct ieee80211_node *);
static int ural_tx_data(struct ural_softc *, struct mbuf *,
struct ieee80211_node *);
-static int ural_transmit(struct ieee80211com *, struct mbuf *);
-static void ural_start(struct ural_softc *);
-static void ural_parent(struct ieee80211com *);
+static void ural_start(struct ifnet *);
+static int ural_ioctl(struct ifnet *, u_long, caddr_t);
static void ural_set_testmode(struct ural_softc *);
static void ural_eeprom_read(struct ural_softc *, uint16_t, void *,
int);
@@ -172,12 +171,12 @@ static void ural_set_chan(struct ural_softc *,
static void ural_disable_rf_tune(struct ural_softc *);
static void ural_enable_tsf_sync(struct ural_softc *);
static void ural_enable_tsf(struct ural_softc *);
-static void ural_update_slot(struct ural_softc *);
+static void ural_update_slot(struct ifnet *);
static void ural_set_txpreamble(struct ural_softc *);
static void ural_set_basicrates(struct ural_softc *,
const struct ieee80211_channel *);
static void ural_set_bssid(struct ural_softc *, const uint8_t *);
-static void ural_set_macaddr(struct ural_softc *, const uint8_t *);
+static void ural_set_macaddr(struct ural_softc *, uint8_t *);
static void ural_update_promisc(struct ieee80211com *);
static void ural_setpromisc(struct ural_softc *);
static const char *ural_get_rf(int);
@@ -185,7 +184,8 @@ static void ural_read_eeprom(struct ural_softc *);
static int ural_bbp_init(struct ural_softc *);
static void ural_set_txantenna(struct ural_softc *, int);
static void ural_set_rxantenna(struct ural_softc *, int);
-static void ural_init(struct ural_softc *);
+static void ural_init_locked(struct ural_softc *);
+static void ural_init(void *);
static void ural_stop(struct ural_softc *);
static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
@@ -422,7 +422,8 @@ ural_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct ural_softc *sc = device_get_softc(self);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp;
+ struct ieee80211com *ic;
uint8_t iface_index, bands;
int error;
@@ -432,7 +433,6 @@ ural_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
- mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = RAL_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device,
@@ -455,6 +455,24 @@ ural_attach(device_t self)
device_printf(self, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
sc->asic_rev, ural_get_rf(sc->rf_rev));
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(sc->sc_dev, "can not if_alloc()\n");
+ goto detach;
+ }
+ ic = ifp->if_l2com;
+
+ ifp->if_softc = sc;
+ if_initname(ifp, "ural", device_get_unit(sc->sc_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = ural_init;
+ ifp->if_ioctl = ural_ioctl;
+ ifp->if_start = ural_start;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -479,14 +497,13 @@ ural_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->sc_bssid);
ic->ic_update_promisc = ural_update_promisc;
ic->ic_raw_xmit = ural_raw_xmit;
ic->ic_scan_start = ural_scan_start;
ic->ic_scan_end = ural_scan_end;
ic->ic_set_channel = ural_set_channel;
- ic->ic_parent = ural_parent;
- ic->ic_transmit = ural_transmit;
+
ic->ic_vap_create = ural_vap_create;
ic->ic_vap_delete = ural_vap_delete;
@@ -510,7 +527,8 @@ static int
ural_detach(device_t self)
{
struct ural_softc *sc = device_get_softc(self);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic;
/* prevent further ioctls */
RAL_LOCK(sc);
@@ -525,9 +543,11 @@ ural_detach(device_t self)
ural_unsetup_tx_list(sc);
RAL_UNLOCK(sc);
- if (ic->ic_softc == sc)
+ if (ifp) {
+ ic = ifp->if_l2com;
ieee80211_ifdetach(ic);
- mbufq_drain(&sc->sc_snd);
+ if_free(ifp);
+ }
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -560,7 +580,7 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ural_softc *sc = ic->ic_softc;
+ struct ural_softc *sc = ic->ic_ifp->if_softc;
struct ural_vap *uvp;
struct ieee80211vap *vap;
@@ -574,7 +594,7 @@ ural_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);
@@ -590,8 +610,7 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status, mac);
+ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
ic->ic_opmode = opmode;
return vap;
}
@@ -615,8 +634,13 @@ ural_tx_free(struct ural_tx_data *data, int txerr)
struct ural_softc *sc = data->sc;
if (data->m != NULL) {
- ieee80211_tx_complete(data->ni, data->m, txerr);
+ if (data->m->m_flags & M_TXCB)
+ ieee80211_process_callback(data->ni, data->m,
+ txerr ? ETIMEDOUT : 0);
+ m_freem(data->m);
data->m = NULL;
+
+ ieee80211_free_node(data->ni);
data->ni = NULL;
}
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
@@ -673,7 +697,7 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ural_vap *uvp = URAL_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct ural_softc *sc = ic->ic_softc;
+ struct ural_softc *sc = ic->ic_ifp->if_softc;
const struct ieee80211_txparam *tp;
struct ieee80211_node *ni;
struct mbuf *m;
@@ -707,11 +731,11 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_free_node(ni);
return (-1);
}
- ural_update_slot(sc);
+ ural_update_slot(ic->ic_ifp);
ural_set_txpreamble(sc);
ural_set_basicrates(sc, ic->ic_bsschan);
- IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
- ural_set_bssid(sc, ic->ic_macaddr);
+ IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
+ ural_set_bssid(sc, sc->sc_bssid);
}
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
@@ -765,6 +789,7 @@ static void
ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct ural_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap;
struct ural_tx_data *data;
struct mbuf *m;
@@ -782,6 +807,9 @@ ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
ural_tx_free(data, 0);
usbd_xfer_set_priv(xfer, NULL);
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@@ -824,13 +852,16 @@ tr_setup:
usbd_transfer_submit(xfer);
}
- ural_start(sc);
+ RAL_UNLOCK(sc);
+ ural_start(ifp);
+ RAL_LOCK(sc);
break;
default: /* Error */
DPRINTFN(11, "transfer error, %s\n",
usbd_errstr(error));
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
data = usbd_xfer_get_priv(xfer);
if (data != NULL) {
ural_tx_free(data, error);
@@ -852,7 +883,8 @@ static void
ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct ural_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_node *ni;
struct mbuf *m = NULL;
struct usb_page_cache *pc;
@@ -870,7 +902,7 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
if (len < (int)(RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN)) {
DPRINTF("%s: xfer too short %d\n",
device_get_nameunit(sc->sc_dev), len);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
goto tr_setup;
}
@@ -889,19 +921,20 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
* filled RAL_TXRX_CSR2:
*/
DPRINTFN(5, "PHY or CRC error\n");
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
goto tr_setup;
}
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
DPRINTF("could not allocate mbuf\n");
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
goto tr_setup;
}
usbd_copy_out(pc, 0, mtod(m, uint8_t *), len);
/* finalize mbuf */
+ m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
if (ieee80211_radiotap_active(ic)) {
@@ -940,8 +973,10 @@ tr_setup:
} else
(void) ieee80211_input_all(ic, m, rssi, nf);
}
+ if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
+ !IFQ_IS_EMPTY(&ifp->if_snd))
+ ural_start(ifp);
RAL_LOCK(sc);
- ural_start(sc);
return;
default: /* Error */
@@ -981,7 +1016,8 @@ static void
ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc,
uint32_t flags, int len, int rate)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint16_t plcp_length;
int remainder;
@@ -1030,10 +1066,12 @@ ural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
+ struct ifnet *ifp = sc->sc_ifp;
const struct ieee80211_txparam *tp;
struct ural_tx_data *data;
if (sc->tx_nfree == 0) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
m_freem(m0);
ieee80211_free_node(ni);
return (EIO);
@@ -1310,73 +1348,78 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
return 0;
}
-static int
-ural_transmit(struct ieee80211com *ic, struct mbuf *m)
-{
- struct ural_softc *sc = ic->ic_softc;
- int error;
-
- RAL_LOCK(sc);
- if (!sc->sc_running) {
- RAL_UNLOCK(sc);
- return (ENXIO);
- }
- error = mbufq_enqueue(&sc->sc_snd, m);
- if (error) {
- RAL_UNLOCK(sc);
- return (error);
- }
- ural_start(sc);
- RAL_UNLOCK(sc);
-
- return (0);
-}
-
static void
-ural_start(struct ural_softc *sc)
+ural_start(struct ifnet *ifp)
{
+ struct ural_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
- RAL_LOCK_ASSERT(sc, MA_OWNED);
-
- if (sc->sc_running == 0)
+ RAL_LOCK(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ RAL_UNLOCK(sc);
return;
-
- while (sc->tx_nfree >= RAL_TX_MINFREE &&
- (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ }
+ for (;;) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+ if (sc->tx_nfree < RAL_TX_MINFREE) {
+ IFQ_DRV_PREPEND(&ifp->if_snd, m);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (ural_tx_data(sc, m, ni) != 0) {
- if_inc_counter(ni->ni_vap->iv_ifp,
- IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
}
+ RAL_UNLOCK(sc);
}
-static void
-ural_parent(struct ieee80211com *ic)
+static int
+ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct ural_softc *sc = ic->ic_softc;
+ struct ural_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error;
int startall = 0;
RAL_LOCK(sc);
- if (sc->sc_detached) {
+ error = sc->sc_detached ? ENXIO : 0;
+ RAL_UNLOCK(sc);
+ if (error)
+ return (error);
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ RAL_LOCK(sc);
+ if (ifp->if_flags & IFF_UP) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ ural_init_locked(sc);
+ startall = 1;
+ } else
+ ural_setpromisc(sc);
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ural_stop(sc);
+ }
RAL_UNLOCK(sc);
- return;
+ if (startall)
+ ieee80211_start_all(ic);
+ break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
+ break;
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
}
- if (ic->ic_nrunning > 0) {
- if (sc->sc_running == 0) {
- ural_init(sc);
- startall = 1;
- } else
- ural_setpromisc(sc);
- } else if (sc->sc_running)
- ural_stop(sc);
- RAL_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
+ return error;
}
static void
@@ -1571,22 +1614,23 @@ ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val)
static void
ural_scan_start(struct ieee80211com *ic)
{
- struct ural_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct ural_softc *sc = ifp->if_softc;
RAL_LOCK(sc);
ural_write(sc, RAL_TXRX_CSR19, 0);
- ural_set_bssid(sc, ieee80211broadcastaddr);
+ ural_set_bssid(sc, ifp->if_broadcastaddr);
RAL_UNLOCK(sc);
}
static void
ural_scan_end(struct ieee80211com *ic)
{
- struct ural_softc *sc = ic->ic_softc;
+ struct ural_softc *sc = ic->ic_ifp->if_softc;
RAL_LOCK(sc);
ural_enable_tsf_sync(sc);
- ural_set_bssid(sc, ic->ic_macaddr);
+ ural_set_bssid(sc, sc->sc_bssid);
RAL_UNLOCK(sc);
}
@@ -1594,7 +1638,7 @@ ural_scan_end(struct ieee80211com *ic)
static void
ural_set_channel(struct ieee80211com *ic)
{
- struct ural_softc *sc = ic->ic_softc;
+ struct ural_softc *sc = ic->ic_ifp->if_softc;
RAL_LOCK(sc);
ural_set_chan(sc, ic->ic_curchan);
@@ -1604,7 +1648,8 @@ ural_set_channel(struct ieee80211com *ic)
static void
ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint8_t power, tmp;
int i, chan;
@@ -1735,7 +1780,8 @@ ural_disable_rf_tune(struct ural_softc *sc)
static void
ural_enable_tsf_sync(struct ural_softc *sc)
{
- 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);
uint16_t logcwmin, preload, tmp;
@@ -1771,9 +1817,10 @@ ural_enable_tsf(struct ural_softc *sc)
#define RAL_RXTX_TURNAROUND 5 /* us */
static void
-ural_update_slot(struct ural_softc *sc)
+ural_update_slot(struct ifnet *ifp)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ural_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
uint16_t slottime, sifs, eifs;
slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
@@ -1798,7 +1845,8 @@ ural_update_slot(struct ural_softc *sc)
static void
ural_set_txpreamble(struct ural_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint16_t tmp;
tmp = ural_read(sc, RAL_TXRX_CSR10);
@@ -1845,7 +1893,7 @@ ural_set_bssid(struct ural_softc *sc, const uint8_t *bssid)
}
static void
-ural_set_macaddr(struct ural_softc *sc, const uint8_t *addr)
+ural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
{
uint16_t tmp;
@@ -1864,17 +1912,18 @@ ural_set_macaddr(struct ural_softc *sc, const uint8_t *addr)
static void
ural_setpromisc(struct ural_softc *sc)
{
+ struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
tmp = ural_read(sc, RAL_TXRX_CSR2);
tmp &= ~RAL_DROP_NOT_TO_ME;
- if (sc->sc_ic.ic_promisc == 0)
+ if (!(ifp->if_flags & IFF_PROMISC))
tmp |= RAL_DROP_NOT_TO_ME;
ural_write(sc, RAL_TXRX_CSR2, tmp);
- DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc ?
+ DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
"entering" : "leaving");
}
@@ -1883,9 +1932,11 @@ ural_update_promisc(struct ieee80211com *ic)
{
struct ural_softc *sc = ic->ic_softc;
+ if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
+
RAL_LOCK(sc);
- if (sc->sc_running)
- ural_setpromisc(sc);
+ ural_setpromisc(sc);
RAL_UNLOCK(sc);
}
@@ -1907,7 +1958,6 @@ ural_get_rf(int rev)
static void
ural_read_eeprom(struct ural_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
uint16_t val;
ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2);
@@ -1920,7 +1970,7 @@ ural_read_eeprom(struct ural_softc *sc)
sc->nb_ant = val & 0x3;
/* read MAC address */
- ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_macaddr, 6);
+ ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6);
/* read default values for BBP registers */
ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16);
@@ -2014,11 +2064,11 @@ ural_set_rxantenna(struct ural_softc *sc, int antenna)
}
static void
-ural_init(struct ural_softc *sc)
+ural_init_locked(struct ural_softc *sc)
{
#define N(a) ((int)(sizeof (a) / sizeof ((a)[0])))
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint16_t tmp;
int i, ntries;
@@ -2065,7 +2115,7 @@ ural_init(struct ural_softc *sc)
ural_set_txantenna(sc, sc->tx_ant);
ural_set_rxantenna(sc, sc->rx_ant);
- ural_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
+ ural_set_macaddr(sc, IF_LLADDR(ifp));
/*
* Allocate Tx and Rx xfer queues.
@@ -2078,12 +2128,13 @@ ural_init(struct ural_softc *sc)
tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION;
if (ic->ic_opmode != IEEE80211_M_HOSTAP)
tmp |= RAL_DROP_TODS;
- if (ic->ic_promisc == 0)
+ if (!(ifp->if_flags & IFF_PROMISC))
tmp |= RAL_DROP_NOT_TO_ME;
}
ural_write(sc, RAL_TXRX_CSR2, tmp);
- sc->sc_running = 1;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
usbd_xfer_set_stall(sc->sc_xfer[URAL_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[URAL_BULK_RD]);
return;
@@ -2093,12 +2144,28 @@ fail: ural_stop(sc);
}
static void
+ural_init(void *priv)
+{
+ struct ural_softc *sc = priv;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ RAL_LOCK(sc);
+ ural_init_locked(sc);
+ RAL_UNLOCK(sc);
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ieee80211_start_all(ic); /* start all vap's */
+}
+
+static void
ural_stop(struct ural_softc *sc)
{
+ struct ifnet *ifp = sc->sc_ifp;
RAL_LOCK_ASSERT(sc, MA_OWNED);
- sc->sc_running = 0;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
/*
* Drain all the transfers, if not already drained:
@@ -2126,23 +2193,27 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ural_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct ural_softc *sc = ifp->if_softc;
RAL_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!sc->sc_running) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->tx_nfree < RAL_TX_MINFREE) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return EIO;
}
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
@@ -2161,6 +2232,7 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
RAL_UNLOCK(sc);
return 0;
bad:
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
RAL_UNLOCK(sc);
ieee80211_free_node(ni);
return EIO; /* XXX */
@@ -2194,7 +2266,8 @@ ural_ratectl_task(void *arg, int pending)
struct ural_vap *uvp = arg;
struct ieee80211vap *vap = &uvp->vap;
struct ieee80211com *ic = vap->iv_ic;
- struct ural_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct ural_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
int ok, fail;
int sum, retrycnt;
@@ -2213,8 +2286,7 @@ ural_ratectl_task(void *arg, int pending)
ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt);
(void) ieee80211_ratectl_rate(ni, NULL, 0);
- /* count TX retry-fail as Tx errors */
- if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */
usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp);
RAL_UNLOCK(sc);
diff --git a/sys/dev/usb/wlan/if_uralvar.h b/sys/dev/usb/wlan/if_uralvar.h
index f40f71d..c62b0e4 100644
--- a/sys/dev/usb/wlan/if_uralvar.h
+++ b/sys/dev/usb/wlan/if_uralvar.h
@@ -89,8 +89,7 @@ enum {
};
struct ural_softc {
- struct ieee80211com sc_ic;
- struct mbufq sc_snd;
+ struct ifnet *sc_ifp;
device_t sc_dev;
struct usb_device *sc_udev;
@@ -110,8 +109,8 @@ struct ural_softc {
uint16_t sta[11];
uint32_t rf_regs[4];
uint8_t txpow[14];
- u_int sc_detached:1,
- sc_running:1;
+ uint8_t sc_bssid[6];
+ uint8_t sc_detached;
struct {
uint8_t val;
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))
diff --git a/sys/dev/usb/wlan/if_urtwn.c b/sys/dev/usb/wlan/if_urtwn.c
index 457a885..6b712b3 100644
--- a/sys/dev/usb/wlan/if_urtwn.c
+++ b/sys/dev/usb/wlan/if_urtwn.c
@@ -169,8 +169,8 @@ static device_detach_t urtwn_detach;
static usb_callback_t urtwn_bulk_tx_callback;
static usb_callback_t urtwn_bulk_rx_callback;
-static usb_error_t urtwn_do_request(struct urtwn_softc *,
- struct usb_device_request *, void *);
+static usb_error_t urtwn_do_request(struct urtwn_softc *sc,
+ struct usb_device_request *req, void *data);
static struct ieee80211vap *urtwn_vap_create(struct ieee80211com *,
const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
const uint8_t [IEEE80211_ADDR_LEN],
@@ -228,9 +228,10 @@ static int8_t urtwn_r88e_get_rssi(struct urtwn_softc *, int, void *);
static int urtwn_tx_start(struct urtwn_softc *,
struct ieee80211_node *, struct mbuf *,
struct urtwn_data *);
-static int urtwn_transmit(struct ieee80211com *, struct mbuf *);
-static void urtwn_start(struct urtwn_softc *);
-static void urtwn_parent(struct ieee80211com *);
+static void urtwn_start(struct ifnet *);
+static void urtwn_start_locked(struct ifnet *,
+ struct urtwn_softc *);
+static int urtwn_ioctl(struct ifnet *, u_long, caddr_t);
static int urtwn_r92c_power_on(struct urtwn_softc *);
static int urtwn_r88e_power_on(struct urtwn_softc *);
static int urtwn_llt_init(struct urtwn_softc *);
@@ -268,8 +269,10 @@ static void urtwn_set_chan(struct urtwn_softc *,
static void urtwn_update_mcast(struct ieee80211com *);
static void urtwn_iq_calib(struct urtwn_softc *);
static void urtwn_lc_calib(struct urtwn_softc *);
-static void urtwn_init(struct urtwn_softc *);
-static void urtwn_stop(struct urtwn_softc *);
+static void urtwn_init(void *);
+static void urtwn_init_locked(void *);
+static void urtwn_stop(struct ifnet *);
+static void urtwn_stop_locked(struct ifnet *);
static void urtwn_abort_xfers(struct urtwn_softc *);
static int urtwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
@@ -365,7 +368,8 @@ urtwn_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct urtwn_softc *sc = device_get_softc(self);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp;
+ struct ieee80211com *ic;
uint8_t iface_index, bands;
int error;
@@ -378,7 +382,6 @@ urtwn_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
callout_init(&sc->sc_watchdog_ch, 0);
- mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = URTWN_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
@@ -421,6 +424,24 @@ urtwn_attach(device_t self)
URTWN_UNLOCK(sc);
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(sc->sc_dev, "can not if_alloc()\n");
+ goto detach;
+ }
+ ic = ifp->if_l2com;
+
+ ifp->if_softc = sc;
+ if_initname(ifp, "urtwn", device_get_unit(sc->sc_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = urtwn_init;
+ ifp->if_ioctl = urtwn_ioctl;
+ ifp->if_start = urtwn_start;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -441,13 +462,12 @@ urtwn_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->sc_bssid);
ic->ic_raw_xmit = urtwn_raw_xmit;
ic->ic_scan_start = urtwn_scan_start;
ic->ic_scan_end = urtwn_scan_end;
ic->ic_set_channel = urtwn_set_channel;
- ic->ic_transmit = urtwn_transmit;
- ic->ic_parent = urtwn_parent;
+
ic->ic_vap_create = urtwn_vap_create;
ic->ic_vap_delete = urtwn_vap_delete;
ic->ic_update_mcast = urtwn_update_mcast;
@@ -471,15 +491,17 @@ static int
urtwn_detach(device_t self)
{
struct urtwn_softc *sc = device_get_softc(self);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
unsigned int x;
/* Prevent further ioctls. */
URTWN_LOCK(sc);
sc->sc_flags |= URTWN_DETACHED;
- urtwn_stop(sc);
URTWN_UNLOCK(sc);
+ urtwn_stop(ifp);
+
callout_drain(&sc->sc_watchdog_ch);
/* Prevent further allocations from RX/TX data lists. */
@@ -505,7 +527,8 @@ urtwn_detach(device_t self)
/* stop all USB transfers */
usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER);
ieee80211_ifdetach(ic);
- mbufq_drain(&sc->sc_snd);
+
+ if_free(ifp);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -576,12 +599,15 @@ urtwn_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 urtwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
+ uvp = (struct urtwn_vap *) malloc(sizeof(struct urtwn_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);
@@ -593,7 +619,7 @@ urtwn_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);
}
@@ -610,7 +636,8 @@ urtwn_vap_delete(struct ieee80211vap *vap)
static struct mbuf *
urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211_frame *wh;
struct mbuf *m;
struct r92c_rx_stat *stat;
@@ -623,7 +650,7 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
* don't pass packets to the ieee80211 framework if the driver isn't
* RUNNING.
*/
- if (!(sc->sc_flags & URTWN_RUNNING))
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
return (NULL);
stat = (struct r92c_rx_stat *)buf;
@@ -635,11 +662,11 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
* This should not happen since we setup our Rx filter
* to not receive these frames.
*/
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return (NULL);
}
if (pktlen < sizeof(*wh) || pktlen > MCLBYTES) {
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return (NULL);
}
@@ -668,6 +695,7 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
}
/* Finalize mbuf. */
+ m->m_pkthdr.rcvif = ifp;
wh = (struct ieee80211_frame *)((uint8_t *)&stat[1] + infosz);
memcpy(mtod(m, uint8_t *), wh, pktlen);
m->m_pkthdr.len = m->m_len = pktlen;
@@ -713,7 +741,7 @@ urtwn_rxeof(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi,
int8_t *nf)
{
struct urtwn_softc *sc = data->sc;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
struct r92c_rx_stat *stat;
struct mbuf *m, *m0 = NULL, *prevm = NULL;
uint32_t rxdw0;
@@ -723,7 +751,7 @@ urtwn_rxeof(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi,
usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
if (len < sizeof(*stat)) {
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return (NULL);
}
@@ -774,7 +802,8 @@ static void
urtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtwn_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, *next;
@@ -837,7 +866,7 @@ tr_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 tr_setup;
}
break;
@@ -848,19 +877,38 @@ static void
urtwn_txeof(struct usb_xfer *xfer, struct urtwn_data *data)
{
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct mbuf *m;
URTWN_ASSERT_LOCKED(sc);
- /* XXX status? */
- ieee80211_tx_complete(data->ni, data->m, 0);
- data->ni = NULL;
- data->m = NULL;
+
+ /*
+ * Do any tx complete callback. Note this must be done before releasing
+ * the node reference.
+ */
+ if (data->m) {
+ 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
urtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
struct urtwn_data *data;
URTWN_ASSERT_LOCKED(sc);
@@ -885,17 +933,16 @@ tr_setup:
STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next);
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
- urtwn_start(sc);
+ urtwn_start_locked(ifp, sc);
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
if (data == NULL)
goto tr_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);
@@ -928,8 +975,11 @@ urtwn_getbuf(struct urtwn_softc *sc)
URTWN_ASSERT_LOCKED(sc);
bf = _urtwn_getbuf(sc);
- if (bf == NULL)
+ if (bf == NULL) {
+ struct ifnet *ifp = sc->sc_ifp;
DPRINTF("%s: stop queue\n", __func__);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ }
return (bf);
}
@@ -1252,7 +1302,7 @@ urtwn_read_rom(struct urtwn_softc *sc)
sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY);
DPRINTF("regulatory type=%d\n", sc->regulatory);
- IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
+ IEEE80211_ADDR_COPY(sc->sc_bssid, rom->macaddr);
sc->sc_rf_write = urtwn_r92c_rf_write;
sc->sc_power_on = urtwn_r92c_power_on;
@@ -1313,7 +1363,7 @@ urtwn_r88e_read_rom(struct urtwn_softc *sc)
if (sc->ofdm_tx_pwr_diff & 0x08)
sc->ofdm_tx_pwr_diff |= 0xf0;
sc->regulatory = MS(sc->r88e_rom[0xc1], R92C_ROM_RF1_REGULATORY);
- IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, &sc->r88e_rom[0xd7]);
+ IEEE80211_ADDR_COPY(sc->sc_bssid, &sc->r88e_rom[0xd7]);
sc->sc_rf_write = urtwn_r88e_rf_write;
sc->sc_power_on = urtwn_r88e_power_on;
@@ -1328,7 +1378,7 @@ urtwn_ra_init(struct urtwn_softc *sc)
{
static const uint8_t map[] =
{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
- 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 ieee80211_rateset *rs;
@@ -1405,7 +1455,8 @@ urtwn_ra_init(struct urtwn_softc *sc)
void
urtwn_tsf_sync_enable(struct urtwn_softc *sc)
{
- 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 = vap->iv_bss;
@@ -1462,7 +1513,7 @@ urtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct urtwn_vap *uvp = URTWN_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct urtwn_softc *sc = ic->ic_softc;
+ struct urtwn_softc *sc = ic->ic_ifp->if_softc;
struct ieee80211_node *ni;
enum ieee80211_state ostate;
uint32_t reg;
@@ -1618,11 +1669,12 @@ static void
urtwn_watchdog(void *arg)
{
struct urtwn_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, urtwn_watchdog, sc);
@@ -1748,9 +1800,10 @@ static int
urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m0, struct urtwn_data *data)
{
+ struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = ni->ni_vap;
struct usb_xfer *xfer;
struct r92c_tx_desc *txd;
@@ -1889,78 +1942,89 @@ urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
return (0);
}
-static int
-urtwn_transmit(struct ieee80211com *ic, struct mbuf *m)
+static void
+urtwn_start(struct ifnet *ifp)
{
- struct urtwn_softc *sc = ic->ic_softc;
- int error;
+ struct urtwn_softc *sc = ifp->if_softc;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
URTWN_LOCK(sc);
- if ((sc->sc_flags & URTWN_RUNNING) == 0) {
- URTWN_UNLOCK(sc);
- return (ENXIO);
- }
- error = mbufq_enqueue(&sc->sc_snd, m);
- if (error) {
- URTWN_UNLOCK(sc);
- return (error);
- }
- urtwn_start(sc);
+ urtwn_start_locked(ifp, sc);
URTWN_UNLOCK(sc);
-
- return (0);
}
static void
-urtwn_start(struct urtwn_softc *sc)
+urtwn_start_locked(struct ifnet *ifp, struct urtwn_softc *sc)
{
struct ieee80211_node *ni;
struct mbuf *m;
struct urtwn_data *bf;
URTWN_ASSERT_LOCKED(sc);
- while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ for (;;) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
bf = urtwn_getbuf(sc);
if (bf == NULL) {
- mbufq_prepend(&sc->sc_snd, m);
+ IFQ_DRV_PREPEND(&ifp->if_snd, m);
break;
}
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
+
if (urtwn_tx_start(sc, ni, m, bf) != 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;
}
+
sc->sc_txtimer = 5;
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
}
}
-static void
-urtwn_parent(struct ieee80211com *ic)
+static int
+urtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct urtwn_softc *sc = ic->ic_softc;
- int startall = 0;
+ struct urtwn_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error = 0, startall = 0;
URTWN_LOCK(sc);
- if (sc->sc_flags & URTWN_DETACHED) {
- URTWN_UNLOCK(sc);
- return;
- }
- if (ic->ic_nrunning > 0) {
- if ((sc->sc_flags & URTWN_RUNNING) == 0) {
- urtwn_init(sc);
- startall = 1;
- }
- } else if (sc->sc_flags & URTWN_RUNNING)
- urtwn_stop(sc);
+ error = (sc->sc_flags & URTWN_DETACHED) ? ENXIO : 0;
URTWN_UNLOCK(sc);
+ if (error != 0)
+ return (error);
- if (startall)
- ieee80211_start_all(ic);
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ urtwn_init(ifp->if_softc);
+ startall = 1;
+ }
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ urtwn_stop(ifp);
+ }
+ 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
@@ -2874,7 +2938,7 @@ urtwn_get_txpower(struct urtwn_softc *sc, int chain,
struct ieee80211_channel *c, struct ieee80211_channel *extc,
uint16_t power[URTWN_RIDX_COUNT])
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct r92c_rom *rom = &sc->rom;
uint16_t cckpow, ofdmpow, htpow, diff, max;
const struct urtwn_txpwr *base;
@@ -2973,7 +3037,7 @@ urtwn_r88e_get_txpower(struct urtwn_softc *sc, int chain,
struct ieee80211_channel *c, struct ieee80211_channel *extc,
uint16_t power[URTWN_RIDX_COUNT])
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
uint16_t cckpow, ofdmpow, bw20pow, htpow;
const struct urtwn_r88e_txpwr *base;
int ridx, chan, group;
@@ -3070,7 +3134,7 @@ urtwn_scan_end(struct ieee80211com *ic)
static void
urtwn_set_channel(struct ieee80211com *ic)
{
- struct urtwn_softc *sc = ic->ic_softc;
+ struct urtwn_softc *sc = ic->ic_ifp->if_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
URTWN_LOCK(sc);
@@ -3092,7 +3156,7 @@ static void
urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c,
struct ieee80211_channel *extc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
uint32_t reg;
u_int chan;
int i;
@@ -3223,18 +3287,17 @@ urtwn_lc_calib(struct urtwn_softc *sc)
}
static void
-urtwn_init(struct urtwn_softc *sc)
+urtwn_init_locked(void *arg)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- uint8_t macaddr[IEEE80211_ADDR_LEN];
+ struct urtwn_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
uint32_t reg;
int error;
URTWN_ASSERT_LOCKED(sc);
- if (sc->sc_flags & URTWN_RUNNING)
- urtwn_stop(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ urtwn_stop_locked(ifp);
/* Init firmware commands ring. */
sc->fwcur = 0;
@@ -3277,8 +3340,8 @@ urtwn_init(struct urtwn_softc *sc)
}
/* Set MAC address. */
- IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr);
- urtwn_write_region_1(sc, R92C_MACID, macaddr, IEEE80211_ADDR_LEN);
+ urtwn_write_region_1(sc, R92C_MACID, IF_LLADDR(ifp),
+ IEEE80211_ADDR_LEN);
/* Set initial network type. */
reg = urtwn_read_4(sc, R92C_CR);
@@ -3402,7 +3465,8 @@ urtwn_init(struct urtwn_softc *sc)
usbd_transfer_start(sc->sc_xfer[URTWN_BULK_RX]);
- sc->sc_flags |= URTWN_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
fail:
@@ -3410,16 +3474,39 @@ fail:
}
static void
-urtwn_stop(struct urtwn_softc *sc)
+urtwn_init(void *arg)
+{
+ struct urtwn_softc *sc = arg;
+
+ URTWN_LOCK(sc);
+ urtwn_init_locked(arg);
+ URTWN_UNLOCK(sc);
+}
+
+static void
+urtwn_stop_locked(struct ifnet *ifp)
{
+ struct urtwn_softc *sc = ifp->if_softc;
URTWN_ASSERT_LOCKED(sc);
- sc->sc_flags &= ~URTWN_RUNNING;
+
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+
callout_stop(&sc->sc_watchdog_ch);
urtwn_abort_xfers(sc);
}
static void
+urtwn_stop(struct ifnet *ifp)
+{
+ struct urtwn_softc *sc = ifp->if_softc;
+
+ URTWN_LOCK(sc);
+ urtwn_stop_locked(ifp);
+ URTWN_UNLOCK(sc);
+}
+
+static void
urtwn_abort_xfers(struct urtwn_softc *sc)
{
int i;
@@ -3436,11 +3523,12 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct urtwn_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct urtwn_softc *sc = ifp->if_softc;
struct urtwn_data *bf;
/* prevent management frames from being sent if we're not ready */
- if (!(sc->sc_flags & URTWN_RUNNING)) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
m_freem(m);
ieee80211_free_node(ni);
return (ENETDOWN);
@@ -3454,8 +3542,10 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return (ENOBUFS);
}
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (urtwn_tx_start(sc, ni, m, bf) != 0) {
ieee80211_free_node(ni);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
URTWN_UNLOCK(sc);
return (EIO);
diff --git a/sys/dev/usb/wlan/if_urtwnreg.h b/sys/dev/usb/wlan/if_urtwnreg.h
index 0ca9db7..2bbec7a 100644
--- a/sys/dev/usb/wlan/if_urtwnreg.h
+++ b/sys/dev/usb/wlan/if_urtwnreg.h
@@ -1172,8 +1172,7 @@ enum {
#define URTWN_EP_QUEUES URTWN_BULK_RX
struct urtwn_softc {
- struct ieee80211com sc_ic;
- struct mbufq sc_snd;
+ struct ifnet *sc_ifp;
device_t sc_dev;
struct usb_device *sc_udev;
@@ -1181,7 +1180,6 @@ struct urtwn_softc {
u_int sc_flags;
#define URTWN_FLAG_CCK_HIPWR 0x01
#define URTWN_DETACHED 0x02
-#define URTWN_RUNNING 0x04
u_int chip;
#define URTWN_CHIP_92C 0x01
@@ -1226,6 +1224,7 @@ struct urtwn_softc {
uint8_t ht40_tx_pwr[5];
int8_t bw20_tx_pwr_diff;
int8_t ofdm_tx_pwr_diff;
+ uint8_t sc_bssid[IEEE80211_ADDR_LEN];
struct callout sc_watchdog_ch;
struct mtx sc_mtx;
diff --git a/sys/dev/usb/wlan/if_urtwvar.h b/sys/dev/usb/wlan/if_urtwvar.h
index a423214..e99cbf4 100644
--- a/sys/dev/usb/wlan/if_urtwvar.h
+++ b/sys/dev/usb/wlan/if_urtwvar.h
@@ -93,14 +93,14 @@ struct urtw_vap {
#define URTW_VAP(vap) ((struct urtw_vap *)(vap))
struct urtw_softc {
- struct ieee80211com sc_ic;
- struct mbufq sc_snd;
+ struct ifnet *sc_ifp;
device_t sc_dev;
struct usb_device *sc_udev;
struct mtx sc_mtx;
void *sc_tx_dma_buf;
int sc_debug;
+ int sc_if_flags;
int sc_flags;
#define URTW_INIT_ONCE (1 << 1)
#define URTW_RTL8187B (1 << 2)
@@ -108,13 +108,13 @@ struct urtw_softc {
#define URTW_RTL8187B_REV_D (1 << 4)
#define URTW_RTL8187B_REV_E (1 << 5)
#define URTW_DETACHED (1 << 6)
-#define URTW_RUNNING (1 << 7)
enum ieee80211_state sc_state;
int sc_epromtype;
#define URTW_EEPROM_93C46 0
#define URTW_EEPROM_93C56 1
uint8_t sc_crcmon;
+ uint8_t sc_bssid[IEEE80211_ADDR_LEN];
struct ieee80211_channel *sc_curchan;
diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c
index a86ab8a..8f9035e 100644
--- a/sys/dev/usb/wlan/if_zyd.c
+++ b/sys/dev/usb/wlan/if_zyd.c
@@ -154,12 +154,12 @@ static int zyd_set_beacon_interval(struct zyd_softc *, int);
static void zyd_rx_data(struct usb_xfer *, int, uint16_t);
static int zyd_tx_start(struct zyd_softc *, struct mbuf *,
struct ieee80211_node *);
-static int zyd_transmit(struct ieee80211com *, struct mbuf *);
-static void zyd_start(struct zyd_softc *);
+static void zyd_start(struct ifnet *);
static int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static void zyd_parent(struct ieee80211com *);
+static int zyd_ioctl(struct ifnet *, u_long, caddr_t);
static void zyd_init_locked(struct zyd_softc *);
+static void zyd_init(void *);
static void zyd_stop(struct zyd_softc *);
static int zyd_loadfirmware(struct zyd_softc *);
static void zyd_scan_start(struct ieee80211com *);
@@ -333,7 +333,8 @@ zyd_attach(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct zyd_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp;
+ struct ieee80211com *ic;
uint8_t iface_index, bands;
int error;
@@ -352,7 +353,6 @@ zyd_attach(device_t dev)
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
MTX_NETWORK_LOCK, MTX_DEF);
STAILQ_INIT(&sc->sc_rqh);
- mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = ZYD_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device,
@@ -372,6 +372,22 @@ zyd_attach(device_t dev)
}
ZYD_UNLOCK(sc);
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(sc->sc_dev, "can not if_alloc()\n");
+ goto detach;
+ }
+ ifp->if_softc = sc;
+ if_initname(ifp, "zyd", device_get_unit(sc->sc_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = zyd_init;
+ ifp->if_ioctl = zyd_ioctl;
+ ifp->if_start = zyd_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 */
@@ -392,17 +408,16 @@ zyd_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 = zyd_raw_xmit;
ic->ic_scan_start = zyd_scan_start;
ic->ic_scan_end = zyd_scan_end;
ic->ic_set_channel = zyd_set_channel;
+
ic->ic_vap_create = zyd_vap_create;
ic->ic_vap_delete = zyd_vap_delete;
ic->ic_update_mcast = zyd_update_mcast;
ic->ic_update_promisc = zyd_update_mcast;
- ic->ic_parent = zyd_parent;
- ic->ic_transmit = zyd_transmit;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -424,7 +439,8 @@ static int
zyd_detach(device_t dev)
{
struct zyd_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic;
unsigned int x;
/*
@@ -449,9 +465,11 @@ zyd_detach(device_t dev)
/* free USB transfers and some data buffers */
usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
- if (ic->ic_softc == sc)
+ if (ifp) {
+ ic = ifp->if_l2com;
ieee80211_ifdetach(ic);
- mbufq_drain(&sc->sc_snd);
+ if_free(ifp);
+ }
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -468,12 +486,15 @@ zyd_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
- zvp = malloc(sizeof(struct zyd_vap), M_80211_VAP, M_WAITOK | M_ZERO);
+ zvp = (struct zyd_vap *) malloc(sizeof(struct zyd_vap),
+ M_80211_VAP, M_NOWAIT | M_ZERO);
+ if (zvp == NULL)
+ return (NULL);
vap = &zvp->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(zvp, M_80211_VAP);
return (NULL);
@@ -488,7 +509,7 @@ zyd_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);
}
@@ -509,8 +530,13 @@ zyd_tx_free(struct zyd_tx_data *data, int txerr)
struct zyd_softc *sc = data->sc;
if (data->m != NULL) {
- ieee80211_tx_complete(data->ni, data->m, txerr);
+ if (data->m->m_flags & M_TXCB)
+ ieee80211_process_callback(data->ni, data->m,
+ txerr ? ETIMEDOUT : 0);
+ m_freem(data->m);
data->m = NULL;
+
+ ieee80211_free_node(data->ni);
data->ni = NULL;
}
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
@@ -567,7 +593,7 @@ zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct zyd_vap *zvp = ZYD_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct zyd_softc *sc = ic->ic_softc;
+ struct zyd_softc *sc = ic->ic_ifp->if_softc;
int error;
DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__,
@@ -592,8 +618,8 @@ zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
/* make data LED blink upon Tx */
zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1);
- IEEE80211_ADDR_COPY(ic->ic_macaddr, vap->iv_bss->ni_bssid);
- zyd_set_bssid(sc, ic->ic_macaddr);
+ IEEE80211_ADDR_COPY(sc->sc_bssid, vap->iv_bss->ni_bssid);
+ zyd_set_bssid(sc, sc->sc_bssid);
break;
default:
break;
@@ -611,7 +637,8 @@ static void
zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct zyd_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 ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct zyd_cmd *cmd = &sc->sc_ibuf;
@@ -654,9 +681,7 @@ zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
ieee80211_free_node(ni);
}
if (le16toh(retry->count) & 0x100)
- /* too many retries */
- if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS,
- 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); /* too many retries */
break;
}
case ZYD_NOTIF_IORD:
@@ -1218,7 +1243,8 @@ zyd_al2230_bandedge6(struct zyd_rf *rf, struct ieee80211_channel *c)
#define N(a) ((int)(sizeof(a) / sizeof((a)[0])))
int error = 0, i;
struct zyd_softc *sc = rf->rf_sc;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6;
int chan = ieee80211_chan2ieee(ic, c);
@@ -1906,7 +1932,7 @@ zyd_get_macaddr(struct zyd_softc *sc)
USETW(req.wIndex, 0);
USETW(req.wLength, IEEE80211_ADDR_LEN);
- error = zyd_do_request(sc, &req, sc->sc_ic.ic_macaddr);
+ error = zyd_do_request(sc, &req, sc->sc_bssid);
if (error != 0) {
device_printf(sc->sc_dev, "could not read EEPROM: %s\n",
usbd_errstr(error));
@@ -1978,41 +2004,36 @@ fail:
static void
zyd_set_multi(struct zyd_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
- uint32_t low, high;
int error;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifmultiaddr *ifma;
+ uint32_t low, high;
+ uint8_t v;
- if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0)
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
low = 0x00000000;
high = 0x80000000;
- if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 ||
- ic->ic_promisc > 0) {
+ if (ic->ic_opmode == IEEE80211_M_MONITOR ||
+ (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
low = 0xffffffff;
high = 0xffffffff;
} else {
- struct ieee80211vap *vap;
- struct ifnet *ifp;
- struct ifmultiaddr *ifma;
- uint8_t v;
-
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
- ifp = vap->iv_ifp;
- if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- v = ((uint8_t *)LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr))[5] >> 2;
- if (v < 32)
- low |= 1 << v;
- else
- high |= 1 << (v - 32);
- }
- if_maddr_runlock(ifp);
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ v = ((uint8_t *)LLADDR((struct sockaddr_dl *)
+ ifma->ifma_addr))[5] >> 2;
+ if (v < 32)
+ low |= 1 << v;
+ else
+ high |= 1 << (v - 32);
}
+ if_maddr_runlock(ifp);
}
/* reprogram multicast global hash table */
@@ -2029,6 +2050,9 @@ zyd_update_mcast(struct ieee80211com *ic)
{
struct zyd_softc *sc = ic->ic_softc;
+ if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ return;
+
ZYD_LOCK(sc);
zyd_set_multi(sc);
ZYD_UNLOCK(sc);
@@ -2037,7 +2061,8 @@ zyd_update_mcast(struct ieee80211com *ic)
static int
zyd_set_rxfilter(struct zyd_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint32_t rxfilter;
switch (ic->ic_opmode) {
@@ -2062,7 +2087,8 @@ static void
zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c)
{
int error;
- struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct zyd_rf *rf = &sc->sc_rf;
uint32_t tmp;
int chan;
@@ -2153,7 +2179,8 @@ static void
zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
{
struct zyd_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 zyd_plcphdr plcp;
struct zyd_rx_stat stat;
struct usb_page_cache *pc;
@@ -2163,7 +2190,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
if (len < ZYD_MIN_FRAGSZ) {
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too short (length=%d)\n",
device_get_nameunit(sc->sc_dev), len);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return;
}
pc = usbd_xfer_get_frame(xfer, 0);
@@ -2174,7 +2201,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
DPRINTF(sc, ZYD_DEBUG_RECV,
"%s: RX status indicated error (%x)\n",
device_get_nameunit(sc->sc_dev), stat.flags);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return;
}
@@ -2186,7 +2213,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
if (rlen > (int)MCLBYTES) {
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too long (length=%d)\n",
device_get_nameunit(sc->sc_dev), rlen);
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return;
} else if (rlen > (int)MHLEN)
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
@@ -2195,9 +2222,10 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
if (m == NULL) {
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: could not allocate rx mbuf\n",
device_get_nameunit(sc->sc_dev));
- counter_u64_add(ic->ic_ierrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return;
}
+ m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = rlen;
usbd_copy_out(pc, offset + sizeof(plcp), mtod(m, uint8_t *), rlen);
@@ -2227,7 +2255,8 @@ static void
zyd_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct zyd_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_node *ni;
struct zyd_rx_desc desc;
struct mbuf *m;
@@ -2299,8 +2328,10 @@ tr_setup:
} else
(void)ieee80211_input_all(ic, m, rssi, nf);
}
+ if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
+ !IFQ_IS_EMPTY(&ifp->if_snd))
+ zyd_start(ifp);
ZYD_LOCK(sc);
- zyd_start(sc);
break;
default: /* Error */
@@ -2355,6 +2386,7 @@ static void
zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct zyd_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap;
struct zyd_tx_data *data;
struct mbuf *m;
@@ -2373,6 +2405,9 @@ zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
zyd_tx_free(data, 0);
usbd_xfer_set_priv(xfer, NULL);
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@@ -2405,14 +2440,16 @@ tr_setup:
usbd_xfer_set_priv(xfer, data);
usbd_transfer_submit(xfer);
}
- zyd_start(sc);
+ ZYD_UNLOCK(sc);
+ zyd_start(ifp);
+ ZYD_LOCK(sc);
break;
default: /* Error */
DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n",
usbd_errstr(error));
- counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
data = usbd_xfer_get_priv(xfer);
usbd_xfer_set_priv(xfer, NULL);
if (data != NULL)
@@ -2553,45 +2590,31 @@ zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
return (0);
}
-static int
-zyd_transmit(struct ieee80211com *ic, struct mbuf *m)
-{
- struct zyd_softc *sc = ic->ic_softc;
- int error;
-
- ZYD_LOCK(sc);
- if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0) {
- ZYD_UNLOCK(sc);
- return (ENXIO);
- }
- error = mbufq_enqueue(&sc->sc_snd, m);
- if (error) {
- ZYD_UNLOCK(sc);
- return (error);
- }
- zyd_start(sc);
- ZYD_UNLOCK(sc);
-
- return (0);
-}
-
static void
-zyd_start(struct zyd_softc *sc)
+zyd_start(struct ifnet *ifp)
{
+ struct zyd_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
- ZYD_LOCK_ASSERT(sc, MA_OWNED);
-
- while (sc->tx_nfree > 0 && (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ ZYD_LOCK(sc);
+ for (;;) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+ if (sc->tx_nfree == 0) {
+ IFQ_DRV_PREPEND(&ifp->if_snd, m);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (zyd_tx_start(sc, m, ni) != 0) {
ieee80211_free_node(ni);
- if_inc_counter(ni->ni_vap->iv_ifp,
- IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
}
+ ZYD_UNLOCK(sc);
}
static int
@@ -2599,17 +2622,19 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct zyd_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct zyd_softc *sc = ifp->if_softc;
ZYD_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(sc->sc_flags & ZYD_FLAG_RUNNING)) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
ZYD_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return (ENETDOWN);
}
if (sc->tx_nfree == 0) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
ZYD_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
@@ -2623,6 +2648,7 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
*/
if (zyd_tx_start(sc, m, ni) != 0) {
ZYD_UNLOCK(sc);
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
return (EIO);
}
@@ -2630,35 +2656,56 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return (0);
}
-static void
-zyd_parent(struct ieee80211com *ic)
+static int
+zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct zyd_softc *sc = ic->ic_softc;
+ struct zyd_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error;
int startall = 0;
ZYD_LOCK(sc);
- if (sc->sc_flags & ZYD_FLAG_DETACHED) {
+ error = (sc->sc_flags & ZYD_FLAG_DETACHED) ? ENXIO : 0;
+ ZYD_UNLOCK(sc);
+ if (error)
+ return (error);
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ ZYD_LOCK(sc);
+ if (ifp->if_flags & IFF_UP) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ zyd_init_locked(sc);
+ startall = 1;
+ } else
+ zyd_set_multi(sc);
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ zyd_stop(sc);
+ }
ZYD_UNLOCK(sc);
- return;
+ 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;
}
- if (ic->ic_nrunning > 0) {
- if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0) {
- zyd_init_locked(sc);
- startall = 1;
- } else
- zyd_set_multi(sc);
- } else if (sc->sc_flags & ZYD_FLAG_RUNNING)
- zyd_stop(sc);
- ZYD_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
+ return (error);
}
static void
zyd_init_locked(struct zyd_softc *sc)
{
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
struct usb_config_descriptor *cd;
int error;
uint32_t val;
@@ -2710,12 +2757,12 @@ zyd_init_locked(struct zyd_softc *sc)
sc->sc_flags |= ZYD_FLAG_INITONCE;
}
- if (sc->sc_flags & ZYD_FLAG_RUNNING)
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
zyd_stop(sc);
DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %6D\n",
- vap ? vap->iv_myaddr : ic->ic_macaddr, ":");
- error = zyd_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
+ IF_LLADDR(ifp), ":");
+ error = zyd_set_macaddr(sc, IF_LLADDR(ifp));
if (error != 0)
return;
@@ -2751,7 +2798,8 @@ zyd_init_locked(struct zyd_softc *sc)
/* enable interrupts */
zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK);
- sc->sc_flags |= ZYD_FLAG_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
usbd_xfer_set_stall(sc->sc_xfer[ZYD_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[ZYD_BULK_RD]);
usbd_transfer_start(sc->sc_xfer[ZYD_INTR_RD]);
@@ -2763,13 +2811,29 @@ fail: zyd_stop(sc);
}
static void
+zyd_init(void *priv)
+{
+ struct zyd_softc *sc = priv;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ ZYD_LOCK(sc);
+ zyd_init_locked(sc);
+ ZYD_UNLOCK(sc);
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ieee80211_start_all(ic); /* start all vap's */
+}
+
+static void
zyd_stop(struct zyd_softc *sc)
{
+ struct ifnet *ifp = sc->sc_ifp;
int error;
ZYD_LOCK_ASSERT(sc, MA_OWNED);
- sc->sc_flags &= ~ZYD_FLAG_RUNNING;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
/*
* Drain all the transfers, if not already drained:
@@ -2861,29 +2925,30 @@ zyd_loadfirmware(struct zyd_softc *sc)
static void
zyd_scan_start(struct ieee80211com *ic)
{
- struct zyd_softc *sc = ic->ic_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct zyd_softc *sc = ifp->if_softc;
ZYD_LOCK(sc);
/* want broadcast address while scanning */
- zyd_set_bssid(sc, ieee80211broadcastaddr);
+ zyd_set_bssid(sc, ifp->if_broadcastaddr);
ZYD_UNLOCK(sc);
}
static void
zyd_scan_end(struct ieee80211com *ic)
{
- struct zyd_softc *sc = ic->ic_softc;
+ struct zyd_softc *sc = ic->ic_ifp->if_softc;
ZYD_LOCK(sc);
/* restore previous bssid */
- zyd_set_bssid(sc, ic->ic_macaddr);
+ zyd_set_bssid(sc, sc->sc_bssid);
ZYD_UNLOCK(sc);
}
static void
zyd_set_channel(struct ieee80211com *ic)
{
- struct zyd_softc *sc = ic->ic_softc;
+ struct zyd_softc *sc = ic->ic_ifp->if_softc;
ZYD_LOCK(sc);
zyd_set_chan(sc, ic->ic_curchan);
diff --git a/sys/dev/usb/wlan/if_zydreg.h b/sys/dev/usb/wlan/if_zydreg.h
index ec61d06..05d94e3 100644
--- a/sys/dev/usb/wlan/if_zydreg.h
+++ b/sys/dev/usb/wlan/if_zydreg.h
@@ -1249,8 +1249,7 @@ enum {
};
struct zyd_softc {
- struct ieee80211com sc_ic;
- struct mbufq sc_snd;
+ struct ifnet *sc_ifp;
device_t sc_dev;
struct usb_device *sc_udev;
@@ -1261,13 +1260,13 @@ struct zyd_softc {
#define ZYD_FLAG_INITONCE (1 << 1)
#define ZYD_FLAG_INITDONE (1 << 2)
#define ZYD_FLAG_DETACHED (1 << 3)
-#define ZYD_FLAG_RUNNING (1 << 4)
struct zyd_rf sc_rf;
STAILQ_HEAD(, zyd_rq) sc_rtx;
STAILQ_HEAD(, zyd_rq) sc_rqh;
+ uint8_t sc_bssid[IEEE80211_ADDR_LEN];
uint16_t sc_fwbase;
uint8_t sc_regdomain;
uint8_t sc_macrev;
OpenPOWER on IntegriCloud