This contains multiple fixes from the upstream kernel. The removed patch was merged upstream. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
		
			
				
	
	
		
			130 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From: Felix Fietkau <nbd@nbd.name>
 | |
| Date: Sat, 9 Jul 2016 15:26:44 +0200
 | |
| Subject: [PATCH] ath9k_hw: issue external reset for QCA955x
 | |
| 
 | |
| The RTC interface on the SoC needs to be reset along with the rest of
 | |
| the WMAC.
 | |
| 
 | |
| Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | |
| ---
 | |
| 
 | |
| --- a/drivers/net/wireless/ath/ath9k/hw.c
 | |
| +++ b/drivers/net/wireless/ath/ath9k/hw.c
 | |
| @@ -1312,39 +1312,56 @@ void ath9k_hw_get_delta_slope_vals(struc
 | |
|  	*coef_exponent = coef_exp - 16;
 | |
|  }
 | |
|  
 | |
| -/* AR9330 WAR:
 | |
| - * call external reset function to reset WMAC if:
 | |
| - * - doing a cold reset
 | |
| - * - we have pending frames in the TX queues.
 | |
| - */
 | |
| -static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
 | |
| +static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type)
 | |
|  {
 | |
| -	int i, npend = 0;
 | |
| +	int i;
 | |
|  
 | |
| -	for (i = 0; i < AR_NUM_QCU; i++) {
 | |
| -		npend = ath9k_hw_numtxpending(ah, i);
 | |
| -		if (npend)
 | |
| -			break;
 | |
| -	}
 | |
| -
 | |
| -	if (ah->external_reset &&
 | |
| -	    (npend || type == ATH9K_RESET_COLD)) {
 | |
| -		int reset_err = 0;
 | |
| -
 | |
| -		ath_dbg(ath9k_hw_common(ah), RESET,
 | |
| -			"reset MAC via external reset\n");
 | |
| -
 | |
| -		reset_err = ah->external_reset();
 | |
| -		if (reset_err) {
 | |
| -			ath_err(ath9k_hw_common(ah),
 | |
| -				"External reset failed, err=%d\n",
 | |
| -				reset_err);
 | |
| -			return false;
 | |
| +	if (type == ATH9K_RESET_COLD)
 | |
| +		return true;
 | |
| +
 | |
| +	if (AR_SREV_9550(ah))
 | |
| +		return true;
 | |
| +
 | |
| +	/* AR9330 WAR:
 | |
| +	 * call external reset function to reset WMAC if:
 | |
| +	 * - doing a cold reset
 | |
| +	 * - we have pending frames in the TX queues.
 | |
| +	 */
 | |
| +	if (AR_SREV_9330(ah)) {
 | |
| +		for (i = 0; i < AR_NUM_QCU; i++) {
 | |
| +			if (ath9k_hw_numtxpending(ah, i))
 | |
| +				return true;
 | |
|  		}
 | |
| +	}
 | |
| +
 | |
| +	return false;
 | |
| +}
 | |
| +
 | |
| +static bool ath9k_hw_external_reset(struct ath_hw *ah, int type)
 | |
| +{
 | |
| +	int err;
 | |
| +
 | |
| +	if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type))
 | |
| +		return true;
 | |
| +
 | |
| +	ath_dbg(ath9k_hw_common(ah), RESET,
 | |
| +		"reset MAC via external reset\n");
 | |
|  
 | |
| -		REG_WRITE(ah, AR_RTC_RESET, 1);
 | |
| +	err = ah->external_reset();
 | |
| +	if (err) {
 | |
| +		ath_err(ath9k_hw_common(ah),
 | |
| +			"External reset failed, err=%d\n", err);
 | |
| +		return false;
 | |
|  	}
 | |
|  
 | |
| +	if (AR_SREV_9550(ah)) {
 | |
| +		REG_WRITE(ah, AR_RTC_RESET, 0);
 | |
| +		udelay(10);
 | |
| +	}
 | |
| +
 | |
| +	REG_WRITE(ah, AR_RTC_RESET, 1);
 | |
| +	udelay(10);
 | |
| +
 | |
|  	return true;
 | |
|  }
 | |
|  
 | |
| @@ -1397,24 +1414,24 @@ static bool ath9k_hw_set_reset(struct at
 | |
|  			rst_flags |= AR_RTC_RC_MAC_COLD;
 | |
|  	}
 | |
|  
 | |
| -	if (AR_SREV_9330(ah)) {
 | |
| -		if (!ath9k_hw_ar9330_reset_war(ah, type))
 | |
| -			return false;
 | |
| -	}
 | |
| -
 | |
|  	if (ath9k_hw_mci_is_enabled(ah))
 | |
|  		ar9003_mci_check_gpm_offset(ah);
 | |
|  
 | |
|  	/* DMA HALT added to resolve ar9300 and ar9580 bus error during
 | |
| -	 * RTC_RC reg read
 | |
| +	 * RTC_RC reg read. Also needed for AR9550 external reset
 | |
|  	 */
 | |
| -	if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) {
 | |
| +	if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) {
 | |
|  		REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
 | |
|  		ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK,
 | |
|  			      20 * AH_WAIT_TIMEOUT);
 | |
| -		REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
 | |
|  	}
 | |
|  
 | |
| +	if (!AR_SREV_9100(ah))
 | |
| +		ath9k_hw_external_reset(ah, type);
 | |
| +
 | |
| +	if (AR_SREV_9300(ah) || AR_SREV_9580(ah))
 | |
| +		REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
 | |
| +
 | |
|  	REG_WRITE(ah, AR_RTC_RC, rst_flags);
 | |
|  
 | |
|  	REGWRITE_BUFFER_FLUSH(ah);
 |