--- a/ath/if_ath.c +++ b/ath/if_ath.c @@ -6734,10 +6734,10 @@ ath_rx_poll(struct net_device *dev, int #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) struct ath_softc *sc = container_of(napi, struct ath_softc, sc_napi); struct net_device *dev = sc->sc_dev; - u_int rx_limit = budget; + int rx_limit = budget; #else struct ath_softc *sc = dev->priv; - u_int rx_limit = min(dev->quota, *budget); + int rx_limit = min(dev->quota, *budget); #endif struct ath_buf *bf; struct ieee80211com *ic = &sc->sc_ic; @@ -6780,13 +6780,15 @@ process_rx_again: break; } - if (rx_limit-- < 2) { + processed += ic->ic_recv; + rx_limit -= ic->ic_recv; + ic->ic_recv = 0; + + /* keep a reserve for napi */ + if (rx_limit < 4) { early_stop = 1; break; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - processed++; -#endif skb = bf->bf_skb; if (skb == NULL) { @@ -7074,8 +7076,8 @@ rx_next: if (sc->sc_isr & HAL_INT_RX) { u_int64_t hw_tsf = ath_hal_gettsf64(ah); sc->sc_isr &= ~HAL_INT_RX; - local_irq_restore(flags); ath_uapsd_processtriggers(sc, hw_tsf); + local_irq_restore(flags); goto process_rx_again; } local_irq_restore(flags); --- a/net80211/ieee80211_input.c +++ b/net80211/ieee80211_input.c @@ -1206,6 +1206,7 @@ ieee80211_deliver_data(struct ieee80211_ } } + vap->iv_ic->ic_recv++; if (skb != NULL) { skb->dev = dev; --- a/net80211/ieee80211_var.h +++ b/net80211/ieee80211_var.h @@ -323,6 +323,7 @@ struct ieee80211com { struct ifmedia ic_media; /* interface media config */ u_int8_t ic_myaddr[IEEE80211_ADDR_LEN]; struct timer_list ic_inact; /* mgmt/inactivity timer */ + u_int ic_recv; /* frame received counter */ unsigned int ic_subifs; u_int32_t ic_flags; /* state flags */