robert@ noticed that iwm(4) Rx throughput increased after running: sysctl net.link.ifrxq.pressure_drop=32 The default value for this sysctl is 8.
dlg@ explained the problem to me: [[[ the pressure stuff counts the number of times ifiq_input (which is called from if_input) gets called before a corresponding ifiq_process call gets run. if ifiq_input gets called a lot before ifiq_process runs, pressure builds up and after ifiq_pressure_drop calls it will shed load by dropping packets. ifiq_input is built to handle a list of packets built by processing the rx ring of a nic in a single interrupt. every hw interrupt should cause a single ifiq_input call. the list is hopefully processed in nettq in between the hw interrupts, but the pressure thresholds give you a bit of leeway. ]]] 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: 1) enqueue frames pulled from hardware to an mbuf list: ieee80211_input() 1) deliver frames to network stack via if_input: ieee80211_input_flush() Existing ieee80211_input() calls don't need to be adjusted because enqueuing happens under the hood onto a new mbuf list in ieee80211com. Drivers call ieee80211_input_flush() once per Rx interrupt. This diff touches all drivers and should be tested on as many drivers as possible. While these changes are mostly mechanical, a lot of this touches legacy drivers which I cannot easily test. Please thoroughly review for errors. bwfm(4) does not use ieee80211_input() for data frames but has the same bug and will need to be fixed separately (patrick@ is aware). I expect that 11n mode in particular will benefit from this. ifq pressure drops can be fairly easily triggered by Rx aggregation. 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 + 43f9de3d52b149afef46a71ff51a94b81b6799b9 --- sys/net80211/ieee80211_proto.c +++ sys/net80211/ieee80211_proto.c @@ -974,9 +974,11 @@ 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 + + s = splnet(); + ml_purge(&ic->ic_ml); + splx(s); ostate = ic->ic_state; if (ifp->if_flags & IFF_DEBUG) 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