diff options
Diffstat (limited to 'sys/dev/wi')
-rw-r--r-- | sys/dev/wi/if_wi.c | 382 | ||||
-rw-r--r-- | sys/dev/wi/if_wi_macio.c | 1 | ||||
-rw-r--r-- | sys/dev/wi/if_wi_pccard.c | 1 | ||||
-rw-r--r-- | sys/dev/wi/if_wi_pci.c | 17 | ||||
-rw-r--r-- | sys/dev/wi/if_wivar.h | 8 |
5 files changed, 162 insertions, 247 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index b316d46..f8af231 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -116,11 +116,9 @@ static struct ieee80211vap *wi_vap_create(struct ieee80211com *, const uint8_t [IEEE80211_ADDR_LEN], const uint8_t [IEEE80211_ADDR_LEN]); static void wi_vap_delete(struct ieee80211vap *vap); -static void wi_stop_locked(struct wi_softc *sc, int disable); -static void wi_start_locked(struct ifnet *); -static void wi_start(struct ifnet *); -static int wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, - struct mbuf *m0); +static int wi_transmit(struct ieee80211com *, struct mbuf *); +static void wi_start(struct wi_softc *); +static int wi_start_tx(struct wi_softc *, struct wi_frame *, struct mbuf *); static int wi_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); static int wi_newstate_sta(struct ieee80211vap *, enum ieee80211_state, int); @@ -131,10 +129,8 @@ static void wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf); static int wi_reset(struct wi_softc *); static void wi_watchdog(void *); -static int wi_ioctl(struct ifnet *, u_long, caddr_t); +static void wi_parent(struct ieee80211com *); static void wi_media_status(struct ifnet *, struct ifmediareq *); -static uint64_t wi_get_counter(struct ifnet *, ift_counter); - static void wi_rx_intr(struct wi_softc *); static void wi_tx_intr(struct wi_softc *); static void wi_tx_ex_intr(struct wi_softc *); @@ -153,10 +149,10 @@ static int wi_write_ssid(struct wi_softc *, int, u_int8_t *, int); static int wi_cmd(struct wi_softc *, int, int, int, int); static int wi_seek_bap(struct wi_softc *, int, int); static int wi_read_bap(struct wi_softc *, int, int, void *, int); -static int wi_write_bap(struct wi_softc *, int, int, void *, int); +static int wi_write_bap(struct wi_softc *, int, int, const void *, int); static int wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int); static int wi_read_rid(struct wi_softc *, int, void *, int *); -static int wi_write_rid(struct wi_softc *, int, void *, int); +static int wi_write_rid(struct wi_softc *, int, const void *, int); static int wi_write_appie(struct wi_softc *, int, const struct ieee80211_appie *); static void wi_scan_start(struct ieee80211com *); @@ -237,8 +233,7 @@ int wi_attach(device_t dev) { struct wi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic; - struct ifnet *ifp; + struct ieee80211com *ic = &sc->sc_ic; int i, nrates, buflen; u_int16_t val; u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE]; @@ -249,15 +244,6 @@ wi_attach(device_t dev) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; int error; - uint8_t macaddr[IEEE80211_ADDR_LEN]; - - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(dev, "can not if_alloc\n"); - wi_free(dev); - return ENOSPC; - } - ic = ifp->if_l2com; sc->sc_firmware_type = WI_NOTYPE; sc->wi_cmd_count = 500; @@ -309,6 +295,7 @@ wi_attach(device_t dev) mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0); + mbufq_init(&sc->sc_snd, ifqmaxlen); /* * Read the station address. @@ -317,12 +304,13 @@ wi_attach(device_t dev) * the probe to fail. */ buflen = IEEE80211_ADDR_LEN; - error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen); + error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr, &buflen); if (error != 0) { buflen = IEEE80211_ADDR_LEN; - error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen); + error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr, + &buflen); } - if (error || IEEE80211_ADDR_EQ(macaddr, empty_macaddr)) { + if (error || IEEE80211_ADDR_EQ(&ic->ic_macaddr, empty_macaddr)) { if (error != 0) device_printf(dev, "mac read failed %d\n", error); else { @@ -333,18 +321,6 @@ wi_attach(device_t dev) return (error); } - ifp->if_softc = sc; - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = wi_ioctl; - ifp->if_start = wi_start; - ifp->if_init = wi_init; - ifp->if_get_counter = wi_get_counter; - 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(dev); ic->ic_phytype = IEEE80211_T_DS; @@ -458,16 +434,17 @@ wi_attach(device_t dev) sc->sc_portnum = WI_DEFAULT_PORT; - ieee80211_ifattach(ic, macaddr); + ieee80211_ifattach(ic); ic->ic_raw_xmit = wi_raw_xmit; ic->ic_scan_start = wi_scan_start; ic->ic_scan_end = wi_scan_end; ic->ic_set_channel = wi_set_channel; - ic->ic_vap_create = wi_vap_create; ic->ic_vap_delete = wi_vap_delete; ic->ic_update_mcast = wi_update_mcast; ic->ic_update_promisc = wi_update_promisc; + ic->ic_transmit = wi_transmit; + ic->ic_parent = wi_parent; ieee80211_radiotap_attach(ic, &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th), @@ -483,7 +460,6 @@ wi_attach(device_t dev) if (error) { device_printf(dev, "bus_setup_intr() failed! (%d)\n", error); ieee80211_ifdetach(ic); - if_free(sc->sc_ifp); wi_free(dev); return error; } @@ -495,21 +471,20 @@ int wi_detach(device_t dev) { struct wi_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; WI_LOCK(sc); /* check if device was removed */ sc->wi_gone |= !bus_child_present(dev); - wi_stop_locked(sc, 0); + wi_stop(sc, 0); WI_UNLOCK(sc); ieee80211_ifdetach(ic); bus_teardown_intr(dev, sc->irq, sc->wi_intrhand); - if_free(sc->sc_ifp); wi_free(dev); + mbufq_drain(&sc->sc_snd); mtx_destroy(&sc->sc_mtx); return (0); } @@ -520,19 +495,16 @@ wi_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 wi_softc *sc = ic->ic_ifp->if_softc; + struct wi_softc *sc = ic->ic_softc; struct wi_vap *wvp; struct ieee80211vap *vap; if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return NULL; - wvp = (struct wi_vap *) malloc(sizeof(struct wi_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (wvp == NULL) - return NULL; + wvp = malloc(sizeof(struct wi_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &wvp->wv_vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); vap->iv_max_aid = WI_MAX_AID; @@ -566,7 +538,7 @@ wi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, } /* complete setup */ - ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status); + ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status, mac); ic->ic_opmode = opmode; return vap; } @@ -585,7 +557,9 @@ wi_shutdown(device_t dev) { struct wi_softc *sc = device_get_softc(dev); + WI_LOCK(sc); wi_stop(sc, 1); + WI_UNLOCK(sc); return (0); } @@ -593,12 +567,12 @@ void wi_intr(void *arg) { struct wi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; u_int16_t status; WI_LOCK(sc); - if (sc->wi_gone || !sc->sc_enabled || (ifp->if_flags & IFF_UP) == 0) { + if (sc->wi_gone || !sc->sc_enabled || + (sc->sc_flags & WI_FLAGS_RUNNING) == 0) { CSR_WRITE_2(sc, WI_INT_EN, 0); CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF); WI_UNLOCK(sc); @@ -617,9 +591,8 @@ wi_intr(void *arg) wi_tx_ex_intr(sc); if (status & WI_EV_INFO) wi_info_intr(sc); - if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 && - !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) - wi_start_locked(ifp); + if (mbufq_first(&sc->sc_snd) != NULL) + wi_start(sc); /* Re-enable interrupts. */ CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS); @@ -642,7 +615,7 @@ wi_enable(struct wi_softc *sc) static int wi_setup_locked(struct wi_softc *sc, int porttype, int mode, - uint8_t mac[IEEE80211_ADDR_LEN]) + const uint8_t mac[IEEE80211_ADDR_LEN]) { int i; @@ -676,26 +649,25 @@ wi_setup_locked(struct wi_softc *sc, int porttype, int mode, return 0; } -static void -wi_init_locked(struct wi_softc *sc) +void +wi_init(struct wi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; int wasenabled; WI_LOCK_ASSERT(sc); wasenabled = sc->sc_enabled; if (wasenabled) - wi_stop_locked(sc, 1); + wi_stop(sc, 1); - if (wi_setup_locked(sc, sc->sc_porttype, 3, IF_LLADDR(ifp)) != 0) { - if_printf(ifp, "interface not running\n"); - wi_stop_locked(sc, 1); + if (wi_setup_locked(sc, sc->sc_porttype, 3, + sc->sc_ic.ic_macaddr) != 0) { + device_printf(sc->sc_dev, "interface not running\n"); + wi_stop(sc, 1); return; } - ifp->if_drv_flags |= IFF_DRV_RUNNING; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + sc->sc_flags |= WI_FLAGS_RUNNING; callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc); @@ -703,24 +675,8 @@ wi_init_locked(struct wi_softc *sc) } void -wi_init(void *arg) -{ - struct wi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - - WI_LOCK(sc); - wi_init_locked(sc); - WI_UNLOCK(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ieee80211_start_all(ic); /* start all vap's */ -} - -static void -wi_stop_locked(struct wi_softc *sc, int disable) +wi_stop(struct wi_softc *sc, int disable) { - struct ifnet *ifp = sc->sc_ifp; WI_LOCK_ASSERT(sc); @@ -736,22 +692,13 @@ wi_stop_locked(struct wi_softc *sc, int disable) sc->sc_tx_timer = 0; sc->sc_false_syns = 0; - ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE | IFF_DRV_RUNNING); -} - -void -wi_stop(struct wi_softc *sc, int disable) -{ - WI_LOCK(sc); - wi_stop_locked(sc, disable); - WI_UNLOCK(sc); + sc->sc_flags &= ~WI_FLAGS_RUNNING; } static void wi_set_channel(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct wi_softc *sc = ifp->if_softc; + struct wi_softc *sc = ic->ic_softc; DPRINTF(("%s: channel %d, %sscanning\n", __func__, ieee80211_chan2ieee(ic, ic->ic_curchan), @@ -766,8 +713,7 @@ wi_set_channel(struct ieee80211com *ic) static void wi_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct wi_softc *sc = ifp->if_softc; + struct wi_softc *sc = ic->ic_softc; struct ieee80211_scan_state *ss = ic->ic_scan; DPRINTF(("%s\n", __func__)); @@ -790,8 +736,7 @@ wi_scan_start(struct ieee80211com *ic) static void wi_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct wi_softc *sc = ifp->if_softc; + struct wi_softc *sc = ic->ic_softc; DPRINTF(("%s: restore port type %d\n", __func__, sc->sc_porttype)); @@ -824,9 +769,8 @@ static int wi_newstate_sta(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; struct ieee80211_node *bss; - struct wi_softc *sc = ifp->if_softc; + struct wi_softc *sc = ic->ic_softc; DPRINTF(("%s: %s -> %s\n", __func__, ieee80211_state_name[vap->iv_state], @@ -894,9 +838,8 @@ static int wi_newstate_hostap(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; struct ieee80211_node *bss; - struct wi_softc *sc = ifp->if_softc; + struct wi_softc *sc = ic->ic_softc; int error; DPRINTF(("%s: %s -> %s\n", __func__, @@ -953,10 +896,30 @@ wi_newstate_hostap(struct ieee80211vap *vap, enum ieee80211_state nstate, int ar return error; } +static int +wi_transmit(struct ieee80211com *ic, struct mbuf *m) +{ + struct wi_softc *sc = ic->ic_softc; + int error; + + WI_LOCK(sc); + if ((sc->sc_flags & WI_FLAGS_RUNNING) == 0) { + WI_UNLOCK(sc); + return (ENXIO); + } + error = mbufq_enqueue(&sc->sc_snd, m); + if (error) { + WI_UNLOCK(sc); + return (error); + } + wi_start(sc); + WI_UNLOCK(sc); + return (0); +} + static void -wi_start_locked(struct ifnet *ifp) +wi_start(struct wi_softc *sc) { - struct wi_softc *sc = ifp->if_softc; struct ieee80211_node *ni; struct ieee80211_frame *wh; struct mbuf *m0; @@ -972,15 +935,8 @@ wi_start_locked(struct ifnet *ifp) memset(&frmhdr, 0, sizeof(frmhdr)); cur = sc->sc_txnext; - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m0); - if (m0 == NULL) - break; - if (sc->sc_txd[cur].d_len != 0) { - IFQ_DRV_PREPEND(&ifp->if_snd, m0); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - break; - } + while (sc->sc_txd[cur].d_len == 0 && + (m0 = mbufq_dequeue(&sc->sc_snd)) != NULL) { ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif; /* reconstruct 802.3 header */ @@ -1029,28 +985,16 @@ wi_start_locked(struct ifnet *ifp) m_adj(m0, sizeof(struct ieee80211_frame)); frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len); ieee80211_free_node(ni); - if (wi_start_tx(ifp, &frmhdr, m0)) + if (wi_start_tx(sc, &frmhdr, m0)) continue; sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf; - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); } } -static void -wi_start(struct ifnet *ifp) -{ - struct wi_softc *sc = ifp->if_softc; - - WI_LOCK(sc); - wi_start_locked(ifp); - WI_UNLOCK(sc); -} - static int -wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0) +wi_start_tx(struct wi_softc *sc, struct wi_frame *frmhdr, struct mbuf *m0) { - struct wi_softc *sc = ifp->if_softc; int cur = sc->sc_txnext; int fid, off, error; @@ -1060,13 +1004,13 @@ wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0) || wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0; m_freem(m0); if (error) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); return -1; } sc->sc_txd[cur].d_len = off; if (sc->sc_txcur == cur) { if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) { - if_printf(ifp, "xmit failed\n"); + device_printf(sc->sc_dev, "xmit failed\n"); sc->sc_txd[cur].d_len = 0; return -1; } @@ -1080,9 +1024,8 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0, const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; - struct ifnet *ifp = ic->ic_ifp; struct ieee80211vap *vap = ni->ni_vap; - struct wi_softc *sc = ifp->if_softc; + struct wi_softc *sc = ic->ic_softc; struct ieee80211_key *k; struct ieee80211_frame *wh; struct wi_frame frmhdr; @@ -1098,7 +1041,6 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0, memset(&frmhdr, 0, sizeof(frmhdr)); cur = sc->sc_txnext; if (sc->sc_txd[cur].d_len != 0) { - ifp->if_drv_flags |= IFF_DRV_OACTIVE; rc = ENOBUFS; goto out; } @@ -1129,7 +1071,7 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0, (caddr_t)&frmhdr.wi_whdr); m_adj(m0, sizeof(struct ieee80211_frame)); frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len); - if (wi_start_tx(ifp, &frmhdr, m0) < 0) { + if (wi_start_tx(sc, &frmhdr, m0) < 0) { m0 = NULL; rc = EIO; goto out; @@ -1160,7 +1102,7 @@ wi_reset(struct wi_softc *sc) } sc->sc_reset = 1; if (i == WI_INIT_TRIES) { - if_printf(sc->sc_ifp, "reset failed\n"); + device_printf(sc->sc_dev, "reset failed\n"); return error; } @@ -1178,7 +1120,6 @@ static void wi_watchdog(void *arg) { struct wi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; WI_LOCK_ASSERT(sc); @@ -1186,65 +1127,52 @@ wi_watchdog(void *arg) return; if (sc->sc_tx_timer && --sc->sc_tx_timer == 0) { - if_printf(ifp, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - wi_init_locked(ifp->if_softc); + device_printf(sc->sc_dev, "device timeout\n"); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); + wi_init(sc); return; } callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc); } -static int -wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +wi_parent(struct ieee80211com *ic) { - struct wi_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + struct wi_softc *sc = ic->ic_softc; + int startall = 0; - switch (cmd) { - case SIOCSIFFLAGS: - WI_LOCK(sc); - /* - * Can't do promisc and hostap at the same time. If all that's - * changing is the promisc flag, try to short-circuit a call to - * wi_init() by just setting PROMISC in the hardware. - */ - if (ifp->if_flags & IFF_UP) { - if (ic->ic_opmode != IEEE80211_M_HOSTAP && - ifp->if_drv_flags & IFF_DRV_RUNNING) { - if ((ifp->if_flags ^ sc->sc_if_flags) & IFF_PROMISC) { - wi_write_val(sc, WI_RID_PROMISC, - (ifp->if_flags & IFF_PROMISC) != 0); - } else { - wi_init_locked(sc); - startall = 1; - } + WI_LOCK(sc); + /* + * Can't do promisc and hostap at the same time. If all that's + * changing is the promisc flag, try to short-circuit a call to + * wi_init() by just setting PROMISC in the hardware. + */ + if (ic->ic_nrunning > 0) { + if (ic->ic_opmode != IEEE80211_M_HOSTAP && + sc->sc_flags & WI_FLAGS_RUNNING) { + if (ic->ic_promisc > 0 && + (sc->sc_flags & WI_FLAGS_PROMISC) == 0) { + wi_write_val(sc, WI_RID_PROMISC, 1); + sc->sc_flags |= WI_FLAGS_PROMISC; + } else if (ic->ic_promisc == 0 && + (sc->sc_flags & WI_FLAGS_PROMISC) != 0) { + wi_write_val(sc, WI_RID_PROMISC, 0); + sc->sc_flags &= ~WI_FLAGS_PROMISC; } else { - wi_init_locked(sc); + wi_init(sc); startall = 1; } } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - wi_stop_locked(sc, 1); - sc->wi_gone = 0; + wi_init(sc); + startall = 1; } - sc->sc_if_flags = ifp->if_flags; - WI_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; + } else if (sc->sc_flags & WI_FLAGS_RUNNING) { + wi_stop(sc, 1); + sc->wi_gone = 0; } - return error; + WI_UNLOCK(sc); + if (startall) + ieee80211_start_all(ic); } static void @@ -1252,7 +1180,7 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr) { struct ieee80211vap *vap = ifp->if_softc; struct ieee80211com *ic = vap->iv_ic; - struct wi_softc *sc = ic->ic_ifp->if_softc; + struct wi_softc *sc = ic->ic_softc; u_int16_t val; int rate, len; @@ -1280,8 +1208,7 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr) static void wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN]) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); struct ieee80211_node *ni = vap->iv_bss; @@ -1295,7 +1222,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN]) * indicator of the firmware's BSSID. Damp spurious * change-of-BSSID indications. */ - if ((ifp->if_flags & IFF_PROMISC) != 0 && + if (ic->ic_promisc > 0 && !ppsratecheck(&sc->sc_last_syn, &sc->sc_false_syns, WI_MAX_FALSE_SYNS)) return; @@ -1316,8 +1243,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN]) static __noinline void wi_rx_intr(struct wi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct wi_frame frmhdr; struct mbuf *m; struct ieee80211_frame *wh; @@ -1332,7 +1258,7 @@ wi_rx_intr(struct wi_softc *sc) /* First read in the frame header */ if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); DPRINTF(("wi_rx_intr: read fid %x failed\n", fid)); return; } @@ -1343,7 +1269,7 @@ wi_rx_intr(struct wi_softc *sc) status = le16toh(frmhdr.wi_status); if (status & WI_STAT_ERRSTAT) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status)); return; } @@ -1358,7 +1284,7 @@ wi_rx_intr(struct wi_softc *sc) if (off + len > MCLBYTES) { if (ic->ic_opmode != IEEE80211_M_MONITOR) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); DPRINTF(("wi_rx_intr: oversized packet\n")); return; } else @@ -1371,7 +1297,7 @@ wi_rx_intr(struct wi_softc *sc) m = m_gethdr(M_NOWAIT, MT_DATA); if (m == NULL) { CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); DPRINTF(("wi_rx_intr: MGET failed\n")); return; } @@ -1380,7 +1306,6 @@ wi_rx_intr(struct wi_softc *sc) wi_read_bap(sc, fid, sizeof(frmhdr), m->m_data + sizeof(struct ieee80211_frame), len); m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len; - m->m_pkthdr.rcvif = ifp; CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX); @@ -1425,7 +1350,6 @@ wi_rx_intr(struct wi_softc *sc) static __noinline void wi_tx_ex_intr(struct wi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; struct wi_frame frmhdr; int fid; @@ -1440,7 +1364,7 @@ wi_tx_ex_intr(struct wi_softc *sc) */ if ((status & WI_TXSTAT_DISCONNECT) == 0) { if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) { - if_printf(ifp, "tx failed"); + device_printf(sc->sc_dev, "tx failed"); if (status & WI_TXSTAT_RET_ERR) printf(", retry limit exceeded"); if (status & WI_TXSTAT_AGED_ERR) @@ -1455,7 +1379,7 @@ wi_tx_ex_intr(struct wi_softc *sc) printf(", status=0x%x", status); printf("\n"); } - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->sc_ic.ic_oerrors, 1); } else DPRINTF(("port disconnected\n")); } else @@ -1466,7 +1390,6 @@ wi_tx_ex_intr(struct wi_softc *sc) static __noinline void wi_tx_intr(struct wi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; int fid, cur; if (sc->wi_gone) @@ -1477,19 +1400,17 @@ wi_tx_intr(struct wi_softc *sc) cur = sc->sc_txcur; if (sc->sc_txd[cur].d_fid != fid) { - if_printf(ifp, "bad alloc %x != %x, cur %d nxt %d\n", + device_printf(sc->sc_dev, "bad alloc %x != %x, cur %d nxt %d\n", fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext); return; } sc->sc_tx_timer = 0; sc->sc_txd[cur].d_len = 0; sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf; - if (sc->sc_txd[cur].d_len == 0) - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - else { + if (sc->sc_txd[cur].d_len != 0) { if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid, 0, 0)) { - if_printf(ifp, "xmit failed\n"); + device_printf(sc->sc_dev, "xmit failed\n"); sc->sc_txd[cur].d_len = 0; } else { sc->sc_tx_timer = 5; @@ -1500,7 +1421,7 @@ wi_tx_intr(struct wi_softc *sc) static __noinline void wi_info_intr(struct wi_softc *sc) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); int i, fid, len, off; u_int16_t ltbuf[2]; @@ -1574,32 +1495,15 @@ finish: CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO); } -static uint64_t -wi_get_counter(struct ifnet *ifp, ift_counter cnt) -{ - struct wi_softc *sc; - - sc = if_getsoftc(ifp); - - switch (cnt) { - case IFCOUNTER_COLLISIONS: - return (sc->sc_stats.wi_tx_single_retries + - sc->sc_stats.wi_tx_multi_retries + - sc->sc_stats.wi_tx_retry_limit); - default: - return (if_get_counter_default(ifp, cnt)); - } -} - static int wi_write_multi(struct wi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - int n; - struct ifmultiaddr *ifma; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap; struct wi_mcast mlist; + int n; - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { + if (ic->ic_allmulti > 0 || ic->ic_promisc > 0) { allmulti: memset(&mlist, 0, sizeof(mlist)); return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist, @@ -1607,17 +1511,23 @@ allmulti: } n = 0; - if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - if (n >= 16) - goto allmulti; - IEEE80211_ADDR_COPY(&mlist.wi_mcast[n], - (LLADDR((struct sockaddr_dl *)ifma->ifma_addr))); - n++; + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { + struct ifnet *ifp; + struct ifmultiaddr *ifma; + + 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; + if (n >= 16) + goto allmulti; + IEEE80211_ADDR_COPY(&mlist.wi_mcast[n], + (LLADDR((struct sockaddr_dl *)ifma->ifma_addr))); + n++; + } + if_maddr_runlock(ifp); } - if_maddr_runlock(ifp); return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist, IEEE80211_ADDR_LEN * n); } @@ -1638,7 +1548,7 @@ wi_update_promisc(struct ieee80211com *ic) /* XXX handle WEP special case handling? */ wi_write_val(sc, WI_RID_PROMISC, (ic->ic_opmode == IEEE80211_M_MONITOR || - (ic->ic_ifp->if_flags & IFF_PROMISC))); + (ic->ic_promisc > 0))); WI_UNLOCK(sc); } @@ -1937,7 +1847,7 @@ wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen) } static int -wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen) +wi_write_bap(struct wi_softc *sc, int id, int off, const void *buf, int buflen) { int error, cnt; @@ -1949,7 +1859,7 @@ wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen) return error; } cnt = (buflen + 1) / 2; - CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt); + CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (const uint16_t *)buf, cnt); sc->sc_bap_off += cnt * 2; return 0; @@ -2039,7 +1949,7 @@ wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp) } static int -wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen) +wi_write_rid(struct wi_softc *sc, int rid, const void *buf, int buflen) { int error; u_int16_t ltbuf[2]; diff --git a/sys/dev/wi/if_wi_macio.c b/sys/dev/wi/if_wi_macio.c index ad931b4..6f25553 100644 --- a/sys/dev/wi/if_wi_macio.c +++ b/sys/dev/wi/if_wi_macio.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/socket.h> #include <sys/systm.h> +#include <sys/mbuf.h> #include <sys/module.h> #include <sys/bus.h> diff --git a/sys/dev/wi/if_wi_pccard.c b/sys/dev/wi/if_wi_pccard.c index fd70e77..414dc20d 100644 --- a/sys/dev/wi/if_wi_pccard.c +++ b/sys/dev/wi/if_wi_pccard.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/socket.h> #include <sys/systm.h> +#include <sys/mbuf.h> #include <sys/module.h> #include <sys/bus.h> diff --git a/sys/dev/wi/if_wi_pci.c b/sys/dev/wi/if_wi_pci.c index 198c599..b218c24 100644 --- a/sys/dev/wi/if_wi_pci.c +++ b/sys/dev/wi/if_wi_pci.c @@ -238,7 +238,9 @@ wi_pci_suspend(device_t dev) { struct wi_softc *sc = device_get_softc(dev); + WI_LOCK(sc); wi_stop(sc, 1); + WI_UNLOCK(sc); return (0); } @@ -247,16 +249,15 @@ static int wi_pci_resume(device_t dev) { struct wi_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; - if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) + WI_LOCK(sc); + if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) { return (0); - - if (ifp->if_flags & IFF_UP) { - ifp->if_init(ifp->if_softc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - ifp->if_start(ifp); + WI_UNLOCK(sc); } - + if (ic->ic_nrunning > 0) + wi_init(sc); + WI_UNLOCK(sc); return (0); } diff --git a/sys/dev/wi/if_wivar.h b/sys/dev/wi/if_wivar.h index f163744..9b668cc 100644 --- a/sys/dev/wi/if_wivar.h +++ b/sys/dev/wi/if_wivar.h @@ -68,7 +68,8 @@ struct wi_vap { #define WI_VAP(vap) ((struct wi_vap *)(vap)) struct wi_softc { - struct ifnet *sc_ifp; + struct ieee80211com sc_ic; + struct mbufq sc_snd; device_t sc_dev; struct mtx sc_mtx; struct callout sc_watchdog; @@ -107,7 +108,6 @@ struct wi_softc { int wi_cmd_count; int sc_flags; - int sc_if_flags; int sc_bap_id; int sc_bap_off; @@ -152,6 +152,8 @@ struct wi_softc { #define WI_FLAGS_HAS_ROAMING 0x0020 #define WI_FLAGS_HAS_FRAGTHR 0x0200 #define WI_FLAGS_HAS_DBMADJUST 0x0400 +#define WI_FLAGS_RUNNING 0x0800 +#define WI_FLAGS_PROMISC 0x1000 struct wi_card_ident { u_int16_t card_id; @@ -180,7 +182,7 @@ int wi_shutdown(device_t); int wi_alloc(device_t, int); void wi_free(device_t); extern devclass_t wi_devclass; -void wi_init(void *); void wi_intr(void *); int wi_mgmt_xmit(struct wi_softc *, caddr_t, int); void wi_stop(struct wi_softc *, int); +void wi_init(struct wi_softc *); |