Index: sys/dev/wpi/if_wpi.c =================================================================== --- sys/dev/wpi/if_wpi.c +++ sys/dev/wpi/if_wpi.c @@ -205,12 +205,12 @@ const struct ieee80211_bpf_params *); static int wpi_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); -static void wpi_start(struct ifnet *); -static void wpi_start_task(void *, int); +static int wpi_transmit(struct ieee80211com *, struct mbuf *); +static void wpi_start(void *, int); static void wpi_watchdog_rfkill(void *); static void wpi_scan_timeout(void *); static void wpi_tx_timeout(void *); -static int wpi_ioctl(struct ifnet *, u_long, caddr_t); +static void wpi_parent(struct ieee80211com *); static int wpi_cmd(struct wpi_softc *, int, const void *, size_t, int); static int wpi_mrr_setup(struct wpi_softc *); static int wpi_add_node(struct wpi_softc *, struct ieee80211_node *); @@ -272,7 +272,7 @@ static void wpi_hw_stop(struct wpi_softc *); static void wpi_radio_on(void *, int); static void wpi_radio_off(void *, int); -static void wpi_init(void *); +static int wpi_init(struct wpi_softc *); static void wpi_stop_locked(struct wpi_softc *); static void wpi_stop(struct wpi_softc *); static void wpi_scan_start(struct ieee80211com *); @@ -329,13 +329,11 @@ { struct wpi_softc *sc = (struct wpi_softc *)device_get_softc(dev); struct ieee80211com *ic; - struct ifnet *ifp; int i, error, rid; #ifdef WPI_DEBUG int supportsa = 1; const struct wpi_ident *ident; #endif - uint8_t macaddr[IEEE80211_ADDR_LEN]; sc->sc_dev = dev; @@ -445,14 +443,7 @@ /* Clear pending interrupts. */ WPI_WRITE(sc, WPI_INT, 0xffffffff); - ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(dev, "can not allocate ifnet structure\n"); - goto fail; - } - - ic = ifp->if_l2com; - ic->ic_ifp = ifp; + ic = &sc->sc_ic; ic->ic_softc = sc; ic->ic_name = device_get_nameunit(dev); ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ @@ -481,7 +472,7 @@ * Read in the eeprom and also setup the channels for * net80211. We don't set the rates as net80211 does this for us */ - if ((error = wpi_read_eeprom(sc, macaddr)) != 0) { + if ((error = wpi_read_eeprom(sc, ic->ic_macaddr)) != 0) { device_printf(dev, "could not read EEPROM, error %d\n", error); goto fail; @@ -503,20 +494,12 @@ } #endif - if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - ifp->if_softc = sc; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_init = wpi_init; - ifp->if_ioctl = wpi_ioctl; - ifp->if_start = wpi_start; - IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); - ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; - IFQ_SET_READY(&ifp->if_snd); - - ieee80211_ifattach(ic, macaddr); + ieee80211_ifattach(ic); ic->ic_vap_create = wpi_vap_create; ic->ic_vap_delete = wpi_vap_delete; + ic->ic_parent = wpi_parent; ic->ic_raw_xmit = wpi_raw_xmit; + ic->ic_transmit = wpi_transmit; ic->ic_node_alloc = wpi_node_alloc; sc->sc_node_free = ic->ic_node_free; ic->ic_node_free = wpi_node_free; @@ -543,7 +526,7 @@ TASK_INIT(&sc->sc_reinittask, 0, wpi_hw_reset, sc); TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc); TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc); - TASK_INIT(&sc->sc_start_task, 0, wpi_start_task, sc); + TASK_INIT(&sc->sc_start_task, 0, wpi_start, sc); sc->sc_tq = taskqueue_create("wpi_taskq", M_WAITOK, taskqueue_thread_enqueue, &sc->sc_tq); @@ -588,14 +571,13 @@ static void wpi_radiotap_attach(struct wpi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct wpi_rx_radiotap_header *rxtap = &sc->sc_rxtap; + struct wpi_tx_radiotap_header *txtap = &sc->sc_txtap; + DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - ieee80211_radiotap_attach(ic, - &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), - WPI_TX_RADIOTAP_PRESENT, - &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), - WPI_RX_RADIOTAP_PRESENT); + ieee80211_radiotap_attach(&sc->sc_ic, + &txtap->wt_ihdr, sizeof(*txtap), WPI_TX_RADIOTAP_PRESENT, + &rxtap->wr_ihdr, sizeof(*rxtap), WPI_RX_RADIOTAP_PRESENT); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); } @@ -646,12 +628,9 @@ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */ return NULL; - wvp = (struct wpi_vap *) malloc(sizeof(struct wpi_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (wvp == NULL) - return NULL; + wvp = malloc(sizeof(struct wpi_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); if (opmode == IEEE80211_M_IBSS || opmode == IEEE80211_M_HOSTAP) { WPI_VAP_LOCK_INIT(wvp); @@ -671,7 +650,7 @@ ieee80211_ratectl_init(vap); /* Complete setup. */ ieee80211_vap_attach(vap, ieee80211_media_change, - ieee80211_media_status); + ieee80211_media_status, mac); ic->ic_opmode = opmode; return vap; } @@ -700,22 +679,21 @@ wpi_detach(device_t dev) { struct wpi_softc *sc = device_get_softc(dev); - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic; + struct ieee80211com *ic = &sc->sc_ic; int qid; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if (ifp != NULL) { - ic = ifp->if_l2com; - + if (ic->ic_vap_create == wpi_vap_create) { ieee80211_draintask(ic, &sc->sc_radioon_task); ieee80211_draintask(ic, &sc->sc_start_task); wpi_stop(sc); - taskqueue_drain_all(sc->sc_tq); - taskqueue_free(sc->sc_tq); + if (sc->sc_tq != NULL) { + taskqueue_drain_all(sc->sc_tq); + taskqueue_free(sc->sc_tq); + } callout_drain(&sc->watchdog_rfkill); callout_drain(&sc->tx_timeout); @@ -748,9 +726,6 @@ bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem), sc->mem); - if (ifp != NULL) - if_free(ifp); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); WPI_TXQ_STATE_LOCK_DESTROY(sc); WPI_TXQ_LOCK_DESTROY(sc); @@ -774,7 +749,7 @@ wpi_suspend(device_t dev) { struct wpi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; ieee80211_suspend_all(ic); return 0; @@ -784,7 +759,7 @@ wpi_resume(device_t dev) { struct wpi_softc *sc = device_get_softc(dev); - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; /* Clear device-specific "PCI retry timeout" register (41h). */ pci_write_config(dev, 0x41, 0, 1); @@ -1191,6 +1166,7 @@ ring->queued = 0; ring->cur = 0; ring->update = 0; + mbufq_init(&ring->snd, ifqmaxlen); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); @@ -1318,6 +1294,7 @@ memset(ring->desc, 0, ring->desc_dma.size); bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map, BUS_DMASYNC_PREWRITE); + mbufq_drain(&ring->snd); sc->qfullmsk &= ~(1 << ring->qid); ring->queued = 0; ring->cur = 0; @@ -1448,8 +1425,7 @@ static void wpi_read_eeprom_band(struct wpi_softc *sc, int n) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct wpi_eeprom_chan *channels = sc->eeprom_channels[n]; const struct wpi_chan_band *band = &wpi_bands[n]; struct ieee80211_channel *c; @@ -1506,8 +1482,7 @@ static int wpi_read_eeprom_channels(struct wpi_softc *sc, int n) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; const struct wpi_chan_band *band = &wpi_bands[n]; int error; @@ -1549,8 +1524,7 @@ wpi_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd, int nchan, struct ieee80211_channel chans[]) { - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; int i; for (i = 0; i < nchan; i++) { @@ -1559,8 +1533,7 @@ channel = wpi_find_eeprom_channel(sc, c); if (channel == NULL) { - if_printf(ic->ic_ifp, - "%s: invalid channel %u freq %u/0x%x\n", + ic_printf(ic, "%s: invalid channel %u freq %u/0x%x\n", __func__, c->ic_ieee, c->ic_freq, c->ic_flags); return EINVAL; } @@ -1672,8 +1645,7 @@ static void wpi_node_free(struct ieee80211_node *ni) { - struct ieee80211com *ic = ni->ni_ic; - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); if (wn->id != WPI_ID_UNDEFINED) { @@ -1700,7 +1672,7 @@ int rssi, int nf) { struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct wpi_softc *sc = vap->iv_ic->ic_softc; struct wpi_vap *wvp = WPI_VAP(vap); uint64_t ni_tstamp, rx_tstamp; @@ -1744,7 +1716,7 @@ static void wpi_restore_node_table(struct wpi_softc *sc, struct wpi_vap *wvp) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; /* Set group keys once. */ WPI_NT_LOCK(sc); @@ -1763,12 +1735,20 @@ { struct wpi_vap *wvp = WPI_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; int error = 0; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); + WPI_TXQ_LOCK(sc); + if (nstate > IEEE80211_S_INIT && sc->sc_running == 0) { + DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); + WPI_TXQ_UNLOCK(sc); + + return ENXIO; + } + WPI_TXQ_UNLOCK(sc); + DPRINTF(sc, WPI_DEBUG_STATE, "%s: %s -> %s\n", __func__, ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]); @@ -1937,8 +1917,7 @@ wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc, struct wpi_rx_data *data) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct wpi_rx_ring *ring = &sc->rxq; struct wpi_rx_stat *stat; struct wpi_rx_head *head; @@ -2019,7 +1998,6 @@ BUS_DMASYNC_PREWRITE); /* Finalize mbuf. */ - m->m_pkthdr.rcvif = ifp; m->m_data = (caddr_t)(head + 1); m->m_pkthdr.len = m->m_len = len; @@ -2073,7 +2051,7 @@ fail2: m_freem(m); -fail1: if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); +fail1: counter_u64_add(ic->ic_ierrors, 1); } static void @@ -2086,7 +2064,6 @@ static void wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc) { - struct ifnet *ifp = sc->sc_ifp; struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3]; struct wpi_tx_data *data = &ring->data[desc->idx]; struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1); @@ -2119,14 +2096,11 @@ * Update rate control statistics for the node. */ if (status & WPI_TX_STATUS_FAIL) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL); - } else { - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + } else ieee80211_ratectl_tx_complete(vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL); - } ieee80211_tx_complete(ni, m, (status & WPI_TX_STATUS_FAIL) != 0); @@ -2135,17 +2109,10 @@ if (ring->queued > 0) { callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc); - if (sc->qfullmsk != 0 && - ring->queued < WPI_TX_RING_LOMARK) { + if ((sc->qfullmsk & (1 << ring->qid)) != 0 && + ring->queued < WPI_TX_RING_LOMARK) { sc->qfullmsk &= ~(1 << ring->qid); - IF_LOCK(&ifp->if_snd); - if (sc->qfullmsk == 0 && - (ifp->if_drv_flags & IFF_DRV_OACTIVE)) { - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - ieee80211_runtask(ic, &sc->sc_start_task); - } else - IF_UNLOCK(&ifp->if_snd); + ieee80211_runtask(ic, &sc->sc_start_task); } } else callout_stop(&sc->tx_timeout); @@ -2203,8 +2170,7 @@ static void wpi_notif_intr(struct wpi_softc *sc) { - 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); uint32_t hw; @@ -2239,7 +2205,7 @@ /* An 802.11 frame has been received. */ wpi_rx_done(sc, desc, data); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { + if (sc->sc_running == 0) { /* wpi_stop() was called. */ return; } @@ -2328,6 +2294,7 @@ device_printf(sc->sc_dev, "microcontroller initialization failed\n"); wpi_stop_locked(sc); + return; } /* Save the address of the error log in SRAM. */ sc->errptr = le32toh(uc->errptr); @@ -2558,7 +2525,6 @@ wpi_intr(void *arg) { struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; uint32_t r1, r2; WPI_LOCK(sc); @@ -2608,7 +2574,7 @@ done: /* Re-enable interrupts. */ - if (ifp->if_flags & IFF_UP) + if (sc->sc_running) WPI_WRITE(sc, WPI_INT_MASK, WPI_INT_MASK_DEF); end: WPI_UNLOCK(sc); @@ -2617,7 +2583,6 @@ static int wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf) { - struct ifnet *ifp = sc->sc_ifp; struct ieee80211_frame *wh; struct wpi_tx_cmd *cmd; struct wpi_tx_data *data; @@ -2633,7 +2598,7 @@ DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if (sc->txq_active == 0) { + if (sc->sc_running == 0) { /* wpi_stop() was called */ error = ENETDOWN; goto fail; @@ -2730,14 +2695,8 @@ if (ring->qid < WPI_CMD_QUEUE_NUM) { /* Mark TX ring as full if we reach a certain threshold. */ WPI_TXQ_STATE_LOCK(sc); - if (++ring->queued > WPI_TX_RING_HIMARK) { + if (++ring->queued > WPI_TX_RING_HIMARK) sc->qfullmsk |= 1 << ring->qid; - - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; - IF_UNLOCK(&ifp->if_snd); - } - callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc); WPI_TXQ_STATE_UNLOCK(sc); } @@ -3031,24 +2990,47 @@ return wpi_cmd2(sc, &tx_data); } +static __inline int +wpi_tx_ring_is_full(struct wpi_softc *sc, int ac) +{ + struct wpi_tx_ring *ring = &sc->txq[ac]; + int retval; + + WPI_TXQ_STATE_LOCK(sc); + retval = (ring->queued > WPI_TX_RING_HIMARK); + WPI_TXQ_STATE_UNLOCK(sc); + + return retval; +} + +static __inline void +wpi_handle_tx_failure(struct ieee80211_node *ni) +{ + /* NB: m is reclaimed on tx failure */ + if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); + ieee80211_free_node(ni); +} + static int wpi_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 wpi_softc *sc = ifp->if_softc; - int error = 0; + struct wpi_softc *sc = ic->ic_softc; + int ac, error = 0; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - ieee80211_free_node(ni); + ac = M_WME_GETAC(m); + + WPI_TX_LOCK(sc); + + if (sc->sc_running == 0 || wpi_tx_ring_is_full(sc, ac)) { m_freem(m); - return ENETDOWN; + error = sc->sc_running ? ENOBUFS : ENETDOWN; + goto unlock; } - WPI_TX_LOCK(sc); if (params == NULL) { /* * Legacy path; interpret frame contents to decide @@ -3062,13 +3044,11 @@ */ error = wpi_tx_data_raw(sc, m, ni, params); } - WPI_TX_UNLOCK(sc); - if (error != 0) { - /* NB: m is reclaimed on tx failure */ - ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); +unlock: WPI_TX_UNLOCK(sc); + if (error != 0) { + wpi_handle_tx_failure(ni); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); return error; @@ -3079,57 +3059,88 @@ return 0; } -/** - * Process data waiting to be sent on the IFNET output queue - */ -static void -wpi_start(struct ifnet *ifp) +static int +wpi_transmit(struct ieee80211com *ic, struct mbuf *m) { - struct wpi_softc *sc = ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; struct ieee80211_node *ni; - struct mbuf *m; + struct mbufq *sndq; + int ac, error; WPI_TX_LOCK(sc); DPRINTF(sc, WPI_DEBUG_XMIT, "%s: called\n", __func__); - for (;;) { - IF_LOCK(&ifp->if_snd); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || - (ifp->if_drv_flags & IFF_DRV_OACTIVE)) { - IF_UNLOCK(&ifp->if_snd); - break; - } - IF_UNLOCK(&ifp->if_snd); + /* Check if interface is up & running. */ + if (sc->sc_running == 0) { + error = ENXIO; + goto unlock; + } - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - if (wpi_tx_data(sc, m, ni) != 0) { - ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } + /* Check for available space. */ + ac = M_WME_GETAC(m); + sndq = &sc->txq[ac].snd; + if (wpi_tx_ring_is_full(sc, ac) || mbufq_len(sndq) != 0) { + /* wpi_tx_done() will dequeue it. */ + error = mbufq_enqueue(sndq, m); + goto unlock; + } + + error = 0; + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + if (wpi_tx_data(sc, m, ni) != 0) { + wpi_handle_tx_failure(ni); } DPRINTF(sc, WPI_DEBUG_XMIT, "%s: done\n", __func__); - WPI_TX_UNLOCK(sc); + +unlock: WPI_TX_UNLOCK(sc); + + return (error); } +/** + * Process data waiting to be sent on the output queue + */ static void -wpi_start_task(void *arg0, int pending) +wpi_start(void *arg0, int pending) { struct wpi_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211_node *ni; + struct mbuf *m; + uint8_t i; + + WPI_TX_LOCK(sc); + if (sc->sc_running == 0) + goto unlock; - wpi_start(ifp); + DPRINTF(sc, WPI_DEBUG_XMIT, "%s: called\n", __func__); + + for (i = 0; i < WPI_CMD_QUEUE_NUM; i++) { + struct mbufq *sndq = &sc->txq[i].snd; + + for (;;) { + if (wpi_tx_ring_is_full(sc, i)) + break; + + if ((m = mbufq_dequeue(sndq)) == NULL) + break; + + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + if (wpi_tx_data(sc, m, ni) != 0) { + wpi_handle_tx_failure(ni); + } + } + } + + DPRINTF(sc, WPI_DEBUG_XMIT, "%s: done\n", __func__); +unlock: WPI_TX_UNLOCK(sc); } static void wpi_watchdog_rfkill(void *arg) { struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; DPRINTF(sc, WPI_DEBUG_WATCHDOG, "RFkill Watchdog: tick\n"); @@ -3146,9 +3157,9 @@ wpi_scan_timeout(void *arg) { struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; - if_printf(ifp, "scan timeout\n"); + ic_printf(ic, "scan timeout\n"); taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask); } @@ -3156,44 +3167,28 @@ wpi_tx_timeout(void *arg) { struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; + struct ieee80211com *ic = &sc->sc_ic; - if_printf(ifp, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ic_printf(ic, "device timeout\n"); taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask); } -static int -wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +wpi_parent(struct ieee80211com *ic) { - struct wpi_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; + struct wpi_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ifreq *ifr = (struct ifreq *) data; - int error = 0; - switch (cmd) { - case SIOCGIFADDR: - error = ether_ioctl(ifp, cmd, data); - break; - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) { - wpi_init(sc); - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 && - vap != NULL) - ieee80211_stop(vap); - } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) - wpi_stop(sc); - break; - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); - break; - default: - error = EINVAL; - break; - } - return error; + if (ic->ic_nrunning > 0) { + if (wpi_init(sc) == 0) { + ieee80211_notify_radio(ic, 1); + ieee80211_start_all(ic); + } else { + ieee80211_notify_radio(ic, 0); + ieee80211_stop(vap); + } + } else + wpi_stop(sc); } /* @@ -3215,9 +3210,13 @@ DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if (sc->txq_active == 0) { + if (sc->sc_running == 0) { /* wpi_stop() was called */ - error = 0; + if (code == WPI_CMD_SCAN) + error = ENETDOWN; + else + error = 0; + goto fail; } @@ -3283,10 +3282,7 @@ WPI_TXQ_UNLOCK(sc); - if (async) - return 0; - - return mtx_sleep(cmd, &sc->sc_mtx, PCATCH, "wpicmd", hz); + return async ? 0 : mtx_sleep(cmd, &sc->sc_mtx, PCATCH, "wpicmd", hz); fail: DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); @@ -3301,8 +3297,7 @@ static int wpi_mrr_setup(struct wpi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct wpi_mrr_setup mrr; int i, error; @@ -3399,14 +3394,13 @@ static int wpi_add_broadcast_node(struct wpi_softc *sc, int async) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct wpi_node_info node; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); memset(&node, 0, sizeof node); - IEEE80211_ADDR_COPY(node.macaddr, ifp->if_broadcastaddr); + IEEE80211_ADDR_COPY(node.macaddr, ieee80211broadcastaddr); node.id = WPI_ID_BROADCAST; node.plcp = (ic->ic_curmode == IEEE80211_MODE_11A) ? wpi_ridx_to_plcp[WPI_RIDX_OFDM6] : wpi_ridx_to_plcp[WPI_RIDX_CCK1]; @@ -3492,7 +3486,7 @@ wpi_updateedca(struct ieee80211com *ic) { #define WPI_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */ - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; struct wpi_edca_params cmd; int aci, error; @@ -3526,8 +3520,7 @@ static void wpi_set_promisc(struct wpi_softc *sc) { - 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); uint32_t promisc_filter; @@ -3535,7 +3528,7 @@ if (vap != NULL && vap->iv_opmode != IEEE80211_M_HOSTAP) promisc_filter |= WPI_FILTER_PROMISC; - if (ifp->if_flags & IFF_PROMISC) + if (ic->ic_promisc > 0) sc->rxon.filter |= htole32(promisc_filter); else sc->rxon.filter &= ~htole32(promisc_filter); @@ -3900,8 +3893,7 @@ static int wpi_config(struct wpi_softc *sc) { - 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_channel *c = ic->ic_curchan; int error; @@ -4011,7 +4003,7 @@ static uint16_t wpi_limit_dwell(struct wpi_softc *sc, uint16_t dwell_time) { - struct ieee80211com *ic = sc->sc_ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); int bintval = 0; @@ -4068,8 +4060,7 @@ static int wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_scan_state *ss = ic->ic_scan; struct ieee80211vap *vap = ss->ss_vap; struct wpi_scan_hdr *hdr; @@ -4171,11 +4162,9 @@ wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ; wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; - IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr); + IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr); IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr); - IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr); - *(uint16_t *)&wh->i_dur[0] = 0; /* filled by h/w */ - *(uint16_t *)&wh->i_seq[0] = 0; /* filled by h/w */ + IEEE80211_ADDR_COPY(wh->i_addr3, ieee80211broadcastaddr); frm = (uint8_t *)(wh + 1); frm = ieee80211_add_ssid(frm, NULL, 0); @@ -4206,7 +4195,6 @@ /* * Calculate the active/passive dwell times. */ - dwell_active = wpi_get_active_dwell_time(sc, c, nssid); dwell_passive = wpi_get_passive_dwell_time(sc, c); @@ -4324,7 +4312,7 @@ struct ieee80211com *ic = wvp->wv_vap.iv_ic; struct ieee80211_beacon_offsets *bo = &wvp->wv_boff; struct wpi_buf *bcn = &wvp->wv_bcbuf; - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; struct wpi_cmd_beacon *cmd = (struct wpi_cmd_beacon *)&bcn->data; struct ieee80211_tim_ie *tie; struct mbuf *m; @@ -4406,7 +4394,7 @@ static void wpi_update_beacon(struct ieee80211vap *vap, int item) { - struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc; + struct wpi_softc *sc = vap->iv_ic->ic_softc; struct wpi_vap *wvp = WPI_VAP(vap); struct wpi_buf *bcn = &wvp->wv_bcbuf; struct ieee80211_beacon_offsets *bo = &wvp->wv_boff; @@ -4448,7 +4436,7 @@ wpi_newassoc(struct ieee80211_node *ni, int isnew) { struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); int error; @@ -4575,7 +4563,7 @@ { const struct ieee80211_cipher *cip = k->wk_cipher; struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); struct wpi_node_info node; uint16_t kflags; @@ -4639,7 +4627,7 @@ { const struct ieee80211_key *k = arg; struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); int error; @@ -4674,7 +4662,7 @@ wpi_del_key(struct ieee80211_node *ni, const struct ieee80211_key *k) { struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); struct wpi_node_info node; uint16_t kflags; @@ -4724,7 +4712,7 @@ { const struct ieee80211_key *k = arg; struct ieee80211vap *vap = ni->ni_vap; - struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc; + struct wpi_softc *sc = ni->ni_ic->ic_softc; struct wpi_node *wn = WPI_NODE(ni); int error; @@ -4746,7 +4734,7 @@ int set) { struct ieee80211com *ic = vap->iv_ic; - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; struct wpi_vap *wvp = WPI_VAP(vap); struct ieee80211_node *ni; int error, ni_ref = 0; @@ -5396,34 +5384,29 @@ wpi_radio_on(void *arg0, int pending) { struct wpi_softc *sc = arg0; - 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); device_printf(sc->sc_dev, "RF switch: radio enabled\n"); - if (vap != NULL) { - wpi_init(sc); - ieee80211_init(vap); - } + WPI_LOCK(sc); + callout_stop(&sc->watchdog_rfkill); + WPI_UNLOCK(sc); - if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_RFKILL) { - WPI_LOCK(sc); - callout_stop(&sc->watchdog_rfkill); - WPI_UNLOCK(sc); - } + if (vap != NULL) + ieee80211_init(vap); } static void wpi_radio_off(void *arg0, int pending) { struct wpi_softc *sc = arg0; - 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); device_printf(sc->sc_dev, "RF switch: radio disabled\n"); + ieee80211_notify_radio(ic, 0); wpi_stop(sc); if (vap != NULL) ieee80211_stop(vap); @@ -5433,19 +5416,16 @@ WPI_UNLOCK(sc); } -static void -wpi_init(void *arg) +static int +wpi_init(struct wpi_softc *sc) { - struct wpi_softc *sc = arg; - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; - int error; + int error = 0; WPI_LOCK(sc); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__); - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + if (sc->sc_running != 0) goto end; /* Check that the radio is not disabled by hardware switch. */ @@ -5454,6 +5434,7 @@ "RF switch: radio disabled (%s)\n", __func__); callout_reset(&sc->watchdog_rfkill, hz, wpi_watchdog_rfkill, sc); + error = EINPROGRESS; goto end; } @@ -5462,9 +5443,11 @@ device_printf(sc->sc_dev, "%s: could not read firmware, error %d\n", __func__, error); - goto fail; + goto end; } + sc->sc_running = 1; + /* Initialize hardware and upload firmware. */ error = wpi_hw_init(sc); wpi_unload_firmware(sc); @@ -5476,7 +5459,6 @@ } /* Configure adapter now that it is ready. */ - sc->txq_active = 1; if ((error = wpi_config(sc)) != 0) { device_printf(sc->sc_dev, "%s: could not configure device, error %d\n", __func__, @@ -5484,34 +5466,34 @@ goto fail; } - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - IF_UNLOCK(&ifp->if_snd); - DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__); WPI_UNLOCK(sc); - ieee80211_start_all(ic); - - return; + return 0; fail: wpi_stop_locked(sc); + end: DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__); WPI_UNLOCK(sc); + + return error; } static void wpi_stop_locked(struct wpi_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; WPI_LOCK_ASSERT(sc); + if (sc->sc_running == 0) + return; + + WPI_TX_LOCK(sc); WPI_TXQ_LOCK(sc); - sc->txq_active = 0; + sc->sc_running = 0; WPI_TXQ_UNLOCK(sc); + WPI_TX_UNLOCK(sc); WPI_TXQ_STATE_LOCK(sc); callout_stop(&sc->tx_timeout); @@ -5522,10 +5504,6 @@ callout_stop(&sc->calib_to); WPI_RXON_UNLOCK(sc); - IF_LOCK(&ifp->if_snd); - ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - IF_UNLOCK(&ifp->if_snd); - /* Power OFF hardware. */ wpi_hw_stop(sc); } @@ -5544,7 +5522,7 @@ static void wpi_scan_start(struct ieee80211com *ic) { - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; wpi_set_led(sc, WPI_LED_LINK, 20, 2); } @@ -5555,8 +5533,7 @@ static void wpi_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); if (vap->iv_state == IEEE80211_S_RUN) @@ -5571,8 +5548,7 @@ wpi_set_channel(struct ieee80211com *ic) { const struct ieee80211_channel *c = ic->ic_curchan; - struct ifnet *ifp = ic->ic_ifp; - struct wpi_softc *sc = ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; int error; DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); @@ -5618,7 +5594,7 @@ { struct ieee80211vap *vap = ss->ss_vap; struct ieee80211com *ic = vap->iv_ic; - struct wpi_softc *sc = ic->ic_ifp->if_softc; + struct wpi_softc *sc = ic->ic_softc; int error; WPI_RXON_LOCK(sc); @@ -5644,19 +5620,18 @@ wpi_hw_reset(void *arg, int pending) { struct wpi_softc *sc = arg; - 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); DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__); + ieee80211_notify_radio(ic, 0); if (vap != NULL && (ic->ic_flags & IEEE80211_F_SCAN)) ieee80211_cancel_scan(vap); wpi_stop(sc); - if (vap != NULL) + if (vap != NULL) { ieee80211_stop(vap); - wpi_init(sc); - if (vap != NULL) ieee80211_init(vap); + } } Index: sys/dev/wpi/if_wpivar.h =================================================================== --- sys/dev/wpi/if_wpivar.h +++ sys/dev/wpi/if_wpivar.h @@ -72,6 +72,7 @@ struct wpi_tx_cmd *cmd; struct wpi_tx_data data[WPI_TX_RING_COUNT]; bus_dma_tag_t data_dmat; + struct mbufq snd; int qid; int queued; int cur; @@ -164,14 +165,15 @@ struct wpi_softc { device_t sc_dev; - - struct ifnet *sc_ifp; int sc_debug; int sc_flags; #define WPI_PS_PATH (1 << 0) + int sc_running; struct mtx sc_mtx; + struct ieee80211com sc_ic; + struct mtx tx_mtx; /* Shared area. */ @@ -181,7 +183,6 @@ struct wpi_tx_ring txq[WPI_NTXQUEUES]; struct mtx txq_mtx; struct mtx txq_state_mtx; - uint32_t txq_active; struct wpi_rx_ring rxq; uint64_t rx_tstamp;