diff options
author | adrian <adrian@FreeBSD.org> | 2015-08-08 01:10:17 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2015-08-08 01:10:17 +0000 |
commit | bad6d5c89b6ffd35818850d95cb88e218dee73b3 (patch) | |
tree | 5973a9059f73ed5abf84d6d98e44f1953e764064 /sys/dev/usb | |
parent | 33a3844dbf69152b9d47f6fa1ac1c2d5b1d502e4 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/dev/usb/wlan/if_rsu.c | 299 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_rsureg.h | 9 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_rum.c | 302 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_rumvar.h | 7 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_run.c | 363 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_runvar.h | 9 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_uath.c | 308 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_uathvar.h | 3 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_upgt.c | 323 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_upgtvar.h | 6 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_ural.c | 284 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_uralvar.h | 7 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_urtw.c | 338 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_urtwn.c | 282 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_urtwnreg.h | 5 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_urtwvar.h | 6 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_zyd.c | 299 | ||||
-rw-r--r-- | sys/dev/usb/wlan/if_zydreg.h | 5 |
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; |