diff options
Diffstat (limited to 'sys/dev/malo/if_malo.c')
-rw-r--r-- | sys/dev/malo/if_malo.c | 439 |
1 files changed, 178 insertions, 261 deletions
diff --git a/sys/dev/malo/if_malo.c b/sys/dev/malo/if_malo.c index 7418379..2790fdc 100644 --- a/sys/dev/malo/if_malo.c +++ b/sys/dev/malo/if_malo.c @@ -102,13 +102,9 @@ enum { (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON)) #define IFF_DUMPPKTS_RECV(sc, wh) \ (((sc->malo_debug & MALO_DEBUG_RECV) && \ - ((sc->malo_debug & MALO_DEBUG_RECV_ALL) || !IS_BEACON(wh))) || \ - (sc->malo_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == \ - (IFF_DEBUG|IFF_LINK2)) + ((sc->malo_debug & MALO_DEBUG_RECV_ALL) || !IS_BEACON(wh)))) #define IFF_DUMPPKTS_XMIT(sc) \ - ((sc->malo_debug & MALO_DEBUG_XMIT) || \ - (sc->malo_ifp->if_flags & (IFF_DEBUG | IFF_LINK2)) == \ - (IFF_DEBUG | IFF_LINK2)) + (sc->malo_debug & MALO_DEBUG_XMIT) #define DPRINTF(sc, m, fmt, ...) do { \ if (sc->malo_debug & (m)) \ printf(fmt, __VA_ARGS__); \ @@ -130,9 +126,10 @@ static int malo_dma_setup(struct malo_softc *); static int malo_setup_hwdma(struct malo_softc *); static void malo_txq_init(struct malo_softc *, struct malo_txq *, int); static void malo_tx_cleanupq(struct malo_softc *, struct malo_txq *); -static void malo_start(struct ifnet *); +static void malo_parent(struct ieee80211com *); +static int malo_transmit(struct ieee80211com *, struct mbuf *); +static void malo_start(struct malo_softc *); static void malo_watchdog(void *); -static int malo_ioctl(struct ifnet *, u_long, caddr_t); static void malo_updateslot(struct ieee80211com *); static int malo_newstate(struct ieee80211vap *, enum ieee80211_state, int); static void malo_scan_start(struct ieee80211com *); @@ -143,7 +140,7 @@ static int malo_raw_xmit(struct ieee80211_node *, struct mbuf *, static void malo_sysctlattach(struct malo_softc *); static void malo_announce(struct malo_softc *); static void malo_dma_cleanup(struct malo_softc *); -static void malo_stop_locked(struct ifnet *, int); +static void malo_stop(struct malo_softc *); static int malo_chan_set(struct malo_softc *, struct ieee80211_channel *); static int malo_mode_init(struct malo_softc *); static void malo_tx_proc(void *, int); @@ -173,30 +170,19 @@ malo_bar0_write4(struct malo_softc *sc, bus_size_t off, uint32_t val) int malo_attach(uint16_t devid, struct malo_softc *sc) { - int error; - struct ieee80211com *ic; - struct ifnet *ifp; + struct ieee80211com *ic = &sc->malo_ic; struct malo_hal *mh; + int error; uint8_t bands; - ifp = sc->malo_ifp = if_alloc(IFT_IEEE80211); - if (ifp == NULL) { - device_printf(sc->malo_dev, "can not if_alloc()\n"); - return ENOSPC; - } - ic = ifp->if_l2com; - MALO_LOCK_INIT(sc); callout_init_mtx(&sc->malo_watchdog_timer, &sc->malo_mtx, 0); - - /* set these up early for if_printf use */ - if_initname(ifp, device_get_name(sc->malo_dev), - device_get_unit(sc->malo_dev)); + mbufq_init(&sc->malo_snd, ifqmaxlen); mh = malo_hal_attach(sc->malo_dev, devid, sc->malo_io1h, sc->malo_io1t, sc->malo_dmat); if (mh == NULL) { - if_printf(ifp, "unable to attach HAL\n"); + device_printf(sc->malo_dev, "unable to attach HAL\n"); error = EIO; goto bad; } @@ -209,13 +195,13 @@ malo_attach(uint16_t devid, struct malo_softc *sc) */ error = malo_hal_fwload(mh, "malo8335-h", "malo8335-m"); if (error != 0) { - if_printf(ifp, "unable to setup firmware\n"); + device_printf(sc->malo_dev, "unable to setup firmware\n"); goto bad1; } /* XXX gethwspecs() extracts correct informations? not maybe! */ error = malo_hal_gethwspecs(mh, &sc->malo_hwspecs); if (error != 0) { - if_printf(ifp, "unable to fetch h/w specs\n"); + device_printf(sc->malo_dev, "unable to fetch h/w specs\n"); goto bad1; } @@ -251,7 +237,8 @@ malo_attach(uint16_t devid, struct malo_softc *sc) */ error = malo_dma_setup(sc); if (error != 0) { - if_printf(ifp, "failed to setup descriptors: %d\n", error); + device_printf(sc->malo_dev, + "failed to setup descriptors: %d\n", error); goto bad1; } error = malo_setup_hwdma(sc); /* push to firmware */ @@ -261,21 +248,11 @@ malo_attach(uint16_t devid, struct malo_softc *sc) sc->malo_tq = taskqueue_create_fast("malo_taskq", M_NOWAIT, taskqueue_thread_enqueue, &sc->malo_tq); taskqueue_start_threads(&sc->malo_tq, 1, PI_NET, - "%s taskq", ifp->if_xname); + "%s taskq", device_get_nameunit(sc->malo_dev)); TASK_INIT(&sc->malo_rxtask, 0, malo_rx_proc, sc); TASK_INIT(&sc->malo_txtask, 0, malo_tx_proc, sc); - ifp->if_softc = sc; - ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; - ifp->if_start = malo_start; - ifp->if_ioctl = malo_ioctl; - ifp->if_init = malo_init; - 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(sc->malo_dev); /* XXX not right but it's not used anywhere important */ @@ -290,6 +267,7 @@ malo_attach(uint16_t devid, struct malo_softc *sc) | IEEE80211_C_TXPMGT /* capable of txpow mgt */ | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ ; + IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->malo_hwspecs.macaddr); /* * Transmit requires space in the packet for a special format transmit @@ -301,16 +279,17 @@ malo_attach(uint16_t devid, struct malo_softc *sc) sizeof(struct ieee80211_frame); /* call MI attach routine. */ - ieee80211_ifattach(ic, sc->malo_hwspecs.macaddr); + ieee80211_ifattach(ic); /* override default methods */ ic->ic_vap_create = malo_vap_create; ic->ic_vap_delete = malo_vap_delete; ic->ic_raw_xmit = malo_raw_xmit; ic->ic_updateslot = malo_updateslot; - ic->ic_scan_start = malo_scan_start; ic->ic_scan_end = malo_scan_end; ic->ic_set_channel = malo_set_channel; + ic->ic_parent = malo_parent; + ic->ic_transmit = malo_transmit; sc->malo_invalid = 0; /* ready to go, enable int handling */ @@ -335,7 +314,6 @@ bad2: bad1: malo_hal_detach(mh); bad: - if_free(ifp); sc->malo_invalid = 1; return error; @@ -347,12 +325,12 @@ malo_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 ifnet *ifp = ic->ic_ifp; + struct malo_softc *sc = ic->ic_softc; struct malo_vap *mvp; struct ieee80211vap *vap; if (!TAILQ_EMPTY(&ic->ic_vaps)) { - if_printf(ifp, "multiple vaps not supported\n"); + device_printf(sc->malo_dev, "multiple vaps not supported\n"); return NULL; } switch (opmode) { @@ -363,18 +341,13 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, case IEEE80211_M_MONITOR: break; default: - if_printf(ifp, "%s mode not supported\n", + device_printf(sc->malo_dev, "%s mode not supported\n", ieee80211_opmode_name[opmode]); return NULL; /* unsupported */ } - mvp = (struct malo_vap *) malloc(sizeof(struct malo_vap), - M_80211_VAP, M_NOWAIT | M_ZERO); - if (mvp == NULL) { - if_printf(ifp, "cannot allocate vap state block\n"); - return NULL; - } + mvp = malloc(sizeof(struct malo_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &mvp->malo_vap; - ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); + ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); /* override state transition machine */ mvp->malo_newstate = vap->iv_newstate; @@ -382,7 +355,7 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, /* complete setup */ ieee80211_vap_attach(vap, - ieee80211_media_change, ieee80211_media_status); + ieee80211_media_change, ieee80211_media_status, mac); ic->ic_opmode = opmode; return vap; } @@ -461,7 +434,6 @@ malo_desc_setup(struct malo_softc *sc, const char *name, int nbuf, size_t bufsize, int ndesc, size_t descsize) { int error; - struct ifnet *ifp = sc->malo_ifp; uint8_t *ds; DPRINTF(sc, MALO_DEBUG_RESET, @@ -488,7 +460,8 @@ malo_desc_setup(struct malo_softc *sc, const char *name, NULL, /* lockarg */ &dd->dd_dmat); if (error != 0) { - if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name); + device_printf(sc->malo_dev, "cannot allocate %s DMA tag\n", + dd->dd_name); return error; } @@ -496,7 +469,8 @@ malo_desc_setup(struct malo_softc *sc, const char *name, error = bus_dmamem_alloc(dd->dd_dmat, (void**) &dd->dd_desc, BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dd->dd_dmamap); if (error != 0) { - if_printf(ifp, "unable to alloc memory for %u %s descriptors, " + device_printf(sc->malo_dev, + "unable to alloc memory for %u %s descriptors, " "error %u\n", nbuf * ndesc, dd->dd_name, error); goto fail1; } @@ -505,7 +479,8 @@ malo_desc_setup(struct malo_softc *sc, const char *name, dd->dd_desc, dd->dd_desc_len, malo_load_cb, &dd->dd_desc_paddr, BUS_DMA_NOWAIT); if (error != 0) { - if_printf(ifp, "unable to map %s descriptors, error %u\n", + device_printf(sc->malo_dev, + "unable to map %s descriptors, error %u\n", dd->dd_name, error); goto fail2; } @@ -532,7 +507,6 @@ fail1: static int malo_rxdma_setup(struct malo_softc *sc) { - struct ifnet *ifp = sc->malo_ifp; int error, bsize, i; struct malo_rxbuf *bf; struct malo_rxdesc *ds; @@ -549,7 +523,8 @@ malo_rxdma_setup(struct malo_softc *sc) bsize = malo_rxbuf * sizeof(struct malo_rxbuf); bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO); if (bf == NULL) { - if_printf(ifp, "malloc of %u rx buffers failed\n", bsize); + device_printf(sc->malo_dev, + "malloc of %u rx buffers failed\n", bsize); return error; } sc->malo_rxdma.dd_bufptr = bf; @@ -562,8 +537,9 @@ malo_rxdma_setup(struct malo_softc *sc) error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT, &bf->bf_dmamap); if (error != 0) { - if_printf(ifp, "%s: unable to dmamap for rx buffer, " - "error %d\n", __func__, error); + device_printf(sc->malo_dev, + "%s: unable to dmamap for rx buffer, error %d\n", + __func__, error); return error; } /* NB: tail is intentional to preserve descriptor order */ @@ -575,7 +551,6 @@ malo_rxdma_setup(struct malo_softc *sc) static int malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq) { - struct ifnet *ifp = sc->malo_ifp; int error, bsize, i; struct malo_txbuf *bf; struct malo_txdesc *ds; @@ -590,7 +565,7 @@ malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq) bsize = malo_txbuf * sizeof(struct malo_txbuf); bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO); if (bf == NULL) { - if_printf(ifp, "malloc of %u tx buffers failed\n", + device_printf(sc->malo_dev, "malloc of %u tx buffers failed\n", malo_txbuf); return ENOMEM; } @@ -605,7 +580,8 @@ malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq) error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT, &bf->bf_dmamap); if (error != 0) { - if_printf(ifp, "unable to create dmamap for tx " + device_printf(sc->malo_dev, + "unable to create dmamap for tx " "buffer %u, error %u\n", i, error); return error; } @@ -1004,33 +980,19 @@ malo_tx_processq(struct malo_softc *sc, struct malo_txq *txq) if (status & MALO_TXD_STATUS_FAILED_AGING) sc->malo_stats.mst_tx_aging++; } - /* - * Do any tx complete callback. Note this must - * be done before releasing the node reference. - * XXX no way to figure out if frame was ACK'd - */ - if (bf->bf_m->m_flags & M_TXCB) { - /* XXX strip fw len in case header inspected */ - m_adj(bf->bf_m, sizeof(uint16_t)); - ieee80211_process_callback(ni, bf->bf_m, - (status & MALO_TXD_STATUS_OK) == 0); - } - /* - * Reclaim reference to node. - * - * NB: the node may be reclaimed here if, for example - * this is a DEAUTH message that was sent and the - * node was timed out due to inactivity. - */ - ieee80211_free_node(ni); - } + /* XXX strip fw len in case header inspected */ + m_adj(bf->bf_m, sizeof(uint16_t)); + ieee80211_tx_complete(ni, bf->bf_m, + (status & MALO_TXD_STATUS_OK) == 0); + } else + m_freem(bf->bf_m); + ds->status = htole32(MALO_TXD_STATUS_IDLE); ds->pktlen = htole32(0); bus_dmamap_sync(sc->malo_dmat, bf->bf_dmamap, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->malo_dmat, bf->bf_dmamap); - m_freem(bf->bf_m); bf->bf_m = NULL; bf->bf_node = NULL; @@ -1049,23 +1011,23 @@ static void malo_tx_proc(void *arg, int npending) { struct malo_softc *sc = arg; - struct ifnet *ifp = sc->malo_ifp; int i, nreaped; /* * Process each active queue. */ nreaped = 0; + MALO_LOCK(sc); for (i = 0; i < MALO_NUM_TX_QUEUES; i++) { if (!STAILQ_EMPTY(&sc->malo_txq[i].active)) nreaped += malo_tx_processq(sc, &sc->malo_txq[i]); } if (nreaped != 0) { - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; sc->malo_timer = 0; - malo_start(ifp); + malo_start(sc); } + MALO_UNLOCK(sc); } static int @@ -1079,8 +1041,7 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni, int error, ismcast, iswep; int copyhdrlen, hdrlen, pktlen; struct ieee80211_frame *wh; - struct ifnet *ifp = sc->malo_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->malo_ic; struct ieee80211vap *vap = ni->ni_vap; struct malo_txdesc *ds; struct malo_txrec *tr; @@ -1225,7 +1186,7 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni, ds->txpriority = txq->qnum; break; default: - if_printf(ifp, "bogus frame type 0x%x (%s)\n", + device_printf(sc->malo_dev, "bogus frame type 0x%x (%s)\n", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__); /* XXX statistic */ m_freem(m0); @@ -1246,37 +1207,52 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni, STAILQ_INSERT_TAIL(&txq->active, bf, bf_list); MALO_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); sc->malo_timer = 5; MALO_TXQ_UNLOCK(txq); return 0; #undef IEEE80211_DIR_DSTODS } +static int +malo_transmit(struct ieee80211com *ic, struct mbuf *m) +{ + struct malo_softc *sc = ic->ic_softc; + int error; + + MALO_LOCK(sc); + if (!sc->malo_running) { + MALO_UNLOCK(sc); + return (ENXIO); + } + error = mbufq_enqueue(&sc->malo_snd, m); + if (error) { + MALO_UNLOCK(sc); + return (error); + } + malo_start(sc); + MALO_UNLOCK(sc); + return (0); +} + static void -malo_start(struct ifnet *ifp) +malo_start(struct malo_softc *sc) { - struct malo_softc *sc = ifp->if_softc; struct ieee80211_node *ni; struct malo_txq *txq = &sc->malo_txq[0]; struct malo_txbuf *bf = NULL; struct mbuf *m; int nqueued = 0; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->malo_invalid) + MALO_LOCK_ASSERT(sc); + + if (!sc->malo_running || sc->malo_invalid) return; - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; + while ((m = mbufq_dequeue(&sc->malo_snd)) != NULL) { ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; bf = malo_getbuf(sc, txq); if (bf == NULL) { - IFQ_DRV_PREPEND(&ifp->if_snd, m); - - /* XXX blocks other traffic */ - ifp->if_drv_flags |= IFF_DRV_OACTIVE; + mbufq_prepend(&sc->malo_snd, m); sc->malo_stats.mst_tx_qstop++; break; } @@ -1284,7 +1260,8 @@ malo_start(struct ifnet *ifp) * Pass the frame to the h/w for transmission. */ if (malo_tx_start(sc, ni, bf, m)) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); if (bf != NULL) { bf->bf_m = NULL; bf->bf_node = NULL; @@ -1328,21 +1305,18 @@ malo_start(struct ifnet *ifp) static void malo_watchdog(void *arg) { - struct malo_softc *sc; - struct ifnet *ifp; + struct malo_softc *sc = arg; - sc = arg; callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc); if (sc->malo_timer == 0 || --sc->malo_timer > 0) return; - ifp = sc->malo_ifp; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && !sc->malo_invalid) { - if_printf(ifp, "watchdog timeout\n"); + if (sc->malo_running && !sc->malo_invalid) { + device_printf(sc->malo_dev, "watchdog timeout\n"); /* XXX no way to reset h/w. now */ - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + counter_u64_add(sc->malo_ic.ic_oerrors, 1); sc->malo_stats.mst_watchdog++; } } @@ -1351,8 +1325,7 @@ static int malo_hal_reset(struct malo_softc *sc) { static int first = 0; - struct ifnet *ifp = sc->malo_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->malo_ic; struct malo_hal *mh = sc->malo_mh; if (first == 0) { @@ -1392,7 +1365,7 @@ malo_getrxmbuf(struct malo_softc *sc, struct malo_rxbuf *bf) mtod(m, caddr_t), MJUMPAGESIZE, malo_load_cb, &paddr, BUS_DMA_NOWAIT); if (error != 0) { - if_printf(sc->malo_ifp, + device_printf(sc->malo_dev, "%s: bus_dmamap_load failed, error %d\n", __func__, error); m_freem(m); return NULL; @@ -1483,26 +1456,23 @@ malo_startrecv(struct malo_softc *sc) static void malo_init_locked(struct malo_softc *sc) { - struct ifnet *ifp = sc->malo_ifp; struct malo_hal *mh = sc->malo_mh; int error; - DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags 0x%x\n", - __func__, ifp->if_flags); - MALO_LOCK_ASSERT(sc); /* * Stop anything previously setup. This is safe whether this is * the first time through or not. */ - malo_stop_locked(ifp, 0); + malo_stop(sc); /* * Push state to the firmware. */ if (!malo_hal_reset(sc)) { - if_printf(ifp, "%s: unable to reset hardware\n", __func__); + device_printf(sc->malo_dev, + "%s: unable to reset hardware\n", __func__); return; } @@ -1511,7 +1481,8 @@ malo_init_locked(struct malo_softc *sc) */ error = malo_startrecv(sc); if (error != 0) { - if_printf(ifp, "%s: unable to start recv logic, error %d\n", + device_printf(sc->malo_dev, + "%s: unable to start recv logic, error %d\n", __func__, error); return; } @@ -1528,7 +1499,7 @@ malo_init_locked(struct malo_softc *sc) | MALO_A2HRIC_BIT_RADAR_DETECT | MALO_A2HRIC_BIT_CHAN_SWITCH; - ifp->if_drv_flags |= IFF_DRV_RUNNING; + sc->malo_running = 1; malo_hal_intrset(mh, sc->malo_imask); callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc); } @@ -1537,18 +1508,13 @@ static void malo_init(void *arg) { struct malo_softc *sc = (struct malo_softc *) arg; - struct ifnet *ifp = sc->malo_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->malo_ic; - DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags 0x%x\n", - __func__, ifp->if_flags); - MALO_LOCK(sc); malo_init_locked(sc); - MALO_UNLOCK(sc); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) + if (sc->malo_running) ieee80211_start_all(ic); /* start all vap's */ } @@ -1558,9 +1524,8 @@ malo_init(void *arg) static void malo_setmcastfilter(struct malo_softc *sc) { - struct ifnet *ifp = sc->malo_ifp; - struct ieee80211com *ic = ifp->if_l2com; - struct ifmultiaddr *ifma; + struct ieee80211com *ic = &sc->malo_ic; + struct ieee80211vap *vap; uint8_t macs[IEEE80211_ADDR_LEN * MALO_HAL_MCAST_MAX]; uint8_t *mp; int nmc; @@ -1568,26 +1533,32 @@ malo_setmcastfilter(struct malo_softc *sc) mp = macs; nmc = 0; - if (ic->ic_opmode == IEEE80211_M_MONITOR || - (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) + if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 || + ic->ic_promisc > 0) goto all; - - if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - if (nmc == MALO_HAL_MCAST_MAX) { - ifp->if_flags |= IFF_ALLMULTI; - if_maddr_runlock(ifp); - goto all; - } - IEEE80211_ADDR_COPY(mp, - LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); + 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 (nmc == MALO_HAL_MCAST_MAX) { + ifp->if_flags |= IFF_ALLMULTI; + if_maddr_runlock(ifp); + goto all; + } + IEEE80211_ADDR_COPY(mp, + LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); - mp += IEEE80211_ADDR_LEN, nmc++; + mp += IEEE80211_ADDR_LEN, nmc++; + } + if_maddr_runlock(ifp); } - if_maddr_runlock(ifp); malo_hal_setmcast(sc->malo_mh, nmc, macs); @@ -1602,8 +1573,7 @@ all: static int malo_mode_init(struct malo_softc *sc) { - struct ifnet *ifp = sc->malo_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->malo_ic; struct malo_hal *mh = sc->malo_mh; /* @@ -1612,7 +1582,7 @@ malo_mode_init(struct malo_softc *sc) * identify internal requests (from the bridge) * versus external requests such as for tcpdump. */ - malo_hal_setpromisc(mh, (ifp->if_flags & IFF_PROMISC) && + malo_hal_setpromisc(mh, ic->ic_promisc > 0 && ic->ic_opmode != IEEE80211_M_HOSTAP); malo_setmcastfilter(sc); @@ -1641,8 +1611,7 @@ malo_tx_draintxq(struct malo_softc *sc, struct malo_txq *txq) MALO_TXQ_UNLOCK(txq); #ifdef MALO_DEBUG if (sc->malo_debug & MALO_DEBUG_RESET) { - struct ifnet *ifp = sc->malo_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->malo_ic; const struct malo_txrec *tr = mtod(bf->bf_m, const struct malo_txrec *); malo_printtxbuf(bf, txq->qnum, ix); @@ -1670,18 +1639,17 @@ malo_tx_draintxq(struct malo_softc *sc, struct malo_txq *txq) } static void -malo_stop_locked(struct ifnet *ifp, int disable) +malo_stop(struct malo_softc *sc) { - struct malo_softc *sc = ifp->if_softc; struct malo_hal *mh = sc->malo_mh; int i; - DPRINTF(sc, MALO_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n", - __func__, sc->malo_invalid, ifp->if_flags); + DPRINTF(sc, MALO_DEBUG_ANY, "%s: invalid %u running %u\n", + __func__, sc->malo_invalid, sc->malo_running); MALO_LOCK_ASSERT(sc); - if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) + if (!sc->malo_running) return; /* @@ -1693,10 +1661,10 @@ malo_stop_locked(struct ifnet *ifp, int disable) * Note that some of this work is not possible if the hardware * is gone (invalid). */ - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + sc->malo_running = 0; callout_stop(&sc->malo_watchdog_timer); sc->malo_timer = 0; - /* diable interrupt. */ + /* disable interrupt. */ malo_hal_intrset(mh, 0); /* turn off the radio. */ malo_hal_setradio(mh, 0, MHP_AUTO_PREAMBLE); @@ -1706,57 +1674,38 @@ malo_stop_locked(struct ifnet *ifp, int disable) malo_tx_draintxq(sc, &sc->malo_txq[i]); } -static int -malo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +malo_parent(struct ieee80211com *ic) { -#define MALO_IS_RUNNING(ifp) \ - ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING)) - struct malo_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, startall = 0; + struct malo_softc *sc = ic->ic_softc; + int startall = 0; MALO_LOCK(sc); - switch (cmd) { - case SIOCSIFFLAGS: - if (MALO_IS_RUNNING(ifp)) { - /* - * To avoid rescanning another access point, - * do not call malo_init() here. Instead, - * only reflect promisc mode settings. - */ - malo_mode_init(sc); - } else if (ifp->if_flags & IFF_UP) { - /* - * Beware of being called during attach/detach - * to reset promiscuous mode. In that case we - * will still be marked UP but not RUNNING. - * However trying to re-init the interface - * is the wrong thing to do as we've already - * torn down much of our state. There's - * probably a better way to deal with this. - */ - if (!sc->malo_invalid) { - malo_init_locked(sc); - startall = 1; - } - } else - malo_stop_locked(ifp, 1); - 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) { + /* + * Beware of being called during attach/detach + * to reset promiscuous mode. In that case we + * will still be marked UP but not RUNNING. + * However trying to re-init the interface + * is the wrong thing to do as we've already + * torn down much of our state. There's + * probably a better way to deal with this. + */ + if (!sc->malo_running && !sc->malo_invalid) { + malo_init(sc); + startall = 1; + } + /* + * To avoid rescanning another access point, + * do not call malo_init() here. Instead, + * only reflect promisc mode settings. + */ + malo_mode_init(sc); + } else if (sc->malo_running) + malo_stop(sc); MALO_UNLOCK(sc); - if (startall) ieee80211_start_all(ic); - return error; -#undef MALO_IS_RUNNING } /* @@ -1773,7 +1722,7 @@ malo_updateslot(struct ieee80211com *ic) int error; /* NB: can be called early; suppress needless cmds */ - if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) + if (!sc->malo_running) return; DPRINTF(sc, MALO_DEBUG_RESET, @@ -1795,7 +1744,7 @@ static int malo_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct ieee80211com *ic = vap->iv_ic; - struct malo_softc *sc = ic->ic_ifp->if_softc; + struct malo_softc *sc = ic->ic_softc; struct malo_hal *mh = sc->malo_mh; int error; @@ -1839,12 +1788,11 @@ malo_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 malo_softc *sc = ifp->if_softc; + struct malo_softc *sc = ic->ic_softc; struct malo_txbuf *bf; struct malo_txq *txq; - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->malo_invalid) { + if (!sc->malo_running || sc->malo_invalid) { ieee80211_free_node(ni); m_freem(m); return ENETDOWN; @@ -1859,8 +1807,6 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, txq = &sc->malo_txq[0]; bf = malo_getbuf(sc, txq); if (bf == NULL) { - /* XXX blocks other traffic */ - ifp->if_drv_flags |= IFF_DRV_OACTIVE; ieee80211_free_node(ni); m_freem(m); return ENOBUFS; @@ -1870,7 +1816,6 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, * Pass the frame to the h/w for transmission. */ if (malo_tx_start(sc, ni, bf, m) != 0) { - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); bf->bf_m = NULL; bf->bf_node = NULL; MALO_TXQ_LOCK(txq); @@ -1915,9 +1860,9 @@ malo_sysctlattach(struct malo_softc *sc) static void malo_announce(struct malo_softc *sc) { - struct ifnet *ifp = sc->malo_ifp; - if_printf(ifp, "versions [hw %d fw %d.%d.%d.%d] (regioncode %d)\n", + device_printf(sc->malo_dev, + "versions [hw %d fw %d.%d.%d.%d] (regioncode %d)\n", sc->malo_hwspecs.hwversion, (sc->malo_hwspecs.fw_releasenum >> 24) & 0xff, (sc->malo_hwspecs.fw_releasenum >> 16) & 0xff, @@ -1926,9 +1871,11 @@ malo_announce(struct malo_softc *sc) sc->malo_hwspecs.regioncode); if (bootverbose || malo_rxbuf != MALO_RXBUF) - if_printf(ifp, "using %u rx buffers\n", malo_rxbuf); + device_printf(sc->malo_dev, + "using %u rx buffers\n", malo_rxbuf); if (bootverbose || malo_txbuf != MALO_TXBUF) - if_printf(ifp, "using %u tx buffers\n", malo_txbuf); + device_printf(sc->malo_dev, + "using %u tx buffers\n", malo_txbuf); } /* @@ -1989,8 +1936,7 @@ malo_chan_set(struct malo_softc *sc, struct ieee80211_channel *chan) static void malo_scan_start(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct malo_softc *sc = ifp->if_softc; + struct malo_softc *sc = ic->ic_softc; DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__); } @@ -1998,8 +1944,7 @@ malo_scan_start(struct ieee80211com *ic) static void malo_scan_end(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct malo_softc *sc = ifp->if_softc; + struct malo_softc *sc = ic->ic_softc; DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__); } @@ -2007,8 +1952,7 @@ malo_scan_end(struct ieee80211com *ic) static void malo_set_channel(struct ieee80211com *ic) { - struct ifnet *ifp = ic->ic_ifp; - struct malo_softc *sc = ifp->if_softc; + struct malo_softc *sc = ic->ic_softc; (void) malo_chan_set(sc, ic->ic_curchan); } @@ -2020,8 +1964,7 @@ malo_rx_proc(void *arg, int npending) ((((const struct ieee80211_frame *)wh)->i_fc[1] & \ IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) struct malo_softc *sc = arg; - struct ifnet *ifp = sc->malo_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->malo_ic; struct malo_rxbuf *bf; struct malo_rxdesc *ds; struct mbuf *m, *mnew; @@ -2078,7 +2021,7 @@ malo_rx_proc(void *arg, int npending) #endif status = ds->status; if (status & MALO_RXD_STATUS_DECRYPT_ERR_MASK) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto rx_next; } /* @@ -2117,7 +2060,7 @@ malo_rx_proc(void *arg, int npending) /* XXX don't need mbuf, just dma buffer */ mnew = malo_getrxmbuf(sc, bf); if (mnew == NULL) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); + counter_u64_add(ic->ic_ierrors, 1); goto rx_next; } /* @@ -2128,7 +2071,6 @@ malo_rx_proc(void *arg, int npending) bf->bf_m = mnew; m->m_data += off - hdrlen; m->m_pkthdr.len = m->m_len = pktlen; - m->m_pkthdr.rcvif = ifp; /* * Piece 802.11 header together. @@ -2158,8 +2100,6 @@ malo_rx_proc(void *arg, int npending) len, ds->rate, rssi); } #endif - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); - /* dispatch */ ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); @@ -2177,22 +2117,11 @@ rx_next: malo_bar0_write4(sc, sc->malo_hwspecs.rxdesc_read, readptr); sc->malo_rxnext = bf; - if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 && - !IFQ_IS_EMPTY(&ifp->if_snd)) - malo_start(ifp); + if (mbufq_first(&sc->malo_snd) != NULL) + malo_start(sc); #undef IEEE80211_DIR_DSTODS } -static void -malo_stop(struct ifnet *ifp, int disable) -{ - struct malo_softc *sc = ifp->if_softc; - - MALO_LOCK(sc); - malo_stop_locked(ifp, disable); - MALO_UNLOCK(sc); -} - /* * Reclaim all tx queue resources. */ @@ -2208,13 +2137,9 @@ malo_tx_cleanup(struct malo_softc *sc) int malo_detach(struct malo_softc *sc) { - struct ifnet *ifp = sc->malo_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->malo_ic; - DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n", - __func__, ifp->if_flags); - - malo_stop(ifp, 1); + malo_stop(sc); if (sc->malo_tq != NULL) { taskqueue_drain(sc->malo_tq, &sc->malo_rxtask); @@ -2240,8 +2165,7 @@ malo_detach(struct malo_softc *sc) malo_dma_cleanup(sc); malo_tx_cleanup(sc); malo_hal_detach(sc->malo_mh); - if_free(ifp); - + mbufq_drain(&sc->malo_snd); MALO_LOCK_DESTROY(sc); return 0; @@ -2250,28 +2174,21 @@ malo_detach(struct malo_softc *sc) void malo_shutdown(struct malo_softc *sc) { - malo_stop(sc->malo_ifp, 1); + + malo_stop(sc); } void malo_suspend(struct malo_softc *sc) { - struct ifnet *ifp = sc->malo_ifp; - DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n", - __func__, ifp->if_flags); - - malo_stop(ifp, 1); + malo_stop(sc); } void malo_resume(struct malo_softc *sc) { - struct ifnet *ifp = sc->malo_ifp; - - DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n", - __func__, ifp->if_flags); - if (ifp->if_flags & IFF_UP) + if (sc->malo_ic.ic_nrunning > 0) malo_init(sc); } |