On Tue, Sep 10, 2019 at 07:08:14PM +0200, Matthias Schmidt wrote:
> Hi Stefan,
> 
> * Stefan Sperling wrote:
> > 
> > New diff with above changes:
> 
> I tested your new diff with two different systems:
> 
> * Thinkpad T450s with iwm (8265, same as yesterday)
> * Thinkpad X220 with iwn (6205)
> 
> and on both systems I see a drastic regression compared to yesterday's
> patch.  The download speeds is around 400-700K/s on both systems.  As
> soon as I switch back to the kernel with yesterday's patch, I end up
> having 4M/s in average, again.

I think I see why. I forgot to convert some existing ieee80211_input()
calls to ieee80211_inputm(), in ieee80211_input.c.
These calls are related to buffered aggregated frames, so aggregated
frames triggered multiple if_input() calls per interrupt again.

In the first diff ieee80211_input() was putting aggregated frames
onto the global mbuf list. With this new diff they get added to the
mbuf list which the driver's rx interrupt handler passed in.

Does this fix the issue?

diff refs/heads/master refs/heads/ifqdrop
blob - d72e8edceada8a680744a6b8478bb91ac9e15e6e
blob + a3203d7eb1a67d478bf280a551a43f2dc66c0965
--- sys/dev/ic/ar5008.c
+++ sys/dev/ic/ar5008.c
@@ -789,7 +789,7 @@ ar5008_rx_radiotap(struct athn_softc *sc, struct mbuf 
 #endif
 
 static __inline int
-ar5008_rx_process(struct athn_softc *sc)
+ar5008_rx_process(struct athn_softc *sc, struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -931,7 +931,7 @@ ar5008_rx_process(struct athn_softc *sc)
        rxi.rxi_rssi = MS(ds->ds_status4, AR_RXS4_RSSI_COMBINED);
        rxi.rxi_rssi += AR_DEFAULT_NOISE_FLOOR;
        rxi.rxi_tstamp = ds->ds_status2;
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
 
        /* Node is no longer needed. */
        ieee80211_release_node(ic, ni);
@@ -960,7 +960,13 @@ ar5008_rx_process(struct athn_softc *sc)
 void
 ar5008_rx_intr(struct athn_softc *sc)
 {
-       while (ar5008_rx_process(sc) == 0);
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct ifnet *ifp = &ic->ic_if;
+
+       while (ar5008_rx_process(sc, &ml) == 0);
+
+       if_input(ifp, &ml);
 }
 
 int
blob - 69ade5ade5a35e632a025db327668d695a0edd2d
blob + dafa3bd1f0b4ca2124c6d963c82e289594e88b27
--- sys/dev/ic/ar9003.c
+++ sys/dev/ic/ar9003.c
@@ -83,7 +83,7 @@ void  ar9003_reset_txsring(struct athn_softc *);
 void   ar9003_rx_enable(struct athn_softc *);
 void   ar9003_rx_radiotap(struct athn_softc *, struct mbuf *,
            struct ar_rx_status *);
-int    ar9003_rx_process(struct athn_softc *, int);
+int    ar9003_rx_process(struct athn_softc *, int, struct mbuf_list *);
 void   ar9003_rx_intr(struct athn_softc *, int);
 int    ar9003_tx_process(struct athn_softc *);
 void   ar9003_tx_intr(struct athn_softc *);
@@ -916,7 +916,7 @@ ar9003_rx_radiotap(struct athn_softc *sc, struct mbuf 
 #endif
 
 int
-ar9003_rx_process(struct athn_softc *sc, int qid)
+ar9003_rx_process(struct athn_softc *sc, int qid, struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -1036,7 +1036,7 @@ ar9003_rx_process(struct athn_softc *sc, int qid)
        rxi.rxi_flags = 0;      /* XXX */
        rxi.rxi_rssi = MS(ds->ds_status5, AR_RXS5_RSSI_COMBINED);
        rxi.rxi_tstamp = ds->ds_status3;
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
 
        /* Node is no longer needed. */
        ieee80211_release_node(ic, ni);
@@ -1066,7 +1066,13 @@ ar9003_rx_process(struct athn_softc *sc, int qid)
 void
 ar9003_rx_intr(struct athn_softc *sc, int qid)
 {
-       while (ar9003_rx_process(sc, qid) == 0);
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct ifnet *ifp = &ic->ic_if;
+
+       while (ar9003_rx_process(sc, qid, &ml) == 0);
+
+       if_input(ifp, &ml);
 }
 
 int
blob - c0c5f4241b010c5c38a557d97963fbdbc884336d
blob + c4414e5113134012edaf4ce4557bb7e25987e9ef
--- sys/dev/ic/ath.c
+++ sys/dev/ic/ath.c
@@ -1795,6 +1795,7 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *b
 void
 ath_rx_proc(void *arg, int npending)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
 #define        PA2DESC(_sc, _pa) \
        ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
                ((_pa) - (_sc)->sc_desc_paddr)))
@@ -1946,7 +1947,7 @@ ath_rx_proc(void *arg, int npending)
                if (!ath_softcrypto && (wh->i_fc[1] & IEEE80211_FC1_WEP)) {
                        /*
                         * WEP is decrypted by hardware. Clear WEP bit
-                        * and trim WEP header for ieee80211_input().
+                        * and trim WEP header for ieee80211_inputm().
                         */
                        wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
                        bcopy(wh, &whbuf, sizeof(whbuf));
@@ -1988,7 +1989,7 @@ ath_rx_proc(void *arg, int npending)
                 */
                rxi.rxi_rssi = ds->ds_rxstat.rs_rssi;
                rxi.rxi_tstamp = ds->ds_rxstat.rs_tstamp;
-               ieee80211_input(ifp, m, ni, &rxi);
+               ieee80211_inputm(ifp, m, ni, &rxi, &ml);
 
                /* Handle the rate adaption */
                ieee80211_rssadapt_input(ic, ni, &an->an_rssadapt,
@@ -2004,6 +2005,8 @@ ath_rx_proc(void *arg, int npending)
        rx_next:
                TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
        } while (ath_rxbuf_init(sc, bf) == 0);
+
+       if_input(ifp, &ml);
 
        ath_hal_set_rx_signal(ah);              /* rx signal state monitoring */
        ath_hal_start_rx(ah);                   /* in case of RXEOL */
blob - cbf21da74007080c510fa9c56a58aedff62fa586
blob + 6f609b3d8e77c27ba27e6be88cff55fbf87bbb2c
--- sys/dev/ic/atw.c
+++ sys/dev/ic/atw.c
@@ -3029,6 +3029,7 @@ atw_hw_decrypted(struct atw_softc *sc, struct ieee8021
 void
 atw_rxintr(struct atw_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        static int rate_tbl[] = {2, 4, 11, 22, 44};
        struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211_rxinfo rxi;
@@ -3183,7 +3184,7 @@ atw_rxintr(struct atw_softc *sc)
 #endif
                rxi.rxi_rssi = (int)rssi;
                rxi.rxi_tstamp = 0;
-               ieee80211_input(ifp, m, ni, &rxi);
+               ieee80211_inputm(ifp, m, ni, &rxi, &ml);
                /*
                 * The frame may have caused the node to be marked for
                 * reclamation (e.g. in response to a DEAUTH message)
@@ -3191,6 +3192,7 @@ atw_rxintr(struct atw_softc *sc)
                 */
                ieee80211_release_node(ic, ni);
        }
+       if_input(ifp, &ml);
 
        /* Update the receive pointer. */
        sc->sc_rxptr = i;
blob - 58417ce6f7de644fe86347459c04553956b2edc0
blob + b383588620701ca5c656d29c0384393696914cdc
--- sys/dev/ic/bwi.c
+++ sys/dev/ic/bwi.c
@@ -8355,6 +8355,7 @@ bwi_next_scan(void *xsc)
 int
 bwi_rxeof(struct bwi_softc *sc, int end_idx)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct bwi_ring_data *rd = &sc->sc_rx_rdata;
        struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
        struct ieee80211com *ic = &sc->sc_ic;
@@ -8455,7 +8456,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
 
                rxi.rxi_rssi = hdr->rxh_rssi;
                rxi.rxi_tstamp = letoh16(hdr->rxh_tsf);
-               ieee80211_input(ifp, m, ni, &rxi);
+               ieee80211_inputm(ifp, m, ni, &rxi, &ml);
 
                ieee80211_release_node(ic, ni);
 
@@ -8466,6 +8467,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
 next:
                idx = (idx + 1) % BWI_RX_NDESC;
        }
+       if_input(ifp, &ml);
 
        rbd->rbd_idx = idx;
        bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
blob - 6a8c5646f0b6f649a60793e127cbd746d8ee89d7
blob + af91b6b414ecc45cd3caceec3f0a7ea6e2aae400
--- sys/dev/ic/malo.c
+++ sys/dev/ic/malo.c
@@ -1593,6 +1593,7 @@ malo_tx_setup_desc(struct malo_softc *sc, struct malo_
 void
 malo_rx_intr(struct malo_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
        struct malo_rx_desc *desc;
@@ -1711,7 +1712,7 @@ malo_rx_intr(struct malo_softc *sc)
                rxi.rxi_flags = 0;
                rxi.rxi_rssi = desc->rssi;
                rxi.rxi_tstamp = 0;     /* unused */
-               ieee80211_input(ifp, m, ni, &rxi);
+               ieee80211_inputm(ifp, m, ni, &rxi, &ml);
 
                /* node is no longer needed */
                ieee80211_release_node(ic, ni);
@@ -1727,6 +1728,7 @@ skip:
                sc->sc_rxring.cur = (sc->sc_rxring.cur + 1) %
                    MALO_RX_RING_COUNT;
        }
+       if_input(ifp, &ml);
 
        malo_mem_write4(sc, sc->sc_RxPdRdPtr, rxRdPtr);
 }
blob - f44264645097e6f991f5642f7973ed5ebe3e5d7e
blob + 695723c6f054b8ab264aefb609696dffbaae6c6b
--- sys/dev/ic/pgt.c
+++ sys/dev/ic/pgt.c
@@ -899,6 +899,7 @@ void
 pgt_input_frames(struct pgt_softc *sc, struct mbuf *m)
 {
        struct ether_header eh;
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct ifnet *ifp;
        struct ieee80211_channel *chan;
        struct ieee80211_rxinfo rxi;
@@ -1022,7 +1023,7 @@ input:
                        rxi.rxi_flags = 0;
                        ni->ni_rssi = rxi.rxi_rssi = rssi;
                        ni->ni_rstamp = rxi.rxi_tstamp = rstamp;
-                       ieee80211_input(ifp, m, ni, &rxi);
+                       ieee80211_inputm(ifp, m, ni, &rxi, &ml);
                        /*
                         * The frame may have caused the node to be marked for
                         * reclamation (e.g. in response to a DEAUTH message)
@@ -1036,6 +1037,7 @@ input:
                        ifp->if_ierrors++;
                }
        }
+       if_input(ifp, &ml);
 }
 
 void
blob - c8d85564272d263215e829d007c11a47741316e6
blob + 4b6e4c0592a9ac543cc83d2ff6ccc692427c0adf
--- sys/dev/ic/rt2560.c
+++ sys/dev/ic/rt2560.c
@@ -1076,6 +1076,7 @@ rt2560_prio_intr(struct rt2560_softc *sc)
 void
 rt2560_decryption_intr(struct rt2560_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
        struct ieee80211_frame *wh;
@@ -1204,7 +1205,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
                rxi.rxi_flags = 0;
                rxi.rxi_rssi = desc->rssi;
                rxi.rxi_tstamp = 0;     /* unused */
-               ieee80211_input(ifp, m, ni, &rxi);
+               ieee80211_inputm(ifp, m, ni, &rxi, &ml);
 
                /* node is no longer needed */
                ieee80211_release_node(ic, ni);
@@ -1220,6 +1221,7 @@ skip:             desc->flags = htole32(RT2560_RX_BUSY);
                sc->rxq.cur_decrypt =
                    (sc->rxq.cur_decrypt + 1) % RT2560_RX_RING_COUNT;
        }
+       if_input(ifp, &ml);
 }
 
 /*
blob - 591115f692d4f77a522d114e5a91d6026e3452fe
blob + 44f767f9bba3aec85758600684dc786d5eab3ed3
--- sys/dev/ic/rt2661.c
+++ sys/dev/ic/rt2661.c
@@ -1153,6 +1153,7 @@ rt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2
 void
 rt2661_rx_intr(struct rt2661_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
        struct ieee80211_frame *wh;
@@ -1279,7 +1280,7 @@ rt2661_rx_intr(struct rt2661_softc *sc)
                rxi.rxi_flags = 0;
                rxi.rxi_rssi = desc->rssi;
                rxi.rxi_tstamp = 0;     /* unused */
-               ieee80211_input(ifp, m, ni, &rxi);
+               ieee80211_inputm(ifp, m, ni, &rxi, &ml);
 
                /*-
                 * Keep track of the average RSSI using an Exponential Moving
@@ -1302,6 +1303,7 @@ skip:             desc->flags |= htole32(RT2661_RX_BUSY);
 
                sc->rxq.cur = (sc->rxq.cur + 1) % RT2661_RX_RING_COUNT;
        }
+       if_input(ifp, &ml);
 }
 
 #ifndef IEEE80211_STA_ONLY
blob - c6c811c835ef4558079c00d50041075b9a8321bb
blob + 286f4c859d84a8dc13a54e74c355bc443cf2f7e8
--- sys/dev/ic/rt2860.c
+++ sys/dev/ic/rt2860.c
@@ -1260,6 +1260,7 @@ rt2860_maxrssi_chain(struct rt2860_softc *sc, const st
 void
 rt2860_rx_intr(struct rt2860_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
        struct ieee80211_frame *wh;
@@ -1419,7 +1420,7 @@ skipbpf:
                /* send the frame to the 802.11 layer */
                rxi.rxi_rssi = rssi;
                rxi.rxi_tstamp = 0;     /* unused */
-               ieee80211_input(ifp, m, ni, &rxi);
+               ieee80211_inputm(ifp, m, ni, &rxi, &ml);
 
                /* node is no longer needed */
                ieee80211_release_node(ic, ni);
@@ -1432,6 +1433,7 @@ skip:             rxd->sdl0 &= ~htole16(RT2860_RX_DDONE);
 
                sc->rxq.cur = (sc->rxq.cur + 1) % RT2860_RX_RING_COUNT;
        }
+       if_input(ifp, &ml);
 
        /* tell HW what we have processed */
        RAL_WRITE(sc, RT2860_RX_CALC_IDX,
blob - ce7686c40fa4b1166d0af3fe54d8cad60704f556
blob + 344ffd4381400698d23f8aaee3c623fe649f885f
--- sys/dev/ic/rtw.c
+++ sys/dev/ic/rtw.c
@@ -1081,6 +1081,7 @@ rtw_intr_rx(struct rtw_softc *sc, u_int16_t isr)
        static const int ratetbl[4] = {2, 4, 11, 22};   /* convert rates:
                                                         * hardware -> net80211
                                                         */
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        u_int next, nproc = 0;
        int hwrate, len, rate, rssi, sq;
        u_int32_t hrssi, hstat, htsfth, htsftl;
@@ -1289,11 +1290,12 @@ rtw_intr_rx(struct rtw_softc *sc, u_int16_t isr)
                rxi.rxi_flags = 0;
                rxi.rxi_rssi = rssi;
                rxi.rxi_tstamp = htsftl;
-               ieee80211_input(&sc->sc_if, m, ni, &rxi);
+               ieee80211_inputm(&sc->sc_if, m, ni, &rxi, &ml);
                ieee80211_release_node(&sc->sc_ic, ni);
 next:
                rtw_rxdesc_init(rdb, rs, next, 0);
        }
+       if_input(&sc->sc_if, &ml);
        rdb->rdb_next = next;
 
        KASSERT(rdb->rdb_next < rdb->rdb_ndesc);
blob - cd0d354d12f45e34327a1d9d2d6ae5b480f9e305
blob + abcd1e0c7f2509e16102d1ea96e245dca587de90
--- sys/dev/pci/if_ipw.c
+++ sys/dev/pci/if_ipw.c
@@ -71,7 +71,8 @@ uint16_t      ipw_read_prom_word(struct ipw_softc *, uint8_
 void           ipw_command_intr(struct ipw_softc *, struct ipw_soft_buf *);
 void           ipw_newstate_intr(struct ipw_softc *, struct ipw_soft_buf *);
 void           ipw_data_intr(struct ipw_softc *, struct ipw_status *,
-                   struct ipw_soft_bd *, struct ipw_soft_buf *);
+                   struct ipw_soft_bd *, struct ipw_soft_buf *,
+                   struct mbuf_list *);
 void           ipw_notification_intr(struct ipw_softc *,
                    struct ipw_soft_buf *);
 void           ipw_rx_intr(struct ipw_softc *);
@@ -816,7 +817,7 @@ ipw_newstate_intr(struct ipw_softc *sc, struct ipw_sof
 
 void
 ipw_data_intr(struct ipw_softc *sc, struct ipw_status *status,
-    struct ipw_soft_bd *sbd, struct ipw_soft_buf *sbuf)
+    struct ipw_soft_bd *sbd, struct ipw_soft_buf *sbuf, struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -903,7 +904,7 @@ ipw_data_intr(struct ipw_softc *sc, struct ipw_status 
        rxi.rxi_flags = 0;
        rxi.rxi_rssi = status->rssi;
        rxi.rxi_tstamp = 0;     /* unused */
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
 
        ieee80211_release_node(ic, ni);
 }
@@ -917,6 +918,7 @@ ipw_notification_intr(struct ipw_softc *sc, struct ipw
 void
 ipw_rx_intr(struct ipw_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct ipw_status *status;
        struct ipw_soft_bd *sbd;
        struct ipw_soft_buf *sbuf;
@@ -949,7 +951,7 @@ ipw_rx_intr(struct ipw_softc *sc)
 
                case IPW_STATUS_CODE_DATA_802_3:
                case IPW_STATUS_CODE_DATA_802_11:
-                       ipw_data_intr(sc, status, sbd, sbuf);
+                       ipw_data_intr(sc, status, sbd, sbuf, &ml);
                        break;
 
                case IPW_STATUS_CODE_NOTIFICATION:
@@ -966,6 +968,7 @@ ipw_rx_intr(struct ipw_softc *sc)
                    i * sizeof (struct ipw_bd), sizeof (struct ipw_bd),
                    BUS_DMASYNC_PREWRITE);
        }
+       if_input(&sc->sc_ic.ic_if, &ml);
 
        /* tell the firmware what we have processed */
        sc->rxcur = (r == 0) ? IPW_NRBD - 1 : r - 1;
blob - bdb4827425118b9159ae05ad1263bdf5c084254f
blob + 84366f6545bde46339adf1da2956b9af8f544469
--- sys/dev/pci/if_iwi.c
+++ sys/dev/pci/if_iwi.c
@@ -87,7 +87,7 @@ int           iwi_find_txnode(struct iwi_softc *, const 
uint8_t
 int            iwi_newstate(struct ieee80211com *, enum ieee80211_state, int);
 uint8_t                iwi_rate(int);
 void           iwi_frame_intr(struct iwi_softc *, struct iwi_rx_data *,
-                   struct iwi_frame *);
+                   struct iwi_frame *, struct mbuf_list *);
 void           iwi_notification_intr(struct iwi_softc *, struct iwi_rx_data *,
                    struct iwi_notif *);
 void           iwi_rx_intr(struct iwi_softc *);
@@ -854,7 +854,7 @@ iwi_rate(int plcp)
 
 void
 iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data,
-    struct iwi_frame *frame)
+    struct iwi_frame *frame, struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -954,7 +954,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_dat
        rxi.rxi_flags = 0;
        rxi.rxi_rssi = frame->rssi_dbm;
        rxi.rxi_tstamp = 0;     /* unused */
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
 
        /* node is no longer needed */
        ieee80211_release_node(ic, ni);
@@ -1073,6 +1073,7 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi
 void
 iwi_rx_intr(struct iwi_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct iwi_rx_data *data;
        struct iwi_hdr *hdr;
        uint32_t hw;
@@ -1090,7 +1091,7 @@ iwi_rx_intr(struct iwi_softc *sc)
                switch (hdr->type) {
                case IWI_HDR_TYPE_FRAME:
                        iwi_frame_intr(sc, data,
-                           (struct iwi_frame *)(hdr + 1));
+                           (struct iwi_frame *)(hdr + 1), &ml);
                        break;
 
                case IWI_HDR_TYPE_NOTIF:
@@ -1105,6 +1106,7 @@ iwi_rx_intr(struct iwi_softc *sc)
 
                sc->rxq.cur = (sc->rxq.cur + 1) % IWI_RX_RING_COUNT;
        }
+       if_input(&sc->sc_ic.ic_if, &ml);
 
        /* tell the firmware what we have processed */
        hw = (hw == 0) ? IWI_RX_RING_COUNT - 1 : hw - 1;
blob - 0b2116dbc13428f1726773000e8e6a8c251d86b4
blob + 26bd730272774dc8cef58c87638c21c0536a016a
--- sys/dev/pci/if_iwm.c
+++ sys/dev/pci/if_iwm.c
@@ -368,7 +368,7 @@ void        iwm_rx_rx_phy_cmd(struct iwm_softc *, struct 
iwm_
            struct iwm_rx_data *);
 int    iwm_get_noise(const struct iwm_statistics_rx_non_phy *);
 void   iwm_rx_rx_mpdu(struct iwm_softc *, struct iwm_rx_packet *,
-           struct iwm_rx_data *);
+           struct iwm_rx_data *, struct mbuf_list *);
 void   iwm_enable_ht_cck_fallback(struct iwm_softc *, struct iwm_node *);
 void   iwm_rx_tx_cmd_single(struct iwm_softc *, struct iwm_rx_packet *,
            struct iwm_node *);
@@ -3431,7 +3431,7 @@ iwm_get_noise(const struct iwm_statistics_rx_non_phy *
 
 void
 iwm_rx_rx_mpdu(struct iwm_softc *sc, struct iwm_rx_packet *pkt,
-    struct iwm_rx_data *data)
+    struct iwm_rx_data *data, struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211_frame *wh;
@@ -3564,9 +3564,9 @@ iwm_rx_rx_mpdu(struct iwm_softc *sc, struct iwm_rx_pac
                bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
        }
 #endif
-       ieee80211_input(IC2IFP(ic), m, ni, &rxi);
+       ieee80211_inputm(IC2IFP(ic), m, ni, &rxi, ml);
        /*
-        * ieee80211_input() might have changed our BSS.
+        * ieee80211_inputm() might have changed our BSS.
         * Restore ic_bss's channel if we are still in the same BSS.
         */
        if (ni == ic->ic_bss && IEEE80211_ADDR_EQ(saved_bssid, ni->ni_macaddr))
@@ -7005,6 +7005,7 @@ do {                                                      
                \
 void
 iwm_notif_intr(struct iwm_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        uint16_t hw;
 
        bus_dmamap_sync(sc->sc_dmat, sc->rxq.stat_dma.map,
@@ -7042,7 +7043,7 @@ iwm_notif_intr(struct iwm_softc *sc)
                        break;
 
                case IWM_REPLY_RX_MPDU_CMD:
-                       iwm_rx_rx_mpdu(sc, pkt, data);
+                       iwm_rx_rx_mpdu(sc, pkt, data, &ml);
                        break;
 
                case IWM_TX_CMD:
@@ -7289,6 +7290,7 @@ iwm_notif_intr(struct iwm_softc *sc)
 
                ADVANCE_RXQ(sc);
        }
+       if_input(&sc->sc_ic.ic_if, &ml);
 
        /*
         * Tell the firmware what we have processed.
blob - 6be794c2cd435c74b1b5c3f028b9613dc74ecf20
blob + c76b53c4c97d6c49f2837667b8758958163246f4
--- sys/dev/pci/if_iwn.c
+++ sys/dev/pci/if_iwn.c
@@ -156,7 +156,7 @@ int         iwn_ccmp_decap(struct iwn_softc *, struct mbuf 
*,
 void           iwn_rx_phy(struct iwn_softc *, struct iwn_rx_desc *,
                    struct iwn_rx_data *);
 void           iwn_rx_done(struct iwn_softc *, struct iwn_rx_desc *,
-                   struct iwn_rx_data *);
+                   struct iwn_rx_data *, struct mbuf_list *);
 void           iwn_rx_compressed_ba(struct iwn_softc *, struct iwn_rx_desc *,
                    struct iwn_rx_data *);
 void           iwn5000_rx_calib_results(struct iwn_softc *,
@@ -1937,7 +1937,7 @@ iwn_ccmp_decap(struct iwn_softc *sc, struct mbuf *m, s
                         * Such frames may be received out of order due to
                         * legitimate retransmissions of failed subframes
                         * in previous A-MPDUs. Duplicates will be handled
-                        * in ieee80211_input() as part of A-MPDU reordering.
+                        * in ieee80211_inputm() as part of A-MPDU reordering.
                         */
                } else if (ieee80211_has_seq(wh)) {
                        /*
@@ -2007,7 +2007,7 @@ iwn_rx_phy(struct iwn_softc *sc, struct iwn_rx_desc *d
  */
 void
 iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
-    struct iwn_rx_data *data)
+    struct iwn_rx_data *data, struct mbuf_list *ml)
 {
        struct iwn_ops *ops = &sc->ops;
        struct ieee80211com *ic = &sc->sc_ic;
@@ -2240,7 +2240,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *
        /* Send the frame to the 802.11 layer. */
        rxi.rxi_rssi = rssi;
        rxi.rxi_tstamp = 0;     /* unused */
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
 
        /* Restore BSS channel. */
        if (ni == ic->ic_bss)
@@ -2737,6 +2737,7 @@ iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc 
 void
 iwn_notif_intr(struct iwn_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct iwn_ops *ops = &sc->ops;
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -2768,7 +2769,7 @@ iwn_notif_intr(struct iwn_softc *sc)
                case IWN_RX_DONE:               /* 4965AGN only. */
                case IWN_MPDU_RX_DONE:
                        /* An 802.11 frame has been received. */
-                       iwn_rx_done(sc, desc, data);
+                       iwn_rx_done(sc, desc, data, &ml);
                        break;
                case IWN_RX_COMPRESSED_BA:
                        /* A Compressed BlockAck has been received. */
@@ -2913,6 +2914,7 @@ iwn_notif_intr(struct iwn_softc *sc)
 
                sc->rxq.cur = (sc->rxq.cur + 1) % IWN_RX_RING_COUNT;
        }
+       if_input(&sc->sc_ic.ic_if, &ml);
 
        /* Tell the firmware what we have processed. */
        hw = (hw == 0) ? IWN_RX_RING_COUNT - 1 : hw - 1;
blob - 2c53aa925247b5056360daf479fca12e45624107
blob + 15629e1a07ec75f8eea39d7a629d2d84da6e550e
--- sys/dev/pci/if_rtwn.c
+++ sys/dev/pci/if_rtwn.c
@@ -248,7 +248,8 @@ uint8_t             rtwn_pci_read_1(void *, uint16_t);
 uint16_t       rtwn_pci_read_2(void *, uint16_t);
 uint32_t       rtwn_pci_read_4(void *, uint16_t);
 void           rtwn_rx_frame(struct rtwn_pci_softc *,
-                   struct r92c_rx_desc_pci *, struct rtwn_rx_data *, int);
+                   struct r92c_rx_desc_pci *, struct rtwn_rx_data *, int,
+                   struct mbuf_list *);
 int            rtwn_tx(void *, struct mbuf *, struct ieee80211_node *);
 void           rtwn_tx_done(struct rtwn_pci_softc *, int);
 int            rtwn_alloc_buffers(void *);
@@ -813,7 +814,7 @@ rtwn_pci_read_4(void *cookie, uint16_t addr)
 
 void
 rtwn_rx_frame(struct rtwn_pci_softc *sc, struct r92c_rx_desc_pci *rx_desc,
-    struct rtwn_rx_data *rx_data, int desc_idx)
+    struct rtwn_rx_data *rx_data, int desc_idx, struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_sc.sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -974,7 +975,7 @@ rtwn_rx_frame(struct rtwn_pci_softc *sc, struct r92c_r
        rxi.rxi_flags = 0;
        rxi.rxi_rssi = rssi;
        rxi.rxi_tstamp = 0;     /* Unused. */
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
        /* Node is no longer needed. */
        ieee80211_release_node(ic, ni);
 }
@@ -1480,6 +1481,7 @@ rtwn_pci_stop(void *cookie)
 int
 rtwn_88e_intr(struct rtwn_pci_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        u_int32_t status, estatus;
        int i;
 
@@ -1511,6 +1513,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);
@@ -1522,8 +1526,9 @@ rtwn_88e_intr(struct rtwn_pci_softc *sc)
                        if (letoh32(rx_desc->rxdw0) & R92C_RXDW0_OWN)
                                continue;
 
-                       rtwn_rx_frame(sc, rx_desc, rx_data, i);
+                       rtwn_rx_frame(sc, rx_desc, rx_data, i, &ml);
                }
+               if_input(&ic->ic_if, &ml);
        }
 
        if (status & R88E_HIMR_HSISR_IND_ON_INT) {
@@ -1543,6 +1548,7 @@ int
 rtwn_intr(void *xsc)
 {
        struct rtwn_pci_softc *sc = xsc;
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        u_int32_t status;
        int i;
 
@@ -1561,6 +1567,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);
@@ -1572,8 +1580,9 @@ rtwn_intr(void *xsc)
                        if (letoh32(rx_desc->rxdw0) & R92C_RXDW0_OWN)
                                continue;
 
-                       rtwn_rx_frame(sc, rx_desc, rx_data, i);
+                       rtwn_rx_frame(sc, rx_desc, rx_data, i, &ml);
                }
+               if_input(&ic->ic_if, &ml);
        }
 
        if (status & R92C_IMR_BDOK)
blob - 2a91ccec016f8047bfe26ede71e8881404fef619
blob + 87f91434312f42404dbb02241eb2d4804ebbdd12
--- sys/dev/pci/if_wpi.c
+++ sys/dev/pci/if_wpi.c
@@ -103,7 +103,7 @@ void                wpi_calib_timeout(void *);
 int            wpi_ccmp_decap(struct wpi_softc *, struct mbuf *,
                    struct ieee80211_key *);
 void           wpi_rx_done(struct wpi_softc *, struct wpi_rx_desc *,
-                   struct wpi_rx_data *);
+                   struct wpi_rx_data *, struct mbuf_list *);
 void           wpi_tx_done(struct wpi_softc *, struct wpi_rx_desc *);
 void           wpi_cmd_done(struct wpi_softc *, struct wpi_rx_desc *);
 void           wpi_notif_intr(struct wpi_softc *);
@@ -1180,7 +1180,7 @@ wpi_ccmp_decap(struct wpi_softc *sc, struct mbuf *m, s
 
 void
 wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc,
-    struct wpi_rx_data *data)
+    struct wpi_rx_data *data, struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -1344,7 +1344,7 @@ wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *
        /* Send the frame to the 802.11 layer. */
        rxi.rxi_rssi = stat->rssi;
        rxi.rxi_tstamp = 0;     /* unused */
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
 
        /* Node is no longer needed. */
        ieee80211_release_node(ic, ni);
@@ -1412,6 +1412,7 @@ wpi_cmd_done(struct wpi_softc *sc, struct wpi_rx_desc 
 void
 wpi_notif_intr(struct wpi_softc *sc)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
        uint32_t hw;
@@ -1438,7 +1439,7 @@ wpi_notif_intr(struct wpi_softc *sc)
                switch (desc->type) {
                case WPI_RX_DONE:
                        /* An 802.11 frame has been received. */
-                       wpi_rx_done(sc, desc, data);
+                       wpi_rx_done(sc, desc, data, &ml);
                        break;
 
                case WPI_TX_DONE:
@@ -1527,6 +1528,7 @@ wpi_notif_intr(struct wpi_softc *sc)
 
                sc->rxq.cur = (sc->rxq.cur + 1) % WPI_RX_RING_COUNT;
        }
+       if_input(&ic->ic_if, &ml);
 
        /* Tell the firmware what we have processed. */
        hw = (hw == 0) ? WPI_RX_RING_COUNT - 1 : hw - 1;
blob - 39edb129685cac47d29224f18c6f2e7c92922720
blob + 281a19ea8aa92c91869ae177649be9196c947ac3
--- sys/dev/usb/if_athn_usb.c
+++ sys/dev/usb/if_athn_usb.c
@@ -176,7 +176,8 @@ void                athn_usb_intr(struct usbd_xfer *, void 
*,
                    usbd_status);
 void           athn_usb_rx_radiotap(struct athn_softc *, struct mbuf *,
                    struct ar_rx_status *);
-void           athn_usb_rx_frame(struct athn_usb_softc *, struct mbuf *);
+void           athn_usb_rx_frame(struct athn_usb_softc *, struct mbuf *,
+                   struct mbuf_list *);
 void           athn_usb_rxeof(struct usbd_xfer *, void *,
                    usbd_status);
 void           athn_usb_txeof(struct usbd_xfer *, void *,
@@ -1994,7 +1995,8 @@ athn_usb_rx_radiotap(struct athn_softc *sc, struct mbu
 #endif
 
 void
-athn_usb_rx_frame(struct athn_usb_softc *usc, struct mbuf *m)
+athn_usb_rx_frame(struct athn_usb_softc *usc, struct mbuf *m,
+    struct mbuf_list *ml)
 {
        struct athn_softc *sc = &usc->sc_sc;
        struct ieee80211com *ic = &sc->sc_ic;
@@ -2060,7 +2062,7 @@ athn_usb_rx_frame(struct athn_usb_softc *usc, struct m
        rxi.rxi_flags = 0;
        rxi.rxi_rssi = rs->rs_rssi + AR_USB_DEFAULT_NF;
        rxi.rxi_tstamp = betoh64(rs->rs_tstamp);
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
 
        /* Node is no longer needed. */
        ieee80211_release_node(ic, ni);
@@ -2074,6 +2076,7 @@ void
 athn_usb_rxeof(struct usbd_xfer *xfer, void *priv,
     usbd_status status)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct athn_usb_rx_data *data = priv;
        struct athn_usb_softc *usc = data->sc;
        struct athn_softc *sc = &usc->sc_sc;
@@ -2101,7 +2104,7 @@ athn_usb_rxeof(struct usbd_xfer *xfer, void *priv,
                        if (__predict_true(stream->m != NULL)) {
                                memcpy(mtod(stream->m, uint8_t *) +
                                    stream->moff, buf, stream->left);
-                               athn_usb_rx_frame(usc, stream->m);
+                               athn_usb_rx_frame(usc, stream->m, &ml);
                                stream->m = NULL;
                        }
                        /* Next header is 32-bit aligned. */
@@ -2167,7 +2170,7 @@ athn_usb_rxeof(struct usbd_xfer *xfer, void *priv,
                if (__predict_true(m != NULL)) {
                        /* We have all the pktlen bytes in this xfer. */
                        memcpy(mtod(m, uint8_t *), buf, pktlen);
-                       athn_usb_rx_frame(usc, m);
+                       athn_usb_rx_frame(usc, m, &ml);
                }
 
                /* Next header is 32-bit aligned. */
@@ -2175,6 +2178,7 @@ athn_usb_rxeof(struct usbd_xfer *xfer, void *priv,
                buf += off;
                len -= off;
        }
+       if_input(ifp, &ml);
 
  resubmit:
        /* Setup a new transfer. */
blob - cb7e65865adb17b86e10bf5c2bc59983a5c8c2c9
blob + 7461c3e57fb2d76faa3c0da0380827a85d19d5f7
--- sys/dev/usb/if_otus.c
+++ sys/dev/usb/if_otus.c
@@ -124,7 +124,8 @@ void                otus_newassoc(struct ieee80211com *, 
struct ieee
                    int);
 void           otus_intr(struct usbd_xfer *, void *, usbd_status);
 void           otus_cmd_rxeof(struct otus_softc *, uint8_t *, int);
-void           otus_sub_rxeof(struct otus_softc *, uint8_t *, int);
+void           otus_sub_rxeof(struct otus_softc *, uint8_t *, int,
+                   struct mbuf_list *);
 void           otus_rxeof(struct usbd_xfer *, void *, usbd_status);
 void           otus_txeof(struct usbd_xfer *, void *, usbd_status);
 int            otus_tx(struct otus_softc *, struct mbuf *,
@@ -1064,7 +1065,8 @@ otus_cmd_rxeof(struct otus_softc *sc, uint8_t *buf, in
 }
 
 void
-otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len)
+otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, int len,
+    struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -1195,7 +1197,7 @@ otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, in
        rxi.rxi_flags = 0;
        rxi.rxi_rssi = tail->rssi;
        rxi.rxi_tstamp = 0;     /* unused */
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
 
        /* Node is no longer needed. */
        ieee80211_release_node(ic, ni);
@@ -1205,6 +1207,7 @@ otus_sub_rxeof(struct otus_softc *sc, uint8_t *buf, in
 void
 otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct otus_rx_data *data = priv;
        struct otus_softc *sc = data->sc;
        caddr_t buf = data->buf;
@@ -1234,13 +1237,14 @@ otus_rxeof(struct usbd_xfer *xfer, void *priv, usbd_st
                        break;
                }
                /* Process sub-xfer. */
-               otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen);
+               otus_sub_rxeof(sc, (uint8_t *)&head[1], hlen, &ml);
 
                /* Next sub-xfer is aligned on a 32-bit boundary. */
                hlen = (sizeof (*head) + hlen + 3) & ~3;
                buf += hlen;
                len -= hlen;
        }
+       if_input(&sc->sc_ic.ic_if, &ml);
 
  resubmit:
        usbd_setup_xfer(xfer, sc->data_rx_pipe, data, data->buf, OTUS_RXBUFSZ,
blob - 417666c3503da89fce1d3dc4301b48376dcf7e41
blob + 71c2c98b878349169107680c071978482dce1678
--- sys/dev/usb/if_rsu.c
+++ sys/dev/usb/if_rsu.c
@@ -161,7 +161,8 @@ void                rsu_event_join_bss(struct rsu_softc *, 
uint8_t *
 void           rsu_rx_event(struct rsu_softc *, uint8_t, uint8_t *, int);
 void           rsu_rx_multi_event(struct rsu_softc *, uint8_t *, int);
 int8_t         rsu_get_rssi(struct rsu_softc *, int, void *);
-void           rsu_rx_frame(struct rsu_softc *, uint8_t *, int);
+void           rsu_rx_frame(struct rsu_softc *, uint8_t *, int,
+                   struct mbuf_list *);
 void           rsu_rx_multi_frame(struct rsu_softc *, uint8_t *, int);
 void           rsu_rxeof(struct usbd_xfer *, void *, usbd_status);
 void           rsu_txeof(struct usbd_xfer *, void *, usbd_status);
@@ -1261,7 +1262,8 @@ rsu_get_rssi(struct rsu_softc *sc, int rate, void *phy
 }
 
 void
-rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen)
+rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen,
+    struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -1371,7 +1373,7 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int p
        rxi.rxi_flags = 0;
        rxi.rxi_rssi = rssi;
        rxi.rxi_tstamp = 0;     /* Unused. */
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
        /* Node is no longer needed. */
        ieee80211_release_node(ic, ni);
        splx(s);
@@ -1380,6 +1382,7 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int p
 void
 rsu_rx_multi_frame(struct rsu_softc *sc, uint8_t *buf, int len)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct r92s_rx_stat *stat;
        uint32_t rxdw0;
        int totlen, pktlen, infosz, npkts;
@@ -1408,13 +1411,14 @@ rsu_rx_multi_frame(struct rsu_softc *sc, uint8_t *buf,
                        break;
 
                /* Process 802.11 frame. */
-               rsu_rx_frame(sc, buf, pktlen);
+               rsu_rx_frame(sc, buf, pktlen, &ml);
 
                /* Next chunk is 128-byte aligned. */
                totlen = (totlen + 127) & ~127;
                buf += totlen;
                len -= totlen;
        }
+       if_input(&sc->sc_ic.ic_if, &ml);
 }
 
 void
blob - fc6ba52f271725fe7afbb4abf1a4a1700920a1b4
blob + f22d6d4decb01bab31aa8c0f6fae587651dd3589
--- sys/dev/usb/if_run.c
+++ sys/dev/usb/if_run.c
@@ -376,7 +376,8 @@ void                run_calibrate_to(void *);
 void           run_calibrate_cb(struct run_softc *, void *);
 void           run_newassoc(struct ieee80211com *, struct ieee80211_node *,
                    int);
-void           run_rx_frame(struct run_softc *, uint8_t *, int);
+void           run_rx_frame(struct run_softc *, uint8_t *, int,
+                   struct mbuf_list *);
 void           run_rxeof(struct usbd_xfer *, void *, usbd_status);
 void           run_txeof(struct usbd_xfer *, void *, usbd_status);
 int            run_tx(struct run_softc *, struct mbuf *,
@@ -2158,7 +2159,8 @@ run_maxrssi_chain(struct run_softc *sc, const struct r
 }
 
 void
-run_rx_frame(struct run_softc *sc, uint8_t *buf, int dmalen)
+run_rx_frame(struct run_softc *sc, uint8_t *buf, int dmalen,
+    struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -2295,7 +2297,7 @@ run_rx_frame(struct run_softc *sc, uint8_t *buf, int d
        ni = ieee80211_find_rxnode(ic, wh);
        rxi.rxi_rssi = rssi;
        rxi.rxi_tstamp = 0;     /* unused */
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
 
        /* node is no longer needed */
        ieee80211_release_node(ic, ni);
@@ -2305,6 +2307,7 @@ run_rx_frame(struct run_softc *sc, uint8_t *buf, int d
 void
 run_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct run_rx_data *data = priv;
        struct run_softc *sc = data->sc;
        uint8_t *buf;
@@ -2348,10 +2351,11 @@ run_rxeof(struct usbd_xfer *xfer, void *priv, usbd_sta
                            dmalen + 8, xferlen));
                        break;
                }
-               run_rx_frame(sc, buf + sizeof (uint32_t), dmalen);
+               run_rx_frame(sc, buf + sizeof (uint32_t), dmalen, &ml);
                buf += dmalen + 8;
                xferlen -= dmalen + 8;
        }
+       if_input(&sc->sc_ic.ic_if, &ml);
 
 skip:  /* setup a new transfer */
        usbd_setup_xfer(xfer, sc->rxq.pipeh, data, data->buf, RUN_MAX_RXSZ,
blob - 96a1ad1a91c3e98ebc6dece98df6ac277046612c
blob + 12fc517090e80d703749a326949aeaaf83617639
--- sys/dev/usb/if_urtwn.c
+++ sys/dev/usb/if_urtwn.c
@@ -380,7 +380,8 @@ void                urtwn_set_key_cb(struct urtwn_softc *, 
void *);
 void           urtwn_delete_key(struct ieee80211com *,
                    struct ieee80211_node *, struct ieee80211_key *);
 void           urtwn_delete_key_cb(struct urtwn_softc *, void *);
-void           urtwn_rx_frame(struct urtwn_softc *, uint8_t *, int);
+void           urtwn_rx_frame(struct urtwn_softc *, uint8_t *, int,
+                   struct mbuf_list *);
 void           urtwn_rxeof(struct usbd_xfer *, void *,
                    usbd_status);
 void           urtwn_txeof(struct usbd_xfer *, void *,
@@ -1083,7 +1084,8 @@ urtwn_delete_key_cb(struct urtwn_softc *sc, void *arg)
 }
 
 void
-urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen)
+urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen,
+    struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_sc.sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -1194,7 +1196,7 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, i
        rxi.rxi_flags = 0;
        rxi.rxi_rssi = rssi;
        rxi.rxi_tstamp = 0;     /* Unused. */
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
        /* Node is no longer needed. */
        ieee80211_release_node(ic, ni);
        splx(s);
@@ -1204,8 +1206,10 @@ void
 urtwn_rxeof(struct usbd_xfer *xfer, void *priv,
     usbd_status status)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        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;
@@ -1298,13 +1302,14 @@ urtwn_rxeof(struct usbd_xfer *xfer, void *priv,
                        break;
 
                /* Process 802.11 frame. */
-               urtwn_rx_frame(sc, buf, pktlen);
+               urtwn_rx_frame(sc, buf, pktlen, &ml);
 
                /* Handle chunk alignment. */
                totlen = (totlen + align) & ~align;
                buf += totlen;
                len -= totlen;
        }
+       if_input(&ic->ic_if, &ml);
 
  resubmit:
        /* Setup a new transfer. */
blob - 689ac7e7178ca36a091d25cc6f2cf8d15cc45b0b
blob + ea8545a4ba48d49eb2830b4e6886613e2e181a7c
--- sys/dev/usb/if_zyd.c
+++ sys/dev/usb/if_zyd.c
@@ -217,7 +217,8 @@ void                zyd_set_chan(struct zyd_softc *, struct 
ieee8021
 int            zyd_set_beacon_interval(struct zyd_softc *, int);
 uint8_t                zyd_plcp_signal(int);
 void           zyd_intr(struct usbd_xfer *, void *, usbd_status);
-void           zyd_rx_data(struct zyd_softc *, const uint8_t *, uint16_t);
+void           zyd_rx_data(struct zyd_softc *, const uint8_t *, uint16_t,
+                   struct mbuf_list *);
 void           zyd_rxeof(struct usbd_xfer *, void *, usbd_status);
 void           zyd_txeof(struct usbd_xfer *, void *, usbd_status);
 int            zyd_tx(struct zyd_softc *, struct mbuf *,
@@ -1894,7 +1895,8 @@ zyd_intr(struct usbd_xfer *xfer, void *priv, usbd_stat
 }
 
 void
-zyd_rx_data(struct zyd_softc *sc, const uint8_t *buf, uint16_t len)
+zyd_rx_data(struct zyd_softc *sc, const uint8_t *buf, uint16_t len,
+    struct mbuf_list *ml)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ifnet *ifp = &ic->ic_if;
@@ -1980,7 +1982,7 @@ zyd_rx_data(struct zyd_softc *sc, const uint8_t *buf, 
        rxi.rxi_flags = 0;
        rxi.rxi_rssi = stat->rssi;
        rxi.rxi_tstamp = 0;     /* unused */
-       ieee80211_input(ifp, m, ni, &rxi);
+       ieee80211_inputm(ifp, m, ni, &rxi, ml);
 
        /* node is no longer needed */
        ieee80211_release_node(ic, ni);
@@ -1991,6 +1993,7 @@ zyd_rx_data(struct zyd_softc *sc, const uint8_t *buf, 
 void
 zyd_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct zyd_rx_data *data = priv;
        struct zyd_softc *sc = data->sc;
        struct ieee80211com *ic = &sc->sc_ic;
@@ -2030,15 +2033,16 @@ zyd_rxeof(struct usbd_xfer *xfer, void *priv, usbd_sta
                        if (len == 0 || p + len >= end)
                                break;
 
-                       zyd_rx_data(sc, p, len);
+                       zyd_rx_data(sc, p, len, &ml);
                        /* next frame is aligned on a 32-bit boundary */
                        p += (len + 3) & ~3;
                }
        } else {
                DPRINTFN(3, ("received single-frame transfer\n"));
 
-               zyd_rx_data(sc, data->buf, len);
+               zyd_rx_data(sc, data->buf, len, &ml);
        }
+       if_input(ifp, &ml);
 
 skip:  /* setup a new transfer */
        usbd_setup_xfer(xfer, sc->zyd_ep[ZYD_ENDPT_BIN], data, NULL,
blob - 73a9d5229502797c5279734663b1ac1591bec309
blob + 884018208fe4e91c192a9925e49a5cc041dd5cac
--- sys/net80211/ieee80211_input.c
+++ sys/net80211/ieee80211_input.c
@@ -61,21 +61,22 @@
 struct mbuf *ieee80211_defrag(struct ieee80211com *, struct mbuf *, int);
 void   ieee80211_defrag_timeout(void *);
 void   ieee80211_input_ba(struct ieee80211com *, struct mbuf *,
-           struct ieee80211_node *, int, struct ieee80211_rxinfo *);
+           struct ieee80211_node *, int, struct ieee80211_rxinfo *,
+           struct mbuf_list *);
 void   ieee80211_input_ba_flush(struct ieee80211com *, struct ieee80211_node *,
-           struct ieee80211_rx_ba *);
+           struct ieee80211_rx_ba *, struct mbuf_list *);
 void   ieee80211_input_ba_gap_timeout(void *arg);
 void   ieee80211_ba_move_window(struct ieee80211com *,
-           struct ieee80211_node *, u_int8_t, u_int16_t);
+           struct ieee80211_node *, u_int8_t, u_int16_t, struct mbuf_list *);
 void   ieee80211_input_ba_seq(struct ieee80211com *,
-           struct ieee80211_node *, uint8_t, uint16_t);
+           struct ieee80211_node *, uint8_t, uint16_t, struct mbuf_list *);
 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,10 +156,16 @@ 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 acts on management frames immediately and queues data frames
+ * on the specified mbuf list. Delivery of queued data frames to upper layers
+ * must be triggered with if_input(). Drivers should call if_input() only once
+ * per Rx interrupt to avoid triggering the input ifq pressure drop mechanism
+ * unnecessarily.
  */
 void
-ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
-    struct ieee80211_rxinfo *rxi)
+ieee80211_inputm(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
+    struct ieee80211_rxinfo *rxi, struct mbuf_list *ml)
 {
        struct ieee80211com *ic = (void *)ifp;
        struct ieee80211_frame *wh;
@@ -259,7 +266,7 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, str
                    (qos & IEEE80211_QOS_ACK_POLICY_MASK) ==
                    IEEE80211_QOS_ACK_POLICY_NORMAL)) {
                        /* go through A-MPDU reordering */
-                       ieee80211_input_ba(ic, m, ni, tid, rxi);
+                       ieee80211_input_ba(ic, m, ni, tid, rxi, ml);
                        return; /* don't free m! */
                }
        }
@@ -463,9 +470,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, ml);
                else
-                       ieee80211_decap(ic, m, ni, hdrlen);
+                       ieee80211_decap(ic, m, ni, hdrlen, ml);
                return;
 
        case IEEE80211_FC0_TYPE_MGT:
@@ -560,6 +567,17 @@ ieee80211_input(struct ifnet *ifp, struct mbuf *m, str
        }
 }
 
+/* Input handler for drivers which only receive one frame per interrupt. */
+void
+ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni,
+    struct ieee80211_rxinfo *rxi)
+{
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
+
+       ieee80211_inputm(ifp, m, ni, rxi, &ml);
+       if_input(ifp, &ml);
+}
+
 /*
  * Handle defragmentation (see 9.5 and Annex C).  We support the concurrent
  * reception of fragments of three fragmented MSDUs or MMPDUs.
@@ -656,7 +674,8 @@ ieee80211_defrag_timeout(void *arg)
  */
 void
 ieee80211_input_ba(struct ieee80211com *ic, struct mbuf *m,
-    struct ieee80211_node *ni, int tid, struct ieee80211_rxinfo *rxi)
+    struct ieee80211_node *ni, int tid, struct ieee80211_rxinfo *rxi,
+    struct mbuf_list *ml)
 {
        struct ifnet *ifp = &ic->ic_if;
        struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
@@ -699,12 +718,12 @@ ieee80211_input_ba(struct ieee80211com *ic, struct mbu
                        ic->ic_stats.is_ht_rx_ba_window_jump++;
                        ba->ba_winmiss = 0;
                        ba->ba_missedsn = 0;
-                       ieee80211_ba_move_window(ic, ni, tid, sn);
+                       ieee80211_ba_move_window(ic, ni, tid, sn, ml);
                } else {
                        ic->ic_stats.is_ht_rx_ba_window_slide++;
                        ieee80211_input_ba_seq(ic, ni, tid,
-                           (ba->ba_winstart + count) & 0xfff);
-                       ieee80211_input_ba_flush(ic, ni, ba);
+                           (ba->ba_winstart + count) & 0xfff, ml);
+                       ieee80211_input_ba_flush(ic, ni, ba, ml);
                }
        }
        /* WinStartB <= SN <= WinEndB */
@@ -730,7 +749,7 @@ ieee80211_input_ba(struct ieee80211com *ic, struct mbu
        else if (timeout_pending(&ba->ba_gap_to))
                timeout_del(&ba->ba_gap_to);
 
-       ieee80211_input_ba_flush(ic, ni, ba);
+       ieee80211_input_ba_flush(ic, ni, ba, ml);
 }
 
 /* 
@@ -739,7 +758,7 @@ ieee80211_input_ba(struct ieee80211com *ic, struct mbu
  */
 void
 ieee80211_input_ba_seq(struct ieee80211com *ic, struct ieee80211_node *ni,
-    uint8_t tid, uint16_t max_seq)
+    uint8_t tid, uint16_t max_seq, struct mbuf_list *ml)
 {
        struct ifnet *ifp = &ic->ic_if;
        struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
@@ -757,8 +776,8 @@ ieee80211_input_ba_seq(struct ieee80211com *ic, struct
                            IEEE80211_SEQ_SEQ_SHIFT;
                        if (!SEQ_LT(seq, max_seq))
                                return;
-                       ieee80211_input(ifp, ba->ba_buf[ba->ba_head].m,
-                           ni, &ba->ba_buf[ba->ba_head].rxi);
+                       ieee80211_inputm(ifp, ba->ba_buf[ba->ba_head].m,
+                           ni, &ba->ba_buf[ba->ba_head].rxi, ml);
                        ba->ba_buf[ba->ba_head].m = NULL;
                } else
                        ic->ic_stats.is_ht_rx_ba_frame_lost++;
@@ -769,15 +788,15 @@ ieee80211_input_ba_seq(struct ieee80211com *ic, struct
 /* Flush a consecutive sequence of frames from the reorder buffer. */
 void
 ieee80211_input_ba_flush(struct ieee80211com *ic, struct ieee80211_node *ni,
-    struct ieee80211_rx_ba *ba)
+    struct ieee80211_rx_ba *ba, struct mbuf_list *ml)
 
 {
        struct ifnet *ifp = &ic->ic_if;
 
        /* pass reordered MPDUs up to the next MAC process */
        while (ba->ba_buf[ba->ba_head].m != NULL) {
-               ieee80211_input(ifp, ba->ba_buf[ba->ba_head].m, ni,
-                   &ba->ba_buf[ba->ba_head].rxi);
+               ieee80211_inputm(ifp, ba->ba_buf[ba->ba_head].m, ni,
+                   &ba->ba_buf[ba->ba_head].rxi, ml);
                ba->ba_buf[ba->ba_head].m = NULL;
 
                ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;
@@ -796,6 +815,7 @@ ieee80211_input_ba_flush(struct ieee80211com *ic, stru
 void
 ieee80211_input_ba_gap_timeout(void *arg)
 {
+       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct ieee80211_rx_ba *ba = arg;
        struct ieee80211_node *ni = ba->ba_ni;
        struct ieee80211com *ic = ni->ni_ic;
@@ -816,7 +836,8 @@ ieee80211_input_ba_gap_timeout(void *arg)
        if (skipped > 0)
                ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;
 
-       ieee80211_input_ba_flush(ic, ni, ba);
+       ieee80211_input_ba_flush(ic, ni, ba, &ml);
+       if_input(&ic->ic_if, &ml);
 
        splx(s);        
 }
@@ -828,7 +849,7 @@ ieee80211_input_ba_gap_timeout(void *arg)
  */
 void
 ieee80211_ba_move_window(struct ieee80211com *ic, struct ieee80211_node *ni,
-    u_int8_t tid, u_int16_t ssn)
+    u_int8_t tid, u_int16_t ssn, struct mbuf_list *ml)
 {
        struct ifnet *ifp = &ic->ic_if;
        struct ieee80211_rx_ba *ba = &ni->ni_rx_ba[tid];
@@ -842,8 +863,8 @@ ieee80211_ba_move_window(struct ieee80211com *ic, stru
        while (count-- > 0) {
                /* gaps may exist */
                if (ba->ba_buf[ba->ba_head].m != NULL) {
-                       ieee80211_input(ifp, ba->ba_buf[ba->ba_head].m, ni,
-                           &ba->ba_buf[ba->ba_head].rxi);
+                       ieee80211_inputm(ifp, ba->ba_buf[ba->ba_head].m, ni,
+                           &ba->ba_buf[ba->ba_head].rxi, ml);
                        ba->ba_buf[ba->ba_head].m = NULL;
                } else
                        ic->ic_stats.is_ht_rx_ba_frame_lost++;
@@ -852,12 +873,12 @@ ieee80211_ba_move_window(struct ieee80211com *ic, stru
        /* move window forward */
        ba->ba_winstart = ssn;
 
-       ieee80211_input_ba_flush(ic, ni, ba);
+       ieee80211_input_ba_flush(ic, ni, ba, ml);
 }
 
 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 +941,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 +1004,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 +1012,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 +1078,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);
@@ -2564,8 +2583,11 @@ ieee80211_recv_addba_req(struct ieee80211com *ic, stru
                        return; /* not a PBAC, ignore */
 
                /* PBAC: treat the ADDBA Request like a BlockAckReq */
-               if (SEQ_LT(ba->ba_winstart, ssn))
-                       ieee80211_ba_move_window(ic, ni, tid, ssn);
+               if (SEQ_LT(ba->ba_winstart, ssn)) {
+                       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
+                       ieee80211_ba_move_window(ic, ni, tid, ssn, &ml);
+                       if_input(&ic->ic_if, &ml);
+               }
                return;
        }
 
@@ -3174,6 +3196,9 @@ ieee80211_bar_tid(struct ieee80211com *ic, struct ieee
        if (ba->ba_timeout_val != 0)
                timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);
 
-       if (SEQ_LT(ba->ba_winstart, ssn))
-               ieee80211_ba_move_window(ic, ni, tid, ssn);
+       if (SEQ_LT(ba->ba_winstart, ssn)) {
+               struct mbuf_list ml = MBUF_LIST_INITIALIZER();
+               ieee80211_ba_move_window(ic, ni, tid, ssn, &ml);
+               if_input(&ic->ic_if, &ml);
+       }
 }
blob - e622d35f4dcd21ea0bb40c6a5d0b3f758e197b38
blob + 52cf8fddfc1658a5c38a4895fff4e858d15bb876
--- sys/net80211/ieee80211_proto.h
+++ sys/net80211/ieee80211_proto.h
@@ -66,6 +66,9 @@ struct ieee80211_rsnparams;
 extern void ieee80211_set_link_state(struct ieee80211com *, int);
 extern u_int ieee80211_get_hdrlen(const struct ieee80211_frame *);
 extern int ieee80211_classify(struct ieee80211com *, struct mbuf *);
+extern void ieee80211_inputm(struct ifnet *, struct mbuf *,
+               struct ieee80211_node *, struct ieee80211_rxinfo *,
+               struct mbuf_list *);
 extern void ieee80211_input(struct ifnet *, struct mbuf *,
                struct ieee80211_node *, struct ieee80211_rxinfo *);
 extern int ieee80211_output(struct ifnet *, struct mbuf *, struct sockaddr *,

Reply via email to