diff options
| -rw-r--r-- | package/mac80211/patches/470-ath5k_decrease_irq_load.patch | 140 | 
1 files changed, 140 insertions, 0 deletions
| diff --git a/package/mac80211/patches/470-ath5k_decrease_irq_load.patch b/package/mac80211/patches/470-ath5k_decrease_irq_load.patch new file mode 100644 index 000000000..5273bb075 --- /dev/null +++ b/package/mac80211/patches/470-ath5k_decrease_irq_load.patch @@ -0,0 +1,140 @@ +--- a/drivers/net/wireless/ath/ath5k/ath5k.h ++++ b/drivers/net/wireless/ath/ath5k/ath5k.h +@@ -872,6 +872,19 @@ enum ath5k_int { + 	AR5K_INT_QTRIG	=	0x40000000, /* Non common */ + 	AR5K_INT_GLOBAL =	0x80000000, +  ++	AR5K_INT_TX_ALL = AR5K_INT_TXOK ++		| AR5K_INT_TXDESC ++		| AR5K_INT_TXERR ++		| AR5K_INT_TXEOL ++		| AR5K_INT_TXURN, ++ ++	AR5K_INT_RX_ALL = AR5K_INT_RXOK ++		| AR5K_INT_RXDESC ++		| AR5K_INT_RXERR ++		| AR5K_INT_RXNOFRM ++		| AR5K_INT_RXEOL ++		| AR5K_INT_RXORN, ++ + 	AR5K_INT_COMMON  = AR5K_INT_RXOK + 		| AR5K_INT_RXDESC + 		| AR5K_INT_RXERR +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -1444,6 +1444,21 @@ ath5k_receive_frame_ok(struct ath5k_soft + } +  + static void ++ath5k_set_current_imask(struct ath5k_softc *sc) ++{ ++	enum ath5k_int imask = sc->imask; ++	unsigned long flags; ++ ++	spin_lock_irqsave(&sc->irqlock, flags); ++	if (sc->rx_pending) ++		imask &= ~AR5K_INT_RX_ALL; ++	if (sc->tx_pending) ++		imask &= ~AR5K_INT_TX_ALL; ++	ath5k_hw_set_imr(sc->ah, imask); ++	spin_unlock_irqrestore(&sc->irqlock, flags); ++} ++ ++static void + ath5k_tasklet_rx(unsigned long data) + { + 	struct ath5k_rx_status rs = {}; +@@ -1506,6 +1521,8 @@ next: + 	} while (ath5k_rxbuf_setup(sc, bf) == 0); + unlock: + 	spin_unlock(&sc->rxbuflock); ++	sc->rx_pending = false; ++	ath5k_set_current_imask(sc); + } +  +  +@@ -1693,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data) + 	for (i=0; i < AR5K_NUM_TX_QUEUES; i++) + 		if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) + 			ath5k_tx_processq(sc, &sc->txqs[i]); ++ ++	sc->tx_pending = false; ++	ath5k_set_current_imask(sc); + } +  +  +@@ -2122,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k + 	 * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ + } +  ++static void ++ath5k_schedule_rx(struct ath5k_softc *sc) ++{ ++	sc->rx_pending = true; ++	tasklet_schedule(&sc->rxtq); ++} ++ ++static void ++ath5k_schedule_tx(struct ath5k_softc *sc) ++{ ++	sc->tx_pending = true; ++	tasklet_schedule(&sc->txtq); ++} ++ + irqreturn_t + ath5k_intr(int irq, void *dev_id) + { +@@ -2164,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id) + 				ieee80211_queue_work(sc->hw, &sc->reset_work); + 			} + 			else +-				tasklet_schedule(&sc->rxtq); ++				ath5k_schedule_rx(sc); + 		} else { + 			if (status & AR5K_INT_SWBA) { + 				tasklet_hi_schedule(&sc->beacontq); +@@ -2182,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id) + 				ath5k_hw_update_tx_triglevel(ah, true); + 			} + 			if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) +-				tasklet_schedule(&sc->rxtq); ++				ath5k_schedule_rx(sc); + 			if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC + 					| AR5K_INT_TXERR | AR5K_INT_TXEOL)) +-				tasklet_schedule(&sc->txtq); ++				ath5k_schedule_tx(sc); + 			if (status & AR5K_INT_BMISS) { + 				/* TODO */ + 			} +@@ -2204,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id) +  + 	} while (ath5k_hw_is_intr_pending(ah) && --counter > 0); +  ++	if (sc->rx_pending || sc->tx_pending) ++		ath5k_set_current_imask(sc); ++ + 	if (unlikely(!counter)) + 		ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); +  +@@ -2575,6 +2612,8 @@ done: +  + static void stop_tasklets(struct ath5k_softc *sc) + { ++	sc->rx_pending = false; ++	sc->tx_pending = false; + 	tasklet_kill(&sc->rxtq); + 	tasklet_kill(&sc->txtq); + 	tasklet_kill(&sc->calib); +--- a/drivers/net/wireless/ath/ath5k/base.h ++++ b/drivers/net/wireless/ath/ath5k/base.h +@@ -207,6 +207,10 @@ struct ath5k_softc { +  + 	enum ath5k_int		imask;		/* interrupt mask copy */ +  ++	spinlock_t		irqlock; ++	bool			rx_pending;	/* rx tasklet pending */ ++	bool			tx_pending;	/* tx tasklet pending */ ++ + 	u8			lladdr[ETH_ALEN]; + 	u8			bssidmask[ETH_ALEN]; +  | 
