--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -6725,10 +6725,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;
@@ -6771,13 +6771,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) {
@@ -7061,8 +7063,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
@@ -1203,6 +1203,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 */
