ath5k: decrease interrupt load for rx/tx interrupts
SVN-Revision: 26579
This commit is contained in:
		
							
								
								
									
										140
									
								
								package/mac80211/patches/470-ath5k_decrease_irq_load.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								package/mac80211/patches/470-ath5k_decrease_irq_load.patch
									
									
									
									
									
										Normal file
									
								
							@@ -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];
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user