mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			62 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			62 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From: Felix Fietkau <nbd@openwrt.org>
 | |
| Date: Thu, 13 Nov 2014 18:29:26 +0100
 | |
| Subject: [PATCH] ath9k: do not access hardware on IRQs during reset
 | |
| 
 | |
| Instead of killing interrupts during reset when the first one happens,
 | |
| kill them before issuing the reset.
 | |
| This fixes an easy to reproduce crash with multiple cards sharing the
 | |
| same IRQ.
 | |
| 
 | |
| Cc: stable@vger.kernel.org
 | |
| Signed-off-by: Felix Fietkau <nbd@openwrt.org>
 | |
| ---
 | |
| 
 | |
| --- a/drivers/net/wireless/ath/ath9k/main.c
 | |
| +++ b/drivers/net/wireless/ath/ath9k/main.c
 | |
| @@ -512,16 +512,13 @@ irqreturn_t ath_isr(int irq, void *dev)
 | |
|  	if (!ah || test_bit(ATH_OP_INVALID, &common->op_flags))
 | |
|  		return IRQ_NONE;
 | |
|  
 | |
| -	/* shared irq, not for us */
 | |
| +	if (!AR_SREV_9100(ah) && test_bit(ATH_OP_HW_RESET, &common->op_flags))
 | |
| +		return IRQ_NONE;
 | |
|  
 | |
| +	/* shared irq, not for us */
 | |
|  	if (!ath9k_hw_intrpend(ah))
 | |
|  		return IRQ_NONE;
 | |
|  
 | |
| -	if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) {
 | |
| -		ath9k_hw_kill_interrupts(ah);
 | |
| -		return IRQ_HANDLED;
 | |
| -	}
 | |
| -
 | |
|  	/*
 | |
|  	 * Figure out the reason(s) for the interrupt.  Note
 | |
|  	 * that the hal returns a pseudo-ISR that may include
 | |
| @@ -532,6 +529,9 @@ irqreturn_t ath_isr(int irq, void *dev)
 | |
|  	ath9k_debug_sync_cause(sc, sync_cause);
 | |
|  	status &= ah->imask;	/* discard unasked-for bits */
 | |
|  
 | |
| +	if (AR_SREV_9100(ah) && test_bit(ATH_OP_HW_RESET, &common->op_flags))
 | |
| +		return IRQ_HANDLED;
 | |
| +
 | |
|  	/*
 | |
|  	 * If there are no status bits set, then this interrupt was not
 | |
|  	 * for me (should have been caught above).
 | |
| @@ -613,6 +613,7 @@ int ath_reset(struct ath_softc *sc, stru
 | |
|  	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 | |
|  	int r;
 | |
|  
 | |
| +	ath9k_hw_kill_interrupts(sc->sc_ah);
 | |
|  	set_bit(ATH_OP_HW_RESET, &common->op_flags);
 | |
|  
 | |
|  	ath9k_ps_wakeup(sc);
 | |
| @@ -633,6 +634,7 @@ void ath9k_queue_reset(struct ath_softc 
 | |
|  #ifdef CPTCFG_ATH9K_DEBUGFS
 | |
|  	RESET_STAT_INC(sc, type);
 | |
|  #endif
 | |
| +	ath9k_hw_kill_interrupts(sc->sc_ah);
 | |
|  	set_bit(ATH_OP_HW_RESET, &common->op_flags);
 | |
|  	ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
 | |
|  }
 |