On 09/09/19(Mon) 16:37, Stefan Sperling wrote: > On Mon, Sep 09, 2019 at 03:10:04PM +0200, Stefan Sperling wrote: > > The wifi stack currently calls if_input once per packet instead of once > > per interrupt. To make the wifi layer play nicely with the network stack > > we can split ieee80211_input() into two parts: > > Updated diff which avoids purging the input queue at every state > change, e.g. even during SCAN->SCAN. With this we only purge the > queue if we're leaving RUN state or going back to INIT state.
Thanks a lot! I must say I looked at this in the past but got lost in ieee80211_input(). Why not keep ieee80211_input() as a wrapper around your new mechanism? This way you don't need to touch all drivers at once. I'd also suggest using a queue on-stack like we do for Ethernet drivers, this would get rid of the cleanup of `ic_ml' when the state change. It would also help developers familiar with Ethernet drivers to understand what's happening ;o) What about: ieee80211_enqueue(ifp, m, ni, &rxi, &ml); ieee80211_inputm(ifp, &ml); Are you sure if_input() needs to be called at splnet()? I don't think so because many pseudo-drivers call it at a different IPL. > diff refs/heads/master refs/heads/ifqdrop > blob - a1ca62ea1a4b5af7d1d1765eb1da131e15e21e4e > blob + bb0660f8da5ea340de57519e471b3a1a88c7da33 > --- sys/dev/ic/acx.c > +++ sys/dev/ic/acx.c > @@ -1398,6 +1398,7 @@ acx_rxeof(struct acx_softc *sc) > rxi.rxi_rssi = head->rbh_level; > rxi.rxi_tstamp = letoh32(head->rbh_time); > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > > ieee80211_release_node(ic, ni); > } else { > blob - d3b9ada242c555f179dad1529c20a1748d4b7917 > blob + d62e42897867623911ae53637503a42178637603 > --- sys/dev/ic/an.c > +++ sys/dev/ic/an.c > @@ -477,6 +477,7 @@ an_rxeof(struct an_softc *sc) > rxi.rxi_rssi = frmhdr.an_rx_signal_strength; > rxi.rxi_tstamp = an_switch32(frmhdr.an_rx_time); > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > ieee80211_release_node(ic, ni); > } > > blob - d72e8edceada8a680744a6b8478bb91ac9e15e6e > blob + 14dc84e692380a6a59b9fd9e3846f83e9a28e461 > --- sys/dev/ic/ar5008.c > +++ sys/dev/ic/ar5008.c > @@ -960,7 +960,12 @@ ar5008_rx_process(struct athn_softc *sc) > void > ar5008_rx_intr(struct athn_softc *sc) > { > + struct ieee80211com *ic = &sc->sc_ic; > + struct ifnet *ifp = &ic->ic_if; > + > while (ar5008_rx_process(sc) == 0); > + > + ieee80211_input_flush(ifp); > } > > int > blob - 69ade5ade5a35e632a025db327668d695a0edd2d > blob + c34c8dae63f268c4baa4b8be396e0a6f6af8d05b > --- sys/dev/ic/ar9003.c > +++ sys/dev/ic/ar9003.c > @@ -1066,7 +1066,12 @@ ar9003_rx_process(struct athn_softc *sc, int qid) > void > ar9003_rx_intr(struct athn_softc *sc, int qid) > { > + struct ieee80211com *ic = &sc->sc_ic; > + struct ifnet *ifp = &ic->ic_if; > + > while (ar9003_rx_process(sc, qid) == 0); > + > + ieee80211_input_flush(ifp); > } > > int > blob - c0c5f4241b010c5c38a557d97963fbdbc884336d > blob + 4d481bf2aada58fd7f9c484e3564db5b3d96d2b0 > --- sys/dev/ic/ath.c > +++ sys/dev/ic/ath.c > @@ -2005,6 +2005,8 @@ ath_rx_proc(void *arg, int npending) > TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list); > } while (ath_rxbuf_init(sc, bf) == 0); > > + ieee80211_input_flush(ifp); > + > ath_hal_set_rx_signal(ah); /* rx signal state monitoring */ > ath_hal_start_rx(ah); /* in case of RXEOL */ > #undef PA2DESC > blob - cbf21da74007080c510fa9c56a58aedff62fa586 > blob + 301b784e1b6878e0b024e17f7e515097fa6363d1 > --- sys/dev/ic/atw.c > +++ sys/dev/ic/atw.c > @@ -3191,6 +3191,7 @@ atw_rxintr(struct atw_softc *sc) > */ > ieee80211_release_node(ic, ni); > } > + ieee80211_input_flush(ifp); > > /* Update the receive pointer. */ > sc->sc_rxptr = i; > blob - 7d6f2c5a5693881e2dffdd1814a757c9563196fc > blob + 9ce7309aeb96e7282fc8ac28e3cfc633e1d9f592 > --- sys/dev/ic/bwfm.c > +++ sys/dev/ic/bwfm.c > @@ -2118,6 +2118,7 @@ bwfm_rx_auth_ind(struct bwfm_softc *sc, struct bwfm_ev > rxi.rxi_rssi = 0; > rxi.rxi_tstamp = 0; > ieee80211_input(ifp, m, ic->ic_bss, &rxi); > + ieee80211_input_flush(ifp); > } > > void > @@ -2174,6 +2175,7 @@ bwfm_rx_assoc_ind(struct bwfm_softc *sc, struct bwfm_e > rxi.rxi_rssi = 0; > rxi.rxi_tstamp = 0; > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > } > > void > @@ -2229,6 +2231,7 @@ bwfm_rx_leave_ind(struct bwfm_softc *sc, struct bwfm_e > rxi.rxi_rssi = 0; > rxi.rxi_tstamp = 0; > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > } > #endif > > @@ -2418,6 +2421,7 @@ bwfm_scan_node(struct bwfm_softc *sc, struct bwfm_bss_ > rxi.rxi_rssi = (int16_t)letoh16(bss->rssi); > rxi.rxi_tstamp = 0; > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > /* Restore channel */ > if (bss_chan) > ni->ni_chan = bss_chan; > blob - 58417ce6f7de644fe86347459c04553956b2edc0 > blob + 25a40399a82089a496698f4a1fb8d88cb59375ac > --- sys/dev/ic/bwi.c > +++ sys/dev/ic/bwi.c > @@ -8466,6 +8466,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx) > next: > idx = (idx + 1) % BWI_RX_NDESC; > } > + ieee80211_input_flush(ifp); > > rbd->rbd_idx = idx; > bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0, > blob - 6a8c5646f0b6f649a60793e127cbd746d8ee89d7 > blob + bcd515d11a392f49f75914f1af6581b35b8cf054 > --- sys/dev/ic/malo.c > +++ sys/dev/ic/malo.c > @@ -1727,6 +1727,7 @@ skip: > sc->sc_rxring.cur = (sc->sc_rxring.cur + 1) % > MALO_RX_RING_COUNT; > } > + ieee80211_input_flush(ifp); > > malo_mem_write4(sc, sc->sc_RxPdRdPtr, rxRdPtr); > } > blob - f44264645097e6f991f5642f7973ed5ebe3e5d7e > blob + 2f316718eb1c5310c46c64394c8b3603b056499e > --- sys/dev/ic/pgt.c > +++ sys/dev/ic/pgt.c > @@ -1036,6 +1036,7 @@ input: > ifp->if_ierrors++; > } > } > + ieee80211_input_flush(ifp); > } > > void > blob - c8d85564272d263215e829d007c11a47741316e6 > blob + 32b3ddbc260c86e39043baef04ceb64edf4c02b4 > --- sys/dev/ic/rt2560.c > +++ sys/dev/ic/rt2560.c > @@ -1220,6 +1220,7 @@ skip: desc->flags = htole32(RT2560_RX_BUSY); > sc->rxq.cur_decrypt = > (sc->rxq.cur_decrypt + 1) % RT2560_RX_RING_COUNT; > } > + ieee80211_input_flush(ifp); > } > > /* > blob - 591115f692d4f77a522d114e5a91d6026e3452fe > blob + 8e090624a986aee3b0748884baa8a84332d92ff5 > --- sys/dev/ic/rt2661.c > +++ sys/dev/ic/rt2661.c > @@ -1302,6 +1302,7 @@ skip: desc->flags |= htole32(RT2661_RX_BUSY); > > sc->rxq.cur = (sc->rxq.cur + 1) % RT2661_RX_RING_COUNT; > } > + ieee80211_input_flush(ifp); > } > > #ifndef IEEE80211_STA_ONLY > blob - c6c811c835ef4558079c00d50041075b9a8321bb > blob + 2fc9aedb090a50080c099d5b24ca96535ccf33dc > --- sys/dev/ic/rt2860.c > +++ sys/dev/ic/rt2860.c > @@ -1432,6 +1432,7 @@ skip: rxd->sdl0 &= ~htole16(RT2860_RX_DDONE); > > sc->rxq.cur = (sc->rxq.cur + 1) % RT2860_RX_RING_COUNT; > } > + ieee80211_input_flush(ifp); > > /* tell HW what we have processed */ > RAL_WRITE(sc, RT2860_RX_CALC_IDX, > blob - ce7686c40fa4b1166d0af3fe54d8cad60704f556 > blob + 420bcd5f0db656fb85833f6ad290b2432c1fe82f > --- sys/dev/ic/rtw.c > +++ sys/dev/ic/rtw.c > @@ -1294,6 +1294,7 @@ rtw_intr_rx(struct rtw_softc *sc, u_int16_t isr) > next: > rtw_rxdesc_init(rdb, rs, next, 0); > } > + ieee80211_input_flush(&sc->sc_if); > rdb->rdb_next = next; > > KASSERT(rdb->rdb_next < rdb->rdb_ndesc); > blob - cd0d354d12f45e34327a1d9d2d6ae5b480f9e305 > blob + cf8f4f3f38d70f01c28136f6a2e3f9f8fa9dc7c4 > --- sys/dev/pci/if_ipw.c > +++ sys/dev/pci/if_ipw.c > @@ -966,6 +966,7 @@ ipw_rx_intr(struct ipw_softc *sc) > i * sizeof (struct ipw_bd), sizeof (struct ipw_bd), > BUS_DMASYNC_PREWRITE); > } > + ieee80211_input_flush(&sc->sc_ic.ic_if); > > /* tell the firmware what we have processed */ > sc->rxcur = (r == 0) ? IPW_NRBD - 1 : r - 1; > blob - bdb4827425118b9159ae05ad1263bdf5c084254f > blob + 77621142318b26269d864de7443d3f6cd27ffe27 > --- sys/dev/pci/if_iwi.c > +++ sys/dev/pci/if_iwi.c > @@ -1105,6 +1105,7 @@ iwi_rx_intr(struct iwi_softc *sc) > > sc->rxq.cur = (sc->rxq.cur + 1) % IWI_RX_RING_COUNT; > } > + ieee80211_input_flush(&sc->sc_ic.ic_if); > > /* tell the firmware what we have processed */ > hw = (hw == 0) ? IWI_RX_RING_COUNT - 1 : hw - 1; > blob - 0b2116dbc13428f1726773000e8e6a8c251d86b4 > blob + d347c3d8f4853099592dd1617dcfd5946bdd5c6c > --- sys/dev/pci/if_iwm.c > +++ sys/dev/pci/if_iwm.c > @@ -7289,6 +7289,7 @@ iwm_notif_intr(struct iwm_softc *sc) > > ADVANCE_RXQ(sc); > } > + ieee80211_input_flush(&sc->sc_ic.ic_if); > > /* > * Tell the firmware what we have processed. > blob - 6be794c2cd435c74b1b5c3f028b9613dc74ecf20 > blob + 06d0e55d42910fc8c60bd29078829399cf337fe4 > --- sys/dev/pci/if_iwn.c > +++ sys/dev/pci/if_iwn.c > @@ -2913,6 +2913,7 @@ iwn_notif_intr(struct iwn_softc *sc) > > sc->rxq.cur = (sc->rxq.cur + 1) % IWN_RX_RING_COUNT; > } > + ieee80211_input_flush(&sc->sc_ic.ic_if); > > /* Tell the firmware what we have processed. */ > hw = (hw == 0) ? IWN_RX_RING_COUNT - 1 : hw - 1; > blob - 2c53aa925247b5056360daf479fca12e45624107 > blob + 9dc76928c677c89fc9f7d2aa09082bf73e62190c > --- sys/dev/pci/if_rtwn.c > +++ sys/dev/pci/if_rtwn.c > @@ -1511,6 +1511,8 @@ rtwn_88e_intr(struct rtwn_pci_softc *sc) > rtwn_tx_done(sc, RTWN_VO_QUEUE); > if ((status & (R88E_HIMR_ROK | R88E_HIMR_RDU)) || > (estatus & R88E_HIMRE_RXFOVW)) { > + struct ieee80211com *ic = &sc->sc_sc.sc_ic; > + > bus_dmamap_sync(sc->sc_dmat, sc->rx_ring.map, 0, > sizeof(struct r92c_rx_desc_pci) * RTWN_RX_LIST_COUNT, > BUS_DMASYNC_POSTREAD); > @@ -1524,6 +1526,7 @@ rtwn_88e_intr(struct rtwn_pci_softc *sc) > > rtwn_rx_frame(sc, rx_desc, rx_data, i); > } > + ieee80211_input_flush(&ic->ic_if); > } > > if (status & R88E_HIMR_HSISR_IND_ON_INT) { > @@ -1561,6 +1564,8 @@ rtwn_intr(void *xsc) > > /* Vendor driver treats RX errors like ROK... */ > if (status & (R92C_IMR_ROK | R92C_IMR_RXFOVW | R92C_IMR_RDU)) { > + struct ieee80211com *ic = &sc->sc_sc.sc_ic; > + > bus_dmamap_sync(sc->sc_dmat, sc->rx_ring.map, 0, > sizeof(struct r92c_rx_desc_pci) * RTWN_RX_LIST_COUNT, > BUS_DMASYNC_POSTREAD); > @@ -1574,6 +1579,7 @@ rtwn_intr(void *xsc) > > rtwn_rx_frame(sc, rx_desc, rx_data, i); > } > + ieee80211_input_flush(&ic->ic_if); > } > > if (status & R92C_IMR_BDOK) > blob - 2a91ccec016f8047bfe26ede71e8881404fef619 > blob + 02f8191621b3c3967aab4abec9447c7cd4e5ffac > --- sys/dev/pci/if_wpi.c > +++ sys/dev/pci/if_wpi.c > @@ -1527,6 +1527,7 @@ wpi_notif_intr(struct wpi_softc *sc) > > sc->rxq.cur = (sc->rxq.cur + 1) % WPI_RX_RING_COUNT; > } > + ieee80211_input_flush(&ic->ic_if); > > /* Tell the firmware what we have processed. */ > hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1; > blob - 39edb129685cac47d29224f18c6f2e7c92922720 > blob + 2fe4fc1af606a4ab32e6dcce83cc7c710e3c814b > --- sys/dev/usb/if_athn_usb.c > +++ sys/dev/usb/if_athn_usb.c > @@ -2175,6 +2175,7 @@ athn_usb_rxeof(struct usbd_xfer *xfer, void *priv, > buf += off; > len -= off; > } > + ieee80211_input_flush(ifp); > > resubmit: > /* Setup a new transfer. */ > blob - 7c49042002e73f07bda3c9a5dc7e13e9d7e97503 > blob + 46fa39efc05c66d59e7e73c94dfe2b5ec635d9ad > --- sys/dev/usb/if_atu.c > +++ sys/dev/usb/if_atu.c > @@ -1743,6 +1743,7 @@ atu_rxeof(struct usbd_xfer *xfer, void *priv, usbd_sta > rxi.rxi_rssi = h->rssi; > rxi.rxi_tstamp = UGETDW(h->rx_time); > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > > ieee80211_release_node(ic, ni); > done1: > blob - cb7e65865adb17b86e10bf5c2bc59983a5c8c2c9 > blob + 3c8da94867b14ab18d315b7c69c1188cc770569d > --- sys/dev/usb/if_otus.c > +++ sys/dev/usb/if_otus.c > @@ -1241,6 +1241,7 @@ otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_st > buf += hlen; > len -= hlen; > } > + ieee80211_input_flush(&sc->sc_ic.ic_if); > > resubmit: > usbd_setup_xfer(xfer, sc->data_rx_pipe, data, data->buf, OTUS_RXBUFSZ, > blob - 9d81664f824def87770512b3e61a015782c99be0 > blob + 623fd79146a1879baf23aee4380611444c21f440 > --- sys/dev/usb/if_ral.c > +++ sys/dev/usb/if_ral.c > @@ -782,6 +782,7 @@ ural_rxeof(struct usbd_xfer *xfer, void *priv, usbd_st > rxi.rxi_rssi = desc->rssi; > rxi.rxi_tstamp = 0; /* unused */ > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > > /* node is no longer needed */ > ieee80211_release_node(ic, ni); > blob - 417666c3503da89fce1d3dc4301b48376dcf7e41 > blob + e8d263d2c4322d44836e0197cdd909adc795648e > --- sys/dev/usb/if_rsu.c > +++ sys/dev/usb/if_rsu.c > @@ -1120,6 +1120,7 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, i > rxi.rxi_rssi = letoh32(bss->rssi); > rxi.rxi_tstamp = 0; > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > /* Node is no longer needed. */ > ieee80211_release_node(ic, ni); > } > @@ -1415,6 +1416,7 @@ rsu_rx_multi_frame(struct rsu_softc *sc, uint8_t *buf, > buf += totlen; > len -= totlen; > } > + ieee80211_input_flush(&sc->sc_ic.ic_if); > } > > void > blob - 7126aaa9540a3f838e7bc1d4e80a06e759e98517 > blob + 3fe904607ebf7584cee0348ebb9d4135510d499e > --- sys/dev/usb/if_rum.c > +++ sys/dev/usb/if_rum.c > @@ -851,6 +851,7 @@ rum_rxeof(struct usbd_xfer *xfer, void *priv, usbd_sta > rxi.rxi_rssi = desc->rssi; > rxi.rxi_tstamp = 0; /* unused */ > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > > /* node is no longer needed */ > ieee80211_release_node(ic, ni); > blob - fc6ba52f271725fe7afbb4abf1a4a1700920a1b4 > blob + 5342470a39c8094143e9372855c0511c2ed0161e > --- sys/dev/usb/if_run.c > +++ sys/dev/usb/if_run.c > @@ -2352,6 +2352,7 @@ run_rxeof(struct usbd_xfer *xfer, void *priv, usbd_sta > buf += dmalen + 8; > xferlen -= dmalen + 8; > } > + ieee80211_input_flush(&sc->sc_ic.ic_if); > > skip: /* setup a new transfer */ > usbd_setup_xfer(xfer, sc->rxq.pipeh, data, data->buf, RUN_MAX_RXSZ, > blob - 30aa31b56bfd1226a4199c9024907adbbb3e429d > blob + d657466dccf52fb1271a3650718feecb6e19c297 > --- sys/dev/usb/if_uath.c > +++ sys/dev/usb/if_uath.c > @@ -1265,6 +1265,7 @@ uath_data_rxeof(struct usbd_xfer *xfer, void *priv, > rxi.rxi_rssi = (int)betoh32(desc->rssi); > rxi.rxi_tstamp = 0; /* unused */ > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > > /* node is no longer needed */ > ieee80211_release_node(ic, ni); > blob - 6c8b66842fb650329fb36d812e76fa41be9ab9c7 > blob + 72928af7c891bcc295dd79d71a2b6155a64eb0a5 > --- sys/dev/usb/if_upgt.c > +++ sys/dev/usb/if_upgt.c > @@ -1748,6 +1748,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkgl > rxi.rxi_rssi = rxdesc->rssi; > rxi.rxi_tstamp = 0; /* unused */ > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > > /* node is no longer needed */ > ieee80211_release_node(ic, ni); > blob - 17d56c174230515195c13c070aed9065a68bc959 > blob + 87bdc93a6df4786458f6eec62ceb025cc7e75a5a > --- sys/dev/usb/if_urtw.c > +++ sys/dev/usb/if_urtw.c > @@ -3161,6 +3161,7 @@ urtw_rxeof(struct usbd_xfer *xfer, void *priv, usbd_st > rxi.rxi_rssi = rssi; > rxi.rxi_tstamp = 0; > ieee80211_input(ifp, m, ni, &rxi); > + ieee80211_input_flush(ifp); > > /* node is no longer needed */ > ieee80211_release_node(ic, ni); > blob - 96a1ad1a91c3e98ebc6dece98df6ac277046612c > blob + 3f353ff8296162cde2163af94099b9a666bb106c > --- sys/dev/usb/if_urtwn.c > +++ sys/dev/usb/if_urtwn.c > @@ -1206,6 +1206,7 @@ urtwn_rxeof(struct usbd_xfer *xfer, void *priv, > { > struct urtwn_rx_data *data = priv; > struct urtwn_softc *sc = data->sc; > + struct ieee80211com *ic = &sc->sc_sc.sc_ic; > struct r92c_rx_desc_usb *rxd; > uint32_t rxdw0; > uint8_t *buf; > @@ -1305,6 +1306,7 @@ urtwn_rxeof(struct usbd_xfer *xfer, void *priv, > buf += totlen; > len -= totlen; > } > + ieee80211_input_flush(&ic->ic_if); > > resubmit: > /* Setup a new transfer. */ > blob - 689ac7e7178ca36a091d25cc6f2cf8d15cc45b0b > blob + 498bb68138994cd361f996c866e95c959a5ddf15 > --- sys/dev/usb/if_zyd.c > +++ sys/dev/usb/if_zyd.c > @@ -2039,6 +2039,7 @@ zyd_rxeof(struct usbd_xfer *xfer, void *priv, usbd_sta > > zyd_rx_data(sc, data->buf, len); > } > + ieee80211_input_flush(ifp); > > skip: /* setup a new transfer */ > usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_BIN], data, NULL, > blob - ace97a38cc4ff76b454c1f6a12655565ad131275 > blob + c20962c799b141638a2fff11d5ceef6d6db47667 > --- sys/net80211/ieee80211.c > +++ sys/net80211/ieee80211.c > @@ -184,6 +184,8 @@ ieee80211_ifattach(struct ifnet *ifp) > ic->ic_bmissthres = 7; /* default 7 beacons */ > ic->ic_dtim_period = 1; /* all TIMs are DTIMs */ > > + ml_init(&ic->ic_ml); > + > ieee80211_node_attach(ifp); > ieee80211_proto_attach(ifp); > > @@ -200,6 +202,7 @@ ieee80211_ifdetach(struct ifnet *ifp) > { > struct ieee80211com *ic = (void *)ifp; > > + ml_purge(&ic->ic_ml); > timeout_del(&ic->ic_bgscan_timeout); > ieee80211_proto_detach(ifp); > ieee80211_crypto_detach(ifp); > blob - 73a9d5229502797c5279734663b1ac1591bec309 > blob + de36481038ec3372d0d5533002cbc62a1ebe2b6a > --- sys/net80211/ieee80211_input.c > +++ sys/net80211/ieee80211_input.c > @@ -71,11 +71,11 @@ void ieee80211_input_ba_seq(struct ieee80211com *, > struct ieee80211_node *, uint8_t, uint16_t); > struct mbuf *ieee80211_align_mbuf(struct mbuf *); > void ieee80211_decap(struct ieee80211com *, struct mbuf *, > - struct ieee80211_node *, int); > + struct ieee80211_node *, int, struct mbuf_list *); > void ieee80211_amsdu_decap(struct ieee80211com *, struct mbuf *, > - struct ieee80211_node *, int); > -void ieee80211_deliver_data(struct ieee80211com *, struct mbuf *, > - struct ieee80211_node *, int); > + struct ieee80211_node *, int, struct mbuf_list *); > +void ieee80211_enqueue_data(struct ieee80211com *, struct mbuf *, > + struct ieee80211_node *, int, struct mbuf_list *); > int ieee80211_parse_edca_params_body(struct ieee80211com *, > const u_int8_t *); > int ieee80211_parse_edca_params(struct ieee80211com *, const u_int8_t *); > @@ -155,6 +155,9 @@ ieee80211_get_hdrlen(const struct ieee80211_frame *wh) > * any units so long as values have consistent units and higher values > * mean ``better signal''. The receive timestamp is currently not used > * by the 802.11 layer. > + * > + * This function only queues frames for delivery. > + * Actual delivery to upper layers is triggered by ieee80211_input_flush(). > */ > void > ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni, > @@ -463,9 +466,9 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, str > > if ((ni->ni_flags & IEEE80211_NODE_HT) && > hasqos && (qos & IEEE80211_QOS_AMSDU)) > - ieee80211_amsdu_decap(ic, m, ni, hdrlen); > + ieee80211_amsdu_decap(ic, m, ni, hdrlen, &ic->ic_ml); > else > - ieee80211_decap(ic, m, ni, hdrlen); > + ieee80211_decap(ic, m, ni, hdrlen, &ic->ic_ml); > return; > > case IEEE80211_FC0_TYPE_MGT: > @@ -561,6 +564,22 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, str > } > > /* > + * Deliver frames queued by ieee80211_input() to the network stack. > + * Drivers should call this function only once per Rx interrupt to avoid > + * triggering the input ifq pressure drop mechanism unnecessarily. > + */ > +void > +ieee80211_input_flush(struct ifnet *ifp) > +{ > + struct ieee80211com *ic = (void *)ifp; > + int s; > + > + s = splnet(); > + if_input(ifp, &ic->ic_ml); > + splx(s); > +} > + > +/* > * Handle defragmentation (see 9.5 and Annex C). We support the concurrent > * reception of fragments of three fragmented MSDUs or MMPDUs. > */ > @@ -856,8 +875,8 @@ ieee80211_ba_move_window(struct ieee80211com *ic, stru > } > > void > -ieee80211_deliver_data(struct ieee80211com *ic, struct mbuf *m, > - struct ieee80211_node *ni, int mcast) > +ieee80211_enqueue_data(struct ieee80211com *ic, struct mbuf *m, > + struct ieee80211_node *ni, int mcast, struct mbuf_list *ml) > { > struct ifnet *ifp = &ic->ic_if; > struct ether_header *eh; > @@ -920,16 +939,14 @@ ieee80211_deliver_data(struct ieee80211com *ic, struct > #endif > ieee80211_eapol_key_input(ic, m, ni); > } else { > - struct mbuf_list ml = MBUF_LIST_INITIALIZER(); > - ml_enqueue(&ml, m); > - if_input(ifp, &ml); > + ml_enqueue(ml, m); > } > } > } > > void > ieee80211_decap(struct ieee80211com *ic, struct mbuf *m, > - struct ieee80211_node *ni, int hdrlen) > + struct ieee80211_node *ni, int hdrlen, struct mbuf_list *ml) > { > struct ether_header eh; > struct ieee80211_frame *wh; > @@ -985,7 +1002,7 @@ ieee80211_decap(struct ieee80211com *ic, struct mbuf * > return; > } > } > - ieee80211_deliver_data(ic, m, ni, mcast); > + ieee80211_enqueue_data(ic, m, ni, mcast, ml); > } > > /* > @@ -993,7 +1010,7 @@ ieee80211_decap(struct ieee80211com *ic, struct mbuf * > */ > void > ieee80211_amsdu_decap(struct ieee80211com *ic, struct mbuf *m, > - struct ieee80211_node *ni, int hdrlen) > + struct ieee80211_node *ni, int hdrlen, struct mbuf_list *ml) > { > struct mbuf *n; > struct ether_header *eh; > @@ -1059,7 +1076,7 @@ ieee80211_amsdu_decap(struct ieee80211com *ic, struct > m_freem(m); > break; > } > - ieee80211_deliver_data(ic, m, ni, mcast); > + ieee80211_enqueue_data(ic, m, ni, mcast, ml); > > if (n->m_pkthdr.len == 0) { > m_freem(n); > blob - d00d1b631f2966efbd88992c92fea88a99e3ddf8 > blob + 87c41116d48d86cf446cae6486ee1dde42a92701 > --- sys/net80211/ieee80211_proto.c > +++ sys/net80211/ieee80211_proto.c > @@ -974,9 +974,7 @@ ieee80211_newstate(struct ieee80211com *ic, enum ieee8 > struct ieee80211_node *ni; > enum ieee80211_state ostate; > u_int rate; > -#ifndef IEEE80211_STA_ONLY > int s; > -#endif > > ostate = ic->ic_state; > if (ifp->if_flags & IFF_DEBUG) > @@ -1060,6 +1058,9 @@ justcleanup: > ic->ic_mgt_timer = 0; > mq_purge(&ic->ic_mgtq); > mq_purge(&ic->ic_pwrsaveq); > + s = splnet(); > + ml_purge(&ic->ic_ml); > + splx(s); > ieee80211_free_allnodes(ic, 1); > break; > } > @@ -1113,6 +1114,9 @@ justcleanup: > ic->ic_bgscan_fail = 0; > ieee80211_stop_ampdu_tx(ic, ni, mgt); > ieee80211_free_allnodes(ic, 1); > + s = splnet(); > + ml_purge(&ic->ic_ml); > + splx(s); > /* FALLTHROUGH */ > case IEEE80211_S_AUTH: > case IEEE80211_S_ASSOC: > @@ -1161,6 +1165,9 @@ justcleanup: > ic->ic_bgscan_fail = 0; > ieee80211_stop_ampdu_tx(ic, ni, mgt); > ieee80211_ba_del(ni); > + s = splnet(); > + ml_purge(&ic->ic_ml); > + splx(s); > switch (mgt) { > case IEEE80211_FC0_SUBTYPE_AUTH: > IEEE80211_SEND_MGMT(ic, ni, > @@ -1193,6 +1200,9 @@ justcleanup: > case IEEE80211_S_RUN: > ieee80211_stop_ampdu_tx(ic, ni, mgt); > ieee80211_ba_del(ni); > + s = splnet(); > + ml_purge(&ic->ic_ml); > + splx(s); > IEEE80211_SEND_MGMT(ic, ni, > IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1); > break; > blob - e622d35f4dcd21ea0bb40c6a5d0b3f758e197b38 > blob + c1d3ad65a46f76266533a4cfd5fffa08b4fa6537 > --- sys/net80211/ieee80211_proto.h > +++ sys/net80211/ieee80211_proto.h > @@ -68,6 +68,7 @@ extern u_int ieee80211_get_hdrlen(const struct ieee802 > extern int ieee80211_classify(struct ieee80211com *, struct mbuf *); > extern void ieee80211_input(struct ifnet *, struct mbuf *, > struct ieee80211_node *, struct ieee80211_rxinfo *); > +extern void ieee80211_input_flush(struct ifnet *); > extern int ieee80211_output(struct ifnet *, struct mbuf *, struct > sockaddr *, > struct rtentry *); > extern void ieee80211_recv_mgmt(struct ieee80211com *, struct mbuf *, > blob - 2a567a01422aaaf6024b05c5589f6f45b3744100 > blob + fcbe48513883c4c81cfb4c4d96e4d5d08a07ab7f > --- sys/net80211/ieee80211_var.h > +++ sys/net80211/ieee80211_var.h > @@ -340,6 +340,8 @@ struct ieee80211com { > u_int8_t ic_dialog_token; > int ic_fixed_mcs; > TAILQ_HEAD(, ieee80211_ess) ic_ess; > + > + struct mbuf_list ic_ml; /* frames queued for if_input() */ > }; > #define ic_if ic_ac.ac_if > #define ic_softc ic_if.if_softc >