diff options
Diffstat (limited to 'drivers/net/wireless')
170 files changed, 23098 insertions, 9884 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 58894366075..2fbe9b4506c 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -38,6 +38,12 @@ config LIBERTAS_THINFIRM  	---help---  	  A library for Marvell Libertas 8xxx devices using thinfirm. +config LIBERTAS_THINFIRM_DEBUG +	bool "Enable full debugging output in the Libertas thin firmware module." +	depends on LIBERTAS_THINFIRM +	---help--- +	  Debugging support. +  config LIBERTAS_THINFIRM_USB  	tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware"  	depends on LIBERTAS_THINFIRM && USB @@ -210,90 +216,7 @@ config USB_NET_RNDIS_WLAN  	  If you choose to build a module, it'll be called rndis_wlan. -config RTL8180 -	tristate "Realtek 8180/8185 PCI support" -	depends on MAC80211 && PCI && EXPERIMENTAL -	select EEPROM_93CX6 -	---help--- -	  This is a driver for RTL8180 and RTL8185 based cards. -	  These are PCI based chips found in cards such as: - -	  (RTL8185 802.11g) -	  A-Link WL54PC - -	  (RTL8180 802.11b) -	  Belkin F5D6020 v3 -	  Belkin F5D6020 v3 -	  Dlink DWL-610 -	  Dlink DWL-510 -	  Netgear MA521 -	  Level-One WPC-0101 -	  Acer Aspire 1357 LMi -	  VCTnet PC-11B1 -	  Ovislink AirLive WL-1120PCM -	  Mentor WL-PCI -	  Linksys WPC11 v4 -	  TrendNET TEW-288PI -	  D-Link DWL-520 Rev D -	  Repotec RP-WP7126 -	  TP-Link TL-WN250/251 -	  Zonet ZEW1000 -	  Longshine LCS-8031-R -	  HomeLine HLW-PCC200 -	  GigaFast WF721-AEX -	  Planet WL-3553 -	  Encore ENLWI-PCI1-NT -	  TrendNET TEW-266PC -	  Gigabyte GN-WLMR101 -	  Siemens-fujitsu Amilo D1840W -	  Edimax EW-7126 -	  PheeNet WL-11PCIR -	  Tonze PC-2100T -	  Planet WL-8303 -	  Dlink DWL-650 v M1 -	  Edimax EW-7106 -	  Q-Tec 770WC -	  Topcom Skyr@cer 4011b -	  Roper FreeLan 802.11b (edition 2004) -	  Wistron Neweb Corp CB-200B -	  Pentagram HorNET -	  QTec 775WC -	  TwinMOS Booming B Series -	  Micronet SP906BB -	  Sweex LC700010 -	  Surecom EP-9428 -	  Safecom SWLCR-1100 - -	  Thanks to Realtek for their support! - -config RTL8187 -	tristate "Realtek 8187 and 8187B USB support" -	depends on MAC80211 && USB -	select EEPROM_93CX6 -	---help--- -	  This is a driver for RTL8187 and RTL8187B based cards. -	  These are USB based chips found in devices such as: - -	  Netgear WG111v2 -	  Level 1 WNC-0301USB -	  Micronet SP907GK V5 -	  Encore ENUWI-G2 -	  Trendnet TEW-424UB -	  ASUS P5B Deluxe/P5K Premium motherboards -	  Toshiba Satellite Pro series of laptops -	  Asus Wireless Link -	  Linksys WUSB54GC-EU v2 -	    (v1 = rt73usb; v3 is rt2070-based, -	     use staging/rt3070 or try rt2800usb) - -	  Thanks to Realtek for their support! - -# If possible, automatically enable LEDs for RTL8187. - -config RTL8187_LEDS -	bool -	depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187) -	default y +source "drivers/net/wireless/rtl818x/Kconfig"  config ADM8211  	tristate "ADMtek ADM8211 support" diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 0fb419936df..7a626d4e100 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1889,6 +1889,7 @@ static void at76_dwork_hw_scan(struct work_struct *work)  }  static int at76_hw_scan(struct ieee80211_hw *hw, +			struct ieee80211_vif *vif,  			struct cfg80211_scan_request *req)  {  	struct at76_priv *priv = hw->priv; diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 0312cee3957..2e9b330f641 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -927,7 +927,6 @@ static void ar9170_rx_phy_status(struct ar9170 *ar,  	/* TODO: we could do something with phy_errors */  	status->signal = ar->noise[0] + phy->rssi_combined; -	status->noise = ar->noise[0];  }  static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len) @@ -2548,8 +2547,7 @@ void *ar9170_alloc(size_t priv_size)  					 BIT(NL80211_IFTYPE_ADHOC);  	ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |  			 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | -			 IEEE80211_HW_SIGNAL_DBM | -			 IEEE80211_HW_NOISE_DBM; +			 IEEE80211_HW_SIGNAL_DBM;  	if (modparam_ht) {  		ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 1fbf6b1f9a7..d32f2828b09 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -71,9 +71,21 @@ struct ath_regulatory {  	struct reg_dmn_pair_mapping *regpair;  }; +/** + * struct ath_ops - Register read/write operations + * + * @read: Register read + * @write: Register write + * @enable_write_buffer: Enable multiple register writes + * @disable_write_buffer: Disable multiple register writes + * @write_flush: Flush buffered register writes + */  struct ath_ops {  	unsigned int (*read)(void *, u32 reg_offset); -        void (*write)(void *, u32 val, u32 reg_offset); +	void (*write)(void *, u32 val, u32 reg_offset); +	void (*enable_write_buffer)(void *); +	void (*disable_write_buffer)(void *); +	void (*write_flush) (void *);  };  struct ath_common; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 93005f1d326..7f5953fac43 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -242,6 +242,8 @@ static int ath5k_set_key(struct ieee80211_hw *hw,  		struct ieee80211_key_conf *key);  static int ath5k_get_stats(struct ieee80211_hw *hw,  		struct ieee80211_low_level_stats *stats); +static int ath5k_get_survey(struct ieee80211_hw *hw, +		int idx, struct survey_info *survey);  static u64 ath5k_get_tsf(struct ieee80211_hw *hw);  static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);  static void ath5k_reset_tsf(struct ieee80211_hw *hw); @@ -267,6 +269,7 @@ static const struct ieee80211_ops ath5k_hw_ops = {  	.configure_filter = ath5k_configure_filter,  	.set_key 	= ath5k_set_key,  	.get_stats 	= ath5k_get_stats, +	.get_survey	= ath5k_get_survey,  	.conf_tx 	= NULL,  	.get_tsf 	= ath5k_get_tsf,  	.set_tsf 	= ath5k_set_tsf, @@ -545,8 +548,7 @@ ath5k_pci_probe(struct pci_dev *pdev,  	SET_IEEE80211_DEV(hw, &pdev->dev);  	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |  		    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | -		    IEEE80211_HW_SIGNAL_DBM | -		    IEEE80211_HW_NOISE_DBM; +		    IEEE80211_HW_SIGNAL_DBM;  	hw->wiphy->interface_modes =  		BIT(NL80211_IFTYPE_AP) | @@ -2027,8 +2029,7 @@ accept:  		rxs->freq = sc->curchan->center_freq;  		rxs->band = sc->curband->band; -		rxs->noise = sc->ah->ah_noise_floor; -		rxs->signal = rxs->noise + rs.rs_rssi; +		rxs->signal = sc->ah->ah_noise_floor + rs.rs_rssi;  		rxs->antenna = rs.rs_antenna; @@ -3292,6 +3293,22 @@ ath5k_get_stats(struct ieee80211_hw *hw,  	return 0;  } +static int ath5k_get_survey(struct ieee80211_hw *hw, int idx, +		struct survey_info *survey) +{ +	struct ath5k_softc *sc = hw->priv; +	struct ieee80211_conf *conf = &hw->conf; + +	 if (idx != 0) +		return -ENOENT; + +	survey->channel = conf->channel; +	survey->filled = SURVEY_INFO_NOISE_DBM; +	survey->noise = sc->ah->ah_noise_floor; + +	return 0; +} +  static u64  ath5k_get_tsf(struct ieee80211_hw *hw)  { diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 174412fc81f..5212e275f1c 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -496,6 +496,8 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)  * Beacon control *  \****************/ +#define ATH5K_MAX_TSF_READ 10 +  /**   * ath5k_hw_get_tsf64 - Get the full 64bit TSF   * @@ -505,10 +507,35 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)   */  u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)  { -	u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); +	u32 tsf_lower, tsf_upper1, tsf_upper2; +	int i; + +	/* +	 * While reading TSF upper and then lower part, the clock is still +	 * counting (or jumping in case of IBSS merge) so we might get +	 * inconsistent values. To avoid this, we read the upper part again +	 * and check it has not been changed. We make the hypothesis that a +	 * maximum of 3 changes can happens in a row (we use 10 as a safe +	 * value). +	 * +	 * Impact on performance is pretty small, since in most cases, only +	 * 3 register reads are needed. +	 */ + +	tsf_upper1 = ath5k_hw_reg_read(ah, AR5K_TSF_U32); +	for (i = 0; i < ATH5K_MAX_TSF_READ; i++) { +		tsf_lower = ath5k_hw_reg_read(ah, AR5K_TSF_L32); +		tsf_upper2 = ath5k_hw_reg_read(ah, AR5K_TSF_U32); +		if (tsf_upper2 == tsf_upper1) +			break; +		tsf_upper1 = tsf_upper2; +	} + +	WARN_ON( i == ATH5K_MAX_TSF_READ ); +  	ATH5K_TRACE(ah->ah_sc); -	return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); +	return (((u64)tsf_upper1 << 32) | tsf_lower);  }  /** diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 97133beda26..dd112be218a 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -13,16 +13,26 @@ ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o  obj-$(CONFIG_ATH9K) += ath9k.o -ath9k_hw-y:=	hw.o \ +ath9k_hw-y:=	\ +		ar9002_hw.o \ +		ar9003_hw.o \ +		hw.o \ +		ar9003_phy.o \ +		ar9002_phy.o \ +		ar5008_phy.o \ +		ar9002_calib.o \ +		ar9003_calib.o \ +		calib.o \  		eeprom.o \  		eeprom_def.o \  		eeprom_4k.o \  		eeprom_9287.o \ -		calib.o \  		ani.o \ -		phy.o \  		btcoex.o \  		mac.o \ +		ar9002_mac.o \ +		ar9003_mac.o \ +		ar9003_eeprom.o  obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 2a0cd64c2bf..ba8b20f0159 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -15,6 +15,7 @@   */  #include "hw.h" +#include "hw-ops.h"  static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,  					struct ath9k_channel *chan) @@ -37,190 +38,6 @@ static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,  	return 0;  } -static bool ath9k_hw_ani_control(struct ath_hw *ah, -				 enum ath9k_ani_cmd cmd, int param) -{ -	struct ar5416AniState *aniState = ah->curani; -	struct ath_common *common = ath9k_hw_common(ah); - -	switch (cmd & ah->ani_function) { -	case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ -		u32 level = param; - -		if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { -			ath_print(common, ATH_DBG_ANI, -				  "level out of range (%u > %u)\n", -				  level, -				  (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); -			return false; -		} - -		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, -			      AR_PHY_DESIRED_SZ_TOT_DES, -			      ah->totalSizeDesired[level]); -		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, -			      AR_PHY_AGC_CTL1_COARSE_LOW, -			      ah->coarse_low[level]); -		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, -			      AR_PHY_AGC_CTL1_COARSE_HIGH, -			      ah->coarse_high[level]); -		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, -			      AR_PHY_FIND_SIG_FIRPWR, -			      ah->firpwr[level]); - -		if (level > aniState->noiseImmunityLevel) -			ah->stats.ast_ani_niup++; -		else if (level < aniState->noiseImmunityLevel) -			ah->stats.ast_ani_nidown++; -		aniState->noiseImmunityLevel = level; -		break; -	} -	case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ -		const int m1ThreshLow[] = { 127, 50 }; -		const int m2ThreshLow[] = { 127, 40 }; -		const int m1Thresh[] = { 127, 0x4d }; -		const int m2Thresh[] = { 127, 0x40 }; -		const int m2CountThr[] = { 31, 16 }; -		const int m2CountThrLow[] = { 63, 48 }; -		u32 on = param ? 1 : 0; - -		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, -			      AR_PHY_SFCORR_LOW_M1_THRESH_LOW, -			      m1ThreshLow[on]); -		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, -			      AR_PHY_SFCORR_LOW_M2_THRESH_LOW, -			      m2ThreshLow[on]); -		REG_RMW_FIELD(ah, AR_PHY_SFCORR, -			      AR_PHY_SFCORR_M1_THRESH, -			      m1Thresh[on]); -		REG_RMW_FIELD(ah, AR_PHY_SFCORR, -			      AR_PHY_SFCORR_M2_THRESH, -			      m2Thresh[on]); -		REG_RMW_FIELD(ah, AR_PHY_SFCORR, -			      AR_PHY_SFCORR_M2COUNT_THR, -			      m2CountThr[on]); -		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, -			      AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, -			      m2CountThrLow[on]); - -		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -			      AR_PHY_SFCORR_EXT_M1_THRESH_LOW, -			      m1ThreshLow[on]); -		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -			      AR_PHY_SFCORR_EXT_M2_THRESH_LOW, -			      m2ThreshLow[on]); -		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -			      AR_PHY_SFCORR_EXT_M1_THRESH, -			      m1Thresh[on]); -		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, -			      AR_PHY_SFCORR_EXT_M2_THRESH, -			      m2Thresh[on]); - -		if (on) -			REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, -				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); -		else -			REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, -				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); - -		if (!on != aniState->ofdmWeakSigDetectOff) { -			if (on) -				ah->stats.ast_ani_ofdmon++; -			else -				ah->stats.ast_ani_ofdmoff++; -			aniState->ofdmWeakSigDetectOff = !on; -		} -		break; -	} -	case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ -		const int weakSigThrCck[] = { 8, 6 }; -		u32 high = param ? 1 : 0; - -		REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, -			      AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, -			      weakSigThrCck[high]); -		if (high != aniState->cckWeakSigThreshold) { -			if (high) -				ah->stats.ast_ani_cckhigh++; -			else -				ah->stats.ast_ani_ccklow++; -			aniState->cckWeakSigThreshold = high; -		} -		break; -	} -	case ATH9K_ANI_FIRSTEP_LEVEL:{ -		const int firstep[] = { 0, 4, 8 }; -		u32 level = param; - -		if (level >= ARRAY_SIZE(firstep)) { -			ath_print(common, ATH_DBG_ANI, -				  "level out of range (%u > %u)\n", -				  level, -				  (unsigned) ARRAY_SIZE(firstep)); -			return false; -		} -		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, -			      AR_PHY_FIND_SIG_FIRSTEP, -			      firstep[level]); -		if (level > aniState->firstepLevel) -			ah->stats.ast_ani_stepup++; -		else if (level < aniState->firstepLevel) -			ah->stats.ast_ani_stepdown++; -		aniState->firstepLevel = level; -		break; -	} -	case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ -		const int cycpwrThr1[] = -			{ 2, 4, 6, 8, 10, 12, 14, 16 }; -		u32 level = param; - -		if (level >= ARRAY_SIZE(cycpwrThr1)) { -			ath_print(common, ATH_DBG_ANI, -				  "level out of range (%u > %u)\n", -				  level, -				  (unsigned) ARRAY_SIZE(cycpwrThr1)); -			return false; -		} -		REG_RMW_FIELD(ah, AR_PHY_TIMING5, -			      AR_PHY_TIMING5_CYCPWR_THR1, -			      cycpwrThr1[level]); -		if (level > aniState->spurImmunityLevel) -			ah->stats.ast_ani_spurup++; -		else if (level < aniState->spurImmunityLevel) -			ah->stats.ast_ani_spurdown++; -		aniState->spurImmunityLevel = level; -		break; -	} -	case ATH9K_ANI_PRESENT: -		break; -	default: -		ath_print(common, ATH_DBG_ANI, -			  "invalid cmd %u\n", cmd); -		return false; -	} - -	ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); -	ath_print(common, ATH_DBG_ANI, -		  "noiseImmunityLevel=%d, spurImmunityLevel=%d, " -		  "ofdmWeakSigDetectOff=%d\n", -		  aniState->noiseImmunityLevel, -		  aniState->spurImmunityLevel, -		  !aniState->ofdmWeakSigDetectOff); -	ath_print(common, ATH_DBG_ANI, -		  "cckWeakSigThreshold=%d, " -		  "firstepLevel=%d, listenTime=%d\n", -		  aniState->cckWeakSigThreshold, -		  aniState->firstepLevel, -		  aniState->listenTime); -	ath_print(common, ATH_DBG_ANI, -		"cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", -		aniState->cycleCount, -		aniState->ofdmPhyErrCount, -		aniState->cckPhyErrCount); - -	return true; -} -  static void ath9k_hw_update_mibstats(struct ath_hw *ah,  				     struct ath9k_mib_stats *stats)  { @@ -262,11 +79,17 @@ static void ath9k_ani_restart(struct ath_hw *ah)  		  "Writing ofdmbase=%u   cckbase=%u\n",  		  aniState->ofdmPhyErrBase,  		  aniState->cckPhyErrBase); + +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);  	REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);  	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);  	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +  	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);  	aniState->ofdmPhyErrCount = 0; @@ -540,8 +363,14 @@ void ath9k_ani_reset(struct ath_hw *ah)  	ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &  			     ~ATH9K_RX_FILTER_PHYERR);  	ath9k_ani_restart(ah); + +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);  	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah);  }  void ath9k_hw_ani_monitor(struct ath_hw *ah, @@ -639,6 +468,8 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)  	ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_FILT_OFDM, 0);  	REG_WRITE(ah, AR_FILT_CCK, 0);  	REG_WRITE(ah, AR_MIBC, @@ -646,6 +477,9 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)  		  & 0x0f);  	REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);  	REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah);  }  /* Freeze the MIB counters, get the stats and then clear them */ @@ -809,20 +643,17 @@ void ath9k_hw_ani_init(struct ath_hw *ah)  	ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",  		  ah->ani[0].cckPhyErrBase); +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);  	REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +  	ath9k_enable_mib_counters(ah);  	ah->aniperiod = ATH9K_ANI_PERIOD;  	if (ah->config.enable_ani)  		ah->proc_phyerr |= HAL_PROCESS_ANI;  } - -void ath9k_hw_ani_disable(struct ath_hw *ah) -{ -	ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, "Disabling ANI\n"); - -	ath9k_hw_disable_mib_counters(ah); -	REG_WRITE(ah, AR_PHY_ERR_1, 0); -	REG_WRITE(ah, AR_PHY_ERR_2, 0); -} diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 4e1ab94a515..3356762ea38 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -118,6 +118,5 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,  void ath9k_hw_procmibevent(struct ath_hw *ah);  void ath9k_hw_ani_setup(struct ath_hw *ah);  void ath9k_hw_ani_init(struct ath_hw *ah); -void ath9k_hw_ani_disable(struct ath_hw *ah);  #endif /* ANI_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h new file mode 100644 index 00000000000..025c31ac614 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h @@ -0,0 +1,742 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_AR5008_H +#define INITVALS_AR5008_H + +static const u32 ar5416Modes[][6] = { +    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, +    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, +    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, +    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, +    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, +    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, +    { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, +    { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, +    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, +    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, +    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, +    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, +    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, +    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, +    { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, +    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, +    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, +    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, +    { 0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de }, +    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, +    { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, +    { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, +    { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, +    { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, +    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, +    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, +    { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, +    { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, +    { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, +    { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, +    { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, +    { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, +    { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, +    { 0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, +    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, +    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, +    { 0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c }, +    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, +    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, +    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, +    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, +    { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, +    { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, +    { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, +    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, +    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, +    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, +    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, +    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, +    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, +    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, +    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, +    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, +    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, +    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, +    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, +    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, +    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const u32 ar5416Common[][2] = { +    { 0x0000000c, 0x00000000 }, +    { 0x00000030, 0x00020015 }, +    { 0x00000034, 0x00000005 }, +    { 0x00000040, 0x00000000 }, +    { 0x00000044, 0x00000008 }, +    { 0x00000048, 0x00000008 }, +    { 0x0000004c, 0x00000010 }, +    { 0x00000050, 0x00000000 }, +    { 0x00000054, 0x0000001f }, +    { 0x00000800, 0x00000000 }, +    { 0x00000804, 0x00000000 }, +    { 0x00000808, 0x00000000 }, +    { 0x0000080c, 0x00000000 }, +    { 0x00000810, 0x00000000 }, +    { 0x00000814, 0x00000000 }, +    { 0x00000818, 0x00000000 }, +    { 0x0000081c, 0x00000000 }, +    { 0x00000820, 0x00000000 }, +    { 0x00000824, 0x00000000 }, +    { 0x00001040, 0x002ffc0f }, +    { 0x00001044, 0x002ffc0f }, +    { 0x00001048, 0x002ffc0f }, +    { 0x0000104c, 0x002ffc0f }, +    { 0x00001050, 0x002ffc0f }, +    { 0x00001054, 0x002ffc0f }, +    { 0x00001058, 0x002ffc0f }, +    { 0x0000105c, 0x002ffc0f }, +    { 0x00001060, 0x002ffc0f }, +    { 0x00001064, 0x002ffc0f }, +    { 0x00001230, 0x00000000 }, +    { 0x00001270, 0x00000000 }, +    { 0x00001038, 0x00000000 }, +    { 0x00001078, 0x00000000 }, +    { 0x000010b8, 0x00000000 }, +    { 0x000010f8, 0x00000000 }, +    { 0x00001138, 0x00000000 }, +    { 0x00001178, 0x00000000 }, +    { 0x000011b8, 0x00000000 }, +    { 0x000011f8, 0x00000000 }, +    { 0x00001238, 0x00000000 }, +    { 0x00001278, 0x00000000 }, +    { 0x000012b8, 0x00000000 }, +    { 0x000012f8, 0x00000000 }, +    { 0x00001338, 0x00000000 }, +    { 0x00001378, 0x00000000 }, +    { 0x000013b8, 0x00000000 }, +    { 0x000013f8, 0x00000000 }, +    { 0x00001438, 0x00000000 }, +    { 0x00001478, 0x00000000 }, +    { 0x000014b8, 0x00000000 }, +    { 0x000014f8, 0x00000000 }, +    { 0x00001538, 0x00000000 }, +    { 0x00001578, 0x00000000 }, +    { 0x000015b8, 0x00000000 }, +    { 0x000015f8, 0x00000000 }, +    { 0x00001638, 0x00000000 }, +    { 0x00001678, 0x00000000 }, +    { 0x000016b8, 0x00000000 }, +    { 0x000016f8, 0x00000000 }, +    { 0x00001738, 0x00000000 }, +    { 0x00001778, 0x00000000 }, +    { 0x000017b8, 0x00000000 }, +    { 0x000017f8, 0x00000000 }, +    { 0x0000103c, 0x00000000 }, +    { 0x0000107c, 0x00000000 }, +    { 0x000010bc, 0x00000000 }, +    { 0x000010fc, 0x00000000 }, +    { 0x0000113c, 0x00000000 }, +    { 0x0000117c, 0x00000000 }, +    { 0x000011bc, 0x00000000 }, +    { 0x000011fc, 0x00000000 }, +    { 0x0000123c, 0x00000000 }, +    { 0x0000127c, 0x00000000 }, +    { 0x000012bc, 0x00000000 }, +    { 0x000012fc, 0x00000000 }, +    { 0x0000133c, 0x00000000 }, +    { 0x0000137c, 0x00000000 }, +    { 0x000013bc, 0x00000000 }, +    { 0x000013fc, 0x00000000 }, +    { 0x0000143c, 0x00000000 }, +    { 0x0000147c, 0x00000000 }, +    { 0x00004030, 0x00000002 }, +    { 0x0000403c, 0x00000002 }, +    { 0x00007010, 0x00000000 }, +    { 0x00007038, 0x000004c2 }, +    { 0x00008004, 0x00000000 }, +    { 0x00008008, 0x00000000 }, +    { 0x0000800c, 0x00000000 }, +    { 0x00008018, 0x00000700 }, +    { 0x00008020, 0x00000000 }, +    { 0x00008038, 0x00000000 }, +    { 0x0000803c, 0x00000000 }, +    { 0x00008048, 0x40000000 }, +    { 0x00008054, 0x00000000 }, +    { 0x00008058, 0x00000000 }, +    { 0x0000805c, 0x000fc78f }, +    { 0x00008060, 0x0000000f }, +    { 0x00008064, 0x00000000 }, +    { 0x000080c0, 0x2a82301a }, +    { 0x000080c4, 0x05dc01e0 }, +    { 0x000080c8, 0x1f402710 }, +    { 0x000080cc, 0x01f40000 }, +    { 0x000080d0, 0x00001e00 }, +    { 0x000080d4, 0x00000000 }, +    { 0x000080d8, 0x00400000 }, +    { 0x000080e0, 0xffffffff }, +    { 0x000080e4, 0x0000ffff }, +    { 0x000080e8, 0x003f3f3f }, +    { 0x000080ec, 0x00000000 }, +    { 0x000080f0, 0x00000000 }, +    { 0x000080f4, 0x00000000 }, +    { 0x000080f8, 0x00000000 }, +    { 0x000080fc, 0x00020000 }, +    { 0x00008100, 0x00020000 }, +    { 0x00008104, 0x00000001 }, +    { 0x00008108, 0x00000052 }, +    { 0x0000810c, 0x00000000 }, +    { 0x00008110, 0x00000168 }, +    { 0x00008118, 0x000100aa }, +    { 0x0000811c, 0x00003210 }, +    { 0x00008124, 0x00000000 }, +    { 0x00008128, 0x00000000 }, +    { 0x0000812c, 0x00000000 }, +    { 0x00008130, 0x00000000 }, +    { 0x00008134, 0x00000000 }, +    { 0x00008138, 0x00000000 }, +    { 0x0000813c, 0x00000000 }, +    { 0x00008144, 0xffffffff }, +    { 0x00008168, 0x00000000 }, +    { 0x0000816c, 0x00000000 }, +    { 0x00008170, 0x32143320 }, +    { 0x00008174, 0xfaa4fa50 }, +    { 0x00008178, 0x00000100 }, +    { 0x0000817c, 0x00000000 }, +    { 0x000081c4, 0x00000000 }, +    { 0x000081ec, 0x00000000 }, +    { 0x000081f0, 0x00000000 }, +    { 0x000081f4, 0x00000000 }, +    { 0x000081f8, 0x00000000 }, +    { 0x000081fc, 0x00000000 }, +    { 0x00008200, 0x00000000 }, +    { 0x00008204, 0x00000000 }, +    { 0x00008208, 0x00000000 }, +    { 0x0000820c, 0x00000000 }, +    { 0x00008210, 0x00000000 }, +    { 0x00008214, 0x00000000 }, +    { 0x00008218, 0x00000000 }, +    { 0x0000821c, 0x00000000 }, +    { 0x00008220, 0x00000000 }, +    { 0x00008224, 0x00000000 }, +    { 0x00008228, 0x00000000 }, +    { 0x0000822c, 0x00000000 }, +    { 0x00008230, 0x00000000 }, +    { 0x00008234, 0x00000000 }, +    { 0x00008238, 0x00000000 }, +    { 0x0000823c, 0x00000000 }, +    { 0x00008240, 0x00100000 }, +    { 0x00008244, 0x0010f400 }, +    { 0x00008248, 0x00000100 }, +    { 0x0000824c, 0x0001e800 }, +    { 0x00008250, 0x00000000 }, +    { 0x00008254, 0x00000000 }, +    { 0x00008258, 0x00000000 }, +    { 0x0000825c, 0x400000ff }, +    { 0x00008260, 0x00080922 }, +    { 0x00008264, 0x88000010 }, +    { 0x00008270, 0x00000000 }, +    { 0x00008274, 0x40000000 }, +    { 0x00008278, 0x003e4180 }, +    { 0x0000827c, 0x00000000 }, +    { 0x00008284, 0x0000002c }, +    { 0x00008288, 0x0000002c }, +    { 0x0000828c, 0x00000000 }, +    { 0x00008294, 0x00000000 }, +    { 0x00008298, 0x00000000 }, +    { 0x00008300, 0x00000000 }, +    { 0x00008304, 0x00000000 }, +    { 0x00008308, 0x00000000 }, +    { 0x0000830c, 0x00000000 }, +    { 0x00008310, 0x00000000 }, +    { 0x00008314, 0x00000000 }, +    { 0x00008318, 0x00000000 }, +    { 0x00008328, 0x00000000 }, +    { 0x0000832c, 0x00000007 }, +    { 0x00008330, 0x00000302 }, +    { 0x00008334, 0x00000e00 }, +    { 0x00008338, 0x00070000 }, +    { 0x0000833c, 0x00000000 }, +    { 0x00008340, 0x000107ff }, +    { 0x00009808, 0x00000000 }, +    { 0x0000980c, 0xad848e19 }, +    { 0x00009810, 0x7d14e000 }, +    { 0x00009814, 0x9c0a9f6b }, +    { 0x0000981c, 0x00000000 }, +    { 0x0000982c, 0x0000a000 }, +    { 0x00009830, 0x00000000 }, +    { 0x0000983c, 0x00200400 }, +    { 0x00009840, 0x206a002e }, +    { 0x0000984c, 0x1284233c }, +    { 0x00009854, 0x00000859 }, +    { 0x00009900, 0x00000000 }, +    { 0x00009904, 0x00000000 }, +    { 0x00009908, 0x00000000 }, +    { 0x0000990c, 0x00000000 }, +    { 0x0000991c, 0x10000fff }, +    { 0x00009920, 0x05100000 }, +    { 0x0000a920, 0x05100000 }, +    { 0x0000b920, 0x05100000 }, +    { 0x00009928, 0x00000001 }, +    { 0x0000992c, 0x00000004 }, +    { 0x00009934, 0x1e1f2022 }, +    { 0x00009938, 0x0a0b0c0d }, +    { 0x0000993c, 0x00000000 }, +    { 0x00009948, 0x9280b212 }, +    { 0x0000994c, 0x00020028 }, +    { 0x00009954, 0x5d50e188 }, +    { 0x00009958, 0x00081fff }, +    { 0x0000c95c, 0x004b6a8e }, +    { 0x0000c968, 0x000003ce }, +    { 0x00009970, 0x190fb515 }, +    { 0x00009974, 0x00000000 }, +    { 0x00009978, 0x00000001 }, +    { 0x0000997c, 0x00000000 }, +    { 0x00009980, 0x00000000 }, +    { 0x00009984, 0x00000000 }, +    { 0x00009988, 0x00000000 }, +    { 0x0000998c, 0x00000000 }, +    { 0x00009990, 0x00000000 }, +    { 0x00009994, 0x00000000 }, +    { 0x00009998, 0x00000000 }, +    { 0x0000999c, 0x00000000 }, +    { 0x000099a0, 0x00000000 }, +    { 0x000099a4, 0x00000001 }, +    { 0x000099a8, 0x001fff00 }, +    { 0x000099ac, 0x00000000 }, +    { 0x000099b0, 0x03051000 }, +    { 0x000099dc, 0x00000000 }, +    { 0x000099e0, 0x00000200 }, +    { 0x000099e4, 0xaaaaaaaa }, +    { 0x000099e8, 0x3c466478 }, +    { 0x000099ec, 0x000000aa }, +    { 0x000099fc, 0x00001042 }, +    { 0x00009b00, 0x00000000 }, +    { 0x00009b04, 0x00000001 }, +    { 0x00009b08, 0x00000002 }, +    { 0x00009b0c, 0x00000003 }, +    { 0x00009b10, 0x00000004 }, +    { 0x00009b14, 0x00000005 }, +    { 0x00009b18, 0x00000008 }, +    { 0x00009b1c, 0x00000009 }, +    { 0x00009b20, 0x0000000a }, +    { 0x00009b24, 0x0000000b }, +    { 0x00009b28, 0x0000000c }, +    { 0x00009b2c, 0x0000000d }, +    { 0x00009b30, 0x00000010 }, +    { 0x00009b34, 0x00000011 }, +    { 0x00009b38, 0x00000012 }, +    { 0x00009b3c, 0x00000013 }, +    { 0x00009b40, 0x00000014 }, +    { 0x00009b44, 0x00000015 }, +    { 0x00009b48, 0x00000018 }, +    { 0x00009b4c, 0x00000019 }, +    { 0x00009b50, 0x0000001a }, +    { 0x00009b54, 0x0000001b }, +    { 0x00009b58, 0x0000001c }, +    { 0x00009b5c, 0x0000001d }, +    { 0x00009b60, 0x00000020 }, +    { 0x00009b64, 0x00000021 }, +    { 0x00009b68, 0x00000022 }, +    { 0x00009b6c, 0x00000023 }, +    { 0x00009b70, 0x00000024 }, +    { 0x00009b74, 0x00000025 }, +    { 0x00009b78, 0x00000028 }, +    { 0x00009b7c, 0x00000029 }, +    { 0x00009b80, 0x0000002a }, +    { 0x00009b84, 0x0000002b }, +    { 0x00009b88, 0x0000002c }, +    { 0x00009b8c, 0x0000002d }, +    { 0x00009b90, 0x00000030 }, +    { 0x00009b94, 0x00000031 }, +    { 0x00009b98, 0x00000032 }, +    { 0x00009b9c, 0x00000033 }, +    { 0x00009ba0, 0x00000034 }, +    { 0x00009ba4, 0x00000035 }, +    { 0x00009ba8, 0x00000035 }, +    { 0x00009bac, 0x00000035 }, +    { 0x00009bb0, 0x00000035 }, +    { 0x00009bb4, 0x00000035 }, +    { 0x00009bb8, 0x00000035 }, +    { 0x00009bbc, 0x00000035 }, +    { 0x00009bc0, 0x00000035 }, +    { 0x00009bc4, 0x00000035 }, +    { 0x00009bc8, 0x00000035 }, +    { 0x00009bcc, 0x00000035 }, +    { 0x00009bd0, 0x00000035 }, +    { 0x00009bd4, 0x00000035 }, +    { 0x00009bd8, 0x00000035 }, +    { 0x00009bdc, 0x00000035 }, +    { 0x00009be0, 0x00000035 }, +    { 0x00009be4, 0x00000035 }, +    { 0x00009be8, 0x00000035 }, +    { 0x00009bec, 0x00000035 }, +    { 0x00009bf0, 0x00000035 }, +    { 0x00009bf4, 0x00000035 }, +    { 0x00009bf8, 0x00000010 }, +    { 0x00009bfc, 0x0000001a }, +    { 0x0000a210, 0x40806333 }, +    { 0x0000a214, 0x00106c10 }, +    { 0x0000a218, 0x009c4060 }, +    { 0x0000a220, 0x018830c6 }, +    { 0x0000a224, 0x00000400 }, +    { 0x0000a228, 0x00000bb5 }, +    { 0x0000a22c, 0x00000011 }, +    { 0x0000a234, 0x20202020 }, +    { 0x0000a238, 0x20202020 }, +    { 0x0000a23c, 0x13c889af }, +    { 0x0000a240, 0x38490a20 }, +    { 0x0000a244, 0x00007bb6 }, +    { 0x0000a248, 0x0fff3ffc }, +    { 0x0000a24c, 0x00000001 }, +    { 0x0000a250, 0x0000a000 }, +    { 0x0000a254, 0x00000000 }, +    { 0x0000a258, 0x0cc75380 }, +    { 0x0000a25c, 0x0f0f0f01 }, +    { 0x0000a260, 0xdfa91f01 }, +    { 0x0000a268, 0x00000000 }, +    { 0x0000a26c, 0x0e79e5c6 }, +    { 0x0000b26c, 0x0e79e5c6 }, +    { 0x0000c26c, 0x0e79e5c6 }, +    { 0x0000d270, 0x00820820 }, +    { 0x0000a278, 0x1ce739ce }, +    { 0x0000a27c, 0x051701ce }, +    { 0x0000a338, 0x00000000 }, +    { 0x0000a33c, 0x00000000 }, +    { 0x0000a340, 0x00000000 }, +    { 0x0000a344, 0x00000000 }, +    { 0x0000a348, 0x3fffffff }, +    { 0x0000a34c, 0x3fffffff }, +    { 0x0000a350, 0x3fffffff }, +    { 0x0000a354, 0x0003ffff }, +    { 0x0000a358, 0x79a8aa1f }, +    { 0x0000d35c, 0x07ffffef }, +    { 0x0000d360, 0x0fffffe7 }, +    { 0x0000d364, 0x17ffffe5 }, +    { 0x0000d368, 0x1fffffe4 }, +    { 0x0000d36c, 0x37ffffe3 }, +    { 0x0000d370, 0x3fffffe3 }, +    { 0x0000d374, 0x57ffffe3 }, +    { 0x0000d378, 0x5fffffe2 }, +    { 0x0000d37c, 0x7fffffe2 }, +    { 0x0000d380, 0x7f3c7bba }, +    { 0x0000d384, 0xf3307ff0 }, +    { 0x0000a388, 0x08000000 }, +    { 0x0000a38c, 0x20202020 }, +    { 0x0000a390, 0x20202020 }, +    { 0x0000a394, 0x1ce739ce }, +    { 0x0000a398, 0x000001ce }, +    { 0x0000a39c, 0x00000001 }, +    { 0x0000a3a0, 0x00000000 }, +    { 0x0000a3a4, 0x00000000 }, +    { 0x0000a3a8, 0x00000000 }, +    { 0x0000a3ac, 0x00000000 }, +    { 0x0000a3b0, 0x00000000 }, +    { 0x0000a3b4, 0x00000000 }, +    { 0x0000a3b8, 0x00000000 }, +    { 0x0000a3bc, 0x00000000 }, +    { 0x0000a3c0, 0x00000000 }, +    { 0x0000a3c4, 0x00000000 }, +    { 0x0000a3c8, 0x00000246 }, +    { 0x0000a3cc, 0x20202020 }, +    { 0x0000a3d0, 0x20202020 }, +    { 0x0000a3d4, 0x20202020 }, +    { 0x0000a3dc, 0x1ce739ce }, +    { 0x0000a3e0, 0x000001ce }, +}; + +static const u32 ar5416Bank0[][2] = { +    { 0x000098b0, 0x1e5795e5 }, +    { 0x000098e0, 0x02008020 }, +}; + +static const u32 ar5416BB_RfGain[][3] = { +    { 0x00009a00, 0x00000000, 0x00000000 }, +    { 0x00009a04, 0x00000040, 0x00000040 }, +    { 0x00009a08, 0x00000080, 0x00000080 }, +    { 0x00009a0c, 0x000001a1, 0x00000141 }, +    { 0x00009a10, 0x000001e1, 0x00000181 }, +    { 0x00009a14, 0x00000021, 0x000001c1 }, +    { 0x00009a18, 0x00000061, 0x00000001 }, +    { 0x00009a1c, 0x00000168, 0x00000041 }, +    { 0x00009a20, 0x000001a8, 0x000001a8 }, +    { 0x00009a24, 0x000001e8, 0x000001e8 }, +    { 0x00009a28, 0x00000028, 0x00000028 }, +    { 0x00009a2c, 0x00000068, 0x00000068 }, +    { 0x00009a30, 0x00000189, 0x000000a8 }, +    { 0x00009a34, 0x000001c9, 0x00000169 }, +    { 0x00009a38, 0x00000009, 0x000001a9 }, +    { 0x00009a3c, 0x00000049, 0x000001e9 }, +    { 0x00009a40, 0x00000089, 0x00000029 }, +    { 0x00009a44, 0x00000170, 0x00000069 }, +    { 0x00009a48, 0x000001b0, 0x00000190 }, +    { 0x00009a4c, 0x000001f0, 0x000001d0 }, +    { 0x00009a50, 0x00000030, 0x00000010 }, +    { 0x00009a54, 0x00000070, 0x00000050 }, +    { 0x00009a58, 0x00000191, 0x00000090 }, +    { 0x00009a5c, 0x000001d1, 0x00000151 }, +    { 0x00009a60, 0x00000011, 0x00000191 }, +    { 0x00009a64, 0x00000051, 0x000001d1 }, +    { 0x00009a68, 0x00000091, 0x00000011 }, +    { 0x00009a6c, 0x000001b8, 0x00000051 }, +    { 0x00009a70, 0x000001f8, 0x00000198 }, +    { 0x00009a74, 0x00000038, 0x000001d8 }, +    { 0x00009a78, 0x00000078, 0x00000018 }, +    { 0x00009a7c, 0x00000199, 0x00000058 }, +    { 0x00009a80, 0x000001d9, 0x00000098 }, +    { 0x00009a84, 0x00000019, 0x00000159 }, +    { 0x00009a88, 0x00000059, 0x00000199 }, +    { 0x00009a8c, 0x00000099, 0x000001d9 }, +    { 0x00009a90, 0x000000d9, 0x00000019 }, +    { 0x00009a94, 0x000000f9, 0x00000059 }, +    { 0x00009a98, 0x000000f9, 0x00000099 }, +    { 0x00009a9c, 0x000000f9, 0x000000d9 }, +    { 0x00009aa0, 0x000000f9, 0x000000f9 }, +    { 0x00009aa4, 0x000000f9, 0x000000f9 }, +    { 0x00009aa8, 0x000000f9, 0x000000f9 }, +    { 0x00009aac, 0x000000f9, 0x000000f9 }, +    { 0x00009ab0, 0x000000f9, 0x000000f9 }, +    { 0x00009ab4, 0x000000f9, 0x000000f9 }, +    { 0x00009ab8, 0x000000f9, 0x000000f9 }, +    { 0x00009abc, 0x000000f9, 0x000000f9 }, +    { 0x00009ac0, 0x000000f9, 0x000000f9 }, +    { 0x00009ac4, 0x000000f9, 0x000000f9 }, +    { 0x00009ac8, 0x000000f9, 0x000000f9 }, +    { 0x00009acc, 0x000000f9, 0x000000f9 }, +    { 0x00009ad0, 0x000000f9, 0x000000f9 }, +    { 0x00009ad4, 0x000000f9, 0x000000f9 }, +    { 0x00009ad8, 0x000000f9, 0x000000f9 }, +    { 0x00009adc, 0x000000f9, 0x000000f9 }, +    { 0x00009ae0, 0x000000f9, 0x000000f9 }, +    { 0x00009ae4, 0x000000f9, 0x000000f9 }, +    { 0x00009ae8, 0x000000f9, 0x000000f9 }, +    { 0x00009aec, 0x000000f9, 0x000000f9 }, +    { 0x00009af0, 0x000000f9, 0x000000f9 }, +    { 0x00009af4, 0x000000f9, 0x000000f9 }, +    { 0x00009af8, 0x000000f9, 0x000000f9 }, +    { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const u32 ar5416Bank1[][2] = { +    { 0x000098b0, 0x02108421 }, +    { 0x000098ec, 0x00000008 }, +}; + +static const u32 ar5416Bank2[][2] = { +    { 0x000098b0, 0x0e73ff17 }, +    { 0x000098e0, 0x00000420 }, +}; + +static const u32 ar5416Bank3[][3] = { +    { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const u32 ar5416Bank6[][3] = { + +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00e00000, 0x00e00000 }, +    { 0x0000989c, 0x005e0000, 0x005e0000 }, +    { 0x0000989c, 0x00120000, 0x00120000 }, +    { 0x0000989c, 0x00620000, 0x00620000 }, +    { 0x0000989c, 0x00020000, 0x00020000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x40ff0000, 0x40ff0000 }, +    { 0x0000989c, 0x005f0000, 0x005f0000 }, +    { 0x0000989c, 0x00870000, 0x00870000 }, +    { 0x0000989c, 0x00f90000, 0x00f90000 }, +    { 0x0000989c, 0x007b0000, 0x007b0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00f50000, 0x00f50000 }, +    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, +    { 0x0000989c, 0x00110000, 0x00110000 }, +    { 0x0000989c, 0x006100a8, 0x006100a8 }, +    { 0x0000989c, 0x004210a2, 0x004210a2 }, +    { 0x0000989c, 0x0014008f, 0x0014008f }, +    { 0x0000989c, 0x00c40003, 0x00c40003 }, +    { 0x0000989c, 0x003000f2, 0x003000f2 }, +    { 0x0000989c, 0x00440016, 0x00440016 }, +    { 0x0000989c, 0x00410040, 0x00410040 }, +    { 0x0000989c, 0x0001805e, 0x0001805e }, +    { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, +    { 0x0000989c, 0x000000f1, 0x000000f1 }, +    { 0x0000989c, 0x00002081, 0x00002081 }, +    { 0x0000989c, 0x000000d4, 0x000000d4 }, +    { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank6TPC[][3] = { +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00e00000, 0x00e00000 }, +    { 0x0000989c, 0x005e0000, 0x005e0000 }, +    { 0x0000989c, 0x00120000, 0x00120000 }, +    { 0x0000989c, 0x00620000, 0x00620000 }, +    { 0x0000989c, 0x00020000, 0x00020000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x40ff0000, 0x40ff0000 }, +    { 0x0000989c, 0x005f0000, 0x005f0000 }, +    { 0x0000989c, 0x00870000, 0x00870000 }, +    { 0x0000989c, 0x00f90000, 0x00f90000 }, +    { 0x0000989c, 0x007b0000, 0x007b0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00f50000, 0x00f50000 }, +    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, +    { 0x0000989c, 0x00110000, 0x00110000 }, +    { 0x0000989c, 0x006100a8, 0x006100a8 }, +    { 0x0000989c, 0x00423022, 0x00423022 }, +    { 0x0000989c, 0x201400df, 0x201400df }, +    { 0x0000989c, 0x00c40002, 0x00c40002 }, +    { 0x0000989c, 0x003000f2, 0x003000f2 }, +    { 0x0000989c, 0x00440016, 0x00440016 }, +    { 0x0000989c, 0x00410040, 0x00410040 }, +    { 0x0000989c, 0x0001805e, 0x0001805e }, +    { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, +    { 0x0000989c, 0x000000e1, 0x000000e1 }, +    { 0x0000989c, 0x00007081, 0x00007081 }, +    { 0x0000989c, 0x000000d4, 0x000000d4 }, +    { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank7[][2] = { +    { 0x0000989c, 0x00000500 }, +    { 0x0000989c, 0x00000800 }, +    { 0x000098cc, 0x0000000e }, +}; + +static const u32 ar5416Addac[][2] = { +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000003 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x0000000c }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000030 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000060 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000058 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x000098cc,  0x00000000 }, +}; + +static const u32 ar5416Modes_9100[][6] = { +    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, +    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, +    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, +    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, +    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, +    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, +    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, +    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, +    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, +    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, +    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, +    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, +    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, +    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, +    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, +    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, +    { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, +    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e }, +    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, +    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, +    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, +    { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, +    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, +    { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, +    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, +    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d }, +    { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 }, +    { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, +    { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e }, +    { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff }, +#ifdef TB243 +    { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, +    { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, +    { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, +    { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 }, +#else +    { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, +    { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, +    { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, +    { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, +#endif +    { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 }, +    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, +    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, +    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, +    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, +    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, +    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, +    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, +    { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, +    { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, +    { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, +    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, +    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, +    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, +    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, +    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, +    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, +    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, +    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, +    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, +    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, +    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, +    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, +    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, +    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +#endif /* INITVALS_AR5008_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c new file mode 100644 index 00000000000..b2c17c98bb3 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -0,0 +1,1374 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "hw-ops.h" +#include "../regd.h" +#include "ar9002_phy.h" + +/* All code below is for non single-chip solutions */ + +/** + * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters + * @rfbuf: + * @reg32: + * @numBits: + * @firstBit: + * @column: + * + * Performs analog "swizzling" of parameters into their location. + * Used on external AR2133/AR5133 radios. + */ +static void ar5008_hw_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, +					   u32 numBits, u32 firstBit, +					   u32 column) +{ +	u32 tmp32, mask, arrayEntry, lastBit; +	int32_t bitPosition, bitsLeft; + +	tmp32 = ath9k_hw_reverse_bits(reg32, numBits); +	arrayEntry = (firstBit - 1) / 8; +	bitPosition = (firstBit - 1) % 8; +	bitsLeft = numBits; +	while (bitsLeft > 0) { +		lastBit = (bitPosition + bitsLeft > 8) ? +		    8 : bitPosition + bitsLeft; +		mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << +		    (column * 8); +		rfBuf[arrayEntry] &= ~mask; +		rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << +				      (column * 8)) & mask; +		bitsLeft -= 8 - bitPosition; +		tmp32 = tmp32 >> (8 - bitPosition); +		bitPosition = 0; +		arrayEntry++; +	} +} + +/* + * Fix on 2.4 GHz band for orientation sensitivity issue by increasing + * rf_pwd_icsyndiv. + * + * Theoretical Rules: + *   if 2 GHz band + *      if forceBiasAuto + *         if synth_freq < 2412 + *            bias = 0 + *         else if 2412 <= synth_freq <= 2422 + *            bias = 1 + *         else // synth_freq > 2422 + *            bias = 2 + *      else if forceBias > 0 + *         bias = forceBias & 7 + *      else + *         no change, use value from ini file + *   else + *      no change, invalid band + * + *  1st Mod: + *    2422 also uses value of 2 + *    <approved> + * + *  2nd Mod: + *    Less than 2412 uses value of 0, 2412 and above uses value of 2 + */ +static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	u32 tmp_reg; +	int reg_writes = 0; +	u32 new_bias = 0; + +	if (!AR_SREV_5416(ah) || synth_freq >= 3000) +		return; + +	BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + +	if (synth_freq < 2412) +		new_bias = 0; +	else if (synth_freq < 2422) +		new_bias = 1; +	else +		new_bias = 2; + +	/* pre-reverse this field */ +	tmp_reg = ath9k_hw_reverse_bits(new_bias, 3); + +	ath_print(common, ATH_DBG_CONFIG, +		  "Force rf_pwd_icsyndiv to %1d on %4d\n", +		  new_bias, synth_freq); + +	/* swizzle rf_pwd_icsyndiv */ +	ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); + +	/* write Bank 6 with new params */ +	REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes); +} + +/** + * ar5008_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios + * @ah: atheros hardware stucture + * @chan: + * + * For the external AR2133/AR5133 radios, takes the MHz channel value and set + * the channel value. Assumes writes enabled to analog bus and bank6 register + * cache in ah->analogBank6Data. + */ +static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	u32 channelSel = 0; +	u32 bModeSynth = 0; +	u32 aModeRefSel = 0; +	u32 reg32 = 0; +	u16 freq; +	struct chan_centers centers; + +	ath9k_hw_get_channel_centers(ah, chan, ¢ers); +	freq = centers.synth_center; + +	if (freq < 4800) { +		u32 txctl; + +		if (((freq - 2192) % 5) == 0) { +			channelSel = ((freq - 672) * 2 - 3040) / 10; +			bModeSynth = 0; +		} else if (((freq - 2224) % 5) == 0) { +			channelSel = ((freq - 704) * 2 - 3040) / 10; +			bModeSynth = 1; +		} else { +			ath_print(common, ATH_DBG_FATAL, +				  "Invalid channel %u MHz\n", freq); +			return -EINVAL; +		} + +		channelSel = (channelSel << 2) & 0xff; +		channelSel = ath9k_hw_reverse_bits(channelSel, 8); + +		txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); +		if (freq == 2484) { + +			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, +				  txctl | AR_PHY_CCK_TX_CTRL_JAPAN); +		} else { +			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, +				  txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); +		} + +	} else if ((freq % 20) == 0 && freq >= 5120) { +		channelSel = +		    ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); +		aModeRefSel = ath9k_hw_reverse_bits(1, 2); +	} else if ((freq % 10) == 0) { +		channelSel = +		    ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); +		if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) +			aModeRefSel = ath9k_hw_reverse_bits(2, 2); +		else +			aModeRefSel = ath9k_hw_reverse_bits(1, 2); +	} else if ((freq % 5) == 0) { +		channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); +		aModeRefSel = ath9k_hw_reverse_bits(1, 2); +	} else { +		ath_print(common, ATH_DBG_FATAL, +			  "Invalid channel %u MHz\n", freq); +		return -EINVAL; +	} + +	ar5008_hw_force_bias(ah, freq); + +	reg32 = +	    (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | +	    (1 << 5) | 0x1; + +	REG_WRITE(ah, AR_PHY(0x37), reg32); + +	ah->curchan = chan; +	ah->curchan_rad_index = -1; + +	return 0; +} + +/** + * ar5008_hw_spur_mitigate - convert baseband spur frequency for external radios + * @ah: atheros hardware structure + * @chan: + * + * For non single-chip solutions. Converts to baseband spur frequency given the + * input channel frequency and compute register settings below. + */ +static void ar5008_hw_spur_mitigate(struct ath_hw *ah, +				    struct ath9k_channel *chan) +{ +	int bb_spur = AR_NO_SPUR; +	int bin, cur_bin; +	int spur_freq_sd; +	int spur_delta_phase; +	int denominator; +	int upper, lower, cur_vit_mask; +	int tmp, new; +	int i; +	int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, +			  AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 +	}; +	int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, +			 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 +	}; +	int inc[4] = { 0, 100, 0, 0 }; + +	int8_t mask_m[123]; +	int8_t mask_p[123]; +	int8_t mask_amt; +	int tmp_mask; +	int cur_bb_spur; +	bool is2GHz = IS_CHAN_2GHZ(chan); + +	memset(&mask_m, 0, sizeof(int8_t) * 123); +	memset(&mask_p, 0, sizeof(int8_t) * 123); + +	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { +		cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); +		if (AR_NO_SPUR == cur_bb_spur) +			break; +		cur_bb_spur = cur_bb_spur - (chan->channel * 10); +		if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { +			bb_spur = cur_bb_spur; +			break; +		} +	} + +	if (AR_NO_SPUR == bb_spur) +		return; + +	bin = bb_spur * 32; + +	tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); +	new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | +		     AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | +		     AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | +		     AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); + +	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); + +	new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | +	       AR_PHY_SPUR_REG_ENABLE_MASK_PPM | +	       AR_PHY_SPUR_REG_MASK_RATE_SELECT | +	       AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | +	       SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); +	REG_WRITE(ah, AR_PHY_SPUR_REG, new); + +	spur_delta_phase = ((bb_spur * 524288) / 100) & +		AR_PHY_TIMING11_SPUR_DELTA_PHASE; + +	denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; +	spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; + +	new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | +	       SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | +	       SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); +	REG_WRITE(ah, AR_PHY_TIMING11, new); + +	cur_bin = -6000; +	upper = bin + 100; +	lower = bin - 100; + +	for (i = 0; i < 4; i++) { +		int pilot_mask = 0; +		int chan_mask = 0; +		int bp = 0; +		for (bp = 0; bp < 30; bp++) { +			if ((cur_bin > lower) && (cur_bin < upper)) { +				pilot_mask = pilot_mask | 0x1 << bp; +				chan_mask = chan_mask | 0x1 << bp; +			} +			cur_bin += 100; +		} +		cur_bin += inc[i]; +		REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); +		REG_WRITE(ah, chan_mask_reg[i], chan_mask); +	} + +	cur_vit_mask = 6100; +	upper = bin + 120; +	lower = bin - 120; + +	for (i = 0; i < 123; i++) { +		if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + +			/* workaround for gcc bug #37014 */ +			volatile int tmp_v = abs(cur_vit_mask - bin); + +			if (tmp_v < 75) +				mask_amt = 1; +			else +				mask_amt = 0; +			if (cur_vit_mask < 0) +				mask_m[abs(cur_vit_mask / 100)] = mask_amt; +			else +				mask_p[cur_vit_mask / 100] = mask_amt; +		} +		cur_vit_mask -= 100; +	} + +	tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) +		| (mask_m[48] << 26) | (mask_m[49] << 24) +		| (mask_m[50] << 22) | (mask_m[51] << 20) +		| (mask_m[52] << 18) | (mask_m[53] << 16) +		| (mask_m[54] << 14) | (mask_m[55] << 12) +		| (mask_m[56] << 10) | (mask_m[57] << 8) +		| (mask_m[58] << 6) | (mask_m[59] << 4) +		| (mask_m[60] << 2) | (mask_m[61] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); +	REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + +	tmp_mask = (mask_m[31] << 28) +		| (mask_m[32] << 26) | (mask_m[33] << 24) +		| (mask_m[34] << 22) | (mask_m[35] << 20) +		| (mask_m[36] << 18) | (mask_m[37] << 16) +		| (mask_m[48] << 14) | (mask_m[39] << 12) +		| (mask_m[40] << 10) | (mask_m[41] << 8) +		| (mask_m[42] << 6) | (mask_m[43] << 4) +		| (mask_m[44] << 2) | (mask_m[45] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + +	tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) +		| (mask_m[18] << 26) | (mask_m[18] << 24) +		| (mask_m[20] << 22) | (mask_m[20] << 20) +		| (mask_m[22] << 18) | (mask_m[22] << 16) +		| (mask_m[24] << 14) | (mask_m[24] << 12) +		| (mask_m[25] << 10) | (mask_m[26] << 8) +		| (mask_m[27] << 6) | (mask_m[28] << 4) +		| (mask_m[29] << 2) | (mask_m[30] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + +	tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) +		| (mask_m[2] << 26) | (mask_m[3] << 24) +		| (mask_m[4] << 22) | (mask_m[5] << 20) +		| (mask_m[6] << 18) | (mask_m[7] << 16) +		| (mask_m[8] << 14) | (mask_m[9] << 12) +		| (mask_m[10] << 10) | (mask_m[11] << 8) +		| (mask_m[12] << 6) | (mask_m[13] << 4) +		| (mask_m[14] << 2) | (mask_m[15] << 0); +	REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + +	tmp_mask = (mask_p[15] << 28) +		| (mask_p[14] << 26) | (mask_p[13] << 24) +		| (mask_p[12] << 22) | (mask_p[11] << 20) +		| (mask_p[10] << 18) | (mask_p[9] << 16) +		| (mask_p[8] << 14) | (mask_p[7] << 12) +		| (mask_p[6] << 10) | (mask_p[5] << 8) +		| (mask_p[4] << 6) | (mask_p[3] << 4) +		| (mask_p[2] << 2) | (mask_p[1] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + +	tmp_mask = (mask_p[30] << 28) +		| (mask_p[29] << 26) | (mask_p[28] << 24) +		| (mask_p[27] << 22) | (mask_p[26] << 20) +		| (mask_p[25] << 18) | (mask_p[24] << 16) +		| (mask_p[23] << 14) | (mask_p[22] << 12) +		| (mask_p[21] << 10) | (mask_p[20] << 8) +		| (mask_p[19] << 6) | (mask_p[18] << 4) +		| (mask_p[17] << 2) | (mask_p[16] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + +	tmp_mask = (mask_p[45] << 28) +		| (mask_p[44] << 26) | (mask_p[43] << 24) +		| (mask_p[42] << 22) | (mask_p[41] << 20) +		| (mask_p[40] << 18) | (mask_p[39] << 16) +		| (mask_p[38] << 14) | (mask_p[37] << 12) +		| (mask_p[36] << 10) | (mask_p[35] << 8) +		| (mask_p[34] << 6) | (mask_p[33] << 4) +		| (mask_p[32] << 2) | (mask_p[31] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + +	tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) +		| (mask_p[59] << 26) | (mask_p[58] << 24) +		| (mask_p[57] << 22) | (mask_p[56] << 20) +		| (mask_p[55] << 18) | (mask_p[54] << 16) +		| (mask_p[53] << 14) | (mask_p[52] << 12) +		| (mask_p[51] << 10) | (mask_p[50] << 8) +		| (mask_p[49] << 6) | (mask_p[48] << 4) +		| (mask_p[47] << 2) | (mask_p[46] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); +} + +/** + * ar5008_hw_rf_alloc_ext_banks - allocates banks for external radio programming + * @ah: atheros hardware structure + * + * Only required for older devices with external AR2133/AR5133 radios. + */ +static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) +{ +#define ATH_ALLOC_BANK(bank, size) do { \ +		bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ +		if (!bank) { \ +			ath_print(common, ATH_DBG_FATAL, \ +				  "Cannot allocate RF banks\n"); \ +			return -ENOMEM; \ +		} \ +	} while (0); + +	struct ath_common *common = ath9k_hw_common(ah); + +	BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + +	ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); +	ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); +	ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows); +	ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows); +	ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows); +	ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows); +	ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows); +	ATH_ALLOC_BANK(ah->addac5416_21, +		       ah->iniAddac.ia_rows * ah->iniAddac.ia_columns); +	ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows); + +	return 0; +#undef ATH_ALLOC_BANK +} + + +/** + * ar5008_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers + * @ah: atheros hardware struture + * For the external AR2133/AR5133 radios banks. + */ +static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah) +{ +#define ATH_FREE_BANK(bank) do { \ +		kfree(bank); \ +		bank = NULL; \ +	} while (0); + +	BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + +	ATH_FREE_BANK(ah->analogBank0Data); +	ATH_FREE_BANK(ah->analogBank1Data); +	ATH_FREE_BANK(ah->analogBank2Data); +	ATH_FREE_BANK(ah->analogBank3Data); +	ATH_FREE_BANK(ah->analogBank6Data); +	ATH_FREE_BANK(ah->analogBank6TPCData); +	ATH_FREE_BANK(ah->analogBank7Data); +	ATH_FREE_BANK(ah->addac5416_21); +	ATH_FREE_BANK(ah->bank6Temp); + +#undef ATH_FREE_BANK +} + +/* * + * ar5008_hw_set_rf_regs - programs rf registers based on EEPROM + * @ah: atheros hardware structure + * @chan: + * @modesIndex: + * + * Used for the external AR2133/AR5133 radios. + * + * Reads the EEPROM header info from the device structure and programs + * all rf registers. This routine requires access to the analog + * rf device. This is not required for single-chip devices. + */ +static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, +				  struct ath9k_channel *chan, +				  u16 modesIndex) +{ +	u32 eepMinorRev; +	u32 ob5GHz = 0, db5GHz = 0; +	u32 ob2GHz = 0, db2GHz = 0; +	int regWrites = 0; + +	/* +	 * Software does not need to program bank data +	 * for single chip devices, that is AR9280 or anything +	 * after that. +	 */ +	if (AR_SREV_9280_10_OR_LATER(ah)) +		return true; + +	/* Setup rf parameters */ +	eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); + +	/* Setup Bank 0 Write */ +	RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); + +	/* Setup Bank 1 Write */ +	RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); + +	/* Setup Bank 2 Write */ +	RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); + +	/* Setup Bank 6 Write */ +	RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, +		      modesIndex); +	{ +		int i; +		for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) { +			ah->analogBank6Data[i] = +			    INI_RA(&ah->iniBank6TPC, i, modesIndex); +		} +	} + +	/* Only the 5 or 2 GHz OB/DB need to be set for a mode */ +	if (eepMinorRev >= 2) { +		if (IS_CHAN_2GHZ(chan)) { +			ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); +			db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2); +			ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, +						       ob2GHz, 3, 197, 0); +			ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, +						       db2GHz, 3, 194, 0); +		} else { +			ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5); +			db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5); +			ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, +						       ob5GHz, 3, 203, 0); +			ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, +						       db5GHz, 3, 200, 0); +		} +	} + +	/* Setup Bank 7 Setup */ +	RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); + +	/* Write Analog registers */ +	REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, +			   regWrites); +	REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, +			   regWrites); +	REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data, +			   regWrites); +	REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data, +			   regWrites); +	REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data, +			   regWrites); +	REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data, +			   regWrites); + +	return true; +} + +static void ar5008_hw_init_bb(struct ath_hw *ah, +			      struct ath9k_channel *chan) +{ +	u32 synthDelay; + +	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; +	if (IS_CHAN_B(chan)) +		synthDelay = (4 * synthDelay) / 22; +	else +		synthDelay /= 10; + +	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + +	udelay(synthDelay + BASE_ACTIVATE_DELAY); +} + +static void ar5008_hw_init_chain_masks(struct ath_hw *ah) +{ +	int rx_chainmask, tx_chainmask; + +	rx_chainmask = ah->rxchainmask; +	tx_chainmask = ah->txchainmask; + +	ENABLE_REGWRITE_BUFFER(ah); + +	switch (rx_chainmask) { +	case 0x5: +		DISABLE_REGWRITE_BUFFER(ah); +		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, +			    AR_PHY_SWAP_ALT_CHAIN); +		ENABLE_REGWRITE_BUFFER(ah); +	case 0x3: +		if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) { +			REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); +			REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); +			break; +		} +	case 0x1: +	case 0x2: +	case 0x7: +		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); +		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); +		break; +	default: +		break; +	} + +	REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); + +	if (tx_chainmask == 0x5) { +		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, +			    AR_PHY_SWAP_ALT_CHAIN); +	} +	if (AR_SREV_9100(ah)) +		REG_WRITE(ah, AR_PHY_ANALOG_SWAP, +			  REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); +} + +static void ar5008_hw_override_ini(struct ath_hw *ah, +				   struct ath9k_channel *chan) +{ +	u32 val; + +	/* +	 * Set the RX_ABORT and RX_DIS and clear if off only after +	 * RXE is set for MAC. This prevents frames with corrupted +	 * descriptor status. +	 */ +	REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); + +	if (AR_SREV_9280_10_OR_LATER(ah)) { +		val = REG_READ(ah, AR_PCU_MISC_MODE2); + +		if (!AR_SREV_9271(ah)) +			val &= ~AR_PCU_MISC_MODE2_HWWAR1; + +		if (AR_SREV_9287_10_OR_LATER(ah)) +			val = val & (~AR_PCU_MISC_MODE2_HWWAR2); + +		REG_WRITE(ah, AR_PCU_MISC_MODE2, val); +	} + +	if (!AR_SREV_5416_20_OR_LATER(ah) || +	    AR_SREV_9280_10_OR_LATER(ah)) +		return; +	/* +	 * Disable BB clock gating +	 * Necessary to avoid issues on AR5416 2.0 +	 */ +	REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); + +	/* +	 * Disable RIFS search on some chips to avoid baseband +	 * hang issues. +	 */ +	if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { +		val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS); +		val &= ~AR_PHY_RIFS_INIT_DELAY; +		REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); +	} +} + +static void ar5008_hw_set_channel_regs(struct ath_hw *ah, +				       struct ath9k_channel *chan) +{ +	u32 phymode; +	u32 enableDacFifo = 0; + +	if (AR_SREV_9285_10_OR_LATER(ah)) +		enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) & +					 AR_PHY_FC_ENABLE_DAC_FIFO); + +	phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 +		| AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo; + +	if (IS_CHAN_HT40(chan)) { +		phymode |= AR_PHY_FC_DYN2040_EN; + +		if ((chan->chanmode == CHANNEL_A_HT40PLUS) || +		    (chan->chanmode == CHANNEL_G_HT40PLUS)) +			phymode |= AR_PHY_FC_DYN2040_PRI_CH; + +	} +	REG_WRITE(ah, AR_PHY_TURBO, phymode); + +	ath9k_hw_set11nmac2040(ah); + +	ENABLE_REGWRITE_BUFFER(ah); + +	REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); +	REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +} + + +static int ar5008_hw_process_ini(struct ath_hw *ah, +				 struct ath9k_channel *chan) +{ +	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); +	int i, regWrites = 0; +	struct ieee80211_channel *channel = chan->chan; +	u32 modesIndex, freqIndex; + +	switch (chan->chanmode) { +	case CHANNEL_A: +	case CHANNEL_A_HT20: +		modesIndex = 1; +		freqIndex = 1; +		break; +	case CHANNEL_A_HT40PLUS: +	case CHANNEL_A_HT40MINUS: +		modesIndex = 2; +		freqIndex = 1; +		break; +	case CHANNEL_G: +	case CHANNEL_G_HT20: +	case CHANNEL_B: +		modesIndex = 4; +		freqIndex = 2; +		break; +	case CHANNEL_G_HT40PLUS: +	case CHANNEL_G_HT40MINUS: +		modesIndex = 3; +		freqIndex = 2; +		break; + +	default: +		return -EINVAL; +	} + +	if (AR_SREV_9287_12_OR_LATER(ah)) { +		/* Enable ASYNC FIFO */ +		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, +				AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); +		REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); +		REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, +				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); +		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, +				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); +	} + +	/* +	 * Set correct baseband to analog shift setting to +	 * access analog chips. +	 */ +	REG_WRITE(ah, AR_PHY(0), 0x00000007); + +	/* Write ADDAC shifts */ +	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); +	ah->eep_ops->set_addac(ah, chan); + +	if (AR_SREV_5416_22_OR_LATER(ah)) { +		REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); +	} else { +		struct ar5416IniArray temp; +		u32 addacSize = +			sizeof(u32) * ah->iniAddac.ia_rows * +			ah->iniAddac.ia_columns; + +		/* For AR5416 2.0/2.1 */ +		memcpy(ah->addac5416_21, +		       ah->iniAddac.ia_array, addacSize); + +		/* override CLKDRV value at [row, column] = [31, 1] */ +		(ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; + +		temp.ia_array = ah->addac5416_21; +		temp.ia_columns = ah->iniAddac.ia_columns; +		temp.ia_rows = ah->iniAddac.ia_rows; +		REG_WRITE_ARRAY(&temp, 1, regWrites); +	} + +	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); + +	ENABLE_REGWRITE_BUFFER(ah); + +	for (i = 0; i < ah->iniModes.ia_rows; i++) { +		u32 reg = INI_RA(&ah->iniModes, i, 0); +		u32 val = INI_RA(&ah->iniModes, i, modesIndex); + +		if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup) +			val &= ~AR_AN_TOP2_PWDCLKIND; + +		REG_WRITE(ah, reg, val); + +		if (reg >= 0x7800 && reg < 0x78a0 +		    && ah->config.analog_shiftreg) { +			udelay(100); +		} + +		DO_DELAY(regWrites); +	} + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); + +	if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah)) +		REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); + +	if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) || +	    AR_SREV_9287_10_OR_LATER(ah)) +		REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); + +	if (AR_SREV_9271_10(ah)) +		REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, +				modesIndex, regWrites); + +	ENABLE_REGWRITE_BUFFER(ah); + +	/* Write common array parameters */ +	for (i = 0; i < ah->iniCommon.ia_rows; i++) { +		u32 reg = INI_RA(&ah->iniCommon, i, 0); +		u32 val = INI_RA(&ah->iniCommon, i, 1); + +		REG_WRITE(ah, reg, val); + +		if (reg >= 0x7800 && reg < 0x78a0 +		    && ah->config.analog_shiftreg) { +			udelay(100); +		} + +		DO_DELAY(regWrites); +	} + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); + +	if (AR_SREV_9271(ah)) { +		if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) +			REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271, +					modesIndex, regWrites); +		else +			REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, +					modesIndex, regWrites); +	} + +	REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); + +	if (IS_CHAN_A_FAST_CLOCK(ah, chan)) { +		REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, +				regWrites); +	} + +	ar5008_hw_override_ini(ah, chan); +	ar5008_hw_set_channel_regs(ah, chan); +	ar5008_hw_init_chain_masks(ah); +	ath9k_olc_init(ah); + +	/* Set TX power */ +	ah->eep_ops->set_txpower(ah, chan, +				 ath9k_regd_get_ctl(regulatory, chan), +				 channel->max_antenna_gain * 2, +				 channel->max_power * 2, +				 min((u32) MAX_RATE_POWER, +				 (u32) regulatory->power_limit)); + +	/* Write analog registers */ +	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { +		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, +			  "ar5416SetRfRegs failed\n"); +		return -EIO; +	} + +	return 0; +} + +static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) +{ +	u32 rfMode = 0; + +	if (chan == NULL) +		return; + +	rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) +		? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; + +	if (!AR_SREV_9280_10_OR_LATER(ah)) +		rfMode |= (IS_CHAN_5GHZ(chan)) ? +			AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; + +	if (IS_CHAN_A_FAST_CLOCK(ah, chan)) +		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); + +	REG_WRITE(ah, AR_PHY_MODE, rfMode); +} + +static void ar5008_hw_mark_phy_inactive(struct ath_hw *ah) +{ +	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); +} + +static void ar5008_hw_set_delta_slope(struct ath_hw *ah, +				      struct ath9k_channel *chan) +{ +	u32 coef_scaled, ds_coef_exp, ds_coef_man; +	u32 clockMhzScaled = 0x64000000; +	struct chan_centers centers; + +	if (IS_CHAN_HALF_RATE(chan)) +		clockMhzScaled = clockMhzScaled >> 1; +	else if (IS_CHAN_QUARTER_RATE(chan)) +		clockMhzScaled = clockMhzScaled >> 2; + +	ath9k_hw_get_channel_centers(ah, chan, ¢ers); +	coef_scaled = clockMhzScaled / centers.synth_center; + +	ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, +				      &ds_coef_exp); + +	REG_RMW_FIELD(ah, AR_PHY_TIMING3, +		      AR_PHY_TIMING3_DSC_MAN, ds_coef_man); +	REG_RMW_FIELD(ah, AR_PHY_TIMING3, +		      AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); + +	coef_scaled = (9 * coef_scaled) / 10; + +	ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, +				      &ds_coef_exp); + +	REG_RMW_FIELD(ah, AR_PHY_HALFGI, +		      AR_PHY_HALFGI_DSC_MAN, ds_coef_man); +	REG_RMW_FIELD(ah, AR_PHY_HALFGI, +		      AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); +} + +static bool ar5008_hw_rfbus_req(struct ath_hw *ah) +{ +	REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); +	return ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, +			   AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT); +} + +static void ar5008_hw_rfbus_done(struct ath_hw *ah) +{ +	u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; +	if (IS_CHAN_B(ah->curchan)) +		synthDelay = (4 * synthDelay) / 22; +	else +		synthDelay /= 10; + +	udelay(synthDelay + BASE_ACTIVATE_DELAY); + +	REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); +} + +static void ar5008_hw_enable_rfkill(struct ath_hw *ah) +{ +	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, +		    AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); + +	REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, +		    AR_GPIO_INPUT_MUX2_RFSILENT); + +	ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); +	REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); +} + +static void ar5008_restore_chainmask(struct ath_hw *ah) +{ +	int rx_chainmask = ah->rxchainmask; + +	if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { +		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); +		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); +	} +} + +static void ar5008_set_diversity(struct ath_hw *ah, bool value) +{ +	u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); +	if (value) +		v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; +	else +		v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; +	REG_WRITE(ah, AR_PHY_CCK_DETECT, v); +} + +static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah, +					 struct ath9k_channel *chan) +{ +	if (chan && IS_CHAN_5GHZ(chan)) +		return 0x1450; +	return 0x1458; +} + +static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah, +					 struct ath9k_channel *chan) +{ +	u32 pll; + +	pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); + +	if (chan && IS_CHAN_HALF_RATE(chan)) +		pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); +	else if (chan && IS_CHAN_QUARTER_RATE(chan)) +		pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); + +	if (chan && IS_CHAN_5GHZ(chan)) +		pll |= SM(0x50, AR_RTC_9160_PLL_DIV); +	else +		pll |= SM(0x58, AR_RTC_9160_PLL_DIV); + +	return pll; +} + +static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah, +					 struct ath9k_channel *chan) +{ +	u32 pll; + +	pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; + +	if (chan && IS_CHAN_HALF_RATE(chan)) +		pll |= SM(0x1, AR_RTC_PLL_CLKSEL); +	else if (chan && IS_CHAN_QUARTER_RATE(chan)) +		pll |= SM(0x2, AR_RTC_PLL_CLKSEL); + +	if (chan && IS_CHAN_5GHZ(chan)) +		pll |= SM(0xa, AR_RTC_PLL_DIV); +	else +		pll |= SM(0xb, AR_RTC_PLL_DIV); + +	return pll; +} + +static bool ar5008_hw_ani_control(struct ath_hw *ah, +				  enum ath9k_ani_cmd cmd, int param) +{ +	struct ar5416AniState *aniState = ah->curani; +	struct ath_common *common = ath9k_hw_common(ah); + +	switch (cmd & ah->ani_function) { +	case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ +		u32 level = param; + +		if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { +			ath_print(common, ATH_DBG_ANI, +				  "level out of range (%u > %u)\n", +				  level, +				  (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); +			return false; +		} + +		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, +			      AR_PHY_DESIRED_SZ_TOT_DES, +			      ah->totalSizeDesired[level]); +		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, +			      AR_PHY_AGC_CTL1_COARSE_LOW, +			      ah->coarse_low[level]); +		REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, +			      AR_PHY_AGC_CTL1_COARSE_HIGH, +			      ah->coarse_high[level]); +		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, +			      AR_PHY_FIND_SIG_FIRPWR, +			      ah->firpwr[level]); + +		if (level > aniState->noiseImmunityLevel) +			ah->stats.ast_ani_niup++; +		else if (level < aniState->noiseImmunityLevel) +			ah->stats.ast_ani_nidown++; +		aniState->noiseImmunityLevel = level; +		break; +	} +	case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ +		const int m1ThreshLow[] = { 127, 50 }; +		const int m2ThreshLow[] = { 127, 40 }; +		const int m1Thresh[] = { 127, 0x4d }; +		const int m2Thresh[] = { 127, 0x40 }; +		const int m2CountThr[] = { 31, 16 }; +		const int m2CountThrLow[] = { 63, 48 }; +		u32 on = param ? 1 : 0; + +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +			      AR_PHY_SFCORR_LOW_M1_THRESH_LOW, +			      m1ThreshLow[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +			      AR_PHY_SFCORR_LOW_M2_THRESH_LOW, +			      m2ThreshLow[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR, +			      AR_PHY_SFCORR_M1_THRESH, +			      m1Thresh[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR, +			      AR_PHY_SFCORR_M2_THRESH, +			      m2Thresh[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR, +			      AR_PHY_SFCORR_M2COUNT_THR, +			      m2CountThr[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +			      AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, +			      m2CountThrLow[on]); + +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +			      AR_PHY_SFCORR_EXT_M1_THRESH_LOW, +			      m1ThreshLow[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +			      AR_PHY_SFCORR_EXT_M2_THRESH_LOW, +			      m2ThreshLow[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +			      AR_PHY_SFCORR_EXT_M1_THRESH, +			      m1Thresh[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +			      AR_PHY_SFCORR_EXT_M2_THRESH, +			      m2Thresh[on]); + +		if (on) +			REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, +				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); +		else +			REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, +				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + +		if (!on != aniState->ofdmWeakSigDetectOff) { +			if (on) +				ah->stats.ast_ani_ofdmon++; +			else +				ah->stats.ast_ani_ofdmoff++; +			aniState->ofdmWeakSigDetectOff = !on; +		} +		break; +	} +	case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ +		const int weakSigThrCck[] = { 8, 6 }; +		u32 high = param ? 1 : 0; + +		REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, +			      AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, +			      weakSigThrCck[high]); +		if (high != aniState->cckWeakSigThreshold) { +			if (high) +				ah->stats.ast_ani_cckhigh++; +			else +				ah->stats.ast_ani_ccklow++; +			aniState->cckWeakSigThreshold = high; +		} +		break; +	} +	case ATH9K_ANI_FIRSTEP_LEVEL:{ +		const int firstep[] = { 0, 4, 8 }; +		u32 level = param; + +		if (level >= ARRAY_SIZE(firstep)) { +			ath_print(common, ATH_DBG_ANI, +				  "level out of range (%u > %u)\n", +				  level, +				  (unsigned) ARRAY_SIZE(firstep)); +			return false; +		} +		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, +			      AR_PHY_FIND_SIG_FIRSTEP, +			      firstep[level]); +		if (level > aniState->firstepLevel) +			ah->stats.ast_ani_stepup++; +		else if (level < aniState->firstepLevel) +			ah->stats.ast_ani_stepdown++; +		aniState->firstepLevel = level; +		break; +	} +	case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ +		const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; +		u32 level = param; + +		if (level >= ARRAY_SIZE(cycpwrThr1)) { +			ath_print(common, ATH_DBG_ANI, +				  "level out of range (%u > %u)\n", +				  level, +				  (unsigned) ARRAY_SIZE(cycpwrThr1)); +			return false; +		} +		REG_RMW_FIELD(ah, AR_PHY_TIMING5, +			      AR_PHY_TIMING5_CYCPWR_THR1, +			      cycpwrThr1[level]); +		if (level > aniState->spurImmunityLevel) +			ah->stats.ast_ani_spurup++; +		else if (level < aniState->spurImmunityLevel) +			ah->stats.ast_ani_spurdown++; +		aniState->spurImmunityLevel = level; +		break; +	} +	case ATH9K_ANI_PRESENT: +		break; +	default: +		ath_print(common, ATH_DBG_ANI, +			  "invalid cmd %u\n", cmd); +		return false; +	} + +	ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); +	ath_print(common, ATH_DBG_ANI, +		  "noiseImmunityLevel=%d, spurImmunityLevel=%d, " +		  "ofdmWeakSigDetectOff=%d\n", +		  aniState->noiseImmunityLevel, +		  aniState->spurImmunityLevel, +		  !aniState->ofdmWeakSigDetectOff); +	ath_print(common, ATH_DBG_ANI, +		  "cckWeakSigThreshold=%d, " +		  "firstepLevel=%d, listenTime=%d\n", +		  aniState->cckWeakSigThreshold, +		  aniState->firstepLevel, +		  aniState->listenTime); +	ath_print(common, ATH_DBG_ANI, +		"cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", +		aniState->cycleCount, +		aniState->ofdmPhyErrCount, +		aniState->cckPhyErrCount); + +	return true; +} + +static void ar5008_hw_do_getnf(struct ath_hw *ah, +			      int16_t nfarray[NUM_NF_READINGS]) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	int16_t nf; + +	nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ctl] [chain 0] is %d\n", nf); +	nfarray[0] = nf; + +	nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ctl] [chain 1] is %d\n", nf); +	nfarray[1] = nf; + +	nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ctl] [chain 2] is %d\n", nf); +	nfarray[2] = nf; + +	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ext] [chain 0] is %d\n", nf); +	nfarray[3] = nf; + +	nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ext] [chain 1] is %d\n", nf); +	nfarray[4] = nf; + +	nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ext] [chain 2] is %d\n", nf); +	nfarray[5] = nf; +} + +static void ar5008_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) +{ +	struct ath9k_nfcal_hist *h; +	int i, j; +	int32_t val; +	const u32 ar5416_cca_regs[6] = { +		AR_PHY_CCA, +		AR_PHY_CH1_CCA, +		AR_PHY_CH2_CCA, +		AR_PHY_EXT_CCA, +		AR_PHY_CH1_EXT_CCA, +		AR_PHY_CH2_EXT_CCA +	}; +	u8 chainmask, rx_chain_status; + +	rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); +	if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) +		chainmask = 0x9; +	else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { +		if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) +			chainmask = 0x1B; +		else +			chainmask = 0x09; +	} else { +		if (rx_chain_status & 0x4) +			chainmask = 0x3F; +		else if (rx_chain_status & 0x2) +			chainmask = 0x1B; +		else +			chainmask = 0x09; +	} + +	h = ah->nfCalHist; + +	for (i = 0; i < NUM_NF_READINGS; i++) { +		if (chainmask & (1 << i)) { +			val = REG_READ(ah, ar5416_cca_regs[i]); +			val &= 0xFFFFFE00; +			val |= (((u32) (h[i].privNF) << 1) & 0x1ff); +			REG_WRITE(ah, ar5416_cca_regs[i], val); +		} +	} + +	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, +		    AR_PHY_AGC_CONTROL_ENABLE_NF); +	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, +		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF); +	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + +	for (j = 0; j < 5; j++) { +		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & +		     AR_PHY_AGC_CONTROL_NF) == 0) +			break; +		udelay(50); +	} + +	ENABLE_REGWRITE_BUFFER(ah); + +	for (i = 0; i < NUM_NF_READINGS; i++) { +		if (chainmask & (1 << i)) { +			val = REG_READ(ah, ar5416_cca_regs[i]); +			val &= 0xFFFFFE00; +			val |= (((u32) (-50) << 1) & 0x1ff); +			REG_WRITE(ah, ar5416_cca_regs[i], val); +		} +	} + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +} + +void ar5008_hw_attach_phy_ops(struct ath_hw *ah) +{ +	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + +	priv_ops->rf_set_freq = ar5008_hw_set_channel; +	priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate; + +	priv_ops->rf_alloc_ext_banks = ar5008_hw_rf_alloc_ext_banks; +	priv_ops->rf_free_ext_banks = ar5008_hw_rf_free_ext_banks; +	priv_ops->set_rf_regs = ar5008_hw_set_rf_regs; +	priv_ops->set_channel_regs = ar5008_hw_set_channel_regs; +	priv_ops->init_bb = ar5008_hw_init_bb; +	priv_ops->process_ini = ar5008_hw_process_ini; +	priv_ops->set_rfmode = ar5008_hw_set_rfmode; +	priv_ops->mark_phy_inactive = ar5008_hw_mark_phy_inactive; +	priv_ops->set_delta_slope = ar5008_hw_set_delta_slope; +	priv_ops->rfbus_req = ar5008_hw_rfbus_req; +	priv_ops->rfbus_done = ar5008_hw_rfbus_done; +	priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; +	priv_ops->restore_chainmask = ar5008_restore_chainmask; +	priv_ops->set_diversity = ar5008_set_diversity; +	priv_ops->ani_control = ar5008_hw_ani_control; +	priv_ops->do_getnf = ar5008_hw_do_getnf; +	priv_ops->loadnf = ar5008_hw_loadnf; + +	if (AR_SREV_9100(ah)) +		priv_ops->compute_pll_control = ar9100_hw_compute_pll_control; +	else if (AR_SREV_9160_10_OR_LATER(ah)) +		priv_ops->compute_pll_control = ar9160_hw_compute_pll_control; +	else +		priv_ops->compute_pll_control = ar5008_hw_compute_pll_control; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h new file mode 100644 index 00000000000..0b94bd385b0 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h @@ -0,0 +1,1254 @@ + +static const u32 ar5416Common_9100[][2] = { +    { 0x0000000c, 0x00000000 }, +    { 0x00000030, 0x00020015 }, +    { 0x00000034, 0x00000005 }, +    { 0x00000040, 0x00000000 }, +    { 0x00000044, 0x00000008 }, +    { 0x00000048, 0x00000008 }, +    { 0x0000004c, 0x00000010 }, +    { 0x00000050, 0x00000000 }, +    { 0x00000054, 0x0000001f }, +    { 0x00000800, 0x00000000 }, +    { 0x00000804, 0x00000000 }, +    { 0x00000808, 0x00000000 }, +    { 0x0000080c, 0x00000000 }, +    { 0x00000810, 0x00000000 }, +    { 0x00000814, 0x00000000 }, +    { 0x00000818, 0x00000000 }, +    { 0x0000081c, 0x00000000 }, +    { 0x00000820, 0x00000000 }, +    { 0x00000824, 0x00000000 }, +    { 0x00001040, 0x002ffc0f }, +    { 0x00001044, 0x002ffc0f }, +    { 0x00001048, 0x002ffc0f }, +    { 0x0000104c, 0x002ffc0f }, +    { 0x00001050, 0x002ffc0f }, +    { 0x00001054, 0x002ffc0f }, +    { 0x00001058, 0x002ffc0f }, +    { 0x0000105c, 0x002ffc0f }, +    { 0x00001060, 0x002ffc0f }, +    { 0x00001064, 0x002ffc0f }, +    { 0x00001230, 0x00000000 }, +    { 0x00001270, 0x00000000 }, +    { 0x00001038, 0x00000000 }, +    { 0x00001078, 0x00000000 }, +    { 0x000010b8, 0x00000000 }, +    { 0x000010f8, 0x00000000 }, +    { 0x00001138, 0x00000000 }, +    { 0x00001178, 0x00000000 }, +    { 0x000011b8, 0x00000000 }, +    { 0x000011f8, 0x00000000 }, +    { 0x00001238, 0x00000000 }, +    { 0x00001278, 0x00000000 }, +    { 0x000012b8, 0x00000000 }, +    { 0x000012f8, 0x00000000 }, +    { 0x00001338, 0x00000000 }, +    { 0x00001378, 0x00000000 }, +    { 0x000013b8, 0x00000000 }, +    { 0x000013f8, 0x00000000 }, +    { 0x00001438, 0x00000000 }, +    { 0x00001478, 0x00000000 }, +    { 0x000014b8, 0x00000000 }, +    { 0x000014f8, 0x00000000 }, +    { 0x00001538, 0x00000000 }, +    { 0x00001578, 0x00000000 }, +    { 0x000015b8, 0x00000000 }, +    { 0x000015f8, 0x00000000 }, +    { 0x00001638, 0x00000000 }, +    { 0x00001678, 0x00000000 }, +    { 0x000016b8, 0x00000000 }, +    { 0x000016f8, 0x00000000 }, +    { 0x00001738, 0x00000000 }, +    { 0x00001778, 0x00000000 }, +    { 0x000017b8, 0x00000000 }, +    { 0x000017f8, 0x00000000 }, +    { 0x0000103c, 0x00000000 }, +    { 0x0000107c, 0x00000000 }, +    { 0x000010bc, 0x00000000 }, +    { 0x000010fc, 0x00000000 }, +    { 0x0000113c, 0x00000000 }, +    { 0x0000117c, 0x00000000 }, +    { 0x000011bc, 0x00000000 }, +    { 0x000011fc, 0x00000000 }, +    { 0x0000123c, 0x00000000 }, +    { 0x0000127c, 0x00000000 }, +    { 0x000012bc, 0x00000000 }, +    { 0x000012fc, 0x00000000 }, +    { 0x0000133c, 0x00000000 }, +    { 0x0000137c, 0x00000000 }, +    { 0x000013bc, 0x00000000 }, +    { 0x000013fc, 0x00000000 }, +    { 0x0000143c, 0x00000000 }, +    { 0x0000147c, 0x00000000 }, +    { 0x00020010, 0x00000003 }, +    { 0x00020038, 0x000004c2 }, +    { 0x00008004, 0x00000000 }, +    { 0x00008008, 0x00000000 }, +    { 0x0000800c, 0x00000000 }, +    { 0x00008018, 0x00000700 }, +    { 0x00008020, 0x00000000 }, +    { 0x00008038, 0x00000000 }, +    { 0x0000803c, 0x00000000 }, +    { 0x00008048, 0x40000000 }, +    { 0x00008054, 0x00004000 }, +    { 0x00008058, 0x00000000 }, +    { 0x0000805c, 0x000fc78f }, +    { 0x00008060, 0x0000000f }, +    { 0x00008064, 0x00000000 }, +    { 0x000080c0, 0x2a82301a }, +    { 0x000080c4, 0x05dc01e0 }, +    { 0x000080c8, 0x1f402710 }, +    { 0x000080cc, 0x01f40000 }, +    { 0x000080d0, 0x00001e00 }, +    { 0x000080d4, 0x00000000 }, +    { 0x000080d8, 0x00400000 }, +    { 0x000080e0, 0xffffffff }, +    { 0x000080e4, 0x0000ffff }, +    { 0x000080e8, 0x003f3f3f }, +    { 0x000080ec, 0x00000000 }, +    { 0x000080f0, 0x00000000 }, +    { 0x000080f4, 0x00000000 }, +    { 0x000080f8, 0x00000000 }, +    { 0x000080fc, 0x00020000 }, +    { 0x00008100, 0x00020000 }, +    { 0x00008104, 0x00000001 }, +    { 0x00008108, 0x00000052 }, +    { 0x0000810c, 0x00000000 }, +    { 0x00008110, 0x00000168 }, +    { 0x00008118, 0x000100aa }, +    { 0x0000811c, 0x00003210 }, +    { 0x00008120, 0x08f04800 }, +    { 0x00008124, 0x00000000 }, +    { 0x00008128, 0x00000000 }, +    { 0x0000812c, 0x00000000 }, +    { 0x00008130, 0x00000000 }, +    { 0x00008134, 0x00000000 }, +    { 0x00008138, 0x00000000 }, +    { 0x0000813c, 0x00000000 }, +    { 0x00008144, 0x00000000 }, +    { 0x00008168, 0x00000000 }, +    { 0x0000816c, 0x00000000 }, +    { 0x00008170, 0x32143320 }, +    { 0x00008174, 0xfaa4fa50 }, +    { 0x00008178, 0x00000100 }, +    { 0x0000817c, 0x00000000 }, +    { 0x000081c4, 0x00000000 }, +    { 0x000081d0, 0x00003210 }, +    { 0x000081ec, 0x00000000 }, +    { 0x000081f0, 0x00000000 }, +    { 0x000081f4, 0x00000000 }, +    { 0x000081f8, 0x00000000 }, +    { 0x000081fc, 0x00000000 }, +    { 0x00008200, 0x00000000 }, +    { 0x00008204, 0x00000000 }, +    { 0x00008208, 0x00000000 }, +    { 0x0000820c, 0x00000000 }, +    { 0x00008210, 0x00000000 }, +    { 0x00008214, 0x00000000 }, +    { 0x00008218, 0x00000000 }, +    { 0x0000821c, 0x00000000 }, +    { 0x00008220, 0x00000000 }, +    { 0x00008224, 0x00000000 }, +    { 0x00008228, 0x00000000 }, +    { 0x0000822c, 0x00000000 }, +    { 0x00008230, 0x00000000 }, +    { 0x00008234, 0x00000000 }, +    { 0x00008238, 0x00000000 }, +    { 0x0000823c, 0x00000000 }, +    { 0x00008240, 0x00100000 }, +    { 0x00008244, 0x0010f400 }, +    { 0x00008248, 0x00000100 }, +    { 0x0000824c, 0x0001e800 }, +    { 0x00008250, 0x00000000 }, +    { 0x00008254, 0x00000000 }, +    { 0x00008258, 0x00000000 }, +    { 0x0000825c, 0x400000ff }, +    { 0x00008260, 0x00080922 }, +    { 0x00008270, 0x00000000 }, +    { 0x00008274, 0x40000000 }, +    { 0x00008278, 0x003e4180 }, +    { 0x0000827c, 0x00000000 }, +    { 0x00008284, 0x0000002c }, +    { 0x00008288, 0x0000002c }, +    { 0x0000828c, 0x00000000 }, +    { 0x00008294, 0x00000000 }, +    { 0x00008298, 0x00000000 }, +    { 0x00008300, 0x00000000 }, +    { 0x00008304, 0x00000000 }, +    { 0x00008308, 0x00000000 }, +    { 0x0000830c, 0x00000000 }, +    { 0x00008310, 0x00000000 }, +    { 0x00008314, 0x00000000 }, +    { 0x00008318, 0x00000000 }, +    { 0x00008328, 0x00000000 }, +    { 0x0000832c, 0x00000007 }, +    { 0x00008330, 0x00000302 }, +    { 0x00008334, 0x00000e00 }, +    { 0x00008338, 0x00000000 }, +    { 0x0000833c, 0x00000000 }, +    { 0x00008340, 0x000107ff }, +    { 0x00009808, 0x00000000 }, +    { 0x0000980c, 0xad848e19 }, +    { 0x00009810, 0x7d14e000 }, +    { 0x00009814, 0x9c0a9f6b }, +    { 0x0000981c, 0x00000000 }, +    { 0x0000982c, 0x0000a000 }, +    { 0x00009830, 0x00000000 }, +    { 0x0000983c, 0x00200400 }, +    { 0x00009840, 0x206a01ae }, +    { 0x0000984c, 0x1284233c }, +    { 0x00009854, 0x00000859 }, +    { 0x00009900, 0x00000000 }, +    { 0x00009904, 0x00000000 }, +    { 0x00009908, 0x00000000 }, +    { 0x0000990c, 0x00000000 }, +    { 0x0000991c, 0x10000fff }, +    { 0x00009920, 0x05100000 }, +    { 0x0000a920, 0x05100000 }, +    { 0x0000b920, 0x05100000 }, +    { 0x00009928, 0x00000001 }, +    { 0x0000992c, 0x00000004 }, +    { 0x00009934, 0x1e1f2022 }, +    { 0x00009938, 0x0a0b0c0d }, +    { 0x0000993c, 0x00000000 }, +    { 0x00009948, 0x9280b212 }, +    { 0x0000994c, 0x00020028 }, +    { 0x0000c95c, 0x004b6a8e }, +    { 0x0000c968, 0x000003ce }, +    { 0x00009970, 0x190fb515 }, +    { 0x00009974, 0x00000000 }, +    { 0x00009978, 0x00000001 }, +    { 0x0000997c, 0x00000000 }, +    { 0x00009980, 0x00000000 }, +    { 0x00009984, 0x00000000 }, +    { 0x00009988, 0x00000000 }, +    { 0x0000998c, 0x00000000 }, +    { 0x00009990, 0x00000000 }, +    { 0x00009994, 0x00000000 }, +    { 0x00009998, 0x00000000 }, +    { 0x0000999c, 0x00000000 }, +    { 0x000099a0, 0x00000000 }, +    { 0x000099a4, 0x00000001 }, +    { 0x000099a8, 0x201fff00 }, +    { 0x000099ac, 0x006f0000 }, +    { 0x000099b0, 0x03051000 }, +    { 0x000099dc, 0x00000000 }, +    { 0x000099e0, 0x00000200 }, +    { 0x000099e4, 0xaaaaaaaa }, +    { 0x000099e8, 0x3c466478 }, +    { 0x000099ec, 0x0cc80caa }, +    { 0x000099fc, 0x00001042 }, +    { 0x00009b00, 0x00000000 }, +    { 0x00009b04, 0x00000001 }, +    { 0x00009b08, 0x00000002 }, +    { 0x00009b0c, 0x00000003 }, +    { 0x00009b10, 0x00000004 }, +    { 0x00009b14, 0x00000005 }, +    { 0x00009b18, 0x00000008 }, +    { 0x00009b1c, 0x00000009 }, +    { 0x00009b20, 0x0000000a }, +    { 0x00009b24, 0x0000000b }, +    { 0x00009b28, 0x0000000c }, +    { 0x00009b2c, 0x0000000d }, +    { 0x00009b30, 0x00000010 }, +    { 0x00009b34, 0x00000011 }, +    { 0x00009b38, 0x00000012 }, +    { 0x00009b3c, 0x00000013 }, +    { 0x00009b40, 0x00000014 }, +    { 0x00009b44, 0x00000015 }, +    { 0x00009b48, 0x00000018 }, +    { 0x00009b4c, 0x00000019 }, +    { 0x00009b50, 0x0000001a }, +    { 0x00009b54, 0x0000001b }, +    { 0x00009b58, 0x0000001c }, +    { 0x00009b5c, 0x0000001d }, +    { 0x00009b60, 0x00000020 }, +    { 0x00009b64, 0x00000021 }, +    { 0x00009b68, 0x00000022 }, +    { 0x00009b6c, 0x00000023 }, +    { 0x00009b70, 0x00000024 }, +    { 0x00009b74, 0x00000025 }, +    { 0x00009b78, 0x00000028 }, +    { 0x00009b7c, 0x00000029 }, +    { 0x00009b80, 0x0000002a }, +    { 0x00009b84, 0x0000002b }, +    { 0x00009b88, 0x0000002c }, +    { 0x00009b8c, 0x0000002d }, +    { 0x00009b90, 0x00000030 }, +    { 0x00009b94, 0x00000031 }, +    { 0x00009b98, 0x00000032 }, +    { 0x00009b9c, 0x00000033 }, +    { 0x00009ba0, 0x00000034 }, +    { 0x00009ba4, 0x00000035 }, +    { 0x00009ba8, 0x00000035 }, +    { 0x00009bac, 0x00000035 }, +    { 0x00009bb0, 0x00000035 }, +    { 0x00009bb4, 0x00000035 }, +    { 0x00009bb8, 0x00000035 }, +    { 0x00009bbc, 0x00000035 }, +    { 0x00009bc0, 0x00000035 }, +    { 0x00009bc4, 0x00000035 }, +    { 0x00009bc8, 0x00000035 }, +    { 0x00009bcc, 0x00000035 }, +    { 0x00009bd0, 0x00000035 }, +    { 0x00009bd4, 0x00000035 }, +    { 0x00009bd8, 0x00000035 }, +    { 0x00009bdc, 0x00000035 }, +    { 0x00009be0, 0x00000035 }, +    { 0x00009be4, 0x00000035 }, +    { 0x00009be8, 0x00000035 }, +    { 0x00009bec, 0x00000035 }, +    { 0x00009bf0, 0x00000035 }, +    { 0x00009bf4, 0x00000035 }, +    { 0x00009bf8, 0x00000010 }, +    { 0x00009bfc, 0x0000001a }, +    { 0x0000a210, 0x40806333 }, +    { 0x0000a214, 0x00106c10 }, +    { 0x0000a218, 0x009c4060 }, +    { 0x0000a220, 0x018830c6 }, +    { 0x0000a224, 0x00000400 }, +    { 0x0000a228, 0x001a0bb5 }, +    { 0x0000a22c, 0x00000000 }, +    { 0x0000a234, 0x20202020 }, +    { 0x0000a238, 0x20202020 }, +    { 0x0000a23c, 0x13c889ae }, +    { 0x0000a240, 0x38490a20 }, +    { 0x0000a244, 0x00007bb6 }, +    { 0x0000a248, 0x0fff3ffc }, +    { 0x0000a24c, 0x00000001 }, +    { 0x0000a250, 0x0000a000 }, +    { 0x0000a254, 0x00000000 }, +    { 0x0000a258, 0x0cc75380 }, +    { 0x0000a25c, 0x0f0f0f01 }, +    { 0x0000a260, 0xdfa91f01 }, +    { 0x0000a268, 0x00000001 }, +    { 0x0000a26c, 0x0ebae9c6 }, +    { 0x0000b26c, 0x0ebae9c6 }, +    { 0x0000c26c, 0x0ebae9c6 }, +    { 0x0000d270, 0x00820820 }, +    { 0x0000a278, 0x1ce739ce }, +    { 0x0000a27c, 0x050701ce }, +    { 0x0000a338, 0x00000000 }, +    { 0x0000a33c, 0x00000000 }, +    { 0x0000a340, 0x00000000 }, +    { 0x0000a344, 0x00000000 }, +    { 0x0000a348, 0x3fffffff }, +    { 0x0000a34c, 0x3fffffff }, +    { 0x0000a350, 0x3fffffff }, +    { 0x0000a354, 0x0003ffff }, +    { 0x0000a358, 0x79a8aa33 }, +    { 0x0000d35c, 0x07ffffef }, +    { 0x0000d360, 0x0fffffe7 }, +    { 0x0000d364, 0x17ffffe5 }, +    { 0x0000d368, 0x1fffffe4 }, +    { 0x0000d36c, 0x37ffffe3 }, +    { 0x0000d370, 0x3fffffe3 }, +    { 0x0000d374, 0x57ffffe3 }, +    { 0x0000d378, 0x5fffffe2 }, +    { 0x0000d37c, 0x7fffffe2 }, +    { 0x0000d380, 0x7f3c7bba }, +    { 0x0000d384, 0xf3307ff0 }, +    { 0x0000a388, 0x0c000000 }, +    { 0x0000a38c, 0x20202020 }, +    { 0x0000a390, 0x20202020 }, +    { 0x0000a394, 0x1ce739ce }, +    { 0x0000a398, 0x000001ce }, +    { 0x0000a39c, 0x00000001 }, +    { 0x0000a3a0, 0x00000000 }, +    { 0x0000a3a4, 0x00000000 }, +    { 0x0000a3a8, 0x00000000 }, +    { 0x0000a3ac, 0x00000000 }, +    { 0x0000a3b0, 0x00000000 }, +    { 0x0000a3b4, 0x00000000 }, +    { 0x0000a3b8, 0x00000000 }, +    { 0x0000a3bc, 0x00000000 }, +    { 0x0000a3c0, 0x00000000 }, +    { 0x0000a3c4, 0x00000000 }, +    { 0x0000a3c8, 0x00000246 }, +    { 0x0000a3cc, 0x20202020 }, +    { 0x0000a3d0, 0x20202020 }, +    { 0x0000a3d4, 0x20202020 }, +    { 0x0000a3dc, 0x1ce739ce }, +    { 0x0000a3e0, 0x000001ce }, +}; + +static const u32 ar5416Bank0_9100[][2] = { +    { 0x000098b0, 0x1e5795e5 }, +    { 0x000098e0, 0x02008020 }, +}; + +static const u32 ar5416BB_RfGain_9100[][3] = { +    { 0x00009a00, 0x00000000, 0x00000000 }, +    { 0x00009a04, 0x00000040, 0x00000040 }, +    { 0x00009a08, 0x00000080, 0x00000080 }, +    { 0x00009a0c, 0x000001a1, 0x00000141 }, +    { 0x00009a10, 0x000001e1, 0x00000181 }, +    { 0x00009a14, 0x00000021, 0x000001c1 }, +    { 0x00009a18, 0x00000061, 0x00000001 }, +    { 0x00009a1c, 0x00000168, 0x00000041 }, +    { 0x00009a20, 0x000001a8, 0x000001a8 }, +    { 0x00009a24, 0x000001e8, 0x000001e8 }, +    { 0x00009a28, 0x00000028, 0x00000028 }, +    { 0x00009a2c, 0x00000068, 0x00000068 }, +    { 0x00009a30, 0x00000189, 0x000000a8 }, +    { 0x00009a34, 0x000001c9, 0x00000169 }, +    { 0x00009a38, 0x00000009, 0x000001a9 }, +    { 0x00009a3c, 0x00000049, 0x000001e9 }, +    { 0x00009a40, 0x00000089, 0x00000029 }, +    { 0x00009a44, 0x00000170, 0x00000069 }, +    { 0x00009a48, 0x000001b0, 0x00000190 }, +    { 0x00009a4c, 0x000001f0, 0x000001d0 }, +    { 0x00009a50, 0x00000030, 0x00000010 }, +    { 0x00009a54, 0x00000070, 0x00000050 }, +    { 0x00009a58, 0x00000191, 0x00000090 }, +    { 0x00009a5c, 0x000001d1, 0x00000151 }, +    { 0x00009a60, 0x00000011, 0x00000191 }, +    { 0x00009a64, 0x00000051, 0x000001d1 }, +    { 0x00009a68, 0x00000091, 0x00000011 }, +    { 0x00009a6c, 0x000001b8, 0x00000051 }, +    { 0x00009a70, 0x000001f8, 0x00000198 }, +    { 0x00009a74, 0x00000038, 0x000001d8 }, +    { 0x00009a78, 0x00000078, 0x00000018 }, +    { 0x00009a7c, 0x00000199, 0x00000058 }, +    { 0x00009a80, 0x000001d9, 0x00000098 }, +    { 0x00009a84, 0x00000019, 0x00000159 }, +    { 0x00009a88, 0x00000059, 0x00000199 }, +    { 0x00009a8c, 0x00000099, 0x000001d9 }, +    { 0x00009a90, 0x000000d9, 0x00000019 }, +    { 0x00009a94, 0x000000f9, 0x00000059 }, +    { 0x00009a98, 0x000000f9, 0x00000099 }, +    { 0x00009a9c, 0x000000f9, 0x000000d9 }, +    { 0x00009aa0, 0x000000f9, 0x000000f9 }, +    { 0x00009aa4, 0x000000f9, 0x000000f9 }, +    { 0x00009aa8, 0x000000f9, 0x000000f9 }, +    { 0x00009aac, 0x000000f9, 0x000000f9 }, +    { 0x00009ab0, 0x000000f9, 0x000000f9 }, +    { 0x00009ab4, 0x000000f9, 0x000000f9 }, +    { 0x00009ab8, 0x000000f9, 0x000000f9 }, +    { 0x00009abc, 0x000000f9, 0x000000f9 }, +    { 0x00009ac0, 0x000000f9, 0x000000f9 }, +    { 0x00009ac4, 0x000000f9, 0x000000f9 }, +    { 0x00009ac8, 0x000000f9, 0x000000f9 }, +    { 0x00009acc, 0x000000f9, 0x000000f9 }, +    { 0x00009ad0, 0x000000f9, 0x000000f9 }, +    { 0x00009ad4, 0x000000f9, 0x000000f9 }, +    { 0x00009ad8, 0x000000f9, 0x000000f9 }, +    { 0x00009adc, 0x000000f9, 0x000000f9 }, +    { 0x00009ae0, 0x000000f9, 0x000000f9 }, +    { 0x00009ae4, 0x000000f9, 0x000000f9 }, +    { 0x00009ae8, 0x000000f9, 0x000000f9 }, +    { 0x00009aec, 0x000000f9, 0x000000f9 }, +    { 0x00009af0, 0x000000f9, 0x000000f9 }, +    { 0x00009af4, 0x000000f9, 0x000000f9 }, +    { 0x00009af8, 0x000000f9, 0x000000f9 }, +    { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const u32 ar5416Bank1_9100[][2] = { +    { 0x000098b0, 0x02108421}, +    { 0x000098ec, 0x00000008}, +}; + +static const u32 ar5416Bank2_9100[][2] = { +    { 0x000098b0, 0x0e73ff17}, +    { 0x000098e0, 0x00000420}, +}; + +static const u32 ar5416Bank3_9100[][3] = { +    { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const u32 ar5416Bank6_9100[][3] = { + +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00e00000, 0x00e00000 }, +    { 0x0000989c, 0x005e0000, 0x005e0000 }, +    { 0x0000989c, 0x00120000, 0x00120000 }, +    { 0x0000989c, 0x00620000, 0x00620000 }, +    { 0x0000989c, 0x00020000, 0x00020000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x005f0000, 0x005f0000 }, +    { 0x0000989c, 0x00870000, 0x00870000 }, +    { 0x0000989c, 0x00f90000, 0x00f90000 }, +    { 0x0000989c, 0x007b0000, 0x007b0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00f50000, 0x00f50000 }, +    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, +    { 0x0000989c, 0x00110000, 0x00110000 }, +    { 0x0000989c, 0x006100a8, 0x006100a8 }, +    { 0x0000989c, 0x004210a2, 0x004210a2 }, +    { 0x0000989c, 0x0014000f, 0x0014000f }, +    { 0x0000989c, 0x00c40002, 0x00c40002 }, +    { 0x0000989c, 0x003000f2, 0x003000f2 }, +    { 0x0000989c, 0x00440016, 0x00440016 }, +    { 0x0000989c, 0x00410040, 0x00410040 }, +    { 0x0000989c, 0x000180d6, 0x000180d6 }, +    { 0x0000989c, 0x0000c0aa, 0x0000c0aa }, +    { 0x0000989c, 0x000000b1, 0x000000b1 }, +    { 0x0000989c, 0x00002000, 0x00002000 }, +    { 0x0000989c, 0x000000d4, 0x000000d4 }, +    { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + + +static const u32 ar5416Bank6TPC_9100[][3] = { + +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00e00000, 0x00e00000 }, +    { 0x0000989c, 0x005e0000, 0x005e0000 }, +    { 0x0000989c, 0x00120000, 0x00120000 }, +    { 0x0000989c, 0x00620000, 0x00620000 }, +    { 0x0000989c, 0x00020000, 0x00020000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x40ff0000, 0x40ff0000 }, +    { 0x0000989c, 0x005f0000, 0x005f0000 }, +    { 0x0000989c, 0x00870000, 0x00870000 }, +    { 0x0000989c, 0x00f90000, 0x00f90000 }, +    { 0x0000989c, 0x007b0000, 0x007b0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00f50000, 0x00f50000 }, +    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, +    { 0x0000989c, 0x00110000, 0x00110000 }, +    { 0x0000989c, 0x006100a8, 0x006100a8 }, +    { 0x0000989c, 0x00423022, 0x00423022 }, +    { 0x0000989c, 0x2014008f, 0x2014008f }, +    { 0x0000989c, 0x00c40002, 0x00c40002 }, +    { 0x0000989c, 0x003000f2, 0x003000f2 }, +    { 0x0000989c, 0x00440016, 0x00440016 }, +    { 0x0000989c, 0x00410040, 0x00410040 }, +    { 0x0000989c, 0x0001805e, 0x0001805e }, +    { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, +    { 0x0000989c, 0x000000e1, 0x000000e1 }, +    { 0x0000989c, 0x00007080, 0x00007080 }, +    { 0x0000989c, 0x000000d4, 0x000000d4 }, +    { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank7_9100[][2] = { +    { 0x0000989c, 0x00000500 }, +    { 0x0000989c, 0x00000800 }, +    { 0x000098cc, 0x0000000e }, +}; + +static const u32 ar5416Addac_9100[][2] = { +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000010 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x000000c0 }, +    {0x0000989c, 0x00000015 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x0000989c, 0x00000000 }, +    {0x000098cc, 0x00000000 }, +}; + +static const u32 ar5416Modes_9160[][6] = { +    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, +    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, +    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, +    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, +    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, +    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, +    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, +    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, +    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, +    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, +    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, +    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, +    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, +    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, +    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, +    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, +    { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, +    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, +    { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, +    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, +    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, +    { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, +    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, +    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, +    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, +    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, +    { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, +    { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, +    { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, +    { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, +    { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, +    { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, +    { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, +    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, +    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, +    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, +    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, +    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, +    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, +    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, +    { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, +    { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, +    { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, +    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, +    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, +    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, +    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, +    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, +    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, +    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, +    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, +    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, +    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, +    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, +    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, +    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, +    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, +}; + +static const u32 ar5416Common_9160[][2] = { +    { 0x0000000c, 0x00000000 }, +    { 0x00000030, 0x00020015 }, +    { 0x00000034, 0x00000005 }, +    { 0x00000040, 0x00000000 }, +    { 0x00000044, 0x00000008 }, +    { 0x00000048, 0x00000008 }, +    { 0x0000004c, 0x00000010 }, +    { 0x00000050, 0x00000000 }, +    { 0x00000054, 0x0000001f }, +    { 0x00000800, 0x00000000 }, +    { 0x00000804, 0x00000000 }, +    { 0x00000808, 0x00000000 }, +    { 0x0000080c, 0x00000000 }, +    { 0x00000810, 0x00000000 }, +    { 0x00000814, 0x00000000 }, +    { 0x00000818, 0x00000000 }, +    { 0x0000081c, 0x00000000 }, +    { 0x00000820, 0x00000000 }, +    { 0x00000824, 0x00000000 }, +    { 0x00001040, 0x002ffc0f }, +    { 0x00001044, 0x002ffc0f }, +    { 0x00001048, 0x002ffc0f }, +    { 0x0000104c, 0x002ffc0f }, +    { 0x00001050, 0x002ffc0f }, +    { 0x00001054, 0x002ffc0f }, +    { 0x00001058, 0x002ffc0f }, +    { 0x0000105c, 0x002ffc0f }, +    { 0x00001060, 0x002ffc0f }, +    { 0x00001064, 0x002ffc0f }, +    { 0x00001230, 0x00000000 }, +    { 0x00001270, 0x00000000 }, +    { 0x00001038, 0x00000000 }, +    { 0x00001078, 0x00000000 }, +    { 0x000010b8, 0x00000000 }, +    { 0x000010f8, 0x00000000 }, +    { 0x00001138, 0x00000000 }, +    { 0x00001178, 0x00000000 }, +    { 0x000011b8, 0x00000000 }, +    { 0x000011f8, 0x00000000 }, +    { 0x00001238, 0x00000000 }, +    { 0x00001278, 0x00000000 }, +    { 0x000012b8, 0x00000000 }, +    { 0x000012f8, 0x00000000 }, +    { 0x00001338, 0x00000000 }, +    { 0x00001378, 0x00000000 }, +    { 0x000013b8, 0x00000000 }, +    { 0x000013f8, 0x00000000 }, +    { 0x00001438, 0x00000000 }, +    { 0x00001478, 0x00000000 }, +    { 0x000014b8, 0x00000000 }, +    { 0x000014f8, 0x00000000 }, +    { 0x00001538, 0x00000000 }, +    { 0x00001578, 0x00000000 }, +    { 0x000015b8, 0x00000000 }, +    { 0x000015f8, 0x00000000 }, +    { 0x00001638, 0x00000000 }, +    { 0x00001678, 0x00000000 }, +    { 0x000016b8, 0x00000000 }, +    { 0x000016f8, 0x00000000 }, +    { 0x00001738, 0x00000000 }, +    { 0x00001778, 0x00000000 }, +    { 0x000017b8, 0x00000000 }, +    { 0x000017f8, 0x00000000 }, +    { 0x0000103c, 0x00000000 }, +    { 0x0000107c, 0x00000000 }, +    { 0x000010bc, 0x00000000 }, +    { 0x000010fc, 0x00000000 }, +    { 0x0000113c, 0x00000000 }, +    { 0x0000117c, 0x00000000 }, +    { 0x000011bc, 0x00000000 }, +    { 0x000011fc, 0x00000000 }, +    { 0x0000123c, 0x00000000 }, +    { 0x0000127c, 0x00000000 }, +    { 0x000012bc, 0x00000000 }, +    { 0x000012fc, 0x00000000 }, +    { 0x0000133c, 0x00000000 }, +    { 0x0000137c, 0x00000000 }, +    { 0x000013bc, 0x00000000 }, +    { 0x000013fc, 0x00000000 }, +    { 0x0000143c, 0x00000000 }, +    { 0x0000147c, 0x00000000 }, +    { 0x00004030, 0x00000002 }, +    { 0x0000403c, 0x00000002 }, +    { 0x00007010, 0x00000020 }, +    { 0x00007038, 0x000004c2 }, +    { 0x00008004, 0x00000000 }, +    { 0x00008008, 0x00000000 }, +    { 0x0000800c, 0x00000000 }, +    { 0x00008018, 0x00000700 }, +    { 0x00008020, 0x00000000 }, +    { 0x00008038, 0x00000000 }, +    { 0x0000803c, 0x00000000 }, +    { 0x00008048, 0x40000000 }, +    { 0x00008054, 0x00000000 }, +    { 0x00008058, 0x00000000 }, +    { 0x0000805c, 0x000fc78f }, +    { 0x00008060, 0x0000000f }, +    { 0x00008064, 0x00000000 }, +    { 0x000080c0, 0x2a82301a }, +    { 0x000080c4, 0x05dc01e0 }, +    { 0x000080c8, 0x1f402710 }, +    { 0x000080cc, 0x01f40000 }, +    { 0x000080d0, 0x00001e00 }, +    { 0x000080d4, 0x00000000 }, +    { 0x000080d8, 0x00400000 }, +    { 0x000080e0, 0xffffffff }, +    { 0x000080e4, 0x0000ffff }, +    { 0x000080e8, 0x003f3f3f }, +    { 0x000080ec, 0x00000000 }, +    { 0x000080f0, 0x00000000 }, +    { 0x000080f4, 0x00000000 }, +    { 0x000080f8, 0x00000000 }, +    { 0x000080fc, 0x00020000 }, +    { 0x00008100, 0x00020000 }, +    { 0x00008104, 0x00000001 }, +    { 0x00008108, 0x00000052 }, +    { 0x0000810c, 0x00000000 }, +    { 0x00008110, 0x00000168 }, +    { 0x00008118, 0x000100aa }, +    { 0x0000811c, 0x00003210 }, +    { 0x00008120, 0x08f04800 }, +    { 0x00008124, 0x00000000 }, +    { 0x00008128, 0x00000000 }, +    { 0x0000812c, 0x00000000 }, +    { 0x00008130, 0x00000000 }, +    { 0x00008134, 0x00000000 }, +    { 0x00008138, 0x00000000 }, +    { 0x0000813c, 0x00000000 }, +    { 0x00008144, 0xffffffff }, +    { 0x00008168, 0x00000000 }, +    { 0x0000816c, 0x00000000 }, +    { 0x00008170, 0x32143320 }, +    { 0x00008174, 0xfaa4fa50 }, +    { 0x00008178, 0x00000100 }, +    { 0x0000817c, 0x00000000 }, +    { 0x000081c4, 0x00000000 }, +    { 0x000081d0, 0x00003210 }, +    { 0x000081ec, 0x00000000 }, +    { 0x000081f0, 0x00000000 }, +    { 0x000081f4, 0x00000000 }, +    { 0x000081f8, 0x00000000 }, +    { 0x000081fc, 0x00000000 }, +    { 0x00008200, 0x00000000 }, +    { 0x00008204, 0x00000000 }, +    { 0x00008208, 0x00000000 }, +    { 0x0000820c, 0x00000000 }, +    { 0x00008210, 0x00000000 }, +    { 0x00008214, 0x00000000 }, +    { 0x00008218, 0x00000000 }, +    { 0x0000821c, 0x00000000 }, +    { 0x00008220, 0x00000000 }, +    { 0x00008224, 0x00000000 }, +    { 0x00008228, 0x00000000 }, +    { 0x0000822c, 0x00000000 }, +    { 0x00008230, 0x00000000 }, +    { 0x00008234, 0x00000000 }, +    { 0x00008238, 0x00000000 }, +    { 0x0000823c, 0x00000000 }, +    { 0x00008240, 0x00100000 }, +    { 0x00008244, 0x0010f400 }, +    { 0x00008248, 0x00000100 }, +    { 0x0000824c, 0x0001e800 }, +    { 0x00008250, 0x00000000 }, +    { 0x00008254, 0x00000000 }, +    { 0x00008258, 0x00000000 }, +    { 0x0000825c, 0x400000ff }, +    { 0x00008260, 0x00080922 }, +    { 0x00008270, 0x00000000 }, +    { 0x00008274, 0x40000000 }, +    { 0x00008278, 0x003e4180 }, +    { 0x0000827c, 0x00000000 }, +    { 0x00008284, 0x0000002c }, +    { 0x00008288, 0x0000002c }, +    { 0x0000828c, 0x00000000 }, +    { 0x00008294, 0x00000000 }, +    { 0x00008298, 0x00000000 }, +    { 0x00008300, 0x00000000 }, +    { 0x00008304, 0x00000000 }, +    { 0x00008308, 0x00000000 }, +    { 0x0000830c, 0x00000000 }, +    { 0x00008310, 0x00000000 }, +    { 0x00008314, 0x00000000 }, +    { 0x00008318, 0x00000000 }, +    { 0x00008328, 0x00000000 }, +    { 0x0000832c, 0x00000007 }, +    { 0x00008330, 0x00000302 }, +    { 0x00008334, 0x00000e00 }, +    { 0x00008338, 0x00ff0000 }, +    { 0x0000833c, 0x00000000 }, +    { 0x00008340, 0x000107ff }, +    { 0x00009808, 0x00000000 }, +    { 0x0000980c, 0xad848e19 }, +    { 0x00009810, 0x7d14e000 }, +    { 0x00009814, 0x9c0a9f6b }, +    { 0x0000981c, 0x00000000 }, +    { 0x0000982c, 0x0000a000 }, +    { 0x00009830, 0x00000000 }, +    { 0x0000983c, 0x00200400 }, +    { 0x00009840, 0x206a01ae }, +    { 0x0000984c, 0x1284233c }, +    { 0x00009854, 0x00000859 }, +    { 0x00009900, 0x00000000 }, +    { 0x00009904, 0x00000000 }, +    { 0x00009908, 0x00000000 }, +    { 0x0000990c, 0x00000000 }, +    { 0x0000991c, 0x10000fff }, +    { 0x00009920, 0x05100000 }, +    { 0x0000a920, 0x05100000 }, +    { 0x0000b920, 0x05100000 }, +    { 0x00009928, 0x00000001 }, +    { 0x0000992c, 0x00000004 }, +    { 0x00009934, 0x1e1f2022 }, +    { 0x00009938, 0x0a0b0c0d }, +    { 0x0000993c, 0x00000000 }, +    { 0x00009948, 0x9280b212 }, +    { 0x0000994c, 0x00020028 }, +    { 0x00009954, 0x5f3ca3de }, +    { 0x00009958, 0x2108ecff }, +    { 0x00009940, 0x00750604 }, +    { 0x0000c95c, 0x004b6a8e }, +    { 0x00009970, 0x190fb515 }, +    { 0x00009974, 0x00000000 }, +    { 0x00009978, 0x00000001 }, +    { 0x0000997c, 0x00000000 }, +    { 0x00009980, 0x00000000 }, +    { 0x00009984, 0x00000000 }, +    { 0x00009988, 0x00000000 }, +    { 0x0000998c, 0x00000000 }, +    { 0x00009990, 0x00000000 }, +    { 0x00009994, 0x00000000 }, +    { 0x00009998, 0x00000000 }, +    { 0x0000999c, 0x00000000 }, +    { 0x000099a0, 0x00000000 }, +    { 0x000099a4, 0x00000001 }, +    { 0x000099a8, 0x201fff00 }, +    { 0x000099ac, 0x006f0000 }, +    { 0x000099b0, 0x03051000 }, +    { 0x000099dc, 0x00000000 }, +    { 0x000099e0, 0x00000200 }, +    { 0x000099e4, 0xaaaaaaaa }, +    { 0x000099e8, 0x3c466478 }, +    { 0x000099ec, 0x0cc80caa }, +    { 0x000099fc, 0x00001042 }, +    { 0x00009b00, 0x00000000 }, +    { 0x00009b04, 0x00000001 }, +    { 0x00009b08, 0x00000002 }, +    { 0x00009b0c, 0x00000003 }, +    { 0x00009b10, 0x00000004 }, +    { 0x00009b14, 0x00000005 }, +    { 0x00009b18, 0x00000008 }, +    { 0x00009b1c, 0x00000009 }, +    { 0x00009b20, 0x0000000a }, +    { 0x00009b24, 0x0000000b }, +    { 0x00009b28, 0x0000000c }, +    { 0x00009b2c, 0x0000000d }, +    { 0x00009b30, 0x00000010 }, +    { 0x00009b34, 0x00000011 }, +    { 0x00009b38, 0x00000012 }, +    { 0x00009b3c, 0x00000013 }, +    { 0x00009b40, 0x00000014 }, +    { 0x00009b44, 0x00000015 }, +    { 0x00009b48, 0x00000018 }, +    { 0x00009b4c, 0x00000019 }, +    { 0x00009b50, 0x0000001a }, +    { 0x00009b54, 0x0000001b }, +    { 0x00009b58, 0x0000001c }, +    { 0x00009b5c, 0x0000001d }, +    { 0x00009b60, 0x00000020 }, +    { 0x00009b64, 0x00000021 }, +    { 0x00009b68, 0x00000022 }, +    { 0x00009b6c, 0x00000023 }, +    { 0x00009b70, 0x00000024 }, +    { 0x00009b74, 0x00000025 }, +    { 0x00009b78, 0x00000028 }, +    { 0x00009b7c, 0x00000029 }, +    { 0x00009b80, 0x0000002a }, +    { 0x00009b84, 0x0000002b }, +    { 0x00009b88, 0x0000002c }, +    { 0x00009b8c, 0x0000002d }, +    { 0x00009b90, 0x00000030 }, +    { 0x00009b94, 0x00000031 }, +    { 0x00009b98, 0x00000032 }, +    { 0x00009b9c, 0x00000033 }, +    { 0x00009ba0, 0x00000034 }, +    { 0x00009ba4, 0x00000035 }, +    { 0x00009ba8, 0x00000035 }, +    { 0x00009bac, 0x00000035 }, +    { 0x00009bb0, 0x00000035 }, +    { 0x00009bb4, 0x00000035 }, +    { 0x00009bb8, 0x00000035 }, +    { 0x00009bbc, 0x00000035 }, +    { 0x00009bc0, 0x00000035 }, +    { 0x00009bc4, 0x00000035 }, +    { 0x00009bc8, 0x00000035 }, +    { 0x00009bcc, 0x00000035 }, +    { 0x00009bd0, 0x00000035 }, +    { 0x00009bd4, 0x00000035 }, +    { 0x00009bd8, 0x00000035 }, +    { 0x00009bdc, 0x00000035 }, +    { 0x00009be0, 0x00000035 }, +    { 0x00009be4, 0x00000035 }, +    { 0x00009be8, 0x00000035 }, +    { 0x00009bec, 0x00000035 }, +    { 0x00009bf0, 0x00000035 }, +    { 0x00009bf4, 0x00000035 }, +    { 0x00009bf8, 0x00000010 }, +    { 0x00009bfc, 0x0000001a }, +    { 0x0000a210, 0x40806333 }, +    { 0x0000a214, 0x00106c10 }, +    { 0x0000a218, 0x009c4060 }, +    { 0x0000a220, 0x018830c6 }, +    { 0x0000a224, 0x00000400 }, +    { 0x0000a228, 0x001a0bb5 }, +    { 0x0000a22c, 0x00000000 }, +    { 0x0000a234, 0x20202020 }, +    { 0x0000a238, 0x20202020 }, +    { 0x0000a23c, 0x13c889af }, +    { 0x0000a240, 0x38490a20 }, +    { 0x0000a244, 0x00007bb6 }, +    { 0x0000a248, 0x0fff3ffc }, +    { 0x0000a24c, 0x00000001 }, +    { 0x0000a250, 0x0000e000 }, +    { 0x0000a254, 0x00000000 }, +    { 0x0000a258, 0x0cc75380 }, +    { 0x0000a25c, 0x0f0f0f01 }, +    { 0x0000a260, 0xdfa91f01 }, +    { 0x0000a268, 0x00000001 }, +    { 0x0000a26c, 0x0ebae9c6 }, +    { 0x0000b26c, 0x0ebae9c6 }, +    { 0x0000c26c, 0x0ebae9c6 }, +    { 0x0000d270, 0x00820820 }, +    { 0x0000a278, 0x1ce739ce }, +    { 0x0000a27c, 0x050701ce }, +    { 0x0000a338, 0x00000000 }, +    { 0x0000a33c, 0x00000000 }, +    { 0x0000a340, 0x00000000 }, +    { 0x0000a344, 0x00000000 }, +    { 0x0000a348, 0x3fffffff }, +    { 0x0000a34c, 0x3fffffff }, +    { 0x0000a350, 0x3fffffff }, +    { 0x0000a354, 0x0003ffff }, +    { 0x0000a358, 0x79bfaa03 }, +    { 0x0000d35c, 0x07ffffef }, +    { 0x0000d360, 0x0fffffe7 }, +    { 0x0000d364, 0x17ffffe5 }, +    { 0x0000d368, 0x1fffffe4 }, +    { 0x0000d36c, 0x37ffffe3 }, +    { 0x0000d370, 0x3fffffe3 }, +    { 0x0000d374, 0x57ffffe3 }, +    { 0x0000d378, 0x5fffffe2 }, +    { 0x0000d37c, 0x7fffffe2 }, +    { 0x0000d380, 0x7f3c7bba }, +    { 0x0000d384, 0xf3307ff0 }, +    { 0x0000a388, 0x0c000000 }, +    { 0x0000a38c, 0x20202020 }, +    { 0x0000a390, 0x20202020 }, +    { 0x0000a394, 0x1ce739ce }, +    { 0x0000a398, 0x000001ce }, +    { 0x0000a39c, 0x00000001 }, +    { 0x0000a3a0, 0x00000000 }, +    { 0x0000a3a4, 0x00000000 }, +    { 0x0000a3a8, 0x00000000 }, +    { 0x0000a3ac, 0x00000000 }, +    { 0x0000a3b0, 0x00000000 }, +    { 0x0000a3b4, 0x00000000 }, +    { 0x0000a3b8, 0x00000000 }, +    { 0x0000a3bc, 0x00000000 }, +    { 0x0000a3c0, 0x00000000 }, +    { 0x0000a3c4, 0x00000000 }, +    { 0x0000a3c8, 0x00000246 }, +    { 0x0000a3cc, 0x20202020 }, +    { 0x0000a3d0, 0x20202020 }, +    { 0x0000a3d4, 0x20202020 }, +    { 0x0000a3dc, 0x1ce739ce }, +    { 0x0000a3e0, 0x000001ce }, +}; + +static const u32 ar5416Bank0_9160[][2] = { +    { 0x000098b0, 0x1e5795e5 }, +    { 0x000098e0, 0x02008020 }, +}; + +static const u32 ar5416BB_RfGain_9160[][3] = { +    { 0x00009a00, 0x00000000, 0x00000000 }, +    { 0x00009a04, 0x00000040, 0x00000040 }, +    { 0x00009a08, 0x00000080, 0x00000080 }, +    { 0x00009a0c, 0x000001a1, 0x00000141 }, +    { 0x00009a10, 0x000001e1, 0x00000181 }, +    { 0x00009a14, 0x00000021, 0x000001c1 }, +    { 0x00009a18, 0x00000061, 0x00000001 }, +    { 0x00009a1c, 0x00000168, 0x00000041 }, +    { 0x00009a20, 0x000001a8, 0x000001a8 }, +    { 0x00009a24, 0x000001e8, 0x000001e8 }, +    { 0x00009a28, 0x00000028, 0x00000028 }, +    { 0x00009a2c, 0x00000068, 0x00000068 }, +    { 0x00009a30, 0x00000189, 0x000000a8 }, +    { 0x00009a34, 0x000001c9, 0x00000169 }, +    { 0x00009a38, 0x00000009, 0x000001a9 }, +    { 0x00009a3c, 0x00000049, 0x000001e9 }, +    { 0x00009a40, 0x00000089, 0x00000029 }, +    { 0x00009a44, 0x00000170, 0x00000069 }, +    { 0x00009a48, 0x000001b0, 0x00000190 }, +    { 0x00009a4c, 0x000001f0, 0x000001d0 }, +    { 0x00009a50, 0x00000030, 0x00000010 }, +    { 0x00009a54, 0x00000070, 0x00000050 }, +    { 0x00009a58, 0x00000191, 0x00000090 }, +    { 0x00009a5c, 0x000001d1, 0x00000151 }, +    { 0x00009a60, 0x00000011, 0x00000191 }, +    { 0x00009a64, 0x00000051, 0x000001d1 }, +    { 0x00009a68, 0x00000091, 0x00000011 }, +    { 0x00009a6c, 0x000001b8, 0x00000051 }, +    { 0x00009a70, 0x000001f8, 0x00000198 }, +    { 0x00009a74, 0x00000038, 0x000001d8 }, +    { 0x00009a78, 0x00000078, 0x00000018 }, +    { 0x00009a7c, 0x00000199, 0x00000058 }, +    { 0x00009a80, 0x000001d9, 0x00000098 }, +    { 0x00009a84, 0x00000019, 0x00000159 }, +    { 0x00009a88, 0x00000059, 0x00000199 }, +    { 0x00009a8c, 0x00000099, 0x000001d9 }, +    { 0x00009a90, 0x000000d9, 0x00000019 }, +    { 0x00009a94, 0x000000f9, 0x00000059 }, +    { 0x00009a98, 0x000000f9, 0x00000099 }, +    { 0x00009a9c, 0x000000f9, 0x000000d9 }, +    { 0x00009aa0, 0x000000f9, 0x000000f9 }, +    { 0x00009aa4, 0x000000f9, 0x000000f9 }, +    { 0x00009aa8, 0x000000f9, 0x000000f9 }, +    { 0x00009aac, 0x000000f9, 0x000000f9 }, +    { 0x00009ab0, 0x000000f9, 0x000000f9 }, +    { 0x00009ab4, 0x000000f9, 0x000000f9 }, +    { 0x00009ab8, 0x000000f9, 0x000000f9 }, +    { 0x00009abc, 0x000000f9, 0x000000f9 }, +    { 0x00009ac0, 0x000000f9, 0x000000f9 }, +    { 0x00009ac4, 0x000000f9, 0x000000f9 }, +    { 0x00009ac8, 0x000000f9, 0x000000f9 }, +    { 0x00009acc, 0x000000f9, 0x000000f9 }, +    { 0x00009ad0, 0x000000f9, 0x000000f9 }, +    { 0x00009ad4, 0x000000f9, 0x000000f9 }, +    { 0x00009ad8, 0x000000f9, 0x000000f9 }, +    { 0x00009adc, 0x000000f9, 0x000000f9 }, +    { 0x00009ae0, 0x000000f9, 0x000000f9 }, +    { 0x00009ae4, 0x000000f9, 0x000000f9 }, +    { 0x00009ae8, 0x000000f9, 0x000000f9 }, +    { 0x00009aec, 0x000000f9, 0x000000f9 }, +    { 0x00009af0, 0x000000f9, 0x000000f9 }, +    { 0x00009af4, 0x000000f9, 0x000000f9 }, +    { 0x00009af8, 0x000000f9, 0x000000f9 }, +    { 0x00009afc, 0x000000f9, 0x000000f9 }, +}; + +static const u32 ar5416Bank1_9160[][2] = { +    { 0x000098b0, 0x02108421 }, +    { 0x000098ec, 0x00000008 }, +}; + +static const u32 ar5416Bank2_9160[][2] = { +    { 0x000098b0, 0x0e73ff17 }, +    { 0x000098e0, 0x00000420 }, +}; + +static const u32 ar5416Bank3_9160[][3] = { +    { 0x000098f0, 0x01400018, 0x01c00018 }, +}; + +static const u32 ar5416Bank6_9160[][3] = { +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00e00000, 0x00e00000 }, +    { 0x0000989c, 0x005e0000, 0x005e0000 }, +    { 0x0000989c, 0x00120000, 0x00120000 }, +    { 0x0000989c, 0x00620000, 0x00620000 }, +    { 0x0000989c, 0x00020000, 0x00020000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x40ff0000, 0x40ff0000 }, +    { 0x0000989c, 0x005f0000, 0x005f0000 }, +    { 0x0000989c, 0x00870000, 0x00870000 }, +    { 0x0000989c, 0x00f90000, 0x00f90000 }, +    { 0x0000989c, 0x007b0000, 0x007b0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00f50000, 0x00f50000 }, +    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, +    { 0x0000989c, 0x00110000, 0x00110000 }, +    { 0x0000989c, 0x006100a8, 0x006100a8 }, +    { 0x0000989c, 0x004210a2, 0x004210a2 }, +    { 0x0000989c, 0x0014008f, 0x0014008f }, +    { 0x0000989c, 0x00c40003, 0x00c40003 }, +    { 0x0000989c, 0x003000f2, 0x003000f2 }, +    { 0x0000989c, 0x00440016, 0x00440016 }, +    { 0x0000989c, 0x00410040, 0x00410040 }, +    { 0x0000989c, 0x0001805e, 0x0001805e }, +    { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, +    { 0x0000989c, 0x000000f1, 0x000000f1 }, +    { 0x0000989c, 0x00002081, 0x00002081 }, +    { 0x0000989c, 0x000000d4, 0x000000d4 }, +    { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank6TPC_9160[][3] = { +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00000000, 0x00000000 }, +    { 0x0000989c, 0x00e00000, 0x00e00000 }, +    { 0x0000989c, 0x005e0000, 0x005e0000 }, +    { 0x0000989c, 0x00120000, 0x00120000 }, +    { 0x0000989c, 0x00620000, 0x00620000 }, +    { 0x0000989c, 0x00020000, 0x00020000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x40ff0000, 0x40ff0000 }, +    { 0x0000989c, 0x005f0000, 0x005f0000 }, +    { 0x0000989c, 0x00870000, 0x00870000 }, +    { 0x0000989c, 0x00f90000, 0x00f90000 }, +    { 0x0000989c, 0x007b0000, 0x007b0000 }, +    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, +    { 0x0000989c, 0x00f50000, 0x00f50000 }, +    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, +    { 0x0000989c, 0x00110000, 0x00110000 }, +    { 0x0000989c, 0x006100a8, 0x006100a8 }, +    { 0x0000989c, 0x00423022, 0x00423022 }, +    { 0x0000989c, 0x2014008f, 0x2014008f }, +    { 0x0000989c, 0x00c40002, 0x00c40002 }, +    { 0x0000989c, 0x003000f2, 0x003000f2 }, +    { 0x0000989c, 0x00440016, 0x00440016 }, +    { 0x0000989c, 0x00410040, 0x00410040 }, +    { 0x0000989c, 0x0001805e, 0x0001805e }, +    { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, +    { 0x0000989c, 0x000000e1, 0x000000e1 }, +    { 0x0000989c, 0x00007080, 0x00007080 }, +    { 0x0000989c, 0x000000d4, 0x000000d4 }, +    { 0x000098d0, 0x0000000f, 0x0010000f }, +}; + +static const u32 ar5416Bank7_9160[][2] = { +    { 0x0000989c, 0x00000500 }, +    { 0x0000989c, 0x00000800 }, +    { 0x000098cc, 0x0000000e }, +}; + +static const u32 ar5416Addac_9160[][2] = { +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x000000c0 }, +    {0x0000989c,  0x00000018 }, +    {0x0000989c,  0x00000004 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x000000c0 }, +    {0x0000989c,  0x00000019 }, +    {0x0000989c,  0x00000004 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000004 }, +    {0x0000989c,  0x00000003 }, +    {0x0000989c,  0x00000008 }, +    {0x0000989c,  0x00000000 }, +    {0x000098cc,  0x00000000 }, +}; + +static const u32 ar5416Addac_91601_1[][2] = { +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x000000c0 }, +    {0x0000989c,  0x00000018 }, +    {0x0000989c,  0x00000004 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x000000c0 }, +    {0x0000989c,  0x00000019 }, +    {0x0000989c,  0x00000004 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x0000989c,  0x00000000 }, +    {0x000098cc,  0x00000000 }, +}; + diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c new file mode 100644 index 00000000000..5fdbb53b47e --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -0,0 +1,1000 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "hw-ops.h" +#include "ar9002_phy.h" + +#define AR9285_CLCAL_REDO_THRESH    1 + +static void ar9002_hw_setup_calibration(struct ath_hw *ah, +					struct ath9k_cal_list *currCal) +{ +	struct ath_common *common = ath9k_hw_common(ah); + +	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), +		      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, +		      currCal->calData->calCountMax); + +	switch (currCal->calData->calType) { +	case IQ_MISMATCH_CAL: +		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "starting IQ Mismatch Calibration\n"); +		break; +	case ADC_GAIN_CAL: +		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "starting ADC Gain Calibration\n"); +		break; +	case ADC_DC_CAL: +		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "starting ADC DC Calibration\n"); +		break; +	case ADC_DC_INIT_CAL: +		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "starting Init ADC DC Calibration\n"); +		break; +	case TEMP_COMP_CAL: +		break; /* Not supported */ +	} + +	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), +		    AR_PHY_TIMING_CTRL4_DO_CAL); +} + +static bool ar9002_hw_per_calibration(struct ath_hw *ah, +				      struct ath9k_channel *ichan, +				      u8 rxchainmask, +				      struct ath9k_cal_list *currCal) +{ +	bool iscaldone = false; + +	if (currCal->calState == CAL_RUNNING) { +		if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & +		      AR_PHY_TIMING_CTRL4_DO_CAL)) { + +			currCal->calData->calCollect(ah); +			ah->cal_samples++; + +			if (ah->cal_samples >= +			    currCal->calData->calNumSamples) { +				int i, numChains = 0; +				for (i = 0; i < AR5416_MAX_CHAINS; i++) { +					if (rxchainmask & (1 << i)) +						numChains++; +				} + +				currCal->calData->calPostProc(ah, numChains); +				ichan->CalValid |= currCal->calData->calType; +				currCal->calState = CAL_DONE; +				iscaldone = true; +			} else { +				ar9002_hw_setup_calibration(ah, currCal); +			} +		} +	} else if (!(ichan->CalValid & currCal->calData->calType)) { +		ath9k_hw_reset_calibration(ah, currCal); +	} + +	return iscaldone; +} + +/* Assumes you are talking about the currently configured channel */ +static bool ar9002_hw_iscal_supported(struct ath_hw *ah, +				      enum ath9k_cal_types calType) +{ +	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; + +	switch (calType & ah->supp_cals) { +	case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ +		return true; +	case ADC_GAIN_CAL: +	case ADC_DC_CAL: +		if (!(conf->channel->band == IEEE80211_BAND_2GHZ && +		      conf_is_ht20(conf))) +			return true; +		break; +	} +	return false; +} + +static void ar9002_hw_iqcal_collect(struct ath_hw *ah) +{ +	int i; + +	for (i = 0; i < AR5416_MAX_CHAINS; i++) { +		ah->totalPowerMeasI[i] += +			REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); +		ah->totalPowerMeasQ[i] += +			REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); +		ah->totalIqCorrMeas[i] += +			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); +		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, +			  "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", +			  ah->cal_samples, i, ah->totalPowerMeasI[i], +			  ah->totalPowerMeasQ[i], +			  ah->totalIqCorrMeas[i]); +	} +} + +static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah) +{ +	int i; + +	for (i = 0; i < AR5416_MAX_CHAINS; i++) { +		ah->totalAdcIOddPhase[i] += +			REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); +		ah->totalAdcIEvenPhase[i] += +			REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); +		ah->totalAdcQOddPhase[i] += +			REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); +		ah->totalAdcQEvenPhase[i] += +			REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + +		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, +			  "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " +			  "oddq=0x%08x; evenq=0x%08x;\n", +			  ah->cal_samples, i, +			  ah->totalAdcIOddPhase[i], +			  ah->totalAdcIEvenPhase[i], +			  ah->totalAdcQOddPhase[i], +			  ah->totalAdcQEvenPhase[i]); +	} +} + +static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah) +{ +	int i; + +	for (i = 0; i < AR5416_MAX_CHAINS; i++) { +		ah->totalAdcDcOffsetIOddPhase[i] += +			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); +		ah->totalAdcDcOffsetIEvenPhase[i] += +			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); +		ah->totalAdcDcOffsetQOddPhase[i] += +			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); +		ah->totalAdcDcOffsetQEvenPhase[i] += +			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); + +		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, +			  "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " +			  "oddq=0x%08x; evenq=0x%08x;\n", +			  ah->cal_samples, i, +			  ah->totalAdcDcOffsetIOddPhase[i], +			  ah->totalAdcDcOffsetIEvenPhase[i], +			  ah->totalAdcDcOffsetQOddPhase[i], +			  ah->totalAdcDcOffsetQEvenPhase[i]); +	} +} + +static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	u32 powerMeasQ, powerMeasI, iqCorrMeas; +	u32 qCoffDenom, iCoffDenom; +	int32_t qCoff, iCoff; +	int iqCorrNeg, i; + +	for (i = 0; i < numChains; i++) { +		powerMeasI = ah->totalPowerMeasI[i]; +		powerMeasQ = ah->totalPowerMeasQ[i]; +		iqCorrMeas = ah->totalIqCorrMeas[i]; + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Starting IQ Cal and Correction for Chain %d\n", +			  i); + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Orignal: Chn %diq_corr_meas = 0x%08x\n", +			  i, ah->totalIqCorrMeas[i]); + +		iqCorrNeg = 0; + +		if (iqCorrMeas > 0x80000000) { +			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; +			iqCorrNeg = 1; +		} + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); +		ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", +			  iqCorrNeg); + +		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; +		qCoffDenom = powerMeasQ / 64; + +		if ((powerMeasQ != 0) && (iCoffDenom != 0) && +		    (qCoffDenom != 0)) { +			iCoff = iqCorrMeas / iCoffDenom; +			qCoff = powerMeasI / qCoffDenom - 64; +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Chn %d iCoff = 0x%08x\n", i, iCoff); +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Chn %d qCoff = 0x%08x\n", i, qCoff); + +			iCoff = iCoff & 0x3f; +			ath_print(common, ATH_DBG_CALIBRATE, +				  "New: Chn %d iCoff = 0x%08x\n", i, iCoff); +			if (iqCorrNeg == 0x0) +				iCoff = 0x40 - iCoff; + +			if (qCoff > 15) +				qCoff = 15; +			else if (qCoff <= -16) +				qCoff = 16; + +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n", +				  i, iCoff, qCoff); + +			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), +				      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, +				      iCoff); +			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), +				      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, +				      qCoff); +			ath_print(common, ATH_DBG_CALIBRATE, +				  "IQ Cal and Correction done for Chain %d\n", +				  i); +		} +	} + +	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), +		    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); +} + +static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; +	u32 qGainMismatch, iGainMismatch, val, i; + +	for (i = 0; i < numChains; i++) { +		iOddMeasOffset = ah->totalAdcIOddPhase[i]; +		iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; +		qOddMeasOffset = ah->totalAdcQOddPhase[i]; +		qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Starting ADC Gain Cal for Chain %d\n", i); + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_odd_i = 0x%08x\n", i, +			  iOddMeasOffset); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_even_i = 0x%08x\n", i, +			  iEvenMeasOffset); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_odd_q = 0x%08x\n", i, +			  qOddMeasOffset); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_even_q = 0x%08x\n", i, +			  qEvenMeasOffset); + +		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { +			iGainMismatch = +				((iEvenMeasOffset * 32) / +				 iOddMeasOffset) & 0x3f; +			qGainMismatch = +				((qOddMeasOffset * 32) / +				 qEvenMeasOffset) & 0x3f; + +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Chn %d gain_mismatch_i = 0x%08x\n", i, +				  iGainMismatch); +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Chn %d gain_mismatch_q = 0x%08x\n", i, +				  qGainMismatch); + +			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); +			val &= 0xfffff000; +			val |= (qGainMismatch) | (iGainMismatch << 6); +			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + +			ath_print(common, ATH_DBG_CALIBRATE, +				  "ADC Gain Cal done for Chain %d\n", i); +		} +	} + +	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), +		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | +		  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); +} + +static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	u32 iOddMeasOffset, iEvenMeasOffset, val, i; +	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; +	const struct ath9k_percal_data *calData = +		ah->cal_list_curr->calData; +	u32 numSamples = +		(1 << (calData->calCountMax + 5)) * calData->calNumSamples; + +	for (i = 0; i < numChains; i++) { +		iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; +		iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; +		qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; +		qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; + +		ath_print(common, ATH_DBG_CALIBRATE, +			   "Starting ADC DC Offset Cal for Chain %d\n", i); + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_odd_i = %d\n", i, +			  iOddMeasOffset); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_even_i = %d\n", i, +			  iEvenMeasOffset); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_odd_q = %d\n", i, +			  qOddMeasOffset); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_even_q = %d\n", i, +			  qEvenMeasOffset); + +		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / +			       numSamples) & 0x1ff; +		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / +			       numSamples) & 0x1ff; + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, +			  iDcMismatch); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, +			  qDcMismatch); + +		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); +		val &= 0xc0000fff; +		val |= (qDcMismatch << 12) | (iDcMismatch << 21); +		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "ADC DC Offset Cal done for Chain %d\n", i); +	} + +	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), +		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | +		  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); +} + +static void ar9287_hw_olc_temp_compensation(struct ath_hw *ah) +{ +	u32 rddata; +	int32_t delta, currPDADC, slope; + +	rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); +	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); + +	if (ah->initPDADC == 0 || currPDADC == 0) { +		/* +		 * Zero value indicates that no frames have been transmitted +		 * yet, can't do temperature compensation until frames are +		 * transmitted. +		 */ +		return; +	} else { +		slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); + +		if (slope == 0) { /* to avoid divide by zero case */ +			delta = 0; +		} else { +			delta = ((currPDADC - ah->initPDADC)*4) / slope; +		} +		REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, +			      AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); +		REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, +			      AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); +	} +} + +static void ar9280_hw_olc_temp_compensation(struct ath_hw *ah) +{ +	u32 rddata, i; +	int delta, currPDADC, regval; + +	rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); +	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); + +	if (ah->initPDADC == 0 || currPDADC == 0) +		return; + +	if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) +		delta = (currPDADC - ah->initPDADC + 4) / 8; +	else +		delta = (currPDADC - ah->initPDADC + 5) / 10; + +	if (delta != ah->PDADCdelta) { +		ah->PDADCdelta = delta; +		for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { +			regval = ah->originalGain[i] - delta; +			if (regval < 0) +				regval = 0; + +			REG_RMW_FIELD(ah, +				      AR_PHY_TX_GAIN_TBL1 + i * 4, +				      AR_PHY_TX_GAIN, regval); +		} +	} +} + +static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) +{ +	u32 regVal; +	unsigned int i; +	u32 regList[][2] = { +		{ 0x786c, 0 }, +		{ 0x7854, 0 }, +		{ 0x7820, 0 }, +		{ 0x7824, 0 }, +		{ 0x7868, 0 }, +		{ 0x783c, 0 }, +		{ 0x7838, 0 } , +		{ 0x7828, 0 } , +	}; + +	for (i = 0; i < ARRAY_SIZE(regList); i++) +		regList[i][1] = REG_READ(ah, regList[i][0]); + +	regVal = REG_READ(ah, 0x7834); +	regVal &= (~(0x1)); +	REG_WRITE(ah, 0x7834, regVal); +	regVal = REG_READ(ah, 0x9808); +	regVal |= (0x1 << 27); +	REG_WRITE(ah, 0x9808, regVal); + +	/* 786c,b23,1, pwddac=1 */ +	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); +	/* 7854, b5,1, pdrxtxbb=1 */ +	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); +	/* 7854, b7,1, pdv2i=1 */ +	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); +	/* 7854, b8,1, pddacinterface=1 */ +	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); +	/* 7824,b12,0, offcal=0 */ +	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); +	/* 7838, b1,0, pwddb=0 */ +	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); +	/* 7820,b11,0, enpacal=0 */ +	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); +	/* 7820,b25,1, pdpadrv1=0 */ +	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); +	/* 7820,b24,0, pdpadrv2=0 */ +	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); +	/* 7820,b23,0, pdpaout=0 */ +	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); +	/* 783c,b14-16,7, padrvgn2tab_0=7 */ +	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); +	/* +	 * 7838,b29-31,0, padrvgn1tab_0=0 +	 * does not matter since we turn it off +	 */ +	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); + +	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); + +	/* Set: +	 * localmode=1,bmode=1,bmoderxtx=1,synthon=1, +	 * txon=1,paon=1,oscon=1,synthon_force=1 +	 */ +	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); +	udelay(30); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); + +	/* find off_6_1; */ +	for (i = 6; i > 0; i--) { +		regVal = REG_READ(ah, 0x7834); +		regVal |= (1 << (20 + i)); +		REG_WRITE(ah, 0x7834, regVal); +		udelay(1); +		/* regVal = REG_READ(ah, 0x7834); */ +		regVal &= (~(0x1 << (20 + i))); +		regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) +			    << (20 + i)); +		REG_WRITE(ah, 0x7834, regVal); +	} + +	regVal = (regVal >> 20) & 0x7f; + +	/* Update PA cal info */ +	if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) { +		if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) +			ah->pacal_info.max_skipcount = +				2 * ah->pacal_info.max_skipcount; +		ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; +	} else { +		ah->pacal_info.max_skipcount = 1; +		ah->pacal_info.skipcount = 0; +		ah->pacal_info.prev_offset = regVal; +	} + +	ENABLE_REGWRITE_BUFFER(ah); + +	regVal = REG_READ(ah, 0x7834); +	regVal |= 0x1; +	REG_WRITE(ah, 0x7834, regVal); +	regVal = REG_READ(ah, 0x9808); +	regVal &= (~(0x1 << 27)); +	REG_WRITE(ah, 0x9808, regVal); + +	for (i = 0; i < ARRAY_SIZE(regList); i++) +		REG_WRITE(ah, regList[i][0], regList[i][1]); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +} + +static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	u32 regVal; +	int i, offset, offs_6_1, offs_0; +	u32 ccomp_org, reg_field; +	u32 regList[][2] = { +		{ 0x786c, 0 }, +		{ 0x7854, 0 }, +		{ 0x7820, 0 }, +		{ 0x7824, 0 }, +		{ 0x7868, 0 }, +		{ 0x783c, 0 }, +		{ 0x7838, 0 }, +	}; + +	ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); + +	/* PA CAL is not needed for high power solution */ +	if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == +	    AR5416_EEP_TXGAIN_HIGH_POWER) +		return; + +	if (AR_SREV_9285_11(ah)) { +		REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); +		udelay(10); +	} + +	for (i = 0; i < ARRAY_SIZE(regList); i++) +		regList[i][1] = REG_READ(ah, regList[i][0]); + +	regVal = REG_READ(ah, 0x7834); +	regVal &= (~(0x1)); +	REG_WRITE(ah, 0x7834, regVal); +	regVal = REG_READ(ah, 0x9808); +	regVal |= (0x1 << 27); +	REG_WRITE(ah, 0x9808, regVal); + +	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); +	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); +	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); +	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); +	ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); + +	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); +	udelay(30); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); + +	for (i = 6; i > 0; i--) { +		regVal = REG_READ(ah, 0x7834); +		regVal |= (1 << (19 + i)); +		REG_WRITE(ah, 0x7834, regVal); +		udelay(1); +		regVal = REG_READ(ah, 0x7834); +		regVal &= (~(0x1 << (19 + i))); +		reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); +		regVal |= (reg_field << (19 + i)); +		REG_WRITE(ah, 0x7834, regVal); +	} + +	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); +	udelay(1); +	reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); +	offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); +	offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); + +	offset = (offs_6_1<<1) | offs_0; +	offset = offset - 0; +	offs_6_1 = offset>>1; +	offs_0 = offset & 1; + +	if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) { +		if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) +			ah->pacal_info.max_skipcount = +				2 * ah->pacal_info.max_skipcount; +		ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; +	} else { +		ah->pacal_info.max_skipcount = 1; +		ah->pacal_info.skipcount = 0; +		ah->pacal_info.prev_offset = offset; +	} + +	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); +	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); + +	regVal = REG_READ(ah, 0x7834); +	regVal |= 0x1; +	REG_WRITE(ah, 0x7834, regVal); +	regVal = REG_READ(ah, 0x9808); +	regVal &= (~(0x1 << 27)); +	REG_WRITE(ah, 0x9808, regVal); + +	for (i = 0; i < ARRAY_SIZE(regList); i++) +		REG_WRITE(ah, regList[i][0], regList[i][1]); + +	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); + +	if (AR_SREV_9285_11(ah)) +		REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); + +} + +static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) +{ +	if (AR_SREV_9271(ah)) { +		if (is_reset || !ah->pacal_info.skipcount) +			ar9271_hw_pa_cal(ah, is_reset); +		else +			ah->pacal_info.skipcount--; +	} else if (AR_SREV_9285_11_OR_LATER(ah)) { +		if (is_reset || !ah->pacal_info.skipcount) +			ar9285_hw_pa_cal(ah, is_reset); +		else +			ah->pacal_info.skipcount--; +	} +} + +static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah) +{ +	if (OLC_FOR_AR9287_10_LATER) +		ar9287_hw_olc_temp_compensation(ah); +	else if (OLC_FOR_AR9280_20_LATER) +		ar9280_hw_olc_temp_compensation(ah); +} + +static bool ar9002_hw_calibrate(struct ath_hw *ah, +				struct ath9k_channel *chan, +				u8 rxchainmask, +				bool longcal) +{ +	bool iscaldone = true; +	struct ath9k_cal_list *currCal = ah->cal_list_curr; + +	if (currCal && +	    (currCal->calState == CAL_RUNNING || +	     currCal->calState == CAL_WAITING)) { +		iscaldone = ar9002_hw_per_calibration(ah, chan, +						      rxchainmask, currCal); +		if (iscaldone) { +			ah->cal_list_curr = currCal = currCal->calNext; + +			if (currCal->calState == CAL_WAITING) { +				iscaldone = false; +				ath9k_hw_reset_calibration(ah, currCal); +			} +		} +	} + +	/* Do NF cal only at longer intervals */ +	if (longcal) { +		/* Do periodic PAOffset Cal */ +		ar9002_hw_pa_cal(ah, false); +		ar9002_hw_olc_temp_compensation(ah); + +		/* +		 * Get the value from the previous NF cal and update +		 * history buffer. +		 */ +		ath9k_hw_getnf(ah, chan); + +		/* +		 * Load the NF from history buffer of the current channel. +		 * NF is slow time-variant, so it is OK to use a historical +		 * value. +		 */ +		ath9k_hw_loadnf(ah, ah->curchan); + +		ath9k_hw_start_nfcal(ah); +	} + +	return iscaldone; +} + +/* Carrier leakage Calibration fix */ +static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) +{ +	struct ath_common *common = ath9k_hw_common(ah); + +	REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); +	if (IS_CHAN_HT20(chan)) { +		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); +		REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); +		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, +			    AR_PHY_AGC_CONTROL_FLTR_CAL); +		REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); +		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); +		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, +				  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { +			ath_print(common, ATH_DBG_CALIBRATE, "offset " +				  "calibration failed to complete in " +				  "1ms; noisy ??\n"); +			return false; +		} +		REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); +		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); +		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); +	} +	REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); +	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); +	REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); +	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); +	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, +			  0, AH_WAIT_TIMEOUT)) { +		ath_print(common, ATH_DBG_CALIBRATE, "offset calibration " +			  "failed to complete in 1ms; noisy ??\n"); +		return false; +	} + +	REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); +	REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); +	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); + +	return true; +} + +static bool ar9285_hw_clc(struct ath_hw *ah, struct ath9k_channel *chan) +{ +	int i; +	u_int32_t txgain_max; +	u_int32_t clc_gain, gain_mask = 0, clc_num = 0; +	u_int32_t reg_clc_I0, reg_clc_Q0; +	u_int32_t i0_num = 0; +	u_int32_t q0_num = 0; +	u_int32_t total_num = 0; +	u_int32_t reg_rf2g5_org; +	bool retv = true; + +	if (!(ar9285_hw_cl_cal(ah, chan))) +		return false; + +	txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7), +			AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); + +	for (i = 0; i < (txgain_max+1); i++) { +		clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & +			   AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; +		if (!(gain_mask & (1 << clc_gain))) { +			gain_mask |= (1 << clc_gain); +			clc_num++; +		} +	} + +	for (i = 0; i < clc_num; i++) { +		reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) +			      & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; +		reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) +			      & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; +		if (reg_clc_I0 == 0) +			i0_num++; + +		if (reg_clc_Q0 == 0) +			q0_num++; +	} +	total_num = i0_num + q0_num; +	if (total_num > AR9285_CLCAL_REDO_THRESH) { +		reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5); +		if (AR_SREV_9285E_20(ah)) { +			REG_WRITE(ah, AR9285_RF2G5, +				  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | +				  AR9285_RF2G5_IC50TX_XE_SET); +		} else { +			REG_WRITE(ah, AR9285_RF2G5, +				  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | +				  AR9285_RF2G5_IC50TX_SET); +		} +		retv = ar9285_hw_cl_cal(ah, chan); +		REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); +	} +	return retv; +} + +static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) +{ +	struct ath_common *common = ath9k_hw_common(ah); + +	if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { +		if (!ar9285_hw_clc(ah, chan)) +			return false; +	} else { +		if (AR_SREV_9280_10_OR_LATER(ah)) { +			if (!AR_SREV_9287_10_OR_LATER(ah)) +				REG_CLR_BIT(ah, AR_PHY_ADC_CTL, +					    AR_PHY_ADC_CTL_OFF_PWDADC); +			REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, +				    AR_PHY_AGC_CONTROL_FLTR_CAL); +		} + +		/* Calibrate the AGC */ +		REG_WRITE(ah, AR_PHY_AGC_CONTROL, +			  REG_READ(ah, AR_PHY_AGC_CONTROL) | +			  AR_PHY_AGC_CONTROL_CAL); + +		/* Poll for offset calibration complete */ +		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, +				   AR_PHY_AGC_CONTROL_CAL, +				   0, AH_WAIT_TIMEOUT)) { +			ath_print(common, ATH_DBG_CALIBRATE, +				  "offset calibration failed to " +				  "complete in 1ms; noisy environment?\n"); +			return false; +		} + +		if (AR_SREV_9280_10_OR_LATER(ah)) { +			if (!AR_SREV_9287_10_OR_LATER(ah)) +				REG_SET_BIT(ah, AR_PHY_ADC_CTL, +					    AR_PHY_ADC_CTL_OFF_PWDADC); +			REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, +				    AR_PHY_AGC_CONTROL_FLTR_CAL); +		} +	} + +	/* Do PA Calibration */ +	ar9002_hw_pa_cal(ah, true); + +	/* Do NF Calibration after DC offset and other calibrations */ +	REG_WRITE(ah, AR_PHY_AGC_CONTROL, +		  REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); + +	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; + +	/* Enable IQ, ADC Gain and ADC DC offset CALs */ +	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { +		if (ar9002_hw_iscal_supported(ah, ADC_GAIN_CAL)) { +			INIT_CAL(&ah->adcgain_caldata); +			INSERT_CAL(ah, &ah->adcgain_caldata); +			ath_print(common, ATH_DBG_CALIBRATE, +				  "enabling ADC Gain Calibration.\n"); +		} +		if (ar9002_hw_iscal_supported(ah, ADC_DC_CAL)) { +			INIT_CAL(&ah->adcdc_caldata); +			INSERT_CAL(ah, &ah->adcdc_caldata); +			ath_print(common, ATH_DBG_CALIBRATE, +				  "enabling ADC DC Calibration.\n"); +		} +		if (ar9002_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { +			INIT_CAL(&ah->iq_caldata); +			INSERT_CAL(ah, &ah->iq_caldata); +			ath_print(common, ATH_DBG_CALIBRATE, +				  "enabling IQ Calibration.\n"); +		} + +		ah->cal_list_curr = ah->cal_list; + +		if (ah->cal_list_curr) +			ath9k_hw_reset_calibration(ah, ah->cal_list_curr); +	} + +	chan->CalValid = 0; + +	return true; +} + +static const struct ath9k_percal_data iq_cal_multi_sample = { +	IQ_MISMATCH_CAL, +	MAX_CAL_SAMPLES, +	PER_MIN_LOG_COUNT, +	ar9002_hw_iqcal_collect, +	ar9002_hw_iqcalibrate +}; +static const struct ath9k_percal_data iq_cal_single_sample = { +	IQ_MISMATCH_CAL, +	MIN_CAL_SAMPLES, +	PER_MAX_LOG_COUNT, +	ar9002_hw_iqcal_collect, +	ar9002_hw_iqcalibrate +}; +static const struct ath9k_percal_data adc_gain_cal_multi_sample = { +	ADC_GAIN_CAL, +	MAX_CAL_SAMPLES, +	PER_MIN_LOG_COUNT, +	ar9002_hw_adc_gaincal_collect, +	ar9002_hw_adc_gaincal_calibrate +}; +static const struct ath9k_percal_data adc_gain_cal_single_sample = { +	ADC_GAIN_CAL, +	MIN_CAL_SAMPLES, +	PER_MAX_LOG_COUNT, +	ar9002_hw_adc_gaincal_collect, +	ar9002_hw_adc_gaincal_calibrate +}; +static const struct ath9k_percal_data adc_dc_cal_multi_sample = { +	ADC_DC_CAL, +	MAX_CAL_SAMPLES, +	PER_MIN_LOG_COUNT, +	ar9002_hw_adc_dccal_collect, +	ar9002_hw_adc_dccal_calibrate +}; +static const struct ath9k_percal_data adc_dc_cal_single_sample = { +	ADC_DC_CAL, +	MIN_CAL_SAMPLES, +	PER_MAX_LOG_COUNT, +	ar9002_hw_adc_dccal_collect, +	ar9002_hw_adc_dccal_calibrate +}; +static const struct ath9k_percal_data adc_init_dc_cal = { +	ADC_DC_INIT_CAL, +	MIN_CAL_SAMPLES, +	INIT_LOG_COUNT, +	ar9002_hw_adc_dccal_collect, +	ar9002_hw_adc_dccal_calibrate +}; + +static void ar9002_hw_init_cal_settings(struct ath_hw *ah) +{ +	if (AR_SREV_9100(ah)) { +		ah->iq_caldata.calData = &iq_cal_multi_sample; +		ah->supp_cals = IQ_MISMATCH_CAL; +		return; +	} + +	if (AR_SREV_9160_10_OR_LATER(ah)) { +		if (AR_SREV_9280_10_OR_LATER(ah)) { +			ah->iq_caldata.calData = &iq_cal_single_sample; +			ah->adcgain_caldata.calData = +				&adc_gain_cal_single_sample; +			ah->adcdc_caldata.calData = +				&adc_dc_cal_single_sample; +			ah->adcdc_calinitdata.calData = +				&adc_init_dc_cal; +		} else { +			ah->iq_caldata.calData = &iq_cal_multi_sample; +			ah->adcgain_caldata.calData = +				&adc_gain_cal_multi_sample; +			ah->adcdc_caldata.calData = +				&adc_dc_cal_multi_sample; +			ah->adcdc_calinitdata.calData = +				&adc_init_dc_cal; +		} +		ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; +	} +} + +void ar9002_hw_attach_calib_ops(struct ath_hw *ah) +{ +	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); +	struct ath_hw_ops *ops = ath9k_hw_ops(ah); + +	priv_ops->init_cal_settings = ar9002_hw_init_cal_settings; +	priv_ops->init_cal = ar9002_hw_init_cal; +	priv_ops->setup_calibration = ar9002_hw_setup_calibration; +	priv_ops->iscal_supported = ar9002_hw_iscal_supported; + +	ops->calibrate = ar9002_hw_calibrate; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c new file mode 100644 index 00000000000..a8a8cdc04af --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -0,0 +1,598 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "ar5008_initvals.h" +#include "ar9001_initvals.h" +#include "ar9002_initvals.h" + +/* General hardware code for the A5008/AR9001/AR9002 hadware families */ + +static bool ar9002_hw_macversion_supported(u32 macversion) +{ +	switch (macversion) { +	case AR_SREV_VERSION_5416_PCI: +	case AR_SREV_VERSION_5416_PCIE: +	case AR_SREV_VERSION_9160: +	case AR_SREV_VERSION_9100: +	case AR_SREV_VERSION_9280: +	case AR_SREV_VERSION_9285: +	case AR_SREV_VERSION_9287: +	case AR_SREV_VERSION_9271: +		return true; +	default: +		break; +	} +	return false; +} + +static void ar9002_hw_init_mode_regs(struct ath_hw *ah) +{ +	if (AR_SREV_9271(ah)) { +		INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271, +			       ARRAY_SIZE(ar9271Modes_9271), 6); +		INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, +			       ARRAY_SIZE(ar9271Common_9271), 2); +		INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271, +			       ar9271Common_normal_cck_fir_coeff_9271, +			       ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2); +		INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271, +			       ar9271Common_japan_2484_cck_fir_coeff_9271, +			       ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2); +		INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, +			       ar9271Modes_9271_1_0_only, +			       ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); +		INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg, +			       ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6); +		INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271, +			       ar9271Modes_high_power_tx_gain_9271, +			       ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6); +		INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, +			       ar9271Modes_normal_power_tx_gain_9271, +			       ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6); +		return; +	} + +	if (AR_SREV_9287_11_OR_LATER(ah)) { +		INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, +				ARRAY_SIZE(ar9287Modes_9287_1_1), 6); +		INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1, +				ARRAY_SIZE(ar9287Common_9287_1_1), 2); +		if (ah->config.pcie_clock_req) +			INIT_INI_ARRAY(&ah->iniPcieSerdes, +			ar9287PciePhy_clkreq_off_L1_9287_1_1, +			ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2); +		else +			INIT_INI_ARRAY(&ah->iniPcieSerdes, +			ar9287PciePhy_clkreq_always_on_L1_9287_1_1, +			ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1), +					2); +	} else if (AR_SREV_9287_10_OR_LATER(ah)) { +		INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0, +				ARRAY_SIZE(ar9287Modes_9287_1_0), 6); +		INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0, +				ARRAY_SIZE(ar9287Common_9287_1_0), 2); + +		if (ah->config.pcie_clock_req) +			INIT_INI_ARRAY(&ah->iniPcieSerdes, +			ar9287PciePhy_clkreq_off_L1_9287_1_0, +			ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2); +		else +			INIT_INI_ARRAY(&ah->iniPcieSerdes, +			ar9287PciePhy_clkreq_always_on_L1_9287_1_0, +			ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0), +				  2); +	} else if (AR_SREV_9285_12_OR_LATER(ah)) { + + +		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, +			       ARRAY_SIZE(ar9285Modes_9285_1_2), 6); +		INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, +			       ARRAY_SIZE(ar9285Common_9285_1_2), 2); + +		if (ah->config.pcie_clock_req) { +			INIT_INI_ARRAY(&ah->iniPcieSerdes, +			ar9285PciePhy_clkreq_off_L1_9285_1_2, +			ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2); +		} else { +			INIT_INI_ARRAY(&ah->iniPcieSerdes, +			ar9285PciePhy_clkreq_always_on_L1_9285_1_2, +			ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2), +				  2); +		} +	} else if (AR_SREV_9285_10_OR_LATER(ah)) { +		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285, +			       ARRAY_SIZE(ar9285Modes_9285), 6); +		INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285, +			       ARRAY_SIZE(ar9285Common_9285), 2); + +		if (ah->config.pcie_clock_req) { +			INIT_INI_ARRAY(&ah->iniPcieSerdes, +			ar9285PciePhy_clkreq_off_L1_9285, +			ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2); +		} else { +			INIT_INI_ARRAY(&ah->iniPcieSerdes, +			ar9285PciePhy_clkreq_always_on_L1_9285, +			ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2); +		} +	} else if (AR_SREV_9280_20_OR_LATER(ah)) { +		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, +			       ARRAY_SIZE(ar9280Modes_9280_2), 6); +		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, +			       ARRAY_SIZE(ar9280Common_9280_2), 2); + +		if (ah->config.pcie_clock_req) { +			INIT_INI_ARRAY(&ah->iniPcieSerdes, +			       ar9280PciePhy_clkreq_off_L1_9280, +			       ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280), 2); +		} else { +			INIT_INI_ARRAY(&ah->iniPcieSerdes, +			       ar9280PciePhy_clkreq_always_on_L1_9280, +			       ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2); +		} +		INIT_INI_ARRAY(&ah->iniModesAdditional, +			       ar9280Modes_fast_clock_9280_2, +			       ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); +	} else if (AR_SREV_9280_10_OR_LATER(ah)) { +		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280, +			       ARRAY_SIZE(ar9280Modes_9280), 6); +		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280, +			       ARRAY_SIZE(ar9280Common_9280), 2); +	} else if (AR_SREV_9160_10_OR_LATER(ah)) { +		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, +			       ARRAY_SIZE(ar5416Modes_9160), 6); +		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160, +			       ARRAY_SIZE(ar5416Common_9160), 2); +		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160, +			       ARRAY_SIZE(ar5416Bank0_9160), 2); +		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160, +			       ARRAY_SIZE(ar5416BB_RfGain_9160), 3); +		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160, +			       ARRAY_SIZE(ar5416Bank1_9160), 2); +		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160, +			       ARRAY_SIZE(ar5416Bank2_9160), 2); +		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160, +			       ARRAY_SIZE(ar5416Bank3_9160), 3); +		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160, +			       ARRAY_SIZE(ar5416Bank6_9160), 3); +		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160, +			       ARRAY_SIZE(ar5416Bank6TPC_9160), 3); +		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160, +			       ARRAY_SIZE(ar5416Bank7_9160), 2); +		if (AR_SREV_9160_11(ah)) { +			INIT_INI_ARRAY(&ah->iniAddac, +				       ar5416Addac_91601_1, +				       ARRAY_SIZE(ar5416Addac_91601_1), 2); +		} else { +			INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160, +				       ARRAY_SIZE(ar5416Addac_9160), 2); +		} +	} else if (AR_SREV_9100_OR_LATER(ah)) { +		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100, +			       ARRAY_SIZE(ar5416Modes_9100), 6); +		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100, +			       ARRAY_SIZE(ar5416Common_9100), 2); +		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100, +			       ARRAY_SIZE(ar5416Bank0_9100), 2); +		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100, +			       ARRAY_SIZE(ar5416BB_RfGain_9100), 3); +		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100, +			       ARRAY_SIZE(ar5416Bank1_9100), 2); +		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100, +			       ARRAY_SIZE(ar5416Bank2_9100), 2); +		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100, +			       ARRAY_SIZE(ar5416Bank3_9100), 3); +		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100, +			       ARRAY_SIZE(ar5416Bank6_9100), 3); +		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100, +			       ARRAY_SIZE(ar5416Bank6TPC_9100), 3); +		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100, +			       ARRAY_SIZE(ar5416Bank7_9100), 2); +		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100, +			       ARRAY_SIZE(ar5416Addac_9100), 2); +	} else { +		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes, +			       ARRAY_SIZE(ar5416Modes), 6); +		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common, +			       ARRAY_SIZE(ar5416Common), 2); +		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0, +			       ARRAY_SIZE(ar5416Bank0), 2); +		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain, +			       ARRAY_SIZE(ar5416BB_RfGain), 3); +		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1, +			       ARRAY_SIZE(ar5416Bank1), 2); +		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2, +			       ARRAY_SIZE(ar5416Bank2), 2); +		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3, +			       ARRAY_SIZE(ar5416Bank3), 3); +		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6, +			       ARRAY_SIZE(ar5416Bank6), 3); +		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC, +			       ARRAY_SIZE(ar5416Bank6TPC), 3); +		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7, +			       ARRAY_SIZE(ar5416Bank7), 2); +		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, +			       ARRAY_SIZE(ar5416Addac), 2); +	} +} + +/* Support for Japan ch.14 (2484) spread */ +void ar9002_hw_cck_chan14_spread(struct ath_hw *ah) +{ +	if (AR_SREV_9287_11_OR_LATER(ah)) { +		INIT_INI_ARRAY(&ah->iniCckfirNormal, +		       ar9287Common_normal_cck_fir_coeff_92871_1, +		       ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_92871_1), +		       2); +		INIT_INI_ARRAY(&ah->iniCckfirJapan2484, +		       ar9287Common_japan_2484_cck_fir_coeff_92871_1, +		       ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_92871_1), +		       2); +	} +} + +static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah) +{ +	u32 rxgain_type; + +	if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= +	    AR5416_EEP_MINOR_VER_17) { +		rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); + +		if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) +			INIT_INI_ARRAY(&ah->iniModesRxGain, +			ar9280Modes_backoff_13db_rxgain_9280_2, +			ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); +		else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) +			INIT_INI_ARRAY(&ah->iniModesRxGain, +			ar9280Modes_backoff_23db_rxgain_9280_2, +			ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); +		else +			INIT_INI_ARRAY(&ah->iniModesRxGain, +			ar9280Modes_original_rxgain_9280_2, +			ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); +	} else { +		INIT_INI_ARRAY(&ah->iniModesRxGain, +			ar9280Modes_original_rxgain_9280_2, +			ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); +	} +} + +static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah) +{ +	u32 txgain_type; + +	if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= +	    AR5416_EEP_MINOR_VER_19) { +		txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); + +		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +			ar9280Modes_high_power_tx_gain_9280_2, +			ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); +		else +			INIT_INI_ARRAY(&ah->iniModesTxGain, +			ar9280Modes_original_tx_gain_9280_2, +			ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); +	} else { +		INIT_INI_ARRAY(&ah->iniModesTxGain, +		ar9280Modes_original_tx_gain_9280_2, +		ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); +	} +} + +static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) +{ +	if (AR_SREV_9287_11_OR_LATER(ah)) +		INIT_INI_ARRAY(&ah->iniModesRxGain, +		ar9287Modes_rx_gain_9287_1_1, +		ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); +	else if (AR_SREV_9287_10(ah)) +		INIT_INI_ARRAY(&ah->iniModesRxGain, +		ar9287Modes_rx_gain_9287_1_0, +		ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6); +	else if (AR_SREV_9280_20(ah)) +		ar9280_20_hw_init_rxgain_ini(ah); + +	if (AR_SREV_9287_11_OR_LATER(ah)) { +		INIT_INI_ARRAY(&ah->iniModesTxGain, +		ar9287Modes_tx_gain_9287_1_1, +		ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); +	} else if (AR_SREV_9287_10(ah)) { +		INIT_INI_ARRAY(&ah->iniModesTxGain, +		ar9287Modes_tx_gain_9287_1_0, +		ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6); +	} else if (AR_SREV_9280_20(ah)) { +		ar9280_20_hw_init_txgain_ini(ah); +	} else if (AR_SREV_9285_12_OR_LATER(ah)) { +		u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); + +		/* txgain table */ +		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { +			if (AR_SREV_9285E_20(ah)) { +				INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9285Modes_XE2_0_high_power, +				ARRAY_SIZE( +				  ar9285Modes_XE2_0_high_power), 6); +			} else { +				INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9285Modes_high_power_tx_gain_9285_1_2, +				ARRAY_SIZE( +				  ar9285Modes_high_power_tx_gain_9285_1_2), 6); +			} +		} else { +			if (AR_SREV_9285E_20(ah)) { +				INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9285Modes_XE2_0_normal_power, +				ARRAY_SIZE( +				  ar9285Modes_XE2_0_normal_power), 6); +			} else { +				INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9285Modes_original_tx_gain_9285_1_2, +				ARRAY_SIZE( +				  ar9285Modes_original_tx_gain_9285_1_2), 6); +			} +		} +	} +} + +/* + * Helper for ASPM support. + * + * Disable PLL when in L0s as well as receiver clock when in L1. + * This power saving option must be enabled through the SerDes. + * + * Programming the SerDes must go through the same 288 bit serial shift + * register as the other analog registers.  Hence the 9 writes. + */ +static void ar9002_hw_configpcipowersave(struct ath_hw *ah, +					 int restore, +					 int power_off) +{ +	u8 i; +	u32 val; + +	if (ah->is_pciexpress != true) +		return; + +	/* Do not touch SerDes registers */ +	if (ah->config.pcie_powersave_enable == 2) +		return; + +	/* Nothing to do on restore for 11N */ +	if (!restore) { +		if (AR_SREV_9280_20_OR_LATER(ah)) { +			/* +			 * AR9280 2.0 or later chips use SerDes values from the +			 * initvals.h initialized depending on chipset during +			 * __ath9k_hw_init() +			 */ +			for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { +				REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), +					  INI_RA(&ah->iniPcieSerdes, i, 1)); +			} +		} else if (AR_SREV_9280(ah) && +			   (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { +			REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); +			REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); + +			/* RX shut off when elecidle is asserted */ +			REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); +			REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); +			REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); + +			/* Shut off CLKREQ active in L1 */ +			if (ah->config.pcie_clock_req) +				REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); +			else +				REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); + +			REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); +			REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); +			REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); + +			/* Load the new settings */ +			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + +		} else { +			ENABLE_REGWRITE_BUFFER(ah); + +			REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); +			REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); + +			/* RX shut off when elecidle is asserted */ +			REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); +			REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); +			REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); + +			/* +			 * Ignore ah->ah_config.pcie_clock_req setting for +			 * pre-AR9280 11n +			 */ +			REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); + +			REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); +			REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); +			REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); + +			/* Load the new settings */ +			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + +			REGWRITE_BUFFER_FLUSH(ah); +			DISABLE_REGWRITE_BUFFER(ah); +		} + +		udelay(1000); + +		/* set bit 19 to allow forcing of pcie core into L1 state */ +		REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + +		/* Several PCIe massages to ensure proper behaviour */ +		if (ah->config.pcie_waen) { +			val = ah->config.pcie_waen; +			if (!power_off) +				val &= (~AR_WA_D3_L1_DISABLE); +		} else { +			if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || +			    AR_SREV_9287(ah)) { +				val = AR9285_WA_DEFAULT; +				if (!power_off) +					val &= (~AR_WA_D3_L1_DISABLE); +			} else if (AR_SREV_9280(ah)) { +				/* +				 * On AR9280 chips bit 22 of 0x4004 needs to be +				 * set otherwise card may disappear. +				 */ +				val = AR9280_WA_DEFAULT; +				if (!power_off) +					val &= (~AR_WA_D3_L1_DISABLE); +			} else +				val = AR_WA_DEFAULT; +		} + +		REG_WRITE(ah, AR_WA, val); +	} + +	if (power_off) { +		/* +		 * Set PCIe workaround bits +		 * bit 14 in WA register (disable L1) should only +		 * be set when device enters D3 and be cleared +		 * when device comes back to D0. +		 */ +		if (ah->config.pcie_waen) { +			if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) +				REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); +		} else { +			if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) || +			      AR_SREV_9287(ah)) && +			     (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || +			    (AR_SREV_9280(ah) && +			     (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { +				REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); +			} +		} +	} +} + +static int ar9002_hw_get_radiorev(struct ath_hw *ah) +{ +	u32 val; +	int i; + +	ENABLE_REGWRITE_BUFFER(ah); + +	REG_WRITE(ah, AR_PHY(0x36), 0x00007058); +	for (i = 0; i < 8; i++) +		REG_WRITE(ah, AR_PHY(0x20), 0x00010000); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); + +	val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; +	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); + +	return ath9k_hw_reverse_bits(val, 8); +} + +int ar9002_hw_rf_claim(struct ath_hw *ah) +{ +	u32 val; + +	REG_WRITE(ah, AR_PHY(0), 0x00000007); + +	val = ar9002_hw_get_radiorev(ah); +	switch (val & AR_RADIO_SREV_MAJOR) { +	case 0: +		val = AR_RAD5133_SREV_MAJOR; +		break; +	case AR_RAD5133_SREV_MAJOR: +	case AR_RAD5122_SREV_MAJOR: +	case AR_RAD2133_SREV_MAJOR: +	case AR_RAD2122_SREV_MAJOR: +		break; +	default: +		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, +			  "Radio Chip Rev 0x%02X not supported\n", +			  val & AR_RADIO_SREV_MAJOR); +		return -EOPNOTSUPP; +	} + +	ah->hw_version.analog5GhzRev = val; + +	return 0; +} + +/* + * Enable ASYNC FIFO + * + * If Async FIFO is enabled, the following counters change as MAC now runs + * at 117 Mhz instead of 88/44MHz when async FIFO is disabled. + * + * The values below tested for ht40 2 chain. + * Overwrite the delay/timeouts initialized in process ini. + */ +void ar9002_hw_enable_async_fifo(struct ath_hw *ah) +{ +	if (AR_SREV_9287_12_OR_LATER(ah)) { +		REG_WRITE(ah, AR_D_GBL_IFS_SIFS, +			  AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); +		REG_WRITE(ah, AR_D_GBL_IFS_SLOT, +			  AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR); +		REG_WRITE(ah, AR_D_GBL_IFS_EIFS, +			  AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR); + +		REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR); +		REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR); + +		REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, +			    AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); +		REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, +			      AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); +	} +} + +/* + * We don't enable WEP aggregation on mac80211 but we keep this + * around for HAL unification purposes. + */ +void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah) +{ +	if (AR_SREV_9287_12_OR_LATER(ah)) { +		REG_SET_BIT(ah, AR_PCU_MISC_MODE2, +				AR_PCU_MISC_MODE2_ENABLE_AGGWEP); +	} +} + +/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */ +void ar9002_hw_attach_ops(struct ath_hw *ah) +{ +	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); +	struct ath_hw_ops *ops = ath9k_hw_ops(ah); + +	priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; +	priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; +	priv_ops->macversion_supported = ar9002_hw_macversion_supported; + +	ops->config_pci_powersave = ar9002_hw_configpcipowersave; + +	ar5008_hw_attach_phy_ops(ah); +	if (AR_SREV_9280_10_OR_LATER(ah)) +		ar9002_hw_attach_phy_ops(ah); + +	ar9002_hw_attach_calib_ops(ah); +	ar9002_hw_attach_mac_ops(ah); +} diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index 455e9d3b3f1..dae7f3304eb 100644 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2010 Atheros Communications Inc.   *   * Permission to use, copy, modify, and/or distribute this software for any   * purpose with or without fee is hereby granted, provided that the above @@ -14,1982 +14,9 @@   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   */ -static const u32 ar5416Modes[][6] = { -    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, -    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, -    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, -    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, -    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, -    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, -    { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, -    { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, -    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, -    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, -    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, -    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, -    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, -    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, -    { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, -    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, -    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, -    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, -    { 0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de }, -    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, -    { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, -    { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, -    { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, -    { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, -    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, -    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, -    { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, -    { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, -    { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, -    { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, -    { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, -    { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, -    { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, -    { 0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, -    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, -    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, -    { 0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c }, -    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, -    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, -    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, -    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, -    { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, -    { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, -    { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, -    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, -    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, -    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, -    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, -    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, -    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, -    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, -    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, -    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, -    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, -    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, -    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, -    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, -    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common[][2] = { -    { 0x0000000c, 0x00000000 }, -    { 0x00000030, 0x00020015 }, -    { 0x00000034, 0x00000005 }, -    { 0x00000040, 0x00000000 }, -    { 0x00000044, 0x00000008 }, -    { 0x00000048, 0x00000008 }, -    { 0x0000004c, 0x00000010 }, -    { 0x00000050, 0x00000000 }, -    { 0x00000054, 0x0000001f }, -    { 0x00000800, 0x00000000 }, -    { 0x00000804, 0x00000000 }, -    { 0x00000808, 0x00000000 }, -    { 0x0000080c, 0x00000000 }, -    { 0x00000810, 0x00000000 }, -    { 0x00000814, 0x00000000 }, -    { 0x00000818, 0x00000000 }, -    { 0x0000081c, 0x00000000 }, -    { 0x00000820, 0x00000000 }, -    { 0x00000824, 0x00000000 }, -    { 0x00001040, 0x002ffc0f }, -    { 0x00001044, 0x002ffc0f }, -    { 0x00001048, 0x002ffc0f }, -    { 0x0000104c, 0x002ffc0f }, -    { 0x00001050, 0x002ffc0f }, -    { 0x00001054, 0x002ffc0f }, -    { 0x00001058, 0x002ffc0f }, -    { 0x0000105c, 0x002ffc0f }, -    { 0x00001060, 0x002ffc0f }, -    { 0x00001064, 0x002ffc0f }, -    { 0x00001230, 0x00000000 }, -    { 0x00001270, 0x00000000 }, -    { 0x00001038, 0x00000000 }, -    { 0x00001078, 0x00000000 }, -    { 0x000010b8, 0x00000000 }, -    { 0x000010f8, 0x00000000 }, -    { 0x00001138, 0x00000000 }, -    { 0x00001178, 0x00000000 }, -    { 0x000011b8, 0x00000000 }, -    { 0x000011f8, 0x00000000 }, -    { 0x00001238, 0x00000000 }, -    { 0x00001278, 0x00000000 }, -    { 0x000012b8, 0x00000000 }, -    { 0x000012f8, 0x00000000 }, -    { 0x00001338, 0x00000000 }, -    { 0x00001378, 0x00000000 }, -    { 0x000013b8, 0x00000000 }, -    { 0x000013f8, 0x00000000 }, -    { 0x00001438, 0x00000000 }, -    { 0x00001478, 0x00000000 }, -    { 0x000014b8, 0x00000000 }, -    { 0x000014f8, 0x00000000 }, -    { 0x00001538, 0x00000000 }, -    { 0x00001578, 0x00000000 }, -    { 0x000015b8, 0x00000000 }, -    { 0x000015f8, 0x00000000 }, -    { 0x00001638, 0x00000000 }, -    { 0x00001678, 0x00000000 }, -    { 0x000016b8, 0x00000000 }, -    { 0x000016f8, 0x00000000 }, -    { 0x00001738, 0x00000000 }, -    { 0x00001778, 0x00000000 }, -    { 0x000017b8, 0x00000000 }, -    { 0x000017f8, 0x00000000 }, -    { 0x0000103c, 0x00000000 }, -    { 0x0000107c, 0x00000000 }, -    { 0x000010bc, 0x00000000 }, -    { 0x000010fc, 0x00000000 }, -    { 0x0000113c, 0x00000000 }, -    { 0x0000117c, 0x00000000 }, -    { 0x000011bc, 0x00000000 }, -    { 0x000011fc, 0x00000000 }, -    { 0x0000123c, 0x00000000 }, -    { 0x0000127c, 0x00000000 }, -    { 0x000012bc, 0x00000000 }, -    { 0x000012fc, 0x00000000 }, -    { 0x0000133c, 0x00000000 }, -    { 0x0000137c, 0x00000000 }, -    { 0x000013bc, 0x00000000 }, -    { 0x000013fc, 0x00000000 }, -    { 0x0000143c, 0x00000000 }, -    { 0x0000147c, 0x00000000 }, -    { 0x00004030, 0x00000002 }, -    { 0x0000403c, 0x00000002 }, -    { 0x00007010, 0x00000000 }, -    { 0x00007038, 0x000004c2 }, -    { 0x00008004, 0x00000000 }, -    { 0x00008008, 0x00000000 }, -    { 0x0000800c, 0x00000000 }, -    { 0x00008018, 0x00000700 }, -    { 0x00008020, 0x00000000 }, -    { 0x00008038, 0x00000000 }, -    { 0x0000803c, 0x00000000 }, -    { 0x00008048, 0x40000000 }, -    { 0x00008054, 0x00000000 }, -    { 0x00008058, 0x00000000 }, -    { 0x0000805c, 0x000fc78f }, -    { 0x00008060, 0x0000000f }, -    { 0x00008064, 0x00000000 }, -    { 0x000080c0, 0x2a82301a }, -    { 0x000080c4, 0x05dc01e0 }, -    { 0x000080c8, 0x1f402710 }, -    { 0x000080cc, 0x01f40000 }, -    { 0x000080d0, 0x00001e00 }, -    { 0x000080d4, 0x00000000 }, -    { 0x000080d8, 0x00400000 }, -    { 0x000080e0, 0xffffffff }, -    { 0x000080e4, 0x0000ffff }, -    { 0x000080e8, 0x003f3f3f }, -    { 0x000080ec, 0x00000000 }, -    { 0x000080f0, 0x00000000 }, -    { 0x000080f4, 0x00000000 }, -    { 0x000080f8, 0x00000000 }, -    { 0x000080fc, 0x00020000 }, -    { 0x00008100, 0x00020000 }, -    { 0x00008104, 0x00000001 }, -    { 0x00008108, 0x00000052 }, -    { 0x0000810c, 0x00000000 }, -    { 0x00008110, 0x00000168 }, -    { 0x00008118, 0x000100aa }, -    { 0x0000811c, 0x00003210 }, -    { 0x00008124, 0x00000000 }, -    { 0x00008128, 0x00000000 }, -    { 0x0000812c, 0x00000000 }, -    { 0x00008130, 0x00000000 }, -    { 0x00008134, 0x00000000 }, -    { 0x00008138, 0x00000000 }, -    { 0x0000813c, 0x00000000 }, -    { 0x00008144, 0xffffffff }, -    { 0x00008168, 0x00000000 }, -    { 0x0000816c, 0x00000000 }, -    { 0x00008170, 0x32143320 }, -    { 0x00008174, 0xfaa4fa50 }, -    { 0x00008178, 0x00000100 }, -    { 0x0000817c, 0x00000000 }, -    { 0x000081c4, 0x00000000 }, -    { 0x000081ec, 0x00000000 }, -    { 0x000081f0, 0x00000000 }, -    { 0x000081f4, 0x00000000 }, -    { 0x000081f8, 0x00000000 }, -    { 0x000081fc, 0x00000000 }, -    { 0x00008200, 0x00000000 }, -    { 0x00008204, 0x00000000 }, -    { 0x00008208, 0x00000000 }, -    { 0x0000820c, 0x00000000 }, -    { 0x00008210, 0x00000000 }, -    { 0x00008214, 0x00000000 }, -    { 0x00008218, 0x00000000 }, -    { 0x0000821c, 0x00000000 }, -    { 0x00008220, 0x00000000 }, -    { 0x00008224, 0x00000000 }, -    { 0x00008228, 0x00000000 }, -    { 0x0000822c, 0x00000000 }, -    { 0x00008230, 0x00000000 }, -    { 0x00008234, 0x00000000 }, -    { 0x00008238, 0x00000000 }, -    { 0x0000823c, 0x00000000 }, -    { 0x00008240, 0x00100000 }, -    { 0x00008244, 0x0010f400 }, -    { 0x00008248, 0x00000100 }, -    { 0x0000824c, 0x0001e800 }, -    { 0x00008250, 0x00000000 }, -    { 0x00008254, 0x00000000 }, -    { 0x00008258, 0x00000000 }, -    { 0x0000825c, 0x400000ff }, -    { 0x00008260, 0x00080922 }, -    { 0x00008264, 0xa8000010 }, -    { 0x00008270, 0x00000000 }, -    { 0x00008274, 0x40000000 }, -    { 0x00008278, 0x003e4180 }, -    { 0x0000827c, 0x00000000 }, -    { 0x00008284, 0x0000002c }, -    { 0x00008288, 0x0000002c }, -    { 0x0000828c, 0x00000000 }, -    { 0x00008294, 0x00000000 }, -    { 0x00008298, 0x00000000 }, -    { 0x00008300, 0x00000000 }, -    { 0x00008304, 0x00000000 }, -    { 0x00008308, 0x00000000 }, -    { 0x0000830c, 0x00000000 }, -    { 0x00008310, 0x00000000 }, -    { 0x00008314, 0x00000000 }, -    { 0x00008318, 0x00000000 }, -    { 0x00008328, 0x00000000 }, -    { 0x0000832c, 0x00000007 }, -    { 0x00008330, 0x00000302 }, -    { 0x00008334, 0x00000e00 }, -    { 0x00008338, 0x00070000 }, -    { 0x0000833c, 0x00000000 }, -    { 0x00008340, 0x000107ff }, -    { 0x00009808, 0x00000000 }, -    { 0x0000980c, 0xad848e19 }, -    { 0x00009810, 0x7d14e000 }, -    { 0x00009814, 0x9c0a9f6b }, -    { 0x0000981c, 0x00000000 }, -    { 0x0000982c, 0x0000a000 }, -    { 0x00009830, 0x00000000 }, -    { 0x0000983c, 0x00200400 }, -    { 0x00009840, 0x206a002e }, -    { 0x0000984c, 0x1284233c }, -    { 0x00009854, 0x00000859 }, -    { 0x00009900, 0x00000000 }, -    { 0x00009904, 0x00000000 }, -    { 0x00009908, 0x00000000 }, -    { 0x0000990c, 0x00000000 }, -    { 0x0000991c, 0x10000fff }, -    { 0x00009920, 0x05100000 }, -    { 0x0000a920, 0x05100000 }, -    { 0x0000b920, 0x05100000 }, -    { 0x00009928, 0x00000001 }, -    { 0x0000992c, 0x00000004 }, -    { 0x00009934, 0x1e1f2022 }, -    { 0x00009938, 0x0a0b0c0d }, -    { 0x0000993c, 0x00000000 }, -    { 0x00009948, 0x9280b212 }, -    { 0x0000994c, 0x00020028 }, -    { 0x00009954, 0x5d50e188 }, -    { 0x00009958, 0x00081fff }, -    { 0x0000c95c, 0x004b6a8e }, -    { 0x0000c968, 0x000003ce }, -    { 0x00009970, 0x190fb515 }, -    { 0x00009974, 0x00000000 }, -    { 0x00009978, 0x00000001 }, -    { 0x0000997c, 0x00000000 }, -    { 0x00009980, 0x00000000 }, -    { 0x00009984, 0x00000000 }, -    { 0x00009988, 0x00000000 }, -    { 0x0000998c, 0x00000000 }, -    { 0x00009990, 0x00000000 }, -    { 0x00009994, 0x00000000 }, -    { 0x00009998, 0x00000000 }, -    { 0x0000999c, 0x00000000 }, -    { 0x000099a0, 0x00000000 }, -    { 0x000099a4, 0x00000001 }, -    { 0x000099a8, 0x001fff00 }, -    { 0x000099ac, 0x00000000 }, -    { 0x000099b0, 0x03051000 }, -    { 0x000099dc, 0x00000000 }, -    { 0x000099e0, 0x00000200 }, -    { 0x000099e4, 0xaaaaaaaa }, -    { 0x000099e8, 0x3c466478 }, -    { 0x000099ec, 0x000000aa }, -    { 0x000099fc, 0x00001042 }, -    { 0x00009b00, 0x00000000 }, -    { 0x00009b04, 0x00000001 }, -    { 0x00009b08, 0x00000002 }, -    { 0x00009b0c, 0x00000003 }, -    { 0x00009b10, 0x00000004 }, -    { 0x00009b14, 0x00000005 }, -    { 0x00009b18, 0x00000008 }, -    { 0x00009b1c, 0x00000009 }, -    { 0x00009b20, 0x0000000a }, -    { 0x00009b24, 0x0000000b }, -    { 0x00009b28, 0x0000000c }, -    { 0x00009b2c, 0x0000000d }, -    { 0x00009b30, 0x00000010 }, -    { 0x00009b34, 0x00000011 }, -    { 0x00009b38, 0x00000012 }, -    { 0x00009b3c, 0x00000013 }, -    { 0x00009b40, 0x00000014 }, -    { 0x00009b44, 0x00000015 }, -    { 0x00009b48, 0x00000018 }, -    { 0x00009b4c, 0x00000019 }, -    { 0x00009b50, 0x0000001a }, -    { 0x00009b54, 0x0000001b }, -    { 0x00009b58, 0x0000001c }, -    { 0x00009b5c, 0x0000001d }, -    { 0x00009b60, 0x00000020 }, -    { 0x00009b64, 0x00000021 }, -    { 0x00009b68, 0x00000022 }, -    { 0x00009b6c, 0x00000023 }, -    { 0x00009b70, 0x00000024 }, -    { 0x00009b74, 0x00000025 }, -    { 0x00009b78, 0x00000028 }, -    { 0x00009b7c, 0x00000029 }, -    { 0x00009b80, 0x0000002a }, -    { 0x00009b84, 0x0000002b }, -    { 0x00009b88, 0x0000002c }, -    { 0x00009b8c, 0x0000002d }, -    { 0x00009b90, 0x00000030 }, -    { 0x00009b94, 0x00000031 }, -    { 0x00009b98, 0x00000032 }, -    { 0x00009b9c, 0x00000033 }, -    { 0x00009ba0, 0x00000034 }, -    { 0x00009ba4, 0x00000035 }, -    { 0x00009ba8, 0x00000035 }, -    { 0x00009bac, 0x00000035 }, -    { 0x00009bb0, 0x00000035 }, -    { 0x00009bb4, 0x00000035 }, -    { 0x00009bb8, 0x00000035 }, -    { 0x00009bbc, 0x00000035 }, -    { 0x00009bc0, 0x00000035 }, -    { 0x00009bc4, 0x00000035 }, -    { 0x00009bc8, 0x00000035 }, -    { 0x00009bcc, 0x00000035 }, -    { 0x00009bd0, 0x00000035 }, -    { 0x00009bd4, 0x00000035 }, -    { 0x00009bd8, 0x00000035 }, -    { 0x00009bdc, 0x00000035 }, -    { 0x00009be0, 0x00000035 }, -    { 0x00009be4, 0x00000035 }, -    { 0x00009be8, 0x00000035 }, -    { 0x00009bec, 0x00000035 }, -    { 0x00009bf0, 0x00000035 }, -    { 0x00009bf4, 0x00000035 }, -    { 0x00009bf8, 0x00000010 }, -    { 0x00009bfc, 0x0000001a }, -    { 0x0000a210, 0x40806333 }, -    { 0x0000a214, 0x00106c10 }, -    { 0x0000a218, 0x009c4060 }, -    { 0x0000a220, 0x018830c6 }, -    { 0x0000a224, 0x00000400 }, -    { 0x0000a228, 0x00000bb5 }, -    { 0x0000a22c, 0x00000011 }, -    { 0x0000a234, 0x20202020 }, -    { 0x0000a238, 0x20202020 }, -    { 0x0000a23c, 0x13c889af }, -    { 0x0000a240, 0x38490a20 }, -    { 0x0000a244, 0x00007bb6 }, -    { 0x0000a248, 0x0fff3ffc }, -    { 0x0000a24c, 0x00000001 }, -    { 0x0000a250, 0x0000a000 }, -    { 0x0000a254, 0x00000000 }, -    { 0x0000a258, 0x0cc75380 }, -    { 0x0000a25c, 0x0f0f0f01 }, -    { 0x0000a260, 0xdfa91f01 }, -    { 0x0000a268, 0x00000000 }, -    { 0x0000a26c, 0x0e79e5c6 }, -    { 0x0000b26c, 0x0e79e5c6 }, -    { 0x0000c26c, 0x0e79e5c6 }, -    { 0x0000d270, 0x00820820 }, -    { 0x0000a278, 0x1ce739ce }, -    { 0x0000a27c, 0x051701ce }, -    { 0x0000a338, 0x00000000 }, -    { 0x0000a33c, 0x00000000 }, -    { 0x0000a340, 0x00000000 }, -    { 0x0000a344, 0x00000000 }, -    { 0x0000a348, 0x3fffffff }, -    { 0x0000a34c, 0x3fffffff }, -    { 0x0000a350, 0x3fffffff }, -    { 0x0000a354, 0x0003ffff }, -    { 0x0000a358, 0x79a8aa1f }, -    { 0x0000d35c, 0x07ffffef }, -    { 0x0000d360, 0x0fffffe7 }, -    { 0x0000d364, 0x17ffffe5 }, -    { 0x0000d368, 0x1fffffe4 }, -    { 0x0000d36c, 0x37ffffe3 }, -    { 0x0000d370, 0x3fffffe3 }, -    { 0x0000d374, 0x57ffffe3 }, -    { 0x0000d378, 0x5fffffe2 }, -    { 0x0000d37c, 0x7fffffe2 }, -    { 0x0000d380, 0x7f3c7bba }, -    { 0x0000d384, 0xf3307ff0 }, -    { 0x0000a388, 0x08000000 }, -    { 0x0000a38c, 0x20202020 }, -    { 0x0000a390, 0x20202020 }, -    { 0x0000a394, 0x1ce739ce }, -    { 0x0000a398, 0x000001ce }, -    { 0x0000a39c, 0x00000001 }, -    { 0x0000a3a0, 0x00000000 }, -    { 0x0000a3a4, 0x00000000 }, -    { 0x0000a3a8, 0x00000000 }, -    { 0x0000a3ac, 0x00000000 }, -    { 0x0000a3b0, 0x00000000 }, -    { 0x0000a3b4, 0x00000000 }, -    { 0x0000a3b8, 0x00000000 }, -    { 0x0000a3bc, 0x00000000 }, -    { 0x0000a3c0, 0x00000000 }, -    { 0x0000a3c4, 0x00000000 }, -    { 0x0000a3c8, 0x00000246 }, -    { 0x0000a3cc, 0x20202020 }, -    { 0x0000a3d0, 0x20202020 }, -    { 0x0000a3d4, 0x20202020 }, -    { 0x0000a3dc, 0x1ce739ce }, -    { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0[][2] = { -    { 0x000098b0, 0x1e5795e5 }, -    { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain[][3] = { -    { 0x00009a00, 0x00000000, 0x00000000 }, -    { 0x00009a04, 0x00000040, 0x00000040 }, -    { 0x00009a08, 0x00000080, 0x00000080 }, -    { 0x00009a0c, 0x000001a1, 0x00000141 }, -    { 0x00009a10, 0x000001e1, 0x00000181 }, -    { 0x00009a14, 0x00000021, 0x000001c1 }, -    { 0x00009a18, 0x00000061, 0x00000001 }, -    { 0x00009a1c, 0x00000168, 0x00000041 }, -    { 0x00009a20, 0x000001a8, 0x000001a8 }, -    { 0x00009a24, 0x000001e8, 0x000001e8 }, -    { 0x00009a28, 0x00000028, 0x00000028 }, -    { 0x00009a2c, 0x00000068, 0x00000068 }, -    { 0x00009a30, 0x00000189, 0x000000a8 }, -    { 0x00009a34, 0x000001c9, 0x00000169 }, -    { 0x00009a38, 0x00000009, 0x000001a9 }, -    { 0x00009a3c, 0x00000049, 0x000001e9 }, -    { 0x00009a40, 0x00000089, 0x00000029 }, -    { 0x00009a44, 0x00000170, 0x00000069 }, -    { 0x00009a48, 0x000001b0, 0x00000190 }, -    { 0x00009a4c, 0x000001f0, 0x000001d0 }, -    { 0x00009a50, 0x00000030, 0x00000010 }, -    { 0x00009a54, 0x00000070, 0x00000050 }, -    { 0x00009a58, 0x00000191, 0x00000090 }, -    { 0x00009a5c, 0x000001d1, 0x00000151 }, -    { 0x00009a60, 0x00000011, 0x00000191 }, -    { 0x00009a64, 0x00000051, 0x000001d1 }, -    { 0x00009a68, 0x00000091, 0x00000011 }, -    { 0x00009a6c, 0x000001b8, 0x00000051 }, -    { 0x00009a70, 0x000001f8, 0x00000198 }, -    { 0x00009a74, 0x00000038, 0x000001d8 }, -    { 0x00009a78, 0x00000078, 0x00000018 }, -    { 0x00009a7c, 0x00000199, 0x00000058 }, -    { 0x00009a80, 0x000001d9, 0x00000098 }, -    { 0x00009a84, 0x00000019, 0x00000159 }, -    { 0x00009a88, 0x00000059, 0x00000199 }, -    { 0x00009a8c, 0x00000099, 0x000001d9 }, -    { 0x00009a90, 0x000000d9, 0x00000019 }, -    { 0x00009a94, 0x000000f9, 0x00000059 }, -    { 0x00009a98, 0x000000f9, 0x00000099 }, -    { 0x00009a9c, 0x000000f9, 0x000000d9 }, -    { 0x00009aa0, 0x000000f9, 0x000000f9 }, -    { 0x00009aa4, 0x000000f9, 0x000000f9 }, -    { 0x00009aa8, 0x000000f9, 0x000000f9 }, -    { 0x00009aac, 0x000000f9, 0x000000f9 }, -    { 0x00009ab0, 0x000000f9, 0x000000f9 }, -    { 0x00009ab4, 0x000000f9, 0x000000f9 }, -    { 0x00009ab8, 0x000000f9, 0x000000f9 }, -    { 0x00009abc, 0x000000f9, 0x000000f9 }, -    { 0x00009ac0, 0x000000f9, 0x000000f9 }, -    { 0x00009ac4, 0x000000f9, 0x000000f9 }, -    { 0x00009ac8, 0x000000f9, 0x000000f9 }, -    { 0x00009acc, 0x000000f9, 0x000000f9 }, -    { 0x00009ad0, 0x000000f9, 0x000000f9 }, -    { 0x00009ad4, 0x000000f9, 0x000000f9 }, -    { 0x00009ad8, 0x000000f9, 0x000000f9 }, -    { 0x00009adc, 0x000000f9, 0x000000f9 }, -    { 0x00009ae0, 0x000000f9, 0x000000f9 }, -    { 0x00009ae4, 0x000000f9, 0x000000f9 }, -    { 0x00009ae8, 0x000000f9, 0x000000f9 }, -    { 0x00009aec, 0x000000f9, 0x000000f9 }, -    { 0x00009af0, 0x000000f9, 0x000000f9 }, -    { 0x00009af4, 0x000000f9, 0x000000f9 }, -    { 0x00009af8, 0x000000f9, 0x000000f9 }, -    { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1[][2] = { -    { 0x000098b0, 0x02108421 }, -    { 0x000098ec, 0x00000008 }, -}; - -static const u32 ar5416Bank2[][2] = { -    { 0x000098b0, 0x0e73ff17 }, -    { 0x000098e0, 0x00000420 }, -}; - -static const u32 ar5416Bank3[][3] = { -    { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6[][3] = { - -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00e00000, 0x00e00000 }, -    { 0x0000989c, 0x005e0000, 0x005e0000 }, -    { 0x0000989c, 0x00120000, 0x00120000 }, -    { 0x0000989c, 0x00620000, 0x00620000 }, -    { 0x0000989c, 0x00020000, 0x00020000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x40ff0000, 0x40ff0000 }, -    { 0x0000989c, 0x005f0000, 0x005f0000 }, -    { 0x0000989c, 0x00870000, 0x00870000 }, -    { 0x0000989c, 0x00f90000, 0x00f90000 }, -    { 0x0000989c, 0x007b0000, 0x007b0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00f50000, 0x00f50000 }, -    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, -    { 0x0000989c, 0x00110000, 0x00110000 }, -    { 0x0000989c, 0x006100a8, 0x006100a8 }, -    { 0x0000989c, 0x004210a2, 0x004210a2 }, -    { 0x0000989c, 0x0014008f, 0x0014008f }, -    { 0x0000989c, 0x00c40003, 0x00c40003 }, -    { 0x0000989c, 0x003000f2, 0x003000f2 }, -    { 0x0000989c, 0x00440016, 0x00440016 }, -    { 0x0000989c, 0x00410040, 0x00410040 }, -    { 0x0000989c, 0x0001805e, 0x0001805e }, -    { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, -    { 0x0000989c, 0x000000f1, 0x000000f1 }, -    { 0x0000989c, 0x00002081, 0x00002081 }, -    { 0x0000989c, 0x000000d4, 0x000000d4 }, -    { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank6TPC[][3] = { -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00e00000, 0x00e00000 }, -    { 0x0000989c, 0x005e0000, 0x005e0000 }, -    { 0x0000989c, 0x00120000, 0x00120000 }, -    { 0x0000989c, 0x00620000, 0x00620000 }, -    { 0x0000989c, 0x00020000, 0x00020000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x40ff0000, 0x40ff0000 }, -    { 0x0000989c, 0x005f0000, 0x005f0000 }, -    { 0x0000989c, 0x00870000, 0x00870000 }, -    { 0x0000989c, 0x00f90000, 0x00f90000 }, -    { 0x0000989c, 0x007b0000, 0x007b0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00f50000, 0x00f50000 }, -    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, -    { 0x0000989c, 0x00110000, 0x00110000 }, -    { 0x0000989c, 0x006100a8, 0x006100a8 }, -    { 0x0000989c, 0x00423022, 0x00423022 }, -    { 0x0000989c, 0x201400df, 0x201400df }, -    { 0x0000989c, 0x00c40002, 0x00c40002 }, -    { 0x0000989c, 0x003000f2, 0x003000f2 }, -    { 0x0000989c, 0x00440016, 0x00440016 }, -    { 0x0000989c, 0x00410040, 0x00410040 }, -    { 0x0000989c, 0x0001805e, 0x0001805e }, -    { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, -    { 0x0000989c, 0x000000e1, 0x000000e1 }, -    { 0x0000989c, 0x00007081, 0x00007081 }, -    { 0x0000989c, 0x000000d4, 0x000000d4 }, -    { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7[][2] = { -    { 0x0000989c, 0x00000500 }, -    { 0x0000989c, 0x00000800 }, -    { 0x000098cc, 0x0000000e }, -}; - -static const u32 ar5416Addac[][2] = { -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000003 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x0000000c }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000030 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000060 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000058 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x000098cc,  0x00000000 }, -}; - -static const u32 ar5416Modes_9100[][6] = { -    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, -    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, -    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, -    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, -    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, -    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, -    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, -    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, -    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, -    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, -    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, -    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, -    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, -    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, -    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, -    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, -    { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, -    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e }, -    { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, -    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, -    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, -    { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, -    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, -    { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, -    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, -    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d }, -    { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 }, -    { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, -    { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e }, -    { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff }, -#ifdef TB243 -    { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, -    { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, -    { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, -    { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 }, -#else -    { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, -    { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, -    { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, -    { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, -#endif -    { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 }, -    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, -    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, -    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, -    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, -    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, -    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, -    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, -    { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, -    { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, -    { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, -    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, -    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, -    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, -    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, -    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, -    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, -    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, -    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, -    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, -    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, -    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, -    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, -    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, -    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common_9100[][2] = { -    { 0x0000000c, 0x00000000 }, -    { 0x00000030, 0x00020015 }, -    { 0x00000034, 0x00000005 }, -    { 0x00000040, 0x00000000 }, -    { 0x00000044, 0x00000008 }, -    { 0x00000048, 0x00000008 }, -    { 0x0000004c, 0x00000010 }, -    { 0x00000050, 0x00000000 }, -    { 0x00000054, 0x0000001f }, -    { 0x00000800, 0x00000000 }, -    { 0x00000804, 0x00000000 }, -    { 0x00000808, 0x00000000 }, -    { 0x0000080c, 0x00000000 }, -    { 0x00000810, 0x00000000 }, -    { 0x00000814, 0x00000000 }, -    { 0x00000818, 0x00000000 }, -    { 0x0000081c, 0x00000000 }, -    { 0x00000820, 0x00000000 }, -    { 0x00000824, 0x00000000 }, -    { 0x00001040, 0x002ffc0f }, -    { 0x00001044, 0x002ffc0f }, -    { 0x00001048, 0x002ffc0f }, -    { 0x0000104c, 0x002ffc0f }, -    { 0x00001050, 0x002ffc0f }, -    { 0x00001054, 0x002ffc0f }, -    { 0x00001058, 0x002ffc0f }, -    { 0x0000105c, 0x002ffc0f }, -    { 0x00001060, 0x002ffc0f }, -    { 0x00001064, 0x002ffc0f }, -    { 0x00001230, 0x00000000 }, -    { 0x00001270, 0x00000000 }, -    { 0x00001038, 0x00000000 }, -    { 0x00001078, 0x00000000 }, -    { 0x000010b8, 0x00000000 }, -    { 0x000010f8, 0x00000000 }, -    { 0x00001138, 0x00000000 }, -    { 0x00001178, 0x00000000 }, -    { 0x000011b8, 0x00000000 }, -    { 0x000011f8, 0x00000000 }, -    { 0x00001238, 0x00000000 }, -    { 0x00001278, 0x00000000 }, -    { 0x000012b8, 0x00000000 }, -    { 0x000012f8, 0x00000000 }, -    { 0x00001338, 0x00000000 }, -    { 0x00001378, 0x00000000 }, -    { 0x000013b8, 0x00000000 }, -    { 0x000013f8, 0x00000000 }, -    { 0x00001438, 0x00000000 }, -    { 0x00001478, 0x00000000 }, -    { 0x000014b8, 0x00000000 }, -    { 0x000014f8, 0x00000000 }, -    { 0x00001538, 0x00000000 }, -    { 0x00001578, 0x00000000 }, -    { 0x000015b8, 0x00000000 }, -    { 0x000015f8, 0x00000000 }, -    { 0x00001638, 0x00000000 }, -    { 0x00001678, 0x00000000 }, -    { 0x000016b8, 0x00000000 }, -    { 0x000016f8, 0x00000000 }, -    { 0x00001738, 0x00000000 }, -    { 0x00001778, 0x00000000 }, -    { 0x000017b8, 0x00000000 }, -    { 0x000017f8, 0x00000000 }, -    { 0x0000103c, 0x00000000 }, -    { 0x0000107c, 0x00000000 }, -    { 0x000010bc, 0x00000000 }, -    { 0x000010fc, 0x00000000 }, -    { 0x0000113c, 0x00000000 }, -    { 0x0000117c, 0x00000000 }, -    { 0x000011bc, 0x00000000 }, -    { 0x000011fc, 0x00000000 }, -    { 0x0000123c, 0x00000000 }, -    { 0x0000127c, 0x00000000 }, -    { 0x000012bc, 0x00000000 }, -    { 0x000012fc, 0x00000000 }, -    { 0x0000133c, 0x00000000 }, -    { 0x0000137c, 0x00000000 }, -    { 0x000013bc, 0x00000000 }, -    { 0x000013fc, 0x00000000 }, -    { 0x0000143c, 0x00000000 }, -    { 0x0000147c, 0x00000000 }, -    { 0x00020010, 0x00000003 }, -    { 0x00020038, 0x000004c2 }, -    { 0x00008004, 0x00000000 }, -    { 0x00008008, 0x00000000 }, -    { 0x0000800c, 0x00000000 }, -    { 0x00008018, 0x00000700 }, -    { 0x00008020, 0x00000000 }, -    { 0x00008038, 0x00000000 }, -    { 0x0000803c, 0x00000000 }, -    { 0x00008048, 0x40000000 }, -    { 0x00008054, 0x00004000 }, -    { 0x00008058, 0x00000000 }, -    { 0x0000805c, 0x000fc78f }, -    { 0x00008060, 0x0000000f }, -    { 0x00008064, 0x00000000 }, -    { 0x000080c0, 0x2a82301a }, -    { 0x000080c4, 0x05dc01e0 }, -    { 0x000080c8, 0x1f402710 }, -    { 0x000080cc, 0x01f40000 }, -    { 0x000080d0, 0x00001e00 }, -    { 0x000080d4, 0x00000000 }, -    { 0x000080d8, 0x00400000 }, -    { 0x000080e0, 0xffffffff }, -    { 0x000080e4, 0x0000ffff }, -    { 0x000080e8, 0x003f3f3f }, -    { 0x000080ec, 0x00000000 }, -    { 0x000080f0, 0x00000000 }, -    { 0x000080f4, 0x00000000 }, -    { 0x000080f8, 0x00000000 }, -    { 0x000080fc, 0x00020000 }, -    { 0x00008100, 0x00020000 }, -    { 0x00008104, 0x00000001 }, -    { 0x00008108, 0x00000052 }, -    { 0x0000810c, 0x00000000 }, -    { 0x00008110, 0x00000168 }, -    { 0x00008118, 0x000100aa }, -    { 0x0000811c, 0x00003210 }, -    { 0x00008120, 0x08f04800 }, -    { 0x00008124, 0x00000000 }, -    { 0x00008128, 0x00000000 }, -    { 0x0000812c, 0x00000000 }, -    { 0x00008130, 0x00000000 }, -    { 0x00008134, 0x00000000 }, -    { 0x00008138, 0x00000000 }, -    { 0x0000813c, 0x00000000 }, -    { 0x00008144, 0x00000000 }, -    { 0x00008168, 0x00000000 }, -    { 0x0000816c, 0x00000000 }, -    { 0x00008170, 0x32143320 }, -    { 0x00008174, 0xfaa4fa50 }, -    { 0x00008178, 0x00000100 }, -    { 0x0000817c, 0x00000000 }, -    { 0x000081c4, 0x00000000 }, -    { 0x000081d0, 0x00003210 }, -    { 0x000081ec, 0x00000000 }, -    { 0x000081f0, 0x00000000 }, -    { 0x000081f4, 0x00000000 }, -    { 0x000081f8, 0x00000000 }, -    { 0x000081fc, 0x00000000 }, -    { 0x00008200, 0x00000000 }, -    { 0x00008204, 0x00000000 }, -    { 0x00008208, 0x00000000 }, -    { 0x0000820c, 0x00000000 }, -    { 0x00008210, 0x00000000 }, -    { 0x00008214, 0x00000000 }, -    { 0x00008218, 0x00000000 }, -    { 0x0000821c, 0x00000000 }, -    { 0x00008220, 0x00000000 }, -    { 0x00008224, 0x00000000 }, -    { 0x00008228, 0x00000000 }, -    { 0x0000822c, 0x00000000 }, -    { 0x00008230, 0x00000000 }, -    { 0x00008234, 0x00000000 }, -    { 0x00008238, 0x00000000 }, -    { 0x0000823c, 0x00000000 }, -    { 0x00008240, 0x00100000 }, -    { 0x00008244, 0x0010f400 }, -    { 0x00008248, 0x00000100 }, -    { 0x0000824c, 0x0001e800 }, -    { 0x00008250, 0x00000000 }, -    { 0x00008254, 0x00000000 }, -    { 0x00008258, 0x00000000 }, -    { 0x0000825c, 0x400000ff }, -    { 0x00008260, 0x00080922 }, -    { 0x00008270, 0x00000000 }, -    { 0x00008274, 0x40000000 }, -    { 0x00008278, 0x003e4180 }, -    { 0x0000827c, 0x00000000 }, -    { 0x00008284, 0x0000002c }, -    { 0x00008288, 0x0000002c }, -    { 0x0000828c, 0x00000000 }, -    { 0x00008294, 0x00000000 }, -    { 0x00008298, 0x00000000 }, -    { 0x00008300, 0x00000000 }, -    { 0x00008304, 0x00000000 }, -    { 0x00008308, 0x00000000 }, -    { 0x0000830c, 0x00000000 }, -    { 0x00008310, 0x00000000 }, -    { 0x00008314, 0x00000000 }, -    { 0x00008318, 0x00000000 }, -    { 0x00008328, 0x00000000 }, -    { 0x0000832c, 0x00000007 }, -    { 0x00008330, 0x00000302 }, -    { 0x00008334, 0x00000e00 }, -    { 0x00008338, 0x00000000 }, -    { 0x0000833c, 0x00000000 }, -    { 0x00008340, 0x000107ff }, -    { 0x00009808, 0x00000000 }, -    { 0x0000980c, 0xad848e19 }, -    { 0x00009810, 0x7d14e000 }, -    { 0x00009814, 0x9c0a9f6b }, -    { 0x0000981c, 0x00000000 }, -    { 0x0000982c, 0x0000a000 }, -    { 0x00009830, 0x00000000 }, -    { 0x0000983c, 0x00200400 }, -    { 0x00009840, 0x206a01ae }, -    { 0x0000984c, 0x1284233c }, -    { 0x00009854, 0x00000859 }, -    { 0x00009900, 0x00000000 }, -    { 0x00009904, 0x00000000 }, -    { 0x00009908, 0x00000000 }, -    { 0x0000990c, 0x00000000 }, -    { 0x0000991c, 0x10000fff }, -    { 0x00009920, 0x05100000 }, -    { 0x0000a920, 0x05100000 }, -    { 0x0000b920, 0x05100000 }, -    { 0x00009928, 0x00000001 }, -    { 0x0000992c, 0x00000004 }, -    { 0x00009934, 0x1e1f2022 }, -    { 0x00009938, 0x0a0b0c0d }, -    { 0x0000993c, 0x00000000 }, -    { 0x00009948, 0x9280b212 }, -    { 0x0000994c, 0x00020028 }, -    { 0x0000c95c, 0x004b6a8e }, -    { 0x0000c968, 0x000003ce }, -    { 0x00009970, 0x190fb515 }, -    { 0x00009974, 0x00000000 }, -    { 0x00009978, 0x00000001 }, -    { 0x0000997c, 0x00000000 }, -    { 0x00009980, 0x00000000 }, -    { 0x00009984, 0x00000000 }, -    { 0x00009988, 0x00000000 }, -    { 0x0000998c, 0x00000000 }, -    { 0x00009990, 0x00000000 }, -    { 0x00009994, 0x00000000 }, -    { 0x00009998, 0x00000000 }, -    { 0x0000999c, 0x00000000 }, -    { 0x000099a0, 0x00000000 }, -    { 0x000099a4, 0x00000001 }, -    { 0x000099a8, 0x201fff00 }, -    { 0x000099ac, 0x006f0000 }, -    { 0x000099b0, 0x03051000 }, -    { 0x000099dc, 0x00000000 }, -    { 0x000099e0, 0x00000200 }, -    { 0x000099e4, 0xaaaaaaaa }, -    { 0x000099e8, 0x3c466478 }, -    { 0x000099ec, 0x0cc80caa }, -    { 0x000099fc, 0x00001042 }, -    { 0x00009b00, 0x00000000 }, -    { 0x00009b04, 0x00000001 }, -    { 0x00009b08, 0x00000002 }, -    { 0x00009b0c, 0x00000003 }, -    { 0x00009b10, 0x00000004 }, -    { 0x00009b14, 0x00000005 }, -    { 0x00009b18, 0x00000008 }, -    { 0x00009b1c, 0x00000009 }, -    { 0x00009b20, 0x0000000a }, -    { 0x00009b24, 0x0000000b }, -    { 0x00009b28, 0x0000000c }, -    { 0x00009b2c, 0x0000000d }, -    { 0x00009b30, 0x00000010 }, -    { 0x00009b34, 0x00000011 }, -    { 0x00009b38, 0x00000012 }, -    { 0x00009b3c, 0x00000013 }, -    { 0x00009b40, 0x00000014 }, -    { 0x00009b44, 0x00000015 }, -    { 0x00009b48, 0x00000018 }, -    { 0x00009b4c, 0x00000019 }, -    { 0x00009b50, 0x0000001a }, -    { 0x00009b54, 0x0000001b }, -    { 0x00009b58, 0x0000001c }, -    { 0x00009b5c, 0x0000001d }, -    { 0x00009b60, 0x00000020 }, -    { 0x00009b64, 0x00000021 }, -    { 0x00009b68, 0x00000022 }, -    { 0x00009b6c, 0x00000023 }, -    { 0x00009b70, 0x00000024 }, -    { 0x00009b74, 0x00000025 }, -    { 0x00009b78, 0x00000028 }, -    { 0x00009b7c, 0x00000029 }, -    { 0x00009b80, 0x0000002a }, -    { 0x00009b84, 0x0000002b }, -    { 0x00009b88, 0x0000002c }, -    { 0x00009b8c, 0x0000002d }, -    { 0x00009b90, 0x00000030 }, -    { 0x00009b94, 0x00000031 }, -    { 0x00009b98, 0x00000032 }, -    { 0x00009b9c, 0x00000033 }, -    { 0x00009ba0, 0x00000034 }, -    { 0x00009ba4, 0x00000035 }, -    { 0x00009ba8, 0x00000035 }, -    { 0x00009bac, 0x00000035 }, -    { 0x00009bb0, 0x00000035 }, -    { 0x00009bb4, 0x00000035 }, -    { 0x00009bb8, 0x00000035 }, -    { 0x00009bbc, 0x00000035 }, -    { 0x00009bc0, 0x00000035 }, -    { 0x00009bc4, 0x00000035 }, -    { 0x00009bc8, 0x00000035 }, -    { 0x00009bcc, 0x00000035 }, -    { 0x00009bd0, 0x00000035 }, -    { 0x00009bd4, 0x00000035 }, -    { 0x00009bd8, 0x00000035 }, -    { 0x00009bdc, 0x00000035 }, -    { 0x00009be0, 0x00000035 }, -    { 0x00009be4, 0x00000035 }, -    { 0x00009be8, 0x00000035 }, -    { 0x00009bec, 0x00000035 }, -    { 0x00009bf0, 0x00000035 }, -    { 0x00009bf4, 0x00000035 }, -    { 0x00009bf8, 0x00000010 }, -    { 0x00009bfc, 0x0000001a }, -    { 0x0000a210, 0x40806333 }, -    { 0x0000a214, 0x00106c10 }, -    { 0x0000a218, 0x009c4060 }, -    { 0x0000a220, 0x018830c6 }, -    { 0x0000a224, 0x00000400 }, -    { 0x0000a228, 0x001a0bb5 }, -    { 0x0000a22c, 0x00000000 }, -    { 0x0000a234, 0x20202020 }, -    { 0x0000a238, 0x20202020 }, -    { 0x0000a23c, 0x13c889ae }, -    { 0x0000a240, 0x38490a20 }, -    { 0x0000a244, 0x00007bb6 }, -    { 0x0000a248, 0x0fff3ffc }, -    { 0x0000a24c, 0x00000001 }, -    { 0x0000a250, 0x0000a000 }, -    { 0x0000a254, 0x00000000 }, -    { 0x0000a258, 0x0cc75380 }, -    { 0x0000a25c, 0x0f0f0f01 }, -    { 0x0000a260, 0xdfa91f01 }, -    { 0x0000a268, 0x00000001 }, -    { 0x0000a26c, 0x0ebae9c6 }, -    { 0x0000b26c, 0x0ebae9c6 }, -    { 0x0000c26c, 0x0ebae9c6 }, -    { 0x0000d270, 0x00820820 }, -    { 0x0000a278, 0x1ce739ce }, -    { 0x0000a27c, 0x050701ce }, -    { 0x0000a338, 0x00000000 }, -    { 0x0000a33c, 0x00000000 }, -    { 0x0000a340, 0x00000000 }, -    { 0x0000a344, 0x00000000 }, -    { 0x0000a348, 0x3fffffff }, -    { 0x0000a34c, 0x3fffffff }, -    { 0x0000a350, 0x3fffffff }, -    { 0x0000a354, 0x0003ffff }, -    { 0x0000a358, 0x79a8aa33 }, -    { 0x0000d35c, 0x07ffffef }, -    { 0x0000d360, 0x0fffffe7 }, -    { 0x0000d364, 0x17ffffe5 }, -    { 0x0000d368, 0x1fffffe4 }, -    { 0x0000d36c, 0x37ffffe3 }, -    { 0x0000d370, 0x3fffffe3 }, -    { 0x0000d374, 0x57ffffe3 }, -    { 0x0000d378, 0x5fffffe2 }, -    { 0x0000d37c, 0x7fffffe2 }, -    { 0x0000d380, 0x7f3c7bba }, -    { 0x0000d384, 0xf3307ff0 }, -    { 0x0000a388, 0x0c000000 }, -    { 0x0000a38c, 0x20202020 }, -    { 0x0000a390, 0x20202020 }, -    { 0x0000a394, 0x1ce739ce }, -    { 0x0000a398, 0x000001ce }, -    { 0x0000a39c, 0x00000001 }, -    { 0x0000a3a0, 0x00000000 }, -    { 0x0000a3a4, 0x00000000 }, -    { 0x0000a3a8, 0x00000000 }, -    { 0x0000a3ac, 0x00000000 }, -    { 0x0000a3b0, 0x00000000 }, -    { 0x0000a3b4, 0x00000000 }, -    { 0x0000a3b8, 0x00000000 }, -    { 0x0000a3bc, 0x00000000 }, -    { 0x0000a3c0, 0x00000000 }, -    { 0x0000a3c4, 0x00000000 }, -    { 0x0000a3c8, 0x00000246 }, -    { 0x0000a3cc, 0x20202020 }, -    { 0x0000a3d0, 0x20202020 }, -    { 0x0000a3d4, 0x20202020 }, -    { 0x0000a3dc, 0x1ce739ce }, -    { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0_9100[][2] = { -    { 0x000098b0, 0x1e5795e5 }, -    { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain_9100[][3] = { -    { 0x00009a00, 0x00000000, 0x00000000 }, -    { 0x00009a04, 0x00000040, 0x00000040 }, -    { 0x00009a08, 0x00000080, 0x00000080 }, -    { 0x00009a0c, 0x000001a1, 0x00000141 }, -    { 0x00009a10, 0x000001e1, 0x00000181 }, -    { 0x00009a14, 0x00000021, 0x000001c1 }, -    { 0x00009a18, 0x00000061, 0x00000001 }, -    { 0x00009a1c, 0x00000168, 0x00000041 }, -    { 0x00009a20, 0x000001a8, 0x000001a8 }, -    { 0x00009a24, 0x000001e8, 0x000001e8 }, -    { 0x00009a28, 0x00000028, 0x00000028 }, -    { 0x00009a2c, 0x00000068, 0x00000068 }, -    { 0x00009a30, 0x00000189, 0x000000a8 }, -    { 0x00009a34, 0x000001c9, 0x00000169 }, -    { 0x00009a38, 0x00000009, 0x000001a9 }, -    { 0x00009a3c, 0x00000049, 0x000001e9 }, -    { 0x00009a40, 0x00000089, 0x00000029 }, -    { 0x00009a44, 0x00000170, 0x00000069 }, -    { 0x00009a48, 0x000001b0, 0x00000190 }, -    { 0x00009a4c, 0x000001f0, 0x000001d0 }, -    { 0x00009a50, 0x00000030, 0x00000010 }, -    { 0x00009a54, 0x00000070, 0x00000050 }, -    { 0x00009a58, 0x00000191, 0x00000090 }, -    { 0x00009a5c, 0x000001d1, 0x00000151 }, -    { 0x00009a60, 0x00000011, 0x00000191 }, -    { 0x00009a64, 0x00000051, 0x000001d1 }, -    { 0x00009a68, 0x00000091, 0x00000011 }, -    { 0x00009a6c, 0x000001b8, 0x00000051 }, -    { 0x00009a70, 0x000001f8, 0x00000198 }, -    { 0x00009a74, 0x00000038, 0x000001d8 }, -    { 0x00009a78, 0x00000078, 0x00000018 }, -    { 0x00009a7c, 0x00000199, 0x00000058 }, -    { 0x00009a80, 0x000001d9, 0x00000098 }, -    { 0x00009a84, 0x00000019, 0x00000159 }, -    { 0x00009a88, 0x00000059, 0x00000199 }, -    { 0x00009a8c, 0x00000099, 0x000001d9 }, -    { 0x00009a90, 0x000000d9, 0x00000019 }, -    { 0x00009a94, 0x000000f9, 0x00000059 }, -    { 0x00009a98, 0x000000f9, 0x00000099 }, -    { 0x00009a9c, 0x000000f9, 0x000000d9 }, -    { 0x00009aa0, 0x000000f9, 0x000000f9 }, -    { 0x00009aa4, 0x000000f9, 0x000000f9 }, -    { 0x00009aa8, 0x000000f9, 0x000000f9 }, -    { 0x00009aac, 0x000000f9, 0x000000f9 }, -    { 0x00009ab0, 0x000000f9, 0x000000f9 }, -    { 0x00009ab4, 0x000000f9, 0x000000f9 }, -    { 0x00009ab8, 0x000000f9, 0x000000f9 }, -    { 0x00009abc, 0x000000f9, 0x000000f9 }, -    { 0x00009ac0, 0x000000f9, 0x000000f9 }, -    { 0x00009ac4, 0x000000f9, 0x000000f9 }, -    { 0x00009ac8, 0x000000f9, 0x000000f9 }, -    { 0x00009acc, 0x000000f9, 0x000000f9 }, -    { 0x00009ad0, 0x000000f9, 0x000000f9 }, -    { 0x00009ad4, 0x000000f9, 0x000000f9 }, -    { 0x00009ad8, 0x000000f9, 0x000000f9 }, -    { 0x00009adc, 0x000000f9, 0x000000f9 }, -    { 0x00009ae0, 0x000000f9, 0x000000f9 }, -    { 0x00009ae4, 0x000000f9, 0x000000f9 }, -    { 0x00009ae8, 0x000000f9, 0x000000f9 }, -    { 0x00009aec, 0x000000f9, 0x000000f9 }, -    { 0x00009af0, 0x000000f9, 0x000000f9 }, -    { 0x00009af4, 0x000000f9, 0x000000f9 }, -    { 0x00009af8, 0x000000f9, 0x000000f9 }, -    { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1_9100[][2] = { -    { 0x000098b0, 0x02108421}, -    { 0x000098ec, 0x00000008}, -}; - -static const u32 ar5416Bank2_9100[][2] = { -    { 0x000098b0, 0x0e73ff17}, -    { 0x000098e0, 0x00000420}, -}; - -static const u32 ar5416Bank3_9100[][3] = { -    { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6_9100[][3] = { - -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00e00000, 0x00e00000 }, -    { 0x0000989c, 0x005e0000, 0x005e0000 }, -    { 0x0000989c, 0x00120000, 0x00120000 }, -    { 0x0000989c, 0x00620000, 0x00620000 }, -    { 0x0000989c, 0x00020000, 0x00020000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x005f0000, 0x005f0000 }, -    { 0x0000989c, 0x00870000, 0x00870000 }, -    { 0x0000989c, 0x00f90000, 0x00f90000 }, -    { 0x0000989c, 0x007b0000, 0x007b0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00f50000, 0x00f50000 }, -    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, -    { 0x0000989c, 0x00110000, 0x00110000 }, -    { 0x0000989c, 0x006100a8, 0x006100a8 }, -    { 0x0000989c, 0x004210a2, 0x004210a2 }, -    { 0x0000989c, 0x0014000f, 0x0014000f }, -    { 0x0000989c, 0x00c40002, 0x00c40002 }, -    { 0x0000989c, 0x003000f2, 0x003000f2 }, -    { 0x0000989c, 0x00440016, 0x00440016 }, -    { 0x0000989c, 0x00410040, 0x00410040 }, -    { 0x0000989c, 0x000180d6, 0x000180d6 }, -    { 0x0000989c, 0x0000c0aa, 0x0000c0aa }, -    { 0x0000989c, 0x000000b1, 0x000000b1 }, -    { 0x0000989c, 0x00002000, 0x00002000 }, -    { 0x0000989c, 0x000000d4, 0x000000d4 }, -    { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - - -static const u32 ar5416Bank6TPC_9100[][3] = { - -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00e00000, 0x00e00000 }, -    { 0x0000989c, 0x005e0000, 0x005e0000 }, -    { 0x0000989c, 0x00120000, 0x00120000 }, -    { 0x0000989c, 0x00620000, 0x00620000 }, -    { 0x0000989c, 0x00020000, 0x00020000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x40ff0000, 0x40ff0000 }, -    { 0x0000989c, 0x005f0000, 0x005f0000 }, -    { 0x0000989c, 0x00870000, 0x00870000 }, -    { 0x0000989c, 0x00f90000, 0x00f90000 }, -    { 0x0000989c, 0x007b0000, 0x007b0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00f50000, 0x00f50000 }, -    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, -    { 0x0000989c, 0x00110000, 0x00110000 }, -    { 0x0000989c, 0x006100a8, 0x006100a8 }, -    { 0x0000989c, 0x00423022, 0x00423022 }, -    { 0x0000989c, 0x2014008f, 0x2014008f }, -    { 0x0000989c, 0x00c40002, 0x00c40002 }, -    { 0x0000989c, 0x003000f2, 0x003000f2 }, -    { 0x0000989c, 0x00440016, 0x00440016 }, -    { 0x0000989c, 0x00410040, 0x00410040 }, -    { 0x0000989c, 0x0001805e, 0x0001805e }, -    { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, -    { 0x0000989c, 0x000000e1, 0x000000e1 }, -    { 0x0000989c, 0x00007080, 0x00007080 }, -    { 0x0000989c, 0x000000d4, 0x000000d4 }, -    { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7_9100[][2] = { -    { 0x0000989c, 0x00000500 }, -    { 0x0000989c, 0x00000800 }, -    { 0x000098cc, 0x0000000e }, -}; - -static const u32 ar5416Addac_9100[][2] = { -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000010 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x000000c0 }, -    {0x0000989c, 0x00000015 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x0000989c, 0x00000000 }, -    {0x000098cc, 0x00000000 }, -}; - -static const u32 ar5416Modes_9160[][6] = { -    { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, -    { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, -    { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, -    { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, -    { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, -    { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, -    { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, -    { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, -    { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, -    { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, -    { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, -    { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, -    { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, -    { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, -    { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, -    { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, -    { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, -    { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, -    { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, -    { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, -    { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, -    { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, -    { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, -    { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, -    { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, -    { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, -    { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, -    { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, -    { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, -    { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, -    { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, -    { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, -    { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, -    { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, -    { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, -    { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, -    { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, -    { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, -    { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, -    { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, -    { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, -    { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, -    { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, -    { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, -    { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, -    { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, -    { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, -    { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, -    { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, -    { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, -    { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, -    { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, -    { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, -    { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, -    { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, -    { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, -    { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -    { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; +#ifndef INITVALS_9002_10_H +#define INITVALS_9002_10_H -static const u32 ar5416Common_9160[][2] = { -    { 0x0000000c, 0x00000000 }, -    { 0x00000030, 0x00020015 }, -    { 0x00000034, 0x00000005 }, -    { 0x00000040, 0x00000000 }, -    { 0x00000044, 0x00000008 }, -    { 0x00000048, 0x00000008 }, -    { 0x0000004c, 0x00000010 }, -    { 0x00000050, 0x00000000 }, -    { 0x00000054, 0x0000001f }, -    { 0x00000800, 0x00000000 }, -    { 0x00000804, 0x00000000 }, -    { 0x00000808, 0x00000000 }, -    { 0x0000080c, 0x00000000 }, -    { 0x00000810, 0x00000000 }, -    { 0x00000814, 0x00000000 }, -    { 0x00000818, 0x00000000 }, -    { 0x0000081c, 0x00000000 }, -    { 0x00000820, 0x00000000 }, -    { 0x00000824, 0x00000000 }, -    { 0x00001040, 0x002ffc0f }, -    { 0x00001044, 0x002ffc0f }, -    { 0x00001048, 0x002ffc0f }, -    { 0x0000104c, 0x002ffc0f }, -    { 0x00001050, 0x002ffc0f }, -    { 0x00001054, 0x002ffc0f }, -    { 0x00001058, 0x002ffc0f }, -    { 0x0000105c, 0x002ffc0f }, -    { 0x00001060, 0x002ffc0f }, -    { 0x00001064, 0x002ffc0f }, -    { 0x00001230, 0x00000000 }, -    { 0x00001270, 0x00000000 }, -    { 0x00001038, 0x00000000 }, -    { 0x00001078, 0x00000000 }, -    { 0x000010b8, 0x00000000 }, -    { 0x000010f8, 0x00000000 }, -    { 0x00001138, 0x00000000 }, -    { 0x00001178, 0x00000000 }, -    { 0x000011b8, 0x00000000 }, -    { 0x000011f8, 0x00000000 }, -    { 0x00001238, 0x00000000 }, -    { 0x00001278, 0x00000000 }, -    { 0x000012b8, 0x00000000 }, -    { 0x000012f8, 0x00000000 }, -    { 0x00001338, 0x00000000 }, -    { 0x00001378, 0x00000000 }, -    { 0x000013b8, 0x00000000 }, -    { 0x000013f8, 0x00000000 }, -    { 0x00001438, 0x00000000 }, -    { 0x00001478, 0x00000000 }, -    { 0x000014b8, 0x00000000 }, -    { 0x000014f8, 0x00000000 }, -    { 0x00001538, 0x00000000 }, -    { 0x00001578, 0x00000000 }, -    { 0x000015b8, 0x00000000 }, -    { 0x000015f8, 0x00000000 }, -    { 0x00001638, 0x00000000 }, -    { 0x00001678, 0x00000000 }, -    { 0x000016b8, 0x00000000 }, -    { 0x000016f8, 0x00000000 }, -    { 0x00001738, 0x00000000 }, -    { 0x00001778, 0x00000000 }, -    { 0x000017b8, 0x00000000 }, -    { 0x000017f8, 0x00000000 }, -    { 0x0000103c, 0x00000000 }, -    { 0x0000107c, 0x00000000 }, -    { 0x000010bc, 0x00000000 }, -    { 0x000010fc, 0x00000000 }, -    { 0x0000113c, 0x00000000 }, -    { 0x0000117c, 0x00000000 }, -    { 0x000011bc, 0x00000000 }, -    { 0x000011fc, 0x00000000 }, -    { 0x0000123c, 0x00000000 }, -    { 0x0000127c, 0x00000000 }, -    { 0x000012bc, 0x00000000 }, -    { 0x000012fc, 0x00000000 }, -    { 0x0000133c, 0x00000000 }, -    { 0x0000137c, 0x00000000 }, -    { 0x000013bc, 0x00000000 }, -    { 0x000013fc, 0x00000000 }, -    { 0x0000143c, 0x00000000 }, -    { 0x0000147c, 0x00000000 }, -    { 0x00004030, 0x00000002 }, -    { 0x0000403c, 0x00000002 }, -    { 0x00007010, 0x00000020 }, -    { 0x00007038, 0x000004c2 }, -    { 0x00008004, 0x00000000 }, -    { 0x00008008, 0x00000000 }, -    { 0x0000800c, 0x00000000 }, -    { 0x00008018, 0x00000700 }, -    { 0x00008020, 0x00000000 }, -    { 0x00008038, 0x00000000 }, -    { 0x0000803c, 0x00000000 }, -    { 0x00008048, 0x40000000 }, -    { 0x00008054, 0x00000000 }, -    { 0x00008058, 0x00000000 }, -    { 0x0000805c, 0x000fc78f }, -    { 0x00008060, 0x0000000f }, -    { 0x00008064, 0x00000000 }, -    { 0x000080c0, 0x2a82301a }, -    { 0x000080c4, 0x05dc01e0 }, -    { 0x000080c8, 0x1f402710 }, -    { 0x000080cc, 0x01f40000 }, -    { 0x000080d0, 0x00001e00 }, -    { 0x000080d4, 0x00000000 }, -    { 0x000080d8, 0x00400000 }, -    { 0x000080e0, 0xffffffff }, -    { 0x000080e4, 0x0000ffff }, -    { 0x000080e8, 0x003f3f3f }, -    { 0x000080ec, 0x00000000 }, -    { 0x000080f0, 0x00000000 }, -    { 0x000080f4, 0x00000000 }, -    { 0x000080f8, 0x00000000 }, -    { 0x000080fc, 0x00020000 }, -    { 0x00008100, 0x00020000 }, -    { 0x00008104, 0x00000001 }, -    { 0x00008108, 0x00000052 }, -    { 0x0000810c, 0x00000000 }, -    { 0x00008110, 0x00000168 }, -    { 0x00008118, 0x000100aa }, -    { 0x0000811c, 0x00003210 }, -    { 0x00008120, 0x08f04800 }, -    { 0x00008124, 0x00000000 }, -    { 0x00008128, 0x00000000 }, -    { 0x0000812c, 0x00000000 }, -    { 0x00008130, 0x00000000 }, -    { 0x00008134, 0x00000000 }, -    { 0x00008138, 0x00000000 }, -    { 0x0000813c, 0x00000000 }, -    { 0x00008144, 0xffffffff }, -    { 0x00008168, 0x00000000 }, -    { 0x0000816c, 0x00000000 }, -    { 0x00008170, 0x32143320 }, -    { 0x00008174, 0xfaa4fa50 }, -    { 0x00008178, 0x00000100 }, -    { 0x0000817c, 0x00000000 }, -    { 0x000081c4, 0x00000000 }, -    { 0x000081d0, 0x00003210 }, -    { 0x000081ec, 0x00000000 }, -    { 0x000081f0, 0x00000000 }, -    { 0x000081f4, 0x00000000 }, -    { 0x000081f8, 0x00000000 }, -    { 0x000081fc, 0x00000000 }, -    { 0x00008200, 0x00000000 }, -    { 0x00008204, 0x00000000 }, -    { 0x00008208, 0x00000000 }, -    { 0x0000820c, 0x00000000 }, -    { 0x00008210, 0x00000000 }, -    { 0x00008214, 0x00000000 }, -    { 0x00008218, 0x00000000 }, -    { 0x0000821c, 0x00000000 }, -    { 0x00008220, 0x00000000 }, -    { 0x00008224, 0x00000000 }, -    { 0x00008228, 0x00000000 }, -    { 0x0000822c, 0x00000000 }, -    { 0x00008230, 0x00000000 }, -    { 0x00008234, 0x00000000 }, -    { 0x00008238, 0x00000000 }, -    { 0x0000823c, 0x00000000 }, -    { 0x00008240, 0x00100000 }, -    { 0x00008244, 0x0010f400 }, -    { 0x00008248, 0x00000100 }, -    { 0x0000824c, 0x0001e800 }, -    { 0x00008250, 0x00000000 }, -    { 0x00008254, 0x00000000 }, -    { 0x00008258, 0x00000000 }, -    { 0x0000825c, 0x400000ff }, -    { 0x00008260, 0x00080922 }, -    { 0x00008270, 0x00000000 }, -    { 0x00008274, 0x40000000 }, -    { 0x00008278, 0x003e4180 }, -    { 0x0000827c, 0x00000000 }, -    { 0x00008284, 0x0000002c }, -    { 0x00008288, 0x0000002c }, -    { 0x0000828c, 0x00000000 }, -    { 0x00008294, 0x00000000 }, -    { 0x00008298, 0x00000000 }, -    { 0x00008300, 0x00000000 }, -    { 0x00008304, 0x00000000 }, -    { 0x00008308, 0x00000000 }, -    { 0x0000830c, 0x00000000 }, -    { 0x00008310, 0x00000000 }, -    { 0x00008314, 0x00000000 }, -    { 0x00008318, 0x00000000 }, -    { 0x00008328, 0x00000000 }, -    { 0x0000832c, 0x00000007 }, -    { 0x00008330, 0x00000302 }, -    { 0x00008334, 0x00000e00 }, -    { 0x00008338, 0x00ff0000 }, -    { 0x0000833c, 0x00000000 }, -    { 0x00008340, 0x000107ff }, -    { 0x00009808, 0x00000000 }, -    { 0x0000980c, 0xad848e19 }, -    { 0x00009810, 0x7d14e000 }, -    { 0x00009814, 0x9c0a9f6b }, -    { 0x0000981c, 0x00000000 }, -    { 0x0000982c, 0x0000a000 }, -    { 0x00009830, 0x00000000 }, -    { 0x0000983c, 0x00200400 }, -    { 0x00009840, 0x206a01ae }, -    { 0x0000984c, 0x1284233c }, -    { 0x00009854, 0x00000859 }, -    { 0x00009900, 0x00000000 }, -    { 0x00009904, 0x00000000 }, -    { 0x00009908, 0x00000000 }, -    { 0x0000990c, 0x00000000 }, -    { 0x0000991c, 0x10000fff }, -    { 0x00009920, 0x05100000 }, -    { 0x0000a920, 0x05100000 }, -    { 0x0000b920, 0x05100000 }, -    { 0x00009928, 0x00000001 }, -    { 0x0000992c, 0x00000004 }, -    { 0x00009934, 0x1e1f2022 }, -    { 0x00009938, 0x0a0b0c0d }, -    { 0x0000993c, 0x00000000 }, -    { 0x00009948, 0x9280b212 }, -    { 0x0000994c, 0x00020028 }, -    { 0x00009954, 0x5f3ca3de }, -    { 0x00009958, 0x2108ecff }, -    { 0x00009940, 0x00750604 }, -    { 0x0000c95c, 0x004b6a8e }, -    { 0x00009970, 0x190fb515 }, -    { 0x00009974, 0x00000000 }, -    { 0x00009978, 0x00000001 }, -    { 0x0000997c, 0x00000000 }, -    { 0x00009980, 0x00000000 }, -    { 0x00009984, 0x00000000 }, -    { 0x00009988, 0x00000000 }, -    { 0x0000998c, 0x00000000 }, -    { 0x00009990, 0x00000000 }, -    { 0x00009994, 0x00000000 }, -    { 0x00009998, 0x00000000 }, -    { 0x0000999c, 0x00000000 }, -    { 0x000099a0, 0x00000000 }, -    { 0x000099a4, 0x00000001 }, -    { 0x000099a8, 0x201fff00 }, -    { 0x000099ac, 0x006f0000 }, -    { 0x000099b0, 0x03051000 }, -    { 0x000099dc, 0x00000000 }, -    { 0x000099e0, 0x00000200 }, -    { 0x000099e4, 0xaaaaaaaa }, -    { 0x000099e8, 0x3c466478 }, -    { 0x000099ec, 0x0cc80caa }, -    { 0x000099fc, 0x00001042 }, -    { 0x00009b00, 0x00000000 }, -    { 0x00009b04, 0x00000001 }, -    { 0x00009b08, 0x00000002 }, -    { 0x00009b0c, 0x00000003 }, -    { 0x00009b10, 0x00000004 }, -    { 0x00009b14, 0x00000005 }, -    { 0x00009b18, 0x00000008 }, -    { 0x00009b1c, 0x00000009 }, -    { 0x00009b20, 0x0000000a }, -    { 0x00009b24, 0x0000000b }, -    { 0x00009b28, 0x0000000c }, -    { 0x00009b2c, 0x0000000d }, -    { 0x00009b30, 0x00000010 }, -    { 0x00009b34, 0x00000011 }, -    { 0x00009b38, 0x00000012 }, -    { 0x00009b3c, 0x00000013 }, -    { 0x00009b40, 0x00000014 }, -    { 0x00009b44, 0x00000015 }, -    { 0x00009b48, 0x00000018 }, -    { 0x00009b4c, 0x00000019 }, -    { 0x00009b50, 0x0000001a }, -    { 0x00009b54, 0x0000001b }, -    { 0x00009b58, 0x0000001c }, -    { 0x00009b5c, 0x0000001d }, -    { 0x00009b60, 0x00000020 }, -    { 0x00009b64, 0x00000021 }, -    { 0x00009b68, 0x00000022 }, -    { 0x00009b6c, 0x00000023 }, -    { 0x00009b70, 0x00000024 }, -    { 0x00009b74, 0x00000025 }, -    { 0x00009b78, 0x00000028 }, -    { 0x00009b7c, 0x00000029 }, -    { 0x00009b80, 0x0000002a }, -    { 0x00009b84, 0x0000002b }, -    { 0x00009b88, 0x0000002c }, -    { 0x00009b8c, 0x0000002d }, -    { 0x00009b90, 0x00000030 }, -    { 0x00009b94, 0x00000031 }, -    { 0x00009b98, 0x00000032 }, -    { 0x00009b9c, 0x00000033 }, -    { 0x00009ba0, 0x00000034 }, -    { 0x00009ba4, 0x00000035 }, -    { 0x00009ba8, 0x00000035 }, -    { 0x00009bac, 0x00000035 }, -    { 0x00009bb0, 0x00000035 }, -    { 0x00009bb4, 0x00000035 }, -    { 0x00009bb8, 0x00000035 }, -    { 0x00009bbc, 0x00000035 }, -    { 0x00009bc0, 0x00000035 }, -    { 0x00009bc4, 0x00000035 }, -    { 0x00009bc8, 0x00000035 }, -    { 0x00009bcc, 0x00000035 }, -    { 0x00009bd0, 0x00000035 }, -    { 0x00009bd4, 0x00000035 }, -    { 0x00009bd8, 0x00000035 }, -    { 0x00009bdc, 0x00000035 }, -    { 0x00009be0, 0x00000035 }, -    { 0x00009be4, 0x00000035 }, -    { 0x00009be8, 0x00000035 }, -    { 0x00009bec, 0x00000035 }, -    { 0x00009bf0, 0x00000035 }, -    { 0x00009bf4, 0x00000035 }, -    { 0x00009bf8, 0x00000010 }, -    { 0x00009bfc, 0x0000001a }, -    { 0x0000a210, 0x40806333 }, -    { 0x0000a214, 0x00106c10 }, -    { 0x0000a218, 0x009c4060 }, -    { 0x0000a220, 0x018830c6 }, -    { 0x0000a224, 0x00000400 }, -    { 0x0000a228, 0x001a0bb5 }, -    { 0x0000a22c, 0x00000000 }, -    { 0x0000a234, 0x20202020 }, -    { 0x0000a238, 0x20202020 }, -    { 0x0000a23c, 0x13c889af }, -    { 0x0000a240, 0x38490a20 }, -    { 0x0000a244, 0x00007bb6 }, -    { 0x0000a248, 0x0fff3ffc }, -    { 0x0000a24c, 0x00000001 }, -    { 0x0000a250, 0x0000e000 }, -    { 0x0000a254, 0x00000000 }, -    { 0x0000a258, 0x0cc75380 }, -    { 0x0000a25c, 0x0f0f0f01 }, -    { 0x0000a260, 0xdfa91f01 }, -    { 0x0000a268, 0x00000001 }, -    { 0x0000a26c, 0x0ebae9c6 }, -    { 0x0000b26c, 0x0ebae9c6 }, -    { 0x0000c26c, 0x0ebae9c6 }, -    { 0x0000d270, 0x00820820 }, -    { 0x0000a278, 0x1ce739ce }, -    { 0x0000a27c, 0x050701ce }, -    { 0x0000a338, 0x00000000 }, -    { 0x0000a33c, 0x00000000 }, -    { 0x0000a340, 0x00000000 }, -    { 0x0000a344, 0x00000000 }, -    { 0x0000a348, 0x3fffffff }, -    { 0x0000a34c, 0x3fffffff }, -    { 0x0000a350, 0x3fffffff }, -    { 0x0000a354, 0x0003ffff }, -    { 0x0000a358, 0x79bfaa03 }, -    { 0x0000d35c, 0x07ffffef }, -    { 0x0000d360, 0x0fffffe7 }, -    { 0x0000d364, 0x17ffffe5 }, -    { 0x0000d368, 0x1fffffe4 }, -    { 0x0000d36c, 0x37ffffe3 }, -    { 0x0000d370, 0x3fffffe3 }, -    { 0x0000d374, 0x57ffffe3 }, -    { 0x0000d378, 0x5fffffe2 }, -    { 0x0000d37c, 0x7fffffe2 }, -    { 0x0000d380, 0x7f3c7bba }, -    { 0x0000d384, 0xf3307ff0 }, -    { 0x0000a388, 0x0c000000 }, -    { 0x0000a38c, 0x20202020 }, -    { 0x0000a390, 0x20202020 }, -    { 0x0000a394, 0x1ce739ce }, -    { 0x0000a398, 0x000001ce }, -    { 0x0000a39c, 0x00000001 }, -    { 0x0000a3a0, 0x00000000 }, -    { 0x0000a3a4, 0x00000000 }, -    { 0x0000a3a8, 0x00000000 }, -    { 0x0000a3ac, 0x00000000 }, -    { 0x0000a3b0, 0x00000000 }, -    { 0x0000a3b4, 0x00000000 }, -    { 0x0000a3b8, 0x00000000 }, -    { 0x0000a3bc, 0x00000000 }, -    { 0x0000a3c0, 0x00000000 }, -    { 0x0000a3c4, 0x00000000 }, -    { 0x0000a3c8, 0x00000246 }, -    { 0x0000a3cc, 0x20202020 }, -    { 0x0000a3d0, 0x20202020 }, -    { 0x0000a3d4, 0x20202020 }, -    { 0x0000a3dc, 0x1ce739ce }, -    { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0_9160[][2] = { -    { 0x000098b0, 0x1e5795e5 }, -    { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain_9160[][3] = { -    { 0x00009a00, 0x00000000, 0x00000000 }, -    { 0x00009a04, 0x00000040, 0x00000040 }, -    { 0x00009a08, 0x00000080, 0x00000080 }, -    { 0x00009a0c, 0x000001a1, 0x00000141 }, -    { 0x00009a10, 0x000001e1, 0x00000181 }, -    { 0x00009a14, 0x00000021, 0x000001c1 }, -    { 0x00009a18, 0x00000061, 0x00000001 }, -    { 0x00009a1c, 0x00000168, 0x00000041 }, -    { 0x00009a20, 0x000001a8, 0x000001a8 }, -    { 0x00009a24, 0x000001e8, 0x000001e8 }, -    { 0x00009a28, 0x00000028, 0x00000028 }, -    { 0x00009a2c, 0x00000068, 0x00000068 }, -    { 0x00009a30, 0x00000189, 0x000000a8 }, -    { 0x00009a34, 0x000001c9, 0x00000169 }, -    { 0x00009a38, 0x00000009, 0x000001a9 }, -    { 0x00009a3c, 0x00000049, 0x000001e9 }, -    { 0x00009a40, 0x00000089, 0x00000029 }, -    { 0x00009a44, 0x00000170, 0x00000069 }, -    { 0x00009a48, 0x000001b0, 0x00000190 }, -    { 0x00009a4c, 0x000001f0, 0x000001d0 }, -    { 0x00009a50, 0x00000030, 0x00000010 }, -    { 0x00009a54, 0x00000070, 0x00000050 }, -    { 0x00009a58, 0x00000191, 0x00000090 }, -    { 0x00009a5c, 0x000001d1, 0x00000151 }, -    { 0x00009a60, 0x00000011, 0x00000191 }, -    { 0x00009a64, 0x00000051, 0x000001d1 }, -    { 0x00009a68, 0x00000091, 0x00000011 }, -    { 0x00009a6c, 0x000001b8, 0x00000051 }, -    { 0x00009a70, 0x000001f8, 0x00000198 }, -    { 0x00009a74, 0x00000038, 0x000001d8 }, -    { 0x00009a78, 0x00000078, 0x00000018 }, -    { 0x00009a7c, 0x00000199, 0x00000058 }, -    { 0x00009a80, 0x000001d9, 0x00000098 }, -    { 0x00009a84, 0x00000019, 0x00000159 }, -    { 0x00009a88, 0x00000059, 0x00000199 }, -    { 0x00009a8c, 0x00000099, 0x000001d9 }, -    { 0x00009a90, 0x000000d9, 0x00000019 }, -    { 0x00009a94, 0x000000f9, 0x00000059 }, -    { 0x00009a98, 0x000000f9, 0x00000099 }, -    { 0x00009a9c, 0x000000f9, 0x000000d9 }, -    { 0x00009aa0, 0x000000f9, 0x000000f9 }, -    { 0x00009aa4, 0x000000f9, 0x000000f9 }, -    { 0x00009aa8, 0x000000f9, 0x000000f9 }, -    { 0x00009aac, 0x000000f9, 0x000000f9 }, -    { 0x00009ab0, 0x000000f9, 0x000000f9 }, -    { 0x00009ab4, 0x000000f9, 0x000000f9 }, -    { 0x00009ab8, 0x000000f9, 0x000000f9 }, -    { 0x00009abc, 0x000000f9, 0x000000f9 }, -    { 0x00009ac0, 0x000000f9, 0x000000f9 }, -    { 0x00009ac4, 0x000000f9, 0x000000f9 }, -    { 0x00009ac8, 0x000000f9, 0x000000f9 }, -    { 0x00009acc, 0x000000f9, 0x000000f9 }, -    { 0x00009ad0, 0x000000f9, 0x000000f9 }, -    { 0x00009ad4, 0x000000f9, 0x000000f9 }, -    { 0x00009ad8, 0x000000f9, 0x000000f9 }, -    { 0x00009adc, 0x000000f9, 0x000000f9 }, -    { 0x00009ae0, 0x000000f9, 0x000000f9 }, -    { 0x00009ae4, 0x000000f9, 0x000000f9 }, -    { 0x00009ae8, 0x000000f9, 0x000000f9 }, -    { 0x00009aec, 0x000000f9, 0x000000f9 }, -    { 0x00009af0, 0x000000f9, 0x000000f9 }, -    { 0x00009af4, 0x000000f9, 0x000000f9 }, -    { 0x00009af8, 0x000000f9, 0x000000f9 }, -    { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1_9160[][2] = { -    { 0x000098b0, 0x02108421 }, -    { 0x000098ec, 0x00000008 }, -}; - -static const u32 ar5416Bank2_9160[][2] = { -    { 0x000098b0, 0x0e73ff17 }, -    { 0x000098e0, 0x00000420 }, -}; - -static const u32 ar5416Bank3_9160[][3] = { -    { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6_9160[][3] = { -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00e00000, 0x00e00000 }, -    { 0x0000989c, 0x005e0000, 0x005e0000 }, -    { 0x0000989c, 0x00120000, 0x00120000 }, -    { 0x0000989c, 0x00620000, 0x00620000 }, -    { 0x0000989c, 0x00020000, 0x00020000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x40ff0000, 0x40ff0000 }, -    { 0x0000989c, 0x005f0000, 0x005f0000 }, -    { 0x0000989c, 0x00870000, 0x00870000 }, -    { 0x0000989c, 0x00f90000, 0x00f90000 }, -    { 0x0000989c, 0x007b0000, 0x007b0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00f50000, 0x00f50000 }, -    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, -    { 0x0000989c, 0x00110000, 0x00110000 }, -    { 0x0000989c, 0x006100a8, 0x006100a8 }, -    { 0x0000989c, 0x004210a2, 0x004210a2 }, -    { 0x0000989c, 0x0014008f, 0x0014008f }, -    { 0x0000989c, 0x00c40003, 0x00c40003 }, -    { 0x0000989c, 0x003000f2, 0x003000f2 }, -    { 0x0000989c, 0x00440016, 0x00440016 }, -    { 0x0000989c, 0x00410040, 0x00410040 }, -    { 0x0000989c, 0x0001805e, 0x0001805e }, -    { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, -    { 0x0000989c, 0x000000f1, 0x000000f1 }, -    { 0x0000989c, 0x00002081, 0x00002081 }, -    { 0x0000989c, 0x000000d4, 0x000000d4 }, -    { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank6TPC_9160[][3] = { -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00000000, 0x00000000 }, -    { 0x0000989c, 0x00e00000, 0x00e00000 }, -    { 0x0000989c, 0x005e0000, 0x005e0000 }, -    { 0x0000989c, 0x00120000, 0x00120000 }, -    { 0x0000989c, 0x00620000, 0x00620000 }, -    { 0x0000989c, 0x00020000, 0x00020000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x40ff0000, 0x40ff0000 }, -    { 0x0000989c, 0x005f0000, 0x005f0000 }, -    { 0x0000989c, 0x00870000, 0x00870000 }, -    { 0x0000989c, 0x00f90000, 0x00f90000 }, -    { 0x0000989c, 0x007b0000, 0x007b0000 }, -    { 0x0000989c, 0x00ff0000, 0x00ff0000 }, -    { 0x0000989c, 0x00f50000, 0x00f50000 }, -    { 0x0000989c, 0x00dc0000, 0x00dc0000 }, -    { 0x0000989c, 0x00110000, 0x00110000 }, -    { 0x0000989c, 0x006100a8, 0x006100a8 }, -    { 0x0000989c, 0x00423022, 0x00423022 }, -    { 0x0000989c, 0x2014008f, 0x2014008f }, -    { 0x0000989c, 0x00c40002, 0x00c40002 }, -    { 0x0000989c, 0x003000f2, 0x003000f2 }, -    { 0x0000989c, 0x00440016, 0x00440016 }, -    { 0x0000989c, 0x00410040, 0x00410040 }, -    { 0x0000989c, 0x0001805e, 0x0001805e }, -    { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, -    { 0x0000989c, 0x000000e1, 0x000000e1 }, -    { 0x0000989c, 0x00007080, 0x00007080 }, -    { 0x0000989c, 0x000000d4, 0x000000d4 }, -    { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7_9160[][2] = { -    { 0x0000989c, 0x00000500 }, -    { 0x0000989c, 0x00000800 }, -    { 0x000098cc, 0x0000000e }, -}; - -static u32 ar5416Addac_9160[][2] = { -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x000000c0 }, -    {0x0000989c,  0x00000018 }, -    {0x0000989c,  0x00000004 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x000000c0 }, -    {0x0000989c,  0x00000019 }, -    {0x0000989c,  0x00000004 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000004 }, -    {0x0000989c,  0x00000003 }, -    {0x0000989c,  0x00000008 }, -    {0x0000989c,  0x00000000 }, -    {0x000098cc,  0x00000000 }, -}; - -static u32 ar5416Addac_91601_1[][2] = { -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x000000c0 }, -    {0x0000989c,  0x00000018 }, -    {0x0000989c,  0x00000004 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x000000c0 }, -    {0x0000989c,  0x00000019 }, -    {0x0000989c,  0x00000004 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x0000989c,  0x00000000 }, -    {0x000098cc,  0x00000000 }, -}; - -/* XXX 9280 1 */  static const u32 ar9280Modes_9280[][6] = {      { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },      { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -2766,7 +793,7 @@ static const u32 ar9280Common_9280_2[][2] = {      { 0x00008258, 0x00000000 },      { 0x0000825c, 0x400000ff },      { 0x00008260, 0x00080922 }, -    { 0x00008264, 0xa8a00010 }, +    { 0x00008264, 0x88a00010 },      { 0x00008270, 0x00000000 },      { 0x00008274, 0x40000000 },      { 0x00008278, 0x003e4180 }, @@ -3441,7 +1468,7 @@ static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {  };  /* AR9285 Revsion 10*/ -static const u_int32_t ar9285Modes_9285[][6] = { +static const u32 ar9285Modes_9285[][6] = {      { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },      { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },      { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, @@ -3763,7 +1790,7 @@ static const u_int32_t ar9285Modes_9285[][6] = {      { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },  }; -static const u_int32_t ar9285Common_9285[][2] = { +static const u32 ar9285Common_9285[][2] = {      { 0x0000000c, 0x00000000 },      { 0x00000030, 0x00020045 },      { 0x00000034, 0x00000005 }, @@ -3936,7 +1963,7 @@ static const u_int32_t ar9285Common_9285[][2] = {      { 0x00008258, 0x00000000 },      { 0x0000825c, 0x400000ff },      { 0x00008260, 0x00080922 }, -    { 0x00008264, 0xa8a00010 }, +    { 0x00008264, 0x88a00010 },      { 0x00008270, 0x00000000 },      { 0x00008274, 0x40000000 },      { 0x00008278, 0x003e4180 }, @@ -4096,7 +2123,7 @@ static const u_int32_t ar9285Common_9285[][2] = {      { 0x00007870, 0x10142c00 },  }; -static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { +static const u32 ar9285PciePhy_clkreq_always_on_L1_9285[][2] = {      {0x00004040,  0x9248fd00 },      {0x00004040,  0x24924924 },      {0x00004040,  0xa8000019 }, @@ -4109,7 +2136,7 @@ static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = {      {0x00004044,  0x00000000 },  }; -static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { +static const u32 ar9285PciePhy_clkreq_off_L1_9285[][2] = {      {0x00004040,  0x9248fd00 },      {0x00004040,  0x24924924 },      {0x00004040,  0xa8000019 }, @@ -4123,7 +2150,7 @@ static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = {  };  /* AR9285 v1_2 PCI Register Writes.  Created: 04/13/09 */ -static const u_int32_t ar9285Modes_9285_1_2[][6] = { +static const u32 ar9285Modes_9285_1_2[][6] = {      /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */      { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },      { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -4429,7 +2456,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = {      { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },  }; -static const u_int32_t ar9285Common_9285_1_2[][2] = { +static const u32 ar9285Common_9285_1_2[][2] = {      { 0x0000000c, 0x00000000 },      { 0x00000030, 0x00020045 },      { 0x00000034, 0x00000005 }, @@ -4748,7 +2775,7 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = {      { 0x00007870, 0x10142c00 },  }; -static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { +static const u32 ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {      /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */      { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, @@ -4789,7 +2816,7 @@ static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = {      { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 },  }; -static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { +static const u32 ar9285Modes_original_tx_gain_9285_1_2[][6] = {      /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */      { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, @@ -4830,7 +2857,7 @@ static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = {      { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },  }; -static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = { +static const u32 ar9285Modes_XE2_0_normal_power[][6] = {      { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 },      { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, @@ -4870,7 +2897,7 @@ static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = {      { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c },  }; -static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = { +static const u32 ar9285Modes_XE2_0_high_power[][6] = {      { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 },      { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, @@ -4910,7 +2937,7 @@ static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = {      { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 },  }; -static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { +static const u32 ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {      {0x00004040,  0x9248fd00 },      {0x00004040,  0x24924924 },      {0x00004040,  0xa8000019 }, @@ -4923,7 +2950,7 @@ static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {      {0x00004044,  0x00000000 },  }; -static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { +static const u32 ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {      {0x00004040,  0x9248fd00 },      {0x00004040,  0x24924924 },      {0x00004040,  0xa8000019 }, @@ -4937,7 +2964,7 @@ static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {  };  /* AR9287 Revision 10 */ -static const u_int32_t ar9287Modes_9287_1_0[][6] = { +static const u32 ar9287Modes_9287_1_0[][6] = {      /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */      { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 },      { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -4984,7 +3011,7 @@ static const u_int32_t ar9287Modes_9287_1_0[][6] = {      { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  }; -static const u_int32_t ar9287Common_9287_1_0[][2] = { +static const u32 ar9287Common_9287_1_0[][2] = {      { 0x0000000c, 0x00000000 },      { 0x00000030, 0x00020015 },      { 0x00000034, 0x00000005 }, @@ -5158,7 +3185,7 @@ static const u_int32_t ar9287Common_9287_1_0[][2] = {      { 0x00008258, 0x00000000 },      { 0x0000825c, 0x400000ff },      { 0x00008260, 0x00080922 }, -    { 0x00008264, 0xa8a00010 }, +    { 0x00008264, 0x88a00010 },      { 0x00008270, 0x00000000 },      { 0x00008274, 0x40000000 },      { 0x00008278, 0x003e4180 }, @@ -5355,7 +3382,7 @@ static const u_int32_t ar9287Common_9287_1_0[][2] = {      { 0x000078b8, 0x2a850160 },  }; -static const u_int32_t ar9287Modes_tx_gain_9287_1_0[][6] = { +static const u32 ar9287Modes_tx_gain_9287_1_0[][6] = {      /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */      { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 }, @@ -5405,7 +3432,7 @@ static const u_int32_t ar9287Modes_tx_gain_9287_1_0[][6] = {  }; -static const u_int32_t ar9287Modes_rx_gain_9287_1_0[][6] = { +static const u32 ar9287Modes_rx_gain_9287_1_0[][6] = {      /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */      { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 },      { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, @@ -5667,7 +3694,7 @@ static const u_int32_t ar9287Modes_rx_gain_9287_1_0[][6] = {      { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 },  }; -static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = { +static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = {      {0x00004040,  0x9248fd00 },      {0x00004040,  0x24924924 },      {0x00004040,  0xa8000019 }, @@ -5680,7 +3707,7 @@ static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = {      {0x00004044,  0x00000000 },  }; -static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = { +static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = {      {0x00004040,  0x9248fd00 },      {0x00004040,  0x24924924 },      {0x00004040,  0xa8000019 }, @@ -5695,7 +3722,7 @@ static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = {  /* AR9287 Revision 11 */ -static const u_int32_t ar9287Modes_9287_1_1[][6] = { +static const u32 ar9287Modes_9287_1_1[][6] = {      /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */      { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 },      { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 }, @@ -5742,7 +3769,7 @@ static const u_int32_t ar9287Modes_9287_1_1[][6] = {      { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  }; -static const u_int32_t ar9287Common_9287_1_1[][2] = { +static const u32 ar9287Common_9287_1_1[][2] = {      { 0x0000000c, 0x00000000 },      { 0x00000030, 0x00020015 },      { 0x00000034, 0x00000005 }, @@ -6112,21 +4139,22 @@ static const u_int32_t ar9287Common_9287_1_1[][2] = {  /*   * For Japanese regulatory requirements, 2484 MHz requires the following three - * registers be programmed differently from the channel between 2412 and 2472 MHz. + * registers be programmed differently from the channel between 2412 and + * 2472 MHz.   */ -static const u_int32_t ar9287Common_normal_cck_fir_coeff_92871_1[][2] = { +static const u32 ar9287Common_normal_cck_fir_coeff_92871_1[][2] = {      { 0x0000a1f4, 0x00fffeff },      { 0x0000a1f8, 0x00f5f9ff },      { 0x0000a1fc, 0xb79f6427 },  }; -static const u_int32_t ar9287Common_japan_2484_cck_fir_coeff_92871_1[][2] = { +static const u32 ar9287Common_japan_2484_cck_fir_coeff_92871_1[][2] = {      { 0x0000a1f4, 0x00000000 },      { 0x0000a1f8, 0xefff0301 },      { 0x0000a1fc, 0xca9228ee },  }; -static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = { +static const u32 ar9287Modes_tx_gain_9287_1_1[][6] = {      /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */      { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 }, @@ -6175,7 +4203,7 @@ static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = {      { 0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000 },  }; -static const u_int32_t ar9287Modes_rx_gain_9287_1_1[][6] = { +static const u32 ar9287Modes_rx_gain_9287_1_1[][6] = {      /* Address      5G-HT20     5G-HT40     2G-HT40     2G-HT20     Turbo   */      { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 },      { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, @@ -6437,7 +4465,7 @@ static const u_int32_t ar9287Modes_rx_gain_9287_1_1[][6] = {      { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 },  }; -static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { +static const u32 ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = {      {0x00004040,  0x9248fd00 },      {0x00004040,  0x24924924 },      {0x00004040,  0xa8000019 }, @@ -6450,7 +4478,7 @@ static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = {      {0x00004044,  0x00000000 },  }; -static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { +static const u32 ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = {      {0x00004040,  0x9248fd00 },      {0x00004040,  0x24924924 },      {0x00004040,  0xa8000019 }, @@ -6465,7 +4493,7 @@ static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = {  /* AR9271 initialization values automaticaly created: 06/04/09 */ -static const u_int32_t ar9271Modes_9271[][6] = { +static const u32 ar9271Modes_9271[][6] = {      { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },      { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },      { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, @@ -6771,7 +4799,7 @@ static const u_int32_t ar9271Modes_9271[][6] = {      { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },  }; -static const u_int32_t ar9271Common_9271[][2] = { +static const u32 ar9271Common_9271[][2] = {      { 0x0000000c, 0x00000000 },      { 0x00000030, 0x00020045 },      { 0x00000034, 0x00000005 }, @@ -6945,7 +4973,7 @@ static const u_int32_t ar9271Common_9271[][2] = {      { 0x00008258, 0x00000000 },      { 0x0000825c, 0x400000ff },      { 0x00008260, 0x00080922 }, -    { 0x00008264, 0xa8a00010 }, +    { 0x00008264, 0x88a00010 },      { 0x00008270, 0x00000000 },      { 0x00008274, 0x40000000 },      { 0x00008278, 0x003e4180 }, @@ -7099,24 +5127,24 @@ static const u_int32_t ar9271Common_9271[][2] = {      { 0x0000d384, 0xf3307ff0 },  }; -static const u_int32_t ar9271Common_normal_cck_fir_coeff_9271[][2] = { +static const u32 ar9271Common_normal_cck_fir_coeff_9271[][2] = {      { 0x0000a1f4, 0x00fffeff },      { 0x0000a1f8, 0x00f5f9ff },      { 0x0000a1fc, 0xb79f6427 },  }; -static const u_int32_t ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = { +static const u32 ar9271Common_japan_2484_cck_fir_coeff_9271[][2] = {      { 0x0000a1f4, 0x00000000 },      { 0x0000a1f8, 0xefff0301 },      { 0x0000a1fc, 0xca9228ee },  }; -static const u_int32_t ar9271Modes_9271_1_0_only[][6] = { +static const u32 ar9271Modes_9271_1_0_only[][6] = {      { 0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311 },      { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },  }; -static const u_int32_t ar9271Modes_9271_ANI_reg[][6] = { +static const u32 ar9271Modes_9271_ANI_reg[][6] = {      { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },      { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e },      { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, @@ -7127,7 +5155,7 @@ static const u_int32_t ar9271Modes_9271_ANI_reg[][6] = {      { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },  }; -static const u_int32_t ar9271Modes_normal_power_tx_gain_9271[][6] = { +static const u32 ar9271Modes_normal_power_tx_gain_9271[][6] = {      { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },      { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 },      { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, @@ -7163,7 +5191,7 @@ static const u_int32_t ar9271Modes_normal_power_tx_gain_9271[][6] = {      { 0x0000a3e0, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd, 0x000003bd },  }; -static const u_int32_t ar9271Modes_high_power_tx_gain_9271[][6] = { +static const u32 ar9271Modes_high_power_tx_gain_9271[][6] = {      { 0x0000a300, 0x00000000, 0x00000000, 0x00010000, 0x00010000, 0x00000000 },      { 0x0000a304, 0x00000000, 0x00000000, 0x00016200, 0x00016200, 0x00000000 },      { 0x0000a308, 0x00000000, 0x00000000, 0x00018201, 0x00018201, 0x00000000 }, @@ -7198,3 +5226,5 @@ static const u_int32_t ar9271Modes_high_power_tx_gain_9271[][6] = {      { 0x0000a3dc, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63, 0x06318c63 },      { 0x0000a3e0, 0x00000063, 0x00000063, 0x00000063, 0x00000063, 0x00000063 },  }; + +#endif /* INITVALS_9002_10_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c new file mode 100644 index 00000000000..2be20d2070c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" + +#define AR_BufLen           0x00000fff + +static void ar9002_hw_rx_enable(struct ath_hw *ah) +{ +	REG_WRITE(ah, AR_CR, AR_CR_RXE); +} + +static void ar9002_hw_set_desc_link(void *ds, u32 ds_link) +{ +	((struct ath_desc*) ds)->ds_link = ds_link; +} + +static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link) +{ +	*ds_link = &((struct ath_desc *)ds)->ds_link; +} + +static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) +{ +	u32 isr = 0; +	u32 mask2 = 0; +	struct ath9k_hw_capabilities *pCap = &ah->caps; +	u32 sync_cause = 0; +	bool fatal_int = false; +	struct ath_common *common = ath9k_hw_common(ah); + +	if (!AR_SREV_9100(ah)) { +		if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { +			if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) +			    == AR_RTC_STATUS_ON) { +				isr = REG_READ(ah, AR_ISR); +			} +		} + +		sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & +			AR_INTR_SYNC_DEFAULT; + +		*masked = 0; + +		if (!isr && !sync_cause) +			return false; +	} else { +		*masked = 0; +		isr = REG_READ(ah, AR_ISR); +	} + +	if (isr) { +		if (isr & AR_ISR_BCNMISC) { +			u32 isr2; +			isr2 = REG_READ(ah, AR_ISR_S2); +			if (isr2 & AR_ISR_S2_TIM) +				mask2 |= ATH9K_INT_TIM; +			if (isr2 & AR_ISR_S2_DTIM) +				mask2 |= ATH9K_INT_DTIM; +			if (isr2 & AR_ISR_S2_DTIMSYNC) +				mask2 |= ATH9K_INT_DTIMSYNC; +			if (isr2 & (AR_ISR_S2_CABEND)) +				mask2 |= ATH9K_INT_CABEND; +			if (isr2 & AR_ISR_S2_GTT) +				mask2 |= ATH9K_INT_GTT; +			if (isr2 & AR_ISR_S2_CST) +				mask2 |= ATH9K_INT_CST; +			if (isr2 & AR_ISR_S2_TSFOOR) +				mask2 |= ATH9K_INT_TSFOOR; +		} + +		isr = REG_READ(ah, AR_ISR_RAC); +		if (isr == 0xffffffff) { +			*masked = 0; +			return false; +		} + +		*masked = isr & ATH9K_INT_COMMON; + +		if (ah->config.rx_intr_mitigation) { +			if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) +				*masked |= ATH9K_INT_RX; +		} + +		if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) +			*masked |= ATH9K_INT_RX; +		if (isr & +		    (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | +		     AR_ISR_TXEOL)) { +			u32 s0_s, s1_s; + +			*masked |= ATH9K_INT_TX; + +			s0_s = REG_READ(ah, AR_ISR_S0_S); +			ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); +			ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); + +			s1_s = REG_READ(ah, AR_ISR_S1_S); +			ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); +			ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); +		} + +		if (isr & AR_ISR_RXORN) { +			ath_print(common, ATH_DBG_INTERRUPT, +				  "receive FIFO overrun interrupt\n"); +		} + +		if (!AR_SREV_9100(ah)) { +			if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { +				u32 isr5 = REG_READ(ah, AR_ISR_S5_S); +				if (isr5 & AR_ISR_S5_TIM_TIMER) +					*masked |= ATH9K_INT_TIM_TIMER; +			} +		} + +		*masked |= mask2; +	} + +	if (AR_SREV_9100(ah)) +		return true; + +	if (isr & AR_ISR_GENTMR) { +		u32 s5_s; + +		s5_s = REG_READ(ah, AR_ISR_S5_S); +		if (isr & AR_ISR_GENTMR) { +			ah->intr_gen_timer_trigger = +				MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); + +			ah->intr_gen_timer_thresh = +				MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); + +			if (ah->intr_gen_timer_trigger) +				*masked |= ATH9K_INT_GENTIMER; + +		} +	} + +	if (sync_cause) { +		fatal_int = +			(sync_cause & +			 (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) +			? true : false; + +		if (fatal_int) { +			if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { +				ath_print(common, ATH_DBG_ANY, +					  "received PCI FATAL interrupt\n"); +			} +			if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { +				ath_print(common, ATH_DBG_ANY, +					  "received PCI PERR interrupt\n"); +			} +			*masked |= ATH9K_INT_FATAL; +		} +		if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { +			ath_print(common, ATH_DBG_INTERRUPT, +				  "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); +			REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); +			REG_WRITE(ah, AR_RC, 0); +			*masked |= ATH9K_INT_FATAL; +		} +		if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { +			ath_print(common, ATH_DBG_INTERRUPT, +				  "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); +		} + +		REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); +		(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); +	} + +	return true; +} + +static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, +				  bool is_firstseg, bool is_lastseg, +				  const void *ds0, dma_addr_t buf_addr, +				  unsigned int qcu) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); + +	ads->ds_data = buf_addr; + +	if (is_firstseg) { +		ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore); +	} else if (is_lastseg) { +		ads->ds_ctl0 = 0; +		ads->ds_ctl1 = seglen; +		ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; +		ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; +	} else { +		ads->ds_ctl0 = 0; +		ads->ds_ctl1 = seglen | AR_TxMore; +		ads->ds_ctl2 = 0; +		ads->ds_ctl3 = 0; +	} +	ads->ds_txstatus0 = ads->ds_txstatus1 = 0; +	ads->ds_txstatus2 = ads->ds_txstatus3 = 0; +	ads->ds_txstatus4 = ads->ds_txstatus5 = 0; +	ads->ds_txstatus6 = ads->ds_txstatus7 = 0; +	ads->ds_txstatus8 = ads->ds_txstatus9 = 0; +} + +static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, +				 struct ath_tx_status *ts) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); + +	if ((ads->ds_txstatus9 & AR_TxDone) == 0) +		return -EINPROGRESS; + +	ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); +	ts->ts_tstamp = ads->AR_SendTimestamp; +	ts->ts_status = 0; +	ts->ts_flags = 0; + +	if (ads->ds_txstatus1 & AR_FrmXmitOK) +		ts->ts_status |= ATH9K_TX_ACKED; +	if (ads->ds_txstatus1 & AR_ExcessiveRetries) +		ts->ts_status |= ATH9K_TXERR_XRETRY; +	if (ads->ds_txstatus1 & AR_Filtered) +		ts->ts_status |= ATH9K_TXERR_FILT; +	if (ads->ds_txstatus1 & AR_FIFOUnderrun) { +		ts->ts_status |= ATH9K_TXERR_FIFO; +		ath9k_hw_updatetxtriglevel(ah, true); +	} +	if (ads->ds_txstatus9 & AR_TxOpExceeded) +		ts->ts_status |= ATH9K_TXERR_XTXOP; +	if (ads->ds_txstatus1 & AR_TxTimerExpired) +		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; + +	if (ads->ds_txstatus1 & AR_DescCfgErr) +		ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; +	if (ads->ds_txstatus1 & AR_TxDataUnderrun) { +		ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; +		ath9k_hw_updatetxtriglevel(ah, true); +	} +	if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { +		ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; +		ath9k_hw_updatetxtriglevel(ah, true); +	} +	if (ads->ds_txstatus0 & AR_TxBaStatus) { +		ts->ts_flags |= ATH9K_TX_BA; +		ts->ba_low = ads->AR_BaBitmapLow; +		ts->ba_high = ads->AR_BaBitmapHigh; +	} + +	ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); +	switch (ts->ts_rateindex) { +	case 0: +		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); +		break; +	case 1: +		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); +		break; +	case 2: +		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); +		break; +	case 3: +		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); +		break; +	} + +	ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); +	ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); +	ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); +	ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); +	ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); +	ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); +	ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); +	ts->evm0 = ads->AR_TxEVM0; +	ts->evm1 = ads->AR_TxEVM1; +	ts->evm2 = ads->AR_TxEVM2; +	ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); +	ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); +	ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); +	ts->ts_antenna = 0; + +	return 0; +} + +static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, +				    u32 pktLen, enum ath9k_pkt_type type, +				    u32 txPower, u32 keyIx, +				    enum ath9k_key_type keyType, u32 flags) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); + +	txPower += ah->txpower_indexoffset; +	if (txPower > 63) +		txPower = 63; + +	ads->ds_ctl0 = (pktLen & AR_FrameLen) +		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) +		| SM(txPower, AR_XmitPower) +		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) +		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) +		| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) +		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); + +	ads->ds_ctl1 = +		(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) +		| SM(type, AR_FrameType) +		| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) +		| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) +		| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); + +	ads->ds_ctl6 = SM(keyType, AR_EncrType); + +	if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { +		ads->ds_ctl8 = 0; +		ads->ds_ctl9 = 0; +		ads->ds_ctl10 = 0; +		ads->ds_ctl11 = 0; +	} +} + +static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, +					  void *lastds, +					  u32 durUpdateEn, u32 rtsctsRate, +					  u32 rtsctsDuration, +					  struct ath9k_11n_rate_series series[], +					  u32 nseries, u32 flags) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); +	struct ar5416_desc *last_ads = AR5416DESC(lastds); +	u32 ds_ctl0; + +	if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { +		ds_ctl0 = ads->ds_ctl0; + +		if (flags & ATH9K_TXDESC_RTSENA) { +			ds_ctl0 &= ~AR_CTSEnable; +			ds_ctl0 |= AR_RTSEnable; +		} else { +			ds_ctl0 &= ~AR_RTSEnable; +			ds_ctl0 |= AR_CTSEnable; +		} + +		ads->ds_ctl0 = ds_ctl0; +	} else { +		ads->ds_ctl0 = +			(ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); +	} + +	ads->ds_ctl2 = set11nTries(series, 0) +		| set11nTries(series, 1) +		| set11nTries(series, 2) +		| set11nTries(series, 3) +		| (durUpdateEn ? AR_DurUpdateEna : 0) +		| SM(0, AR_BurstDur); + +	ads->ds_ctl3 = set11nRate(series, 0) +		| set11nRate(series, 1) +		| set11nRate(series, 2) +		| set11nRate(series, 3); + +	ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) +		| set11nPktDurRTSCTS(series, 1); + +	ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) +		| set11nPktDurRTSCTS(series, 3); + +	ads->ds_ctl7 = set11nRateFlags(series, 0) +		| set11nRateFlags(series, 1) +		| set11nRateFlags(series, 2) +		| set11nRateFlags(series, 3) +		| SM(rtsctsRate, AR_RTSCTSRate); +	last_ads->ds_ctl2 = ads->ds_ctl2; +	last_ads->ds_ctl3 = ads->ds_ctl3; +} + +static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, +					u32 aggrLen) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); + +	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); +	ads->ds_ctl6 &= ~AR_AggrLen; +	ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); +} + +static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, +					 u32 numDelims) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); +	unsigned int ctl6; + +	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); + +	ctl6 = ads->ds_ctl6; +	ctl6 &= ~AR_PadDelim; +	ctl6 |= SM(numDelims, AR_PadDelim); +	ads->ds_ctl6 = ctl6; +} + +static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); + +	ads->ds_ctl1 |= AR_IsAggr; +	ads->ds_ctl1 &= ~AR_MoreAggr; +	ads->ds_ctl6 &= ~AR_PadDelim; +} + +static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); + +	ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); +} + +static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds, +					   u32 burstDuration) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); + +	ads->ds_ctl2 &= ~AR_BurstDur; +	ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); +} + +static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, +					    u32 vmf) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); + +	if (vmf) +		ads->ds_ctl0 |= AR_VirtMoreFrag; +	else +		ads->ds_ctl0 &= ~AR_VirtMoreFrag; +} + +void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, +			  u32 size, u32 flags) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); +	struct ath9k_hw_capabilities *pCap = &ah->caps; + +	ads->ds_ctl1 = size & AR_BufLen; +	if (flags & ATH9K_RXDESC_INTREQ) +		ads->ds_ctl1 |= AR_RxIntrReq; + +	ads->ds_rxstatus8 &= ~AR_RxDone; +	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) +		memset(&(ads->u), 0, sizeof(ads->u)); +} +EXPORT_SYMBOL(ath9k_hw_setuprxdesc); + +void ar9002_hw_attach_mac_ops(struct ath_hw *ah) +{ +	struct ath_hw_ops *ops = ath9k_hw_ops(ah); + +	ops->rx_enable = ar9002_hw_rx_enable; +	ops->set_desc_link = ar9002_hw_set_desc_link; +	ops->get_desc_link = ar9002_hw_get_desc_link; +	ops->get_isr = ar9002_hw_get_isr; +	ops->fill_txdesc = ar9002_hw_fill_txdesc; +	ops->proc_txdesc = ar9002_hw_proc_txdesc; +	ops->set11n_txdesc = ar9002_hw_set11n_txdesc; +	ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario; +	ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first; +	ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; +	ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; +	ops->clr11n_aggr = ar9002_hw_clr11n_aggr; +	ops->set11n_burstduration = ar9002_hw_set11n_burstduration; +	ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c new file mode 100644 index 00000000000..ed314e89bfe --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Programming Atheros 802.11n analog front end radios + * + * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express + * devices have either an external AR2133 analog front end radio for single + * band 2.4 GHz communication or an AR5133 analog front end radio for dual + * band 2.4 GHz / 5 GHz communication. + * + * All devices after the AR5416 and AR5418 family starting with the AR9280 + * have their analog front radios, MAC/BB and host PCIe/USB interface embedded + * into a single-chip and require less programming. + * + * The following single-chips exist with a respective embedded radio: + * + * AR9280 - 11n dual-band 2x2 MIMO for PCIe + * AR9281 - 11n single-band 1x2 MIMO for PCIe + * AR9285 - 11n single-band 1x1 for PCIe + * AR9287 - 11n single-band 2x2 MIMO for PCIe + * + * AR9220 - 11n dual-band 2x2 MIMO for PCI + * AR9223 - 11n single-band 2x2 MIMO for PCI + * + * AR9287 - 11n single-band 1x1 MIMO for USB + */ + +#include "hw.h" +#include "ar9002_phy.h" + +/** + * ar9002_hw_set_channel - set channel on single-chip device + * @ah: atheros hardware structure + * @chan: + * + * This is the function to change channel on single-chip devices, that is + * all devices after ar9280. + * + * This function takes the channel value in MHz and sets + * hardware channel value. Assumes writes have been enabled to analog bus. + * + * Actual Expression, + * + * For 2GHz channel, + * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + * + * For 5GHz channel, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) + * (freq_ref = 40MHz/(24>>amodeRefSel)) + */ +static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) +{ +	u16 bMode, fracMode, aModeRefSel = 0; +	u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; +	struct chan_centers centers; +	u32 refDivA = 24; + +	ath9k_hw_get_channel_centers(ah, chan, ¢ers); +	freq = centers.synth_center; + +	reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); +	reg32 &= 0xc0000000; + +	if (freq < 4800) { /* 2 GHz, fractional mode */ +		u32 txctl; +		int regWrites = 0; + +		bMode = 1; +		fracMode = 1; +		aModeRefSel = 0; +		channelSel = CHANSEL_2G(freq); + +		if (AR_SREV_9287_11_OR_LATER(ah)) { +			if (freq == 2484) { +				/* Enable channel spreading for channel 14 */ +				REG_WRITE_ARRAY(&ah->iniCckfirJapan2484, +						1, regWrites); +			} else { +				REG_WRITE_ARRAY(&ah->iniCckfirNormal, +						1, regWrites); +			} +		} else { +			txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); +			if (freq == 2484) { +				/* Enable channel spreading for channel 14 */ +				REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, +					  txctl | AR_PHY_CCK_TX_CTRL_JAPAN); +			} else { +				REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, +					  txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); +			} +		} +	} else { +		bMode = 0; +		fracMode = 0; + +		switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) { +		case 0: +			if ((freq % 20) == 0) +				aModeRefSel = 3; +			else if ((freq % 10) == 0) +				aModeRefSel = 2; +			if (aModeRefSel) +				break; +		case 1: +		default: +			aModeRefSel = 0; +			/* +			 * Enable 2G (fractional) mode for channels +			 * which are 5MHz spaced. +			 */ +			fracMode = 1; +			refDivA = 1; +			channelSel = CHANSEL_5G(freq); + +			/* RefDivA setting */ +			REG_RMW_FIELD(ah, AR_AN_SYNTH9, +				      AR_AN_SYNTH9_REFDIVA, refDivA); + +		} + +		if (!fracMode) { +			ndiv = (freq * (refDivA >> aModeRefSel)) / 60; +			channelSel = ndiv & 0x1ff; +			channelFrac = (ndiv & 0xfffffe00) * 2; +			channelSel = (channelSel << 17) | channelFrac; +		} +	} + +	reg32 = reg32 | +	    (bMode << 29) | +	    (fracMode << 28) | (aModeRefSel << 26) | (channelSel); + +	REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); + +	ah->curchan = chan; +	ah->curchan_rad_index = -1; + +	return 0; +} + +/** + * ar9002_hw_spur_mitigate - convert baseband spur frequency + * @ah: atheros hardware structure + * @chan: + * + * For single-chip solutions. Converts to baseband spur frequency given the + * input channel frequency and compute register settings below. + */ +static void ar9002_hw_spur_mitigate(struct ath_hw *ah, +				    struct ath9k_channel *chan) +{ +	int bb_spur = AR_NO_SPUR; +	int freq; +	int bin, cur_bin; +	int bb_spur_off, spur_subchannel_sd; +	int spur_freq_sd; +	int spur_delta_phase; +	int denominator; +	int upper, lower, cur_vit_mask; +	int tmp, newVal; +	int i; +	int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, +			  AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 +	}; +	int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, +			 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 +	}; +	int inc[4] = { 0, 100, 0, 0 }; +	struct chan_centers centers; + +	int8_t mask_m[123]; +	int8_t mask_p[123]; +	int8_t mask_amt; +	int tmp_mask; +	int cur_bb_spur; +	bool is2GHz = IS_CHAN_2GHZ(chan); + +	memset(&mask_m, 0, sizeof(int8_t) * 123); +	memset(&mask_p, 0, sizeof(int8_t) * 123); + +	ath9k_hw_get_channel_centers(ah, chan, ¢ers); +	freq = centers.synth_center; + +	ah->config.spurmode = SPUR_ENABLE_EEPROM; +	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { +		cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); + +		if (is2GHz) +			cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; +		else +			cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; + +		if (AR_NO_SPUR == cur_bb_spur) +			break; +		cur_bb_spur = cur_bb_spur - freq; + +		if (IS_CHAN_HT40(chan)) { +			if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && +			    (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { +				bb_spur = cur_bb_spur; +				break; +			} +		} else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && +			   (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { +			bb_spur = cur_bb_spur; +			break; +		} +	} + +	if (AR_NO_SPUR == bb_spur) { +		REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, +			    AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); +		return; +	} else { +		REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, +			    AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); +	} + +	bin = bb_spur * 320; + +	tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); + +	ENABLE_REGWRITE_BUFFER(ah); + +	newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | +			AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | +			AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | +			AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); +	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); + +	newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | +		  AR_PHY_SPUR_REG_ENABLE_MASK_PPM | +		  AR_PHY_SPUR_REG_MASK_RATE_SELECT | +		  AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | +		  SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); +	REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); + +	if (IS_CHAN_HT40(chan)) { +		if (bb_spur < 0) { +			spur_subchannel_sd = 1; +			bb_spur_off = bb_spur + 10; +		} else { +			spur_subchannel_sd = 0; +			bb_spur_off = bb_spur - 10; +		} +	} else { +		spur_subchannel_sd = 0; +		bb_spur_off = bb_spur; +	} + +	if (IS_CHAN_HT40(chan)) +		spur_delta_phase = +			((bb_spur * 262144) / +			 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; +	else +		spur_delta_phase = +			((bb_spur * 524288) / +			 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; + +	denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; +	spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; + +	newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | +		  SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | +		  SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); +	REG_WRITE(ah, AR_PHY_TIMING11, newVal); + +	newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; +	REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); + +	cur_bin = -6000; +	upper = bin + 100; +	lower = bin - 100; + +	for (i = 0; i < 4; i++) { +		int pilot_mask = 0; +		int chan_mask = 0; +		int bp = 0; +		for (bp = 0; bp < 30; bp++) { +			if ((cur_bin > lower) && (cur_bin < upper)) { +				pilot_mask = pilot_mask | 0x1 << bp; +				chan_mask = chan_mask | 0x1 << bp; +			} +			cur_bin += 100; +		} +		cur_bin += inc[i]; +		REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); +		REG_WRITE(ah, chan_mask_reg[i], chan_mask); +	} + +	cur_vit_mask = 6100; +	upper = bin + 120; +	lower = bin - 120; + +	for (i = 0; i < 123; i++) { +		if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { + +			/* workaround for gcc bug #37014 */ +			volatile int tmp_v = abs(cur_vit_mask - bin); + +			if (tmp_v < 75) +				mask_amt = 1; +			else +				mask_amt = 0; +			if (cur_vit_mask < 0) +				mask_m[abs(cur_vit_mask / 100)] = mask_amt; +			else +				mask_p[cur_vit_mask / 100] = mask_amt; +		} +		cur_vit_mask -= 100; +	} + +	tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) +		| (mask_m[48] << 26) | (mask_m[49] << 24) +		| (mask_m[50] << 22) | (mask_m[51] << 20) +		| (mask_m[52] << 18) | (mask_m[53] << 16) +		| (mask_m[54] << 14) | (mask_m[55] << 12) +		| (mask_m[56] << 10) | (mask_m[57] << 8) +		| (mask_m[58] << 6) | (mask_m[59] << 4) +		| (mask_m[60] << 2) | (mask_m[61] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); +	REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); + +	tmp_mask = (mask_m[31] << 28) +		| (mask_m[32] << 26) | (mask_m[33] << 24) +		| (mask_m[34] << 22) | (mask_m[35] << 20) +		| (mask_m[36] << 18) | (mask_m[37] << 16) +		| (mask_m[48] << 14) | (mask_m[39] << 12) +		| (mask_m[40] << 10) | (mask_m[41] << 8) +		| (mask_m[42] << 6) | (mask_m[43] << 4) +		| (mask_m[44] << 2) | (mask_m[45] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); + +	tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) +		| (mask_m[18] << 26) | (mask_m[18] << 24) +		| (mask_m[20] << 22) | (mask_m[20] << 20) +		| (mask_m[22] << 18) | (mask_m[22] << 16) +		| (mask_m[24] << 14) | (mask_m[24] << 12) +		| (mask_m[25] << 10) | (mask_m[26] << 8) +		| (mask_m[27] << 6) | (mask_m[28] << 4) +		| (mask_m[29] << 2) | (mask_m[30] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); + +	tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) +		| (mask_m[2] << 26) | (mask_m[3] << 24) +		| (mask_m[4] << 22) | (mask_m[5] << 20) +		| (mask_m[6] << 18) | (mask_m[7] << 16) +		| (mask_m[8] << 14) | (mask_m[9] << 12) +		| (mask_m[10] << 10) | (mask_m[11] << 8) +		| (mask_m[12] << 6) | (mask_m[13] << 4) +		| (mask_m[14] << 2) | (mask_m[15] << 0); +	REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); + +	tmp_mask = (mask_p[15] << 28) +		| (mask_p[14] << 26) | (mask_p[13] << 24) +		| (mask_p[12] << 22) | (mask_p[11] << 20) +		| (mask_p[10] << 18) | (mask_p[9] << 16) +		| (mask_p[8] << 14) | (mask_p[7] << 12) +		| (mask_p[6] << 10) | (mask_p[5] << 8) +		| (mask_p[4] << 6) | (mask_p[3] << 4) +		| (mask_p[2] << 2) | (mask_p[1] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); + +	tmp_mask = (mask_p[30] << 28) +		| (mask_p[29] << 26) | (mask_p[28] << 24) +		| (mask_p[27] << 22) | (mask_p[26] << 20) +		| (mask_p[25] << 18) | (mask_p[24] << 16) +		| (mask_p[23] << 14) | (mask_p[22] << 12) +		| (mask_p[21] << 10) | (mask_p[20] << 8) +		| (mask_p[19] << 6) | (mask_p[18] << 4) +		| (mask_p[17] << 2) | (mask_p[16] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); + +	tmp_mask = (mask_p[45] << 28) +		| (mask_p[44] << 26) | (mask_p[43] << 24) +		| (mask_p[42] << 22) | (mask_p[41] << 20) +		| (mask_p[40] << 18) | (mask_p[39] << 16) +		| (mask_p[38] << 14) | (mask_p[37] << 12) +		| (mask_p[36] << 10) | (mask_p[35] << 8) +		| (mask_p[34] << 6) | (mask_p[33] << 4) +		| (mask_p[32] << 2) | (mask_p[31] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); + +	tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) +		| (mask_p[59] << 26) | (mask_p[58] << 24) +		| (mask_p[57] << 22) | (mask_p[56] << 20) +		| (mask_p[55] << 18) | (mask_p[54] << 16) +		| (mask_p[53] << 14) | (mask_p[52] << 12) +		| (mask_p[51] << 10) | (mask_p[50] << 8) +		| (mask_p[49] << 6) | (mask_p[48] << 4) +		| (mask_p[47] << 2) | (mask_p[46] << 0); +	REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); +	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +} + +static void ar9002_olc_init(struct ath_hw *ah) +{ +	u32 i; + +	if (!OLC_FOR_AR9280_20_LATER) +		return; + +	if (OLC_FOR_AR9287_10_LATER) { +		REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9, +				AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL); +		ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0, +				AR9287_AN_TXPC0_TXPCMODE, +				AR9287_AN_TXPC0_TXPCMODE_S, +				AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE); +		udelay(100); +	} else { +		for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) +			ah->originalGain[i] = +				MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), +						AR_PHY_TX_GAIN); +		ah->PDADCdelta = 0; +	} +} + +static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah, +					 struct ath9k_channel *chan) +{ +	u32 pll; + +	pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); + +	if (chan && IS_CHAN_HALF_RATE(chan)) +		pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); +	else if (chan && IS_CHAN_QUARTER_RATE(chan)) +		pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); + +	if (chan && IS_CHAN_5GHZ(chan)) { +		if (IS_CHAN_A_FAST_CLOCK(ah, chan)) +			pll = 0x142c; +		else if (AR_SREV_9280_20(ah)) +			pll = 0x2850; +		else +			pll |= SM(0x28, AR_RTC_9160_PLL_DIV); +	} else { +		pll |= SM(0x2c, AR_RTC_9160_PLL_DIV); +	} + +	return pll; +} + +static void ar9002_hw_do_getnf(struct ath_hw *ah, +			      int16_t nfarray[NUM_NF_READINGS]) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	int16_t nf; + +	nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); + +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ctl] [chain 0] is %d\n", nf); + +	if (AR_SREV_9271(ah) && (nf >= -114)) +		nf = -116; + +	nfarray[0] = nf; + +	if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { +		nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), +				AR9280_PHY_CH1_MINCCA_PWR); + +		if (nf & 0x100) +			nf = 0 - ((nf ^ 0x1ff) + 1); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "NF calibrated [ctl] [chain 1] is %d\n", nf); +		nfarray[1] = nf; +	} + +	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ext] [chain 0] is %d\n", nf); + +	if (AR_SREV_9271(ah) && (nf >= -114)) +		nf = -116; + +	nfarray[3] = nf; + +	if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { +		nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), +				AR9280_PHY_CH1_EXT_MINCCA_PWR); + +		if (nf & 0x100) +			nf = 0 - ((nf ^ 0x1ff) + 1); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "NF calibrated [ext] [chain 1] is %d\n", nf); +		nfarray[4] = nf; +	} +} + +void ar9002_hw_attach_phy_ops(struct ath_hw *ah) +{ +	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + +	priv_ops->set_rf_regs = NULL; +	priv_ops->rf_alloc_ext_banks = NULL; +	priv_ops->rf_free_ext_banks = NULL; +	priv_ops->rf_set_freq = ar9002_hw_set_channel; +	priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; +	priv_ops->olc_init = ar9002_olc_init; +	priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; +	priv_ops->do_getnf = ar9002_hw_do_getnf; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h new file mode 100644 index 00000000000..81bf6e5840e --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef AR9002_PHY_H +#define AR9002_PHY_H + +#define AR_PHY_TEST             0x9800 +#define PHY_AGC_CLR             0x10000000 +#define RFSILENT_BB             0x00002000 + +#define AR_PHY_TURBO                0x9804 +#define AR_PHY_FC_TURBO_MODE        0x00000001 +#define AR_PHY_FC_TURBO_SHORT       0x00000002 +#define AR_PHY_FC_DYN2040_EN        0x00000004 +#define AR_PHY_FC_DYN2040_PRI_ONLY  0x00000008 +#define AR_PHY_FC_DYN2040_PRI_CH    0x00000010 +/* For 25 MHz channel spacing -- not used but supported by hw */ +#define AR_PHY_FC_DYN2040_EXT_CH    0x00000020 +#define AR_PHY_FC_HT_EN             0x00000040 +#define AR_PHY_FC_SHORT_GI_40       0x00000080 +#define AR_PHY_FC_WALSH             0x00000100 +#define AR_PHY_FC_SINGLE_HT_LTF1    0x00000200 +#define AR_PHY_FC_ENABLE_DAC_FIFO   0x00000800 + +#define AR_PHY_TEST2			0x9808 + +#define AR_PHY_TIMING2           0x9810 +#define AR_PHY_TIMING3           0x9814 +#define AR_PHY_TIMING3_DSC_MAN   0xFFFE0000 +#define AR_PHY_TIMING3_DSC_MAN_S 17 +#define AR_PHY_TIMING3_DSC_EXP   0x0001E000 +#define AR_PHY_TIMING3_DSC_EXP_S 13 + +#define AR_PHY_CHIP_ID_REV_0      0x80 +#define AR_PHY_CHIP_ID_REV_1      0x81 +#define AR_PHY_CHIP_ID_9160_REV_0 0xb0 + +#define AR_PHY_ACTIVE       0x981C +#define AR_PHY_ACTIVE_EN    0x00000001 +#define AR_PHY_ACTIVE_DIS   0x00000000 + +#define AR_PHY_RF_CTL2             0x9824 +#define AR_PHY_TX_END_DATA_START   0x000000FF +#define AR_PHY_TX_END_DATA_START_S 0 +#define AR_PHY_TX_END_PA_ON        0x0000FF00 +#define AR_PHY_TX_END_PA_ON_S      8 + +#define AR_PHY_RF_CTL3                  0x9828 +#define AR_PHY_TX_END_TO_A2_RX_ON       0x00FF0000 +#define AR_PHY_TX_END_TO_A2_RX_ON_S     16 + +#define AR_PHY_ADC_CTL                  0x982C +#define AR_PHY_ADC_CTL_OFF_INBUFGAIN    0x00000003 +#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S  0 +#define AR_PHY_ADC_CTL_OFF_PWDDAC       0x00002000 +#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP   0x00004000 +#define AR_PHY_ADC_CTL_OFF_PWDADC       0x00008000 +#define AR_PHY_ADC_CTL_ON_INBUFGAIN     0x00030000 +#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S   16 + +#define AR_PHY_ADC_SERIAL_CTL       0x9830 +#define AR_PHY_SEL_INTERNAL_ADDAC   0x00000000 +#define AR_PHY_SEL_EXTERNAL_RADIO   0x00000001 + +#define AR_PHY_RF_CTL4                    0x9834 +#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF    0xFF000000 +#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S  24 +#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF    0x00FF0000 +#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S  16 +#define AR_PHY_RF_CTL4_FRAME_XPAB_ON      0x0000FF00 +#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S    8 +#define AR_PHY_RF_CTL4_FRAME_XPAA_ON      0x000000FF +#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S    0 + +#define AR_PHY_TSTDAC_CONST               0x983c + +#define AR_PHY_SETTLING          0x9844 +#define AR_PHY_SETTLING_SWITCH   0x00003F80 +#define AR_PHY_SETTLING_SWITCH_S 7 + +#define AR_PHY_RXGAIN                   0x9848 +#define AR_PHY_RXGAIN_TXRX_ATTEN        0x0003F000 +#define AR_PHY_RXGAIN_TXRX_ATTEN_S      12 +#define AR_PHY_RXGAIN_TXRX_RF_MAX       0x007C0000 +#define AR_PHY_RXGAIN_TXRX_RF_MAX_S     18 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN    0x00003F80 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S  7 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN   0x001FC000 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 + +#define AR_PHY_DESIRED_SZ           0x9850 +#define AR_PHY_DESIRED_SZ_ADC       0x000000FF +#define AR_PHY_DESIRED_SZ_ADC_S     0 +#define AR_PHY_DESIRED_SZ_PGA       0x0000FF00 +#define AR_PHY_DESIRED_SZ_PGA_S     8 +#define AR_PHY_DESIRED_SZ_TOT_DES   0x0FF00000 +#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 + +#define AR_PHY_FIND_SIG           0x9858 +#define AR_PHY_FIND_SIG_FIRSTEP   0x0003F000 +#define AR_PHY_FIND_SIG_FIRSTEP_S 12 +#define AR_PHY_FIND_SIG_FIRPWR    0x03FC0000 +#define AR_PHY_FIND_SIG_FIRPWR_S  18 + +#define AR_PHY_AGC_CTL1                  0x985C +#define AR_PHY_AGC_CTL1_COARSE_LOW       0x00007F80 +#define AR_PHY_AGC_CTL1_COARSE_LOW_S     7 +#define AR_PHY_AGC_CTL1_COARSE_HIGH      0x003F8000 +#define AR_PHY_AGC_CTL1_COARSE_HIGH_S    15 + +#define AR_PHY_CCA                  0x9864 +#define AR_PHY_MINCCA_PWR           0x0FF80000 +#define AR_PHY_MINCCA_PWR_S         19 +#define AR_PHY_CCA_THRESH62         0x0007F000 +#define AR_PHY_CCA_THRESH62_S       12 +#define AR9280_PHY_MINCCA_PWR       0x1FF00000 +#define AR9280_PHY_MINCCA_PWR_S     20 +#define AR9280_PHY_CCA_THRESH62     0x000FF000 +#define AR9280_PHY_CCA_THRESH62_S   12 + +#define AR_PHY_SFCORR_LOW                    0x986C +#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW  0x00000001 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW    0x00003F00 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S  8 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW      0x001FC000 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S    14 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW      0x0FE00000 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S    21 + +#define AR_PHY_SFCORR                0x9868 +#define AR_PHY_SFCORR_M2COUNT_THR    0x0000001F +#define AR_PHY_SFCORR_M2COUNT_THR_S  0 +#define AR_PHY_SFCORR_M1_THRESH      0x00FE0000 +#define AR_PHY_SFCORR_M1_THRESH_S    17 +#define AR_PHY_SFCORR_M2_THRESH      0x7F000000 +#define AR_PHY_SFCORR_M2_THRESH_S    24 + +#define AR_PHY_SLEEP_CTR_CONTROL    0x9870 +#define AR_PHY_SLEEP_CTR_LIMIT      0x9874 +#define AR_PHY_SYNTH_CONTROL        0x9874 +#define AR_PHY_SLEEP_SCAL           0x9878 + +#define AR_PHY_PLL_CTL          0x987c +#define AR_PHY_PLL_CTL_40       0xaa +#define AR_PHY_PLL_CTL_40_5413  0x04 +#define AR_PHY_PLL_CTL_44       0xab +#define AR_PHY_PLL_CTL_44_2133  0xeb +#define AR_PHY_PLL_CTL_40_2133  0xea + +#define AR_PHY_SPECTRAL_SCAN			0x9910  /* AR9280 spectral scan configuration register */ +#define	AR_PHY_SPECTRAL_SCAN_ENABLE		0x1 +#define AR_PHY_SPECTRAL_SCAN_ENA		0x00000001  /* Enable spectral scan, reg 68, bit 0 */ +#define AR_PHY_SPECTRAL_SCAN_ENA_S		0  /* Enable spectral scan, reg 68, bit 0 */ +#define AR_PHY_SPECTRAL_SCAN_ACTIVE		0x00000002  /* Activate spectral scan reg 68, bit 1*/ +#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S		1  /* Activate spectral scan reg 68, bit 1*/ +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD		0x000000F0  /* Interval for FFT reports, reg 68, bits 4-7*/ +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S	4 +#define AR_PHY_SPECTRAL_SCAN_PERIOD		0x0000FF00  /* Interval for FFT reports, reg 68, bits 8-15*/ +#define AR_PHY_SPECTRAL_SCAN_PERIOD_S		8 +#define AR_PHY_SPECTRAL_SCAN_COUNT		0x00FF0000  /* Number of reports, reg 68, bits 16-23*/ +#define AR_PHY_SPECTRAL_SCAN_COUNT_S		16 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT	0x01000000  /* Short repeat, reg 68, bit 24*/ +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S	24  /* Short repeat, reg 68, bit 24*/ + +#define AR_PHY_RX_DELAY           0x9914 +#define AR_PHY_SEARCH_START_DELAY 0x9918 +#define AR_PHY_RX_DELAY_DELAY     0x00003FFF + +#define AR_PHY_TIMING_CTRL4(_i)     (0x9920 + ((_i) << 12)) +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S   0 +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 +#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S   5 +#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE   0x800 +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 +#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S   12 +#define AR_PHY_TIMING_CTRL4_DO_CAL    0x10000 + +#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI	0x80000000 +#define	AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER	0x40000000 +#define	AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK	0x20000000 +#define	AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK	0x10000000 + +#define AR_PHY_TIMING5               0x9924 +#define AR_PHY_TIMING5_CYCPWR_THR1   0x000000FE +#define AR_PHY_TIMING5_CYCPWR_THR1_S 1 + +#define AR_PHY_POWER_TX_RATE1               0x9934 +#define AR_PHY_POWER_TX_RATE2               0x9938 +#define AR_PHY_POWER_TX_RATE_MAX            0x993c +#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 + +#define AR_PHY_FRAME_CTL            0x9944 +#define AR_PHY_FRAME_CTL_TX_CLIP    0x00000038 +#define AR_PHY_FRAME_CTL_TX_CLIP_S  3 + +#define AR_PHY_TXPWRADJ                   0x994C +#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA    0x00000FC0 +#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S  6 +#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX   0x00FC0000 +#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18 + +#define AR_PHY_RADAR_EXT      0x9940 +#define AR_PHY_RADAR_EXT_ENA  0x00004000 + +#define AR_PHY_RADAR_0          0x9954 +#define AR_PHY_RADAR_0_ENA      0x00000001 +#define AR_PHY_RADAR_0_FFT_ENA  0x80000000 +#define AR_PHY_RADAR_0_INBAND   0x0000003e +#define AR_PHY_RADAR_0_INBAND_S 1 +#define AR_PHY_RADAR_0_PRSSI    0x00000FC0 +#define AR_PHY_RADAR_0_PRSSI_S  6 +#define AR_PHY_RADAR_0_HEIGHT   0x0003F000 +#define AR_PHY_RADAR_0_HEIGHT_S 12 +#define AR_PHY_RADAR_0_RRSSI    0x00FC0000 +#define AR_PHY_RADAR_0_RRSSI_S  18 +#define AR_PHY_RADAR_0_FIRPWR   0x7F000000 +#define AR_PHY_RADAR_0_FIRPWR_S 24 + +#define AR_PHY_RADAR_1                  0x9958 +#define AR_PHY_RADAR_1_RELPWR_ENA       0x00800000 +#define AR_PHY_RADAR_1_USE_FIR128       0x00400000 +#define AR_PHY_RADAR_1_RELPWR_THRESH    0x003F0000 +#define AR_PHY_RADAR_1_RELPWR_THRESH_S  16 +#define AR_PHY_RADAR_1_BLOCK_CHECK      0x00008000 +#define AR_PHY_RADAR_1_MAX_RRSSI        0x00004000 +#define AR_PHY_RADAR_1_RELSTEP_CHECK    0x00002000 +#define AR_PHY_RADAR_1_RELSTEP_THRESH   0x00001F00 +#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 +#define AR_PHY_RADAR_1_MAXLEN           0x000000FF +#define AR_PHY_RADAR_1_MAXLEN_S         0 + +#define AR_PHY_SWITCH_CHAIN_0     0x9960 +#define AR_PHY_SWITCH_COM         0x9964 + +#define AR_PHY_SIGMA_DELTA            0x996C +#define AR_PHY_SIGMA_DELTA_ADC_SEL    0x00000003 +#define AR_PHY_SIGMA_DELTA_ADC_SEL_S  0 +#define AR_PHY_SIGMA_DELTA_FILT2      0x000000F8 +#define AR_PHY_SIGMA_DELTA_FILT2_S    3 +#define AR_PHY_SIGMA_DELTA_FILT1      0x00001F00 +#define AR_PHY_SIGMA_DELTA_FILT1_S    8 +#define AR_PHY_SIGMA_DELTA_ADC_CLIP   0x01FFE000 +#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13 + +#define AR_PHY_RESTART          0x9970 +#define AR_PHY_RESTART_DIV_GC   0x001C0000 +#define AR_PHY_RESTART_DIV_GC_S 18 + +#define AR_PHY_RFBUS_REQ        0x997C +#define AR_PHY_RFBUS_REQ_EN     0x00000001 + +#define	AR_PHY_TIMING7		        0x9980 +#define	AR_PHY_TIMING8		        0x9984 +#define	AR_PHY_TIMING8_PILOT_MASK_2	0x000FFFFF +#define	AR_PHY_TIMING8_PILOT_MASK_2_S	0 + +#define	AR_PHY_BIN_MASK2_1	0x9988 +#define	AR_PHY_BIN_MASK2_2	0x998c +#define	AR_PHY_BIN_MASK2_3	0x9990 +#define	AR_PHY_BIN_MASK2_4	0x9994 + +#define	AR_PHY_BIN_MASK_1	0x9900 +#define	AR_PHY_BIN_MASK_2	0x9904 +#define	AR_PHY_BIN_MASK_3	0x9908 + +#define	AR_PHY_MASK_CTL		0x990c + +#define	AR_PHY_BIN_MASK2_4_MASK_4	0x00003FFF +#define	AR_PHY_BIN_MASK2_4_MASK_4_S	0 + +#define	AR_PHY_TIMING9		        0x9998 +#define	AR_PHY_TIMING10		        0x999c +#define	AR_PHY_TIMING10_PILOT_MASK_2	0x000FFFFF +#define	AR_PHY_TIMING10_PILOT_MASK_2_S	0 + +#define	AR_PHY_TIMING11			        0x99a0 +#define	AR_PHY_TIMING11_SPUR_DELTA_PHASE	0x000FFFFF +#define	AR_PHY_TIMING11_SPUR_DELTA_PHASE_S	0 +#define AR_PHY_TIMING11_USE_SPUR_IN_AGC		0x40000000 +#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR	0x80000000 + +#define AR_PHY_RX_CHAINMASK     0x99a4 +#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) +#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 +#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 + +#define AR_PHY_MULTICHAIN_GAIN_CTL          0x99ac +#define AR_PHY_9285_ANT_DIV_CTL_ALL         0x7f000000 +#define AR_PHY_9285_ANT_DIV_CTL             0x01000000 +#define AR_PHY_9285_ANT_DIV_CTL_S           24 +#define AR_PHY_9285_ANT_DIV_ALT_LNACONF     0x06000000 +#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S   25 +#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF    0x18000000 +#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S  27 +#define AR_PHY_9285_ANT_DIV_ALT_GAINTB      0x20000000 +#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S    29 +#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB     0x40000000 +#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S   30 +#define AR_PHY_9285_ANT_DIV_LNA1            2 +#define AR_PHY_9285_ANT_DIV_LNA2            1 +#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2  3 +#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 +#define AR_PHY_9285_ANT_DIV_GAINTB_0        0 +#define AR_PHY_9285_ANT_DIV_GAINTB_1        1 + +#define AR_PHY_EXT_CCA0             0x99b8 +#define AR_PHY_EXT_CCA0_THRESH62    0x000000FF +#define AR_PHY_EXT_CCA0_THRESH62_S  0 + +#define AR_PHY_EXT_CCA                  0x99bc +#define AR_PHY_EXT_CCA_CYCPWR_THR1      0x0000FE00 +#define AR_PHY_EXT_CCA_CYCPWR_THR1_S    9 +#define AR_PHY_EXT_CCA_THRESH62         0x007F0000 +#define AR_PHY_EXT_CCA_THRESH62_S       16 +#define AR_PHY_EXT_MINCCA_PWR           0xFF800000 +#define AR_PHY_EXT_MINCCA_PWR_S         23 +#define AR9280_PHY_EXT_MINCCA_PWR       0x01FF0000 +#define AR9280_PHY_EXT_MINCCA_PWR_S     16 + +#define AR_PHY_SFCORR_EXT                 0x99c0 +#define AR_PHY_SFCORR_EXT_M1_THRESH       0x0000007F +#define AR_PHY_SFCORR_EXT_M1_THRESH_S     0 +#define AR_PHY_SFCORR_EXT_M2_THRESH       0x00003F80 +#define AR_PHY_SFCORR_EXT_M2_THRESH_S     7 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW   0x001FC000 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW   0x0FE00000 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 +#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S   28 + +#define AR_PHY_HALFGI           0x99D0 +#define AR_PHY_HALFGI_DSC_MAN   0x0007FFF0 +#define AR_PHY_HALFGI_DSC_MAN_S 4 +#define AR_PHY_HALFGI_DSC_EXP   0x0000000F +#define AR_PHY_HALFGI_DSC_EXP_S 0 + +#define AR_PHY_CHAN_INFO_MEMORY               0x99DC +#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK  0x0001 + +#define AR_PHY_HEAVY_CLIP_ENABLE         0x99E0 + +#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS    0x99EC +#define AR_PHY_RIFS_INIT_DELAY         0x03ff0000 + +#define AR_PHY_M_SLEEP      0x99f0 +#define AR_PHY_REFCLKDLY    0x99f4 +#define AR_PHY_REFCLKPD     0x99f8 + +#define AR_PHY_CALMODE      0x99f0 + +#define AR_PHY_CALMODE_IQ           0x00000000 +#define AR_PHY_CALMODE_ADC_GAIN     0x00000001 +#define AR_PHY_CALMODE_ADC_DC_PER   0x00000002 +#define AR_PHY_CALMODE_ADC_DC_INIT  0x00000003 + +#define AR_PHY_CAL_MEAS_0(_i)     (0x9c10 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_1(_i)     (0x9c14 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_2(_i)     (0x9c18 + ((_i) << 12)) +#define AR_PHY_CAL_MEAS_3(_i)     (0x9c1c + ((_i) << 12)) + +#define AR_PHY_CURRENT_RSSI 0x9c1c +#define AR9280_PHY_CURRENT_RSSI 0x9c3c + +#define AR_PHY_RFBUS_GRANT       0x9C20 +#define AR_PHY_RFBUS_GRANT_EN    0x00000001 + +#define AR_PHY_CHAN_INFO_GAIN_DIFF             0x9CF4 +#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 + +#define AR_PHY_CHAN_INFO_GAIN          0x9CFC + +#define AR_PHY_MODE         0xA200 +#define AR_PHY_MODE_ASYNCFIFO 0x80 +#define AR_PHY_MODE_AR2133  0x08 +#define AR_PHY_MODE_AR5111  0x00 +#define AR_PHY_MODE_AR5112  0x08 +#define AR_PHY_MODE_DYNAMIC 0x04 +#define AR_PHY_MODE_RF2GHZ  0x02 +#define AR_PHY_MODE_RF5GHZ  0x00 +#define AR_PHY_MODE_CCK     0x01 +#define AR_PHY_MODE_OFDM    0x00 +#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100 + +#define AR_PHY_CCK_TX_CTRL       0xA204 +#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 +#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK         0x0000000C +#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S       2 + +#define AR_PHY_CCK_DETECT                           0xA208 +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK          0x0000003F +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S        0 +/* [12:6] settling time for antenna switch */ +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME           0x00001FC0 +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S         6 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV    0x2000 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S  13 + +#define AR_PHY_GAIN_2GHZ                0xA20C +#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN    0x00FC0000 +#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S  18 +#define AR_PHY_GAIN_2GHZ_BSW_MARGIN     0x00003C00 +#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S   10 +#define AR_PHY_GAIN_2GHZ_BSW_ATTEN      0x0000001F +#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S    0 + +#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN     0x003E0000 +#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S   17 +#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN     0x0001F000 +#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S   12 +#define AR_PHY_GAIN_2GHZ_XATTEN2_DB         0x00000FC0 +#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S       6 +#define AR_PHY_GAIN_2GHZ_XATTEN1_DB         0x0000003F +#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S       0 + +#define AR_PHY_CCK_RXCTRL4  0xA21C +#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT   0x01F80000 +#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 + +#define AR_PHY_DAG_CTRLCCK  0xA228 +#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR  0x00000200 +#define AR_PHY_DAG_CTRLCCK_RSSI_THR     0x0001FC00 +#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S   10 + +#define AR_PHY_FORCE_CLKEN_CCK              0xA22C +#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX      0x00000040 + +#define AR_PHY_POWER_TX_RATE3   0xA234 +#define AR_PHY_POWER_TX_RATE4   0xA238 + +#define AR_PHY_SCRM_SEQ_XR       0xA23C +#define AR_PHY_HEADER_DETECT_XR  0xA240 +#define AR_PHY_CHIRP_DETECTED_XR 0xA244 +#define AR_PHY_BLUETOOTH         0xA254 + +#define AR_PHY_TPCRG1   0xA258 +#define AR_PHY_TPCRG1_NUM_PD_GAIN   0x0000c000 +#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 + +#define AR_PHY_TPCRG1_PD_GAIN_1    0x00030000 +#define AR_PHY_TPCRG1_PD_GAIN_1_S  16 +#define AR_PHY_TPCRG1_PD_GAIN_2    0x000C0000 +#define AR_PHY_TPCRG1_PD_GAIN_2_S  18 +#define AR_PHY_TPCRG1_PD_GAIN_3    0x00300000 +#define AR_PHY_TPCRG1_PD_GAIN_3_S  20 + +#define AR_PHY_TPCRG1_PD_CAL_ENABLE   0x00400000 +#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 + +#define AR_PHY_TX_PWRCTRL4       0xa264 +#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID     0x00000001 +#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S   0 +#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT       0x000001FE +#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S     1 + +#define AR_PHY_TX_PWRCTRL6_0     0xa270 +#define AR_PHY_TX_PWRCTRL6_1     0xb270 +#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE     0x03000000 +#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S   24 + +#define AR_PHY_TX_PWRCTRL7       0xa274 +#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN     0x01F80000 +#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S   19 + +#define AR_PHY_TX_PWRCTRL9       0xa27C +#define AR_PHY_TX_DESIRED_SCALE_CCK        0x00007C00 +#define AR_PHY_TX_DESIRED_SCALE_CCK_S      10 +#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL  0x80000000 +#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 + +#define AR_PHY_TX_GAIN_TBL1      0xa300 +#define AR_PHY_TX_GAIN                     0x0007F000 +#define AR_PHY_TX_GAIN_S                   12 + +#define AR_PHY_CH0_TX_PWRCTRL11  0xa398 +#define AR_PHY_CH1_TX_PWRCTRL11  0xb398 +#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP   0x0000FC00 +#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 + +#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 +#define AR_PHY_MASK2_M_31_45     0xa3a4 +#define AR_PHY_MASK2_M_16_30     0xa3a8 +#define AR_PHY_MASK2_M_00_15     0xa3ac +#define AR_PHY_MASK2_P_15_01     0xa3b8 +#define AR_PHY_MASK2_P_30_16     0xa3bc +#define AR_PHY_MASK2_P_45_31     0xa3c0 +#define AR_PHY_MASK2_P_61_45     0xa3c4 +#define AR_PHY_SPUR_REG          0x994c + +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL       (0xFF << 18) +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S     18 + +#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM      0x20000 +#define AR_PHY_SPUR_REG_MASK_RATE_SELECT     (0xFF << 9) +#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S   9 +#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH     0x7F +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S   0 + +#define AR_PHY_PILOT_MASK_01_30   0xa3b0 +#define AR_PHY_PILOT_MASK_31_60   0xa3b4 + +#define AR_PHY_CHANNEL_MASK_01_30 0x99d4 +#define AR_PHY_CHANNEL_MASK_31_60 0x99d8 + +#define AR_PHY_ANALOG_SWAP      0xa268 +#define AR_PHY_SWAP_ALT_CHAIN   0x00000040 + +#define AR_PHY_TPCRG5   0xA26C +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP       0x0000000F +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S     0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1    0x000003F0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S  4 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2    0x0000FC00 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S  10 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3    0x003F0000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S  16 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4    0x0FC00000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S  22 + +/* Carrier leak calibration control, do it after AGC calibration */ +#define AR_PHY_CL_CAL_CTL       0xA358 +#define AR_PHY_CL_CAL_ENABLE    0x00000002 +#define AR_PHY_PARALLEL_CAL_ENABLE    0x00000001 + +#define AR_PHY_POWER_TX_RATE5   0xA38C +#define AR_PHY_POWER_TX_RATE6   0xA390 + +#define AR_PHY_CAL_CHAINMASK    0xA39C + +#define AR_PHY_POWER_TX_SUB     0xA3C8 +#define AR_PHY_POWER_TX_RATE7   0xA3CC +#define AR_PHY_POWER_TX_RATE8   0xA3D0 +#define AR_PHY_POWER_TX_RATE9   0xA3D4 + +#define AR_PHY_XPA_CFG		0xA3D8 +#define AR_PHY_FORCE_XPA_CFG	0x000000001 +#define AR_PHY_FORCE_XPA_CFG_S	0 + +#define AR_PHY_CH1_CCA          0xa864 +#define AR_PHY_CH1_MINCCA_PWR   0x0FF80000 +#define AR_PHY_CH1_MINCCA_PWR_S 19 +#define AR9280_PHY_CH1_MINCCA_PWR   0x1FF00000 +#define AR9280_PHY_CH1_MINCCA_PWR_S 20 + +#define AR_PHY_CH2_CCA          0xb864 +#define AR_PHY_CH2_MINCCA_PWR   0x0FF80000 +#define AR_PHY_CH2_MINCCA_PWR_S 19 + +#define AR_PHY_CH1_EXT_CCA          0xa9bc +#define AR_PHY_CH1_EXT_MINCCA_PWR   0xFF800000 +#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 +#define AR9280_PHY_CH1_EXT_MINCCA_PWR   0x01FF0000 +#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16 + +#define AR_PHY_CH2_EXT_CCA          0xb9bc +#define AR_PHY_CH2_EXT_MINCCA_PWR   0xFF800000 +#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 + +#endif diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c new file mode 100644 index 00000000000..5fcafb46087 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -0,0 +1,803 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "hw-ops.h" +#include "ar9003_phy.h" + +static void ar9003_hw_setup_calibration(struct ath_hw *ah, +					struct ath9k_cal_list *currCal) +{ +	struct ath_common *common = ath9k_hw_common(ah); + +	/* Select calibration to run */ +	switch (currCal->calData->calType) { +	case IQ_MISMATCH_CAL: +		/* +		 * Start calibration with +		 * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples +		 */ +		REG_RMW_FIELD(ah, AR_PHY_TIMING4, +			      AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX, +		currCal->calData->calCountMax); +		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "starting IQ Mismatch Calibration\n"); + +		/* Kick-off cal */ +		REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL); +		break; +	case TEMP_COMP_CAL: +		REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, +			      AR_PHY_65NM_CH0_THERM_LOCAL, 1); +		REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, +			      AR_PHY_65NM_CH0_THERM_START, 1); + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "starting Temperature Compensation Calibration\n"); +		break; +	case ADC_DC_INIT_CAL: +	case ADC_GAIN_CAL: +	case ADC_DC_CAL: +		/* Not yet */ +		break; +	} +} + +/* + * Generic calibration routine. + * Recalibrate the lower PHY chips to account for temperature/environment + * changes. + */ +static bool ar9003_hw_per_calibration(struct ath_hw *ah, +				      struct ath9k_channel *ichan, +				      u8 rxchainmask, +				      struct ath9k_cal_list *currCal) +{ +	/* Cal is assumed not done until explicitly set below */ +	bool iscaldone = false; + +	/* Calibration in progress. */ +	if (currCal->calState == CAL_RUNNING) { +		/* Check to see if it has finished. */ +		if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) { +			/* +			* Accumulate cal measures for active chains +			*/ +			currCal->calData->calCollect(ah); +			ah->cal_samples++; + +			if (ah->cal_samples >= +			    currCal->calData->calNumSamples) { +				unsigned int i, numChains = 0; +				for (i = 0; i < AR9300_MAX_CHAINS; i++) { +					if (rxchainmask & (1 << i)) +						numChains++; +				} + +				/* +				* Process accumulated data +				*/ +				currCal->calData->calPostProc(ah, numChains); + +				/* Calibration has finished. */ +				ichan->CalValid |= currCal->calData->calType; +				currCal->calState = CAL_DONE; +				iscaldone = true; +			} else { +			/* +			 * Set-up collection of another sub-sample until we +			 * get desired number +			 */ +			ar9003_hw_setup_calibration(ah, currCal); +			} +		} +	} else if (!(ichan->CalValid & currCal->calData->calType)) { +		/* If current cal is marked invalid in channel, kick it off */ +		ath9k_hw_reset_calibration(ah, currCal); +	} + +	return iscaldone; +} + +static bool ar9003_hw_calibrate(struct ath_hw *ah, +				struct ath9k_channel *chan, +				u8 rxchainmask, +				bool longcal) +{ +	bool iscaldone = true; +	struct ath9k_cal_list *currCal = ah->cal_list_curr; + +	/* +	 * For given calibration: +	 * 1. Call generic cal routine +	 * 2. When this cal is done (isCalDone) if we have more cals waiting +	 *    (eg after reset), mask this to upper layers by not propagating +	 *    isCalDone if it is set to TRUE. +	 *    Instead, change isCalDone to FALSE and setup the waiting cal(s) +	 *    to be run. +	 */ +	if (currCal && +	    (currCal->calState == CAL_RUNNING || +	     currCal->calState == CAL_WAITING)) { +		iscaldone = ar9003_hw_per_calibration(ah, chan, +						      rxchainmask, currCal); +		if (iscaldone) { +			ah->cal_list_curr = currCal = currCal->calNext; + +			if (currCal->calState == CAL_WAITING) { +				iscaldone = false; +				ath9k_hw_reset_calibration(ah, currCal); +			} +		} +	} + +	/* Do NF cal only at longer intervals */ +	if (longcal) { +		/* +		 * Load the NF from history buffer of the current channel. +		 * NF is slow time-variant, so it is OK to use a historical +		 * value. +		 */ +		ath9k_hw_loadnf(ah, ah->curchan); + +		/* start NF calibration, without updating BB NF register */ +		ath9k_hw_start_nfcal(ah); +	} + +	return iscaldone; +} + +static void ar9003_hw_iqcal_collect(struct ath_hw *ah) +{ +	int i; + +	/* Accumulate IQ cal measures for active chains */ +	for (i = 0; i < AR5416_MAX_CHAINS; i++) { +		ah->totalPowerMeasI[i] += +			REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); +		ah->totalPowerMeasQ[i] += +			REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); +		ah->totalIqCorrMeas[i] += +			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); +		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, +			  "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", +			  ah->cal_samples, i, ah->totalPowerMeasI[i], +			  ah->totalPowerMeasQ[i], +			  ah->totalIqCorrMeas[i]); +	} +} + +static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	u32 powerMeasQ, powerMeasI, iqCorrMeas; +	u32 qCoffDenom, iCoffDenom; +	int32_t qCoff, iCoff; +	int iqCorrNeg, i; +	const u_int32_t offset_array[3] = { +		AR_PHY_RX_IQCAL_CORR_B0, +		AR_PHY_RX_IQCAL_CORR_B1, +		AR_PHY_RX_IQCAL_CORR_B2, +	}; + +	for (i = 0; i < numChains; i++) { +		powerMeasI = ah->totalPowerMeasI[i]; +		powerMeasQ = ah->totalPowerMeasQ[i]; +		iqCorrMeas = ah->totalIqCorrMeas[i]; + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Starting IQ Cal and Correction for Chain %d\n", +			  i); + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Orignal: Chn %diq_corr_meas = 0x%08x\n", +			  i, ah->totalIqCorrMeas[i]); + +		iqCorrNeg = 0; + +		if (iqCorrMeas > 0x80000000) { +			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; +			iqCorrNeg = 1; +		} + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); +		ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", +			  iqCorrNeg); + +		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256; +		qCoffDenom = powerMeasQ / 64; + +		if ((iCoffDenom != 0) && (qCoffDenom != 0)) { +			iCoff = iqCorrMeas / iCoffDenom; +			qCoff = powerMeasI / qCoffDenom - 64; +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Chn %d iCoff = 0x%08x\n", i, iCoff); +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Chn %d qCoff = 0x%08x\n", i, qCoff); + +			/* Force bounds on iCoff */ +			if (iCoff >= 63) +				iCoff = 63; +			else if (iCoff <= -63) +				iCoff = -63; + +			/* Negate iCoff if iqCorrNeg == 0 */ +			if (iqCorrNeg == 0x0) +				iCoff = -iCoff; + +			/* Force bounds on qCoff */ +			if (qCoff >= 63) +				qCoff = 63; +			else if (qCoff <= -63) +				qCoff = -63; + +			iCoff = iCoff & 0x7f; +			qCoff = qCoff & 0x7f; + +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n", +				  i, iCoff, qCoff); +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Register offset (0x%04x) " +				  "before update = 0x%x\n", +				  offset_array[i], +				  REG_READ(ah, offset_array[i])); + +			REG_RMW_FIELD(ah, offset_array[i], +				      AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, +				      iCoff); +			REG_RMW_FIELD(ah, offset_array[i], +				      AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, +				      qCoff); +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Register offset (0x%04x) QI COFF " +				  "(bitfields 0x%08x) after update = 0x%x\n", +				  offset_array[i], +				  AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, +				  REG_READ(ah, offset_array[i])); +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Register offset (0x%04x) QQ COFF " +				  "(bitfields 0x%08x) after update = 0x%x\n", +				  offset_array[i], +				  AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, +				  REG_READ(ah, offset_array[i])); + +			ath_print(common, ATH_DBG_CALIBRATE, +				  "IQ Cal and Correction done for Chain %d\n", +				  i); +		} +	} + +	REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0, +		    AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "IQ Cal and Correction (offset 0x%04x) enabled " +		  "(bit position 0x%08x). New Value 0x%08x\n", +		  (unsigned) (AR_PHY_RX_IQCAL_CORR_B0), +		  AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE, +		  REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0)); +} + +static const struct ath9k_percal_data iq_cal_single_sample = { +	IQ_MISMATCH_CAL, +	MIN_CAL_SAMPLES, +	PER_MAX_LOG_COUNT, +	ar9003_hw_iqcal_collect, +	ar9003_hw_iqcalibrate +}; + +static void ar9003_hw_init_cal_settings(struct ath_hw *ah) +{ +	ah->iq_caldata.calData = &iq_cal_single_sample; +	ah->supp_cals = IQ_MISMATCH_CAL; +} + +static bool ar9003_hw_iscal_supported(struct ath_hw *ah, +				      enum ath9k_cal_types calType) +{ +	switch (calType & ah->supp_cals) { +	case IQ_MISMATCH_CAL: +		/* +		 * XXX: Run IQ Mismatch for non-CCK only +		 * Note that CHANNEL_B is never set though. +		 */ +		return true; +	case ADC_GAIN_CAL: +	case ADC_DC_CAL: +		return false; +	case TEMP_COMP_CAL: +		return true; +	} + +	return false; +} + +/* + * solve 4x4 linear equation used in loopback iq cal. + */ +static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah, +				   s32 sin_2phi_1, +				   s32 cos_2phi_1, +				   s32 sin_2phi_2, +				   s32 cos_2phi_2, +				   s32 mag_a0_d0, +				   s32 phs_a0_d0, +				   s32 mag_a1_d0, +				   s32 phs_a1_d0, +				   s32 solved_eq[]) +{ +	s32 f1 = cos_2phi_1 - cos_2phi_2, +	    f3 = sin_2phi_1 - sin_2phi_2, +	    f2; +	s32 mag_tx, phs_tx, mag_rx, phs_rx; +	const s32 result_shift = 1 << 15; +	struct ath_common *common = ath9k_hw_common(ah); + +	f2 = (f1 * f1 + f3 * f3) / result_shift; + +	if (!f2) { +		ath_print(common, ATH_DBG_CALIBRATE, "Divide by 0\n"); +		return false; +	} + +	/* mag mismatch, tx */ +	mag_tx = f1 * (mag_a0_d0  - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0); +	/* phs mismatch, tx */ +	phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0); + +	mag_tx = (mag_tx / f2); +	phs_tx = (phs_tx / f2); + +	/* mag mismatch, rx */ +	mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) / +		 result_shift; +	/* phs mismatch, rx */ +	phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) / +		 result_shift; + +	solved_eq[0] = mag_tx; +	solved_eq[1] = phs_tx; +	solved_eq[2] = mag_rx; +	solved_eq[3] = phs_rx; + +	return true; +} + +static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah, s32 in_re, s32 in_im) +{ +	s32 abs_i = abs(in_re), +	    abs_q = abs(in_im), +	    max_abs, min_abs; + +	if (abs_i > abs_q) { +		max_abs = abs_i; +		min_abs = abs_q; +	} else { +		max_abs = abs_q; +		min_abs = abs_i; +	} + +	return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4); +} + +#define DELPT 32 + +static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, +				   s32 chain_idx, +				   const s32 iq_res[], +				   s32 iqc_coeff[]) +{ +	s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0, +	    i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1, +	    i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0, +	    i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1; +	s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1, +	    phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1, +	    sin_2phi_1, cos_2phi_1, +	    sin_2phi_2, cos_2phi_2; +	s32 mag_tx, phs_tx, mag_rx, phs_rx; +	s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx, +	    q_q_coff, q_i_coff; +	const s32 res_scale = 1 << 15; +	const s32 delpt_shift = 1 << 8; +	s32 mag1, mag2; +	struct ath_common *common = ath9k_hw_common(ah); + +	i2_m_q2_a0_d0 = iq_res[0] & 0xfff; +	i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff; +	iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8); + +	if (i2_m_q2_a0_d0 > 0x800) +		i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1); + +	if (i2_p_q2_a0_d0 > 0x800) +		i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1); + +	if (iq_corr_a0_d0 > 0x800) +		iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1); + +	i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff; +	i2_p_q2_a0_d1 = (iq_res[2] & 0xfff); +	iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff; + +	if (i2_m_q2_a0_d1 > 0x800) +		i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1); + +	if (i2_p_q2_a0_d1 > 0x800) +		i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1); + +	if (iq_corr_a0_d1 > 0x800) +		iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1); + +	i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8); +	i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff; +	iq_corr_a1_d0 = iq_res[4] & 0xfff; + +	if (i2_m_q2_a1_d0 > 0x800) +		i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1); + +	if (i2_p_q2_a1_d0 > 0x800) +		i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1); + +	if (iq_corr_a1_d0 > 0x800) +		iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1); + +	i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff; +	i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8); +	iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff; + +	if (i2_m_q2_a1_d1 > 0x800) +		i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1); + +	if (i2_p_q2_a1_d1 > 0x800) +		i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1); + +	if (iq_corr_a1_d1 > 0x800) +		iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1); + +	if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) || +	    (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Divide by 0:\na0_d0=%d\n" +			  "a0_d1=%d\na2_d0=%d\na1_d1=%d\n", +			  i2_p_q2_a0_d0, i2_p_q2_a0_d1, +			  i2_p_q2_a1_d0, i2_p_q2_a1_d1); +		return false; +	} + +	mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0; +	phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0; + +	mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1; +	phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1; + +	mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0; +	phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0; + +	mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1; +	phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1; + +	/* w/o analog phase shift */ +	sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT); +	/* w/o analog phase shift */ +	cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT); +	/* w/  analog phase shift */ +	sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT); +	/* w/  analog phase shift */ +	cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT); + +	/* +	 * force sin^2 + cos^2 = 1; +	 * find magnitude by approximation +	 */ +	mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1); +	mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2); + +	if ((mag1 == 0) || (mag2 == 0)) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Divide by 0: mag1=%d, mag2=%d\n", +			  mag1, mag2); +		return false; +	} + +	/* normalization sin and cos by mag */ +	sin_2phi_1 = (sin_2phi_1 * res_scale / mag1); +	cos_2phi_1 = (cos_2phi_1 * res_scale / mag1); +	sin_2phi_2 = (sin_2phi_2 * res_scale / mag2); +	cos_2phi_2 = (cos_2phi_2 * res_scale / mag2); + +	/* calculate IQ mismatch */ +	if (!ar9003_hw_solve_iq_cal(ah, +			     sin_2phi_1, cos_2phi_1, +			     sin_2phi_2, cos_2phi_2, +			     mag_a0_d0, phs_a0_d0, +			     mag_a1_d0, +			     phs_a1_d0, solved_eq)) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Call to ar9003_hw_solve_iq_cal() failed.\n"); +		return false; +	} + +	mag_tx = solved_eq[0]; +	phs_tx = solved_eq[1]; +	mag_rx = solved_eq[2]; +	phs_rx = solved_eq[3]; + +	ath_print(common, ATH_DBG_CALIBRATE, +		  "chain %d: mag mismatch=%d phase mismatch=%d\n", +		  chain_idx, mag_tx/res_scale, phs_tx/res_scale); + +	if (res_scale == mag_tx) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Divide by 0: mag_tx=%d, res_scale=%d\n", +			  mag_tx, res_scale); +		return false; +	} + +	/* calculate and quantize Tx IQ correction factor */ +	mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx); +	phs_corr_tx = -phs_tx; + +	q_q_coff = (mag_corr_tx * 128 / res_scale); +	q_i_coff = (phs_corr_tx * 256 / res_scale); + +	ath_print(common, ATH_DBG_CALIBRATE, +		  "tx chain %d: mag corr=%d  phase corr=%d\n", +		  chain_idx, q_q_coff, q_i_coff); + +	if (q_i_coff < -63) +		q_i_coff = -63; +	if (q_i_coff > 63) +		q_i_coff = 63; +	if (q_q_coff < -63) +		q_q_coff = -63; +	if (q_q_coff > 63) +		q_q_coff = 63; + +	iqc_coeff[0] = (q_q_coff * 128) + q_i_coff; + +	ath_print(common, ATH_DBG_CALIBRATE, +		  "tx chain %d: iq corr coeff=%x\n", +		  chain_idx, iqc_coeff[0]); + +	if (-mag_rx == res_scale) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Divide by 0: mag_rx=%d, res_scale=%d\n", +			  mag_rx, res_scale); +		return false; +	} + +	/* calculate and quantize Rx IQ correction factors */ +	mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx); +	phs_corr_rx = -phs_rx; + +	q_q_coff = (mag_corr_rx * 128 / res_scale); +	q_i_coff = (phs_corr_rx * 256 / res_scale); + +	ath_print(common, ATH_DBG_CALIBRATE, +		  "rx chain %d: mag corr=%d  phase corr=%d\n", +		  chain_idx, q_q_coff, q_i_coff); + +	if (q_i_coff < -63) +		q_i_coff = -63; +	if (q_i_coff > 63) +		q_i_coff = 63; +	if (q_q_coff < -63) +		q_q_coff = -63; +	if (q_q_coff > 63) +		q_q_coff = 63; + +	iqc_coeff[1] = (q_q_coff * 128) + q_i_coff; + +	ath_print(common, ATH_DBG_CALIBRATE, +		  "rx chain %d: iq corr coeff=%x\n", +		  chain_idx, iqc_coeff[1]); + +	return true; +} + +static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	const u32 txiqcal_status[AR9300_MAX_CHAINS] = { +		AR_PHY_TX_IQCAL_STATUS_B0, +		AR_PHY_TX_IQCAL_STATUS_B1, +		AR_PHY_TX_IQCAL_STATUS_B2, +	}; +	const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = { +		AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, +		AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, +		AR_PHY_TX_IQCAL_CORR_COEFF_01_B2, +	}; +	const u32 rx_corr[AR9300_MAX_CHAINS] = { +		AR_PHY_RX_IQCAL_CORR_B0, +		AR_PHY_RX_IQCAL_CORR_B1, +		AR_PHY_RX_IQCAL_CORR_B2, +	}; +	const u_int32_t chan_info_tab[] = { +		AR_PHY_CHAN_INFO_TAB_0, +		AR_PHY_CHAN_INFO_TAB_1, +		AR_PHY_CHAN_INFO_TAB_2, +	}; +	s32 iq_res[6]; +	s32 iqc_coeff[2]; +	s32 i, j; +	u32 num_chains = 0; + +	for (i = 0; i < AR9300_MAX_CHAINS; i++) { +		if (ah->txchainmask & (1 << i)) +			num_chains++; +	} + +	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, +		      AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, +		      DELPT); +	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, +		      AR_PHY_TX_IQCAL_START_DO_CAL, +		      AR_PHY_TX_IQCAL_START_DO_CAL); + +	if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, +			   AR_PHY_TX_IQCAL_START_DO_CAL, +			   0, AH_WAIT_TIMEOUT)) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Tx IQ Cal not complete.\n"); +		goto TX_IQ_CAL_FAILED; +	} + +	for (i = 0; i < num_chains; i++) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "Doing Tx IQ Cal for chain %d.\n", i); + +		if (REG_READ(ah, txiqcal_status[i]) & +			     AR_PHY_TX_IQCAL_STATUS_FAILED) { +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Tx IQ Cal failed for chain %d.\n", i); +			goto TX_IQ_CAL_FAILED; +		} + +		for (j = 0; j < 3; j++) { +			u_int8_t idx = 2 * j, +			offset = 4 * j; + +			REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, +				      AR_PHY_CHAN_INFO_TAB_S2_READ, 0); + +			/* 32 bits */ +			iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset); + +			REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, +				      AR_PHY_CHAN_INFO_TAB_S2_READ, 1); + +			/* 16 bits */ +			iq_res[idx+1] = 0xffff & REG_READ(ah, +							  chan_info_tab[i] + +							  offset); + +			ath_print(common, ATH_DBG_CALIBRATE, +				  "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", +				  idx, iq_res[idx], idx+1, iq_res[idx+1]); +		} + +		if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, iqc_coeff)) { +			ath_print(common, ATH_DBG_CALIBRATE, +				  "Failed in calculation of IQ correction.\n"); +			goto TX_IQ_CAL_FAILED; +		} + +		ath_print(common, ATH_DBG_CALIBRATE, +			  "IQ_COEFF[0] = 0x%x IQ_COEFF[1] = 0x%x\n", +			  iqc_coeff[0], iqc_coeff[1]); + +		REG_RMW_FIELD(ah, tx_corr_coeff[i], +			      AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, +			      iqc_coeff[0]); +		REG_RMW_FIELD(ah, rx_corr[i], +			      AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF, +			      iqc_coeff[1] >> 7); +		REG_RMW_FIELD(ah, rx_corr[i], +			      AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF, +			      iqc_coeff[1]); +	} + +	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, +		      AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1); +	REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, +		      AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); + +	return; + +TX_IQ_CAL_FAILED: +	ath_print(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); +	return; +} + +static bool ar9003_hw_init_cal(struct ath_hw *ah, +			       struct ath9k_channel *chan) +{ +	struct ath_common *common = ath9k_hw_common(ah); + +	/* +	 * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain mode before +	 * running AGC/TxIQ cals +	 */ +	ar9003_hw_set_chain_masks(ah, 0x7, 0x7); + +	/* Calibrate the AGC */ +	REG_WRITE(ah, AR_PHY_AGC_CONTROL, +		  REG_READ(ah, AR_PHY_AGC_CONTROL) | +		  AR_PHY_AGC_CONTROL_CAL); + +	/* Poll for offset calibration complete */ +	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, +			   0, AH_WAIT_TIMEOUT)) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "offset calibration failed to " +			  "complete in 1ms; noisy environment?\n"); +		return false; +	} + +	/* Do Tx IQ Calibration */ +	if (ah->config.tx_iq_calibration) +		ar9003_hw_tx_iq_cal(ah); + +	/* Revert chainmasks to their original values before NF cal */ +	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); + +	/* Initialize list pointers */ +	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; + +	if (ar9003_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { +		INIT_CAL(&ah->iq_caldata); +		INSERT_CAL(ah, &ah->iq_caldata); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "enabling IQ Calibration.\n"); +	} + +	if (ar9003_hw_iscal_supported(ah, TEMP_COMP_CAL)) { +		INIT_CAL(&ah->tempCompCalData); +		INSERT_CAL(ah, &ah->tempCompCalData); +		ath_print(common, ATH_DBG_CALIBRATE, +			  "enabling Temperature Compensation Calibration.\n"); +	} + +	/* Initialize current pointer to first element in list */ +	ah->cal_list_curr = ah->cal_list; + +	if (ah->cal_list_curr) +		ath9k_hw_reset_calibration(ah, ah->cal_list_curr); + +	chan->CalValid = 0; + +	return true; +} + +void ar9003_hw_attach_calib_ops(struct ath_hw *ah) +{ +	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); +	struct ath_hw_ops *ops = ath9k_hw_ops(ah); + +	priv_ops->init_cal_settings = ar9003_hw_init_cal_settings; +	priv_ops->init_cal = ar9003_hw_init_cal; +	priv_ops->setup_calibration = ar9003_hw_setup_calibration; +	priv_ops->iscal_supported = ar9003_hw_iscal_supported; + +	ops->calibrate = ar9003_hw_calibrate; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c new file mode 100644 index 00000000000..8a79550dff7 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -0,0 +1,1860 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "ar9003_phy.h" +#include "ar9003_eeprom.h" + +#define COMP_HDR_LEN 4 +#define COMP_CKSUM_LEN 2 + +#define AR_CH0_TOP (0x00016288) +#define AR_CH0_TOP_XPABIASLVL (0x3) +#define AR_CH0_TOP_XPABIASLVL_S (8) + +#define AR_CH0_THERM (0x00016290) +#define AR_CH0_THERM_SPARE (0x3f) +#define AR_CH0_THERM_SPARE_S (0) + +#define AR_SWITCH_TABLE_COM_ALL (0xffff) +#define AR_SWITCH_TABLE_COM_ALL_S (0) + +#define AR_SWITCH_TABLE_COM2_ALL (0xffffff) +#define AR_SWITCH_TABLE_COM2_ALL_S (0) + +#define AR_SWITCH_TABLE_ALL (0xfff) +#define AR_SWITCH_TABLE_ALL_S (0) + +static const struct ar9300_eeprom ar9300_default = { +	.eepromVersion = 2, +	.templateVersion = 2, +	.macAddr = {1, 2, 3, 4, 5, 6}, +	.custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +		     0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +	.baseEepHeader = { +		.regDmn = {0, 0x1f}, +		.txrxMask =  0x77, /* 4 bits tx and 4 bits rx */ +		.opCapFlags = { +			.opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, +			.eepMisc = 0, +		}, +		.rfSilent = 0, +		.blueToothOptions = 0, +		.deviceCap = 0, +		.deviceType = 5, /* takes lower byte in eeprom location */ +		.pwrTableOffset = AR9300_PWR_TABLE_OFFSET, +		.params_for_tuning_caps = {0, 0}, +		.featureEnable = 0x0c, +		 /* +		  * bit0 - enable tx temp comp - disabled +		  * bit1 - enable tx volt comp - disabled +		  * bit2 - enable fastClock - enabled +		  * bit3 - enable doubling - enabled +		  * bit4 - enable internal regulator - disabled +		  */ +		.miscConfiguration = 0, /* bit0 - turn down drivestrength */ +		.eepromWriteEnableGpio = 3, +		.wlanDisableGpio = 0, +		.wlanLedGpio = 8, +		.rxBandSelectGpio = 0xff, +		.txrxgain = 0, +		.swreg = 0, +	 }, +	.modalHeader2G = { +	/* ar9300_modal_eep_header  2g */ +		/* 4 idle,t1,t2,b(4 bits per setting) */ +		.antCtrlCommon = 0x110, +		/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ +		.antCtrlCommon2 = 0x22222, + +		/* +		 * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, +		 * rx1, rx12, b (2 bits each) +		 */ +		.antCtrlChain = {0x150, 0x150, 0x150}, + +		/* +		 * xatten1DB[AR9300_MAX_CHAINS];  3 xatten1_db +		 * for ar9280 (0xa20c/b20c 5:0) +		 */ +		.xatten1DB = {0, 0, 0}, + +		/* +		 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin +		 * for ar9280 (0xa20c/b20c 16:12 +		 */ +		.xatten1Margin = {0, 0, 0}, +		.tempSlope = 36, +		.voltSlope = 0, + +		/* +		 * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur +		 * channels in usual fbin coding format +		 */ +		.spurChans = {0, 0, 0, 0, 0}, + +		/* +		 * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check +		 * if the register is per chain +		 */ +		.noiseFloorThreshCh = {-1, 0, 0}, +		.ob = {1, 1, 1},/* 3 chain */ +		.db_stage2 = {1, 1, 1}, /* 3 chain  */ +		.db_stage3 = {0, 0, 0}, +		.db_stage4 = {0, 0, 0}, +		.xpaBiasLvl = 0, +		.txFrameToDataStart = 0x0e, +		.txFrameToPaOn = 0x0e, +		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ +		.antennaGain = 0, +		.switchSettling = 0x2c, +		.adcDesiredSize = -30, +		.txEndToXpaOff = 0, +		.txEndToRxOn = 0x2, +		.txFrameToXpaOn = 0xe, +		.thresh62 = 28, +		.futureModal = { /* [32] */ +			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +		}, +	 }, +	.calFreqPier2G = { +		FREQ2FBIN(2412, 1), +		FREQ2FBIN(2437, 1), +		FREQ2FBIN(2472, 1), +	 }, +	/* ar9300_cal_data_per_freq_op_loop 2g */ +	.calPierData2G = { +		{ {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, +		{ {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, +		{ {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, +	 }, +	.calTarget_freqbin_Cck = { +		FREQ2FBIN(2412, 1), +		FREQ2FBIN(2484, 1), +	 }, +	.calTarget_freqbin_2G = { +		FREQ2FBIN(2412, 1), +		FREQ2FBIN(2437, 1), +		FREQ2FBIN(2472, 1) +	 }, +	.calTarget_freqbin_2GHT20 = { +		FREQ2FBIN(2412, 1), +		FREQ2FBIN(2437, 1), +		FREQ2FBIN(2472, 1) +	 }, +	.calTarget_freqbin_2GHT40 = { +		FREQ2FBIN(2412, 1), +		FREQ2FBIN(2437, 1), +		FREQ2FBIN(2472, 1) +	 }, +	.calTargetPowerCck = { +		 /* 1L-5L,5S,11L,11S */ +		 { {36, 36, 36, 36} }, +		 { {36, 36, 36, 36} }, +	}, +	.calTargetPower2G = { +		 /* 6-24,36,48,54 */ +		 { {32, 32, 28, 24} }, +		 { {32, 32, 28, 24} }, +		 { {32, 32, 28, 24} }, +	}, +	.calTargetPower2GHT20 = { +		{ {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, +		{ {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, +		{ {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, +	}, +	.calTargetPower2GHT40 = { +		{ {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, +		{ {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, +		{ {32, 32, 32, 32, 28, 20, 32, 32, 28, 20, 32, 32, 28, 20} }, +	}, +	.ctlIndex_2G =  { +		0x11, 0x12, 0x15, 0x17, 0x41, 0x42, +		0x45, 0x47, 0x31, 0x32, 0x35, 0x37, +	}, +	.ctl_freqbin_2G = { +		{ +			FREQ2FBIN(2412, 1), +			FREQ2FBIN(2417, 1), +			FREQ2FBIN(2457, 1), +			FREQ2FBIN(2462, 1) +		}, +		{ +			FREQ2FBIN(2412, 1), +			FREQ2FBIN(2417, 1), +			FREQ2FBIN(2462, 1), +			0xFF, +		}, + +		{ +			FREQ2FBIN(2412, 1), +			FREQ2FBIN(2417, 1), +			FREQ2FBIN(2462, 1), +			0xFF, +		}, +		{ +			FREQ2FBIN(2422, 1), +			FREQ2FBIN(2427, 1), +			FREQ2FBIN(2447, 1), +			FREQ2FBIN(2452, 1) +		}, + +		{ +			/* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), +			/* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), +			/* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), +			/* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), +		}, + +		{ +			/* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), +			/* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), +			/* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), +			0, +		}, + +		{ +			/* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), +			/* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), +			FREQ2FBIN(2472, 1), +			0, +		}, + +		{ +			/* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), +			/* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), +			/* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), +			/* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), +		}, + +		{ +			/* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), +			/* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), +			/* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), +		}, + +		{ +			/* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), +			/* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), +			/* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), +			0 +		}, + +		{ +			/* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), +			/* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), +			/* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), +			0 +		}, + +		{ +			/* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), +			/* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), +			/* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), +			/* Data[11].ctlEdges[3].bChannel */ +			FREQ2FBIN(2462, 1), +		} +	 }, +	.ctlPowerData_2G = { +		 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, +		 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, +		 { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } }, + +		 { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } }, +		 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, +		 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, + +		 { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } }, +		 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, +		 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, + +		 { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, +		 { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } }, +	 }, +	.modalHeader5G = { +		/* 4 idle,t1,t2,b (4 bits per setting) */ +		.antCtrlCommon = 0x110, +		/* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ +		.antCtrlCommon2 = 0x22222, +		 /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ +		.antCtrlChain = { +			0x000, 0x000, 0x000, +		}, +		 /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ +		.xatten1DB = {0, 0, 0}, + +		/* +		 * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin +		 * for merlin (0xa20c/b20c 16:12 +		 */ +		.xatten1Margin = {0, 0, 0}, +		.tempSlope = 68, +		.voltSlope = 0, +		/* spurChans spur channels in usual fbin coding format */ +		.spurChans = {0, 0, 0, 0, 0}, +		/* noiseFloorThreshCh Check if the register is per chain */ +		.noiseFloorThreshCh = {-1, 0, 0}, +		.ob = {3, 3, 3}, /* 3 chain */ +		.db_stage2 = {3, 3, 3}, /* 3 chain */ +		.db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ +		.db_stage4 = {3, 3, 3},	 /* don't exist for 2G */ +		.xpaBiasLvl = 0, +		.txFrameToDataStart = 0x0e, +		.txFrameToPaOn = 0x0e, +		.txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ +		.antennaGain = 0, +		.switchSettling = 0x2d, +		.adcDesiredSize = -30, +		.txEndToXpaOff = 0, +		.txEndToRxOn = 0x2, +		.txFrameToXpaOn = 0xe, +		.thresh62 = 28, +		.futureModal = { +			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +		}, +	 }, +	.calFreqPier5G = { +		FREQ2FBIN(5180, 0), +		FREQ2FBIN(5220, 0), +		FREQ2FBIN(5320, 0), +		FREQ2FBIN(5400, 0), +		FREQ2FBIN(5500, 0), +		FREQ2FBIN(5600, 0), +		FREQ2FBIN(5725, 0), +		FREQ2FBIN(5825, 0) +	}, +	.calPierData5G = { +			{ +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +			}, +			{ +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +			}, +			{ +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +				{0, 0, 0, 0, 0}, +			}, + +	}, +	.calTarget_freqbin_5G = { +		FREQ2FBIN(5180, 0), +		FREQ2FBIN(5220, 0), +		FREQ2FBIN(5320, 0), +		FREQ2FBIN(5400, 0), +		FREQ2FBIN(5500, 0), +		FREQ2FBIN(5600, 0), +		FREQ2FBIN(5725, 0), +		FREQ2FBIN(5825, 0) +	}, +	.calTarget_freqbin_5GHT20 = { +		FREQ2FBIN(5180, 0), +		FREQ2FBIN(5240, 0), +		FREQ2FBIN(5320, 0), +		FREQ2FBIN(5500, 0), +		FREQ2FBIN(5700, 0), +		FREQ2FBIN(5745, 0), +		FREQ2FBIN(5725, 0), +		FREQ2FBIN(5825, 0) +	}, +	.calTarget_freqbin_5GHT40 = { +		FREQ2FBIN(5180, 0), +		FREQ2FBIN(5240, 0), +		FREQ2FBIN(5320, 0), +		FREQ2FBIN(5500, 0), +		FREQ2FBIN(5700, 0), +		FREQ2FBIN(5745, 0), +		FREQ2FBIN(5725, 0), +		FREQ2FBIN(5825, 0) +	 }, +	.calTargetPower5G = { +		/* 6-24,36,48,54 */ +		{ {20, 20, 20, 10} }, +		{ {20, 20, 20, 10} }, +		{ {20, 20, 20, 10} }, +		{ {20, 20, 20, 10} }, +		{ {20, 20, 20, 10} }, +		{ {20, 20, 20, 10} }, +		{ {20, 20, 20, 10} }, +		{ {20, 20, 20, 10} }, +	 }, +	.calTargetPower5GHT20 = { +		/* +		 * 0_8_16,1-3_9-11_17-19, +		 * 4,5,6,7,12,13,14,15,20,21,22,23 +		 */ +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +	 }, +	.calTargetPower5GHT40 =  { +		/* +		 * 0_8_16,1-3_9-11_17-19, +		 * 4,5,6,7,12,13,14,15,20,21,22,23 +		 */ +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +		{ {20, 20, 10, 10, 0, 0, 10, 10, 0, 0, 10, 10, 0, 0} }, +	 }, +	.ctlIndex_5G =  { +		0x10, 0x16, 0x18, 0x40, 0x46, +		0x48, 0x30, 0x36, 0x38 +	}, +	.ctl_freqbin_5G =  { +		{ +			/* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), +			/* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), +			/* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), +			/* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), +			/* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), +			/* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), +			/* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), +			/* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) +		}, +		{ +			/* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), +			/* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), +			/* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), +			/* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), +			/* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), +			/* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), +			/* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), +			/* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) +		}, + +		{ +			/* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), +			/* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), +			/* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), +			/* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), +			/* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), +			/* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), +			/* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), +			/* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) +		}, + +		{ +			/* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), +			/* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), +			/* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), +			/* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), +			/* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), +			/* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), +			/* Data[3].ctlEdges[6].bChannel */ 0xFF, +			/* Data[3].ctlEdges[7].bChannel */ 0xFF, +		}, + +		{ +			/* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), +			/* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), +			/* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), +			/* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), +			/* Data[4].ctlEdges[4].bChannel */ 0xFF, +			/* Data[4].ctlEdges[5].bChannel */ 0xFF, +			/* Data[4].ctlEdges[6].bChannel */ 0xFF, +			/* Data[4].ctlEdges[7].bChannel */ 0xFF, +		}, + +		{ +			/* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), +			/* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), +			/* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), +			/* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), +			/* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), +			/* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), +			/* Data[5].ctlEdges[6].bChannel */ 0xFF, +			/* Data[5].ctlEdges[7].bChannel */ 0xFF +		}, + +		{ +			/* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), +			/* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), +			/* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), +			/* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), +			/* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), +			/* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), +			/* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), +			/* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) +		}, + +		{ +			/* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), +			/* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), +			/* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), +			/* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), +			/* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), +			/* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), +			/* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), +			/* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) +		}, + +		{ +			/* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), +			/* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), +			/* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), +			/* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), +			/* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), +			/* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), +			/* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), +			/* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) +		} +	 }, +	.ctlPowerData_5G = { +		{ +			{ +				{60, 1}, {60, 1}, {60, 1}, {60, 1}, +				{60, 1}, {60, 1}, {60, 1}, {60, 0}, +			} +		}, +		{ +			{ +				{60, 1}, {60, 1}, {60, 1}, {60, 1}, +				{60, 1}, {60, 1}, {60, 1}, {60, 0}, +			} +		}, +		{ +			{ +				{60, 0}, {60, 1}, {60, 0}, {60, 1}, +				{60, 1}, {60, 1}, {60, 1}, {60, 1}, +			} +		}, +		{ +			{ +				{60, 0}, {60, 1}, {60, 1}, {60, 0}, +				{60, 1}, {60, 0}, {60, 0}, {60, 0}, +			} +		}, +		{ +			{ +				{60, 1}, {60, 1}, {60, 1}, {60, 0}, +				{60, 0}, {60, 0}, {60, 0}, {60, 0}, +			} +		}, +		{ +			{ +				{60, 1}, {60, 1}, {60, 1}, {60, 1}, +				{60, 1}, {60, 0}, {60, 0}, {60, 0}, +			} +		}, +		{ +			{ +				{60, 1}, {60, 1}, {60, 1}, {60, 1}, +				{60, 1}, {60, 1}, {60, 1}, {60, 1}, +			} +		}, +		{ +			{ +				{60, 1}, {60, 1}, {60, 0}, {60, 1}, +				{60, 1}, {60, 1}, {60, 1}, {60, 0}, +			} +		}, +		{ +			{ +				{60, 1}, {60, 0}, {60, 1}, {60, 1}, +				{60, 1}, {60, 1}, {60, 0}, {60, 1}, +			} +		}, +	 } +}; + +static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) +{ +	return 0; +} + +static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, +				      enum eeprom_param param) +{ +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; +	struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader; + +	switch (param) { +	case EEP_MAC_LSW: +		return eep->macAddr[0] << 8 | eep->macAddr[1]; +	case EEP_MAC_MID: +		return eep->macAddr[2] << 8 | eep->macAddr[3]; +	case EEP_MAC_MSW: +		return eep->macAddr[4] << 8 | eep->macAddr[5]; +	case EEP_REG_0: +		return pBase->regDmn[0]; +	case EEP_REG_1: +		return pBase->regDmn[1]; +	case EEP_OP_CAP: +		return pBase->deviceCap; +	case EEP_OP_MODE: +		return pBase->opCapFlags.opFlags; +	case EEP_RF_SILENT: +		return pBase->rfSilent; +	case EEP_TX_MASK: +		return (pBase->txrxMask >> 4) & 0xf; +	case EEP_RX_MASK: +		return pBase->txrxMask & 0xf; +	case EEP_DRIVE_STRENGTH: +#define AR9300_EEP_BASE_DRIV_STRENGTH	0x1 +		return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH; +	case EEP_INTERNAL_REGULATOR: +		/* Bit 4 is internal regulator flag */ +		return (pBase->featureEnable & 0x10) >> 4; +	case EEP_SWREG: +		return pBase->swreg; +	default: +		return 0; +	} +} + +#ifdef __BIG_ENDIAN +static void ar9300_swap_eeprom(struct ar9300_eeprom *eep) +{ +	u32 dword; +	u16 word; +	int i; + +	word = swab16(eep->baseEepHeader.regDmn[0]); +	eep->baseEepHeader.regDmn[0] = word; + +	word = swab16(eep->baseEepHeader.regDmn[1]); +	eep->baseEepHeader.regDmn[1] = word; + +	dword = swab32(eep->baseEepHeader.swreg); +	eep->baseEepHeader.swreg = dword; + +	dword = swab32(eep->modalHeader2G.antCtrlCommon); +	eep->modalHeader2G.antCtrlCommon = dword; + +	dword = swab32(eep->modalHeader2G.antCtrlCommon2); +	eep->modalHeader2G.antCtrlCommon2 = dword; + +	dword = swab32(eep->modalHeader5G.antCtrlCommon); +	eep->modalHeader5G.antCtrlCommon = dword; + +	dword = swab32(eep->modalHeader5G.antCtrlCommon2); +	eep->modalHeader5G.antCtrlCommon2 = dword; + +	for (i = 0; i < AR9300_MAX_CHAINS; i++) { +		word = swab16(eep->modalHeader2G.antCtrlChain[i]); +		eep->modalHeader2G.antCtrlChain[i] = word; + +		word = swab16(eep->modalHeader5G.antCtrlChain[i]); +		eep->modalHeader5G.antCtrlChain[i] = word; +	} +} +#endif + +static bool ar9300_hw_read_eeprom(struct ath_hw *ah, +				  long address, u8 *buffer, int many) +{ +	int i; +	u8 value[2]; +	unsigned long eepAddr; +	unsigned long byteAddr; +	u16 *svalue; +	struct ath_common *common = ath9k_hw_common(ah); + +	if ((address < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) { +		ath_print(common, ATH_DBG_EEPROM, +			  "eeprom address not in range\n"); +		return false; +	} + +	for (i = 0; i < many; i++) { +		eepAddr = (u16) (address + i) / 2; +		byteAddr = (u16) (address + i) % 2; +		svalue = (u16 *) value; +		if (!ath9k_hw_nvram_read(common, eepAddr, svalue)) { +			ath_print(common, ATH_DBG_EEPROM, +				  "unable to read eeprom region\n"); +			return false; +		} +		*svalue = le16_to_cpu(*svalue); +		buffer[i] = value[byteAddr]; +	} + +	return true; +} + +static bool ar9300_read_eeprom(struct ath_hw *ah, +			       int address, u8 *buffer, int many) +{ +	int it; + +	for (it = 0; it < many; it++) +		if (!ar9300_hw_read_eeprom(ah, +					   (address - it), +					   (buffer + it), 1)) +			return false; +	return true; +} + +static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference, +				   int *length, int *major, int *minor) +{ +	unsigned long value[4]; + +	value[0] = best[0]; +	value[1] = best[1]; +	value[2] = best[2]; +	value[3] = best[3]; +	*code = ((value[0] >> 5) & 0x0007); +	*reference = (value[0] & 0x001f) | ((value[1] >> 2) & 0x0020); +	*length = ((value[1] << 4) & 0x07f0) | ((value[2] >> 4) & 0x000f); +	*major = (value[2] & 0x000f); +	*minor = (value[3] & 0x00ff); +} + +static u16 ar9300_comp_cksum(u8 *data, int dsize) +{ +	int it, checksum = 0; + +	for (it = 0; it < dsize; it++) { +		checksum += data[it]; +		checksum &= 0xffff; +	} + +	return checksum; +} + +static bool ar9300_uncompress_block(struct ath_hw *ah, +				    u8 *mptr, +				    int mdataSize, +				    u8 *block, +				    int size) +{ +	int it; +	int spot; +	int offset; +	int length; +	struct ath_common *common = ath9k_hw_common(ah); + +	spot = 0; + +	for (it = 0; it < size; it += (length+2)) { +		offset = block[it]; +		offset &= 0xff; +		spot += offset; +		length = block[it+1]; +		length &= 0xff; + +		if (length > 0 && spot >= 0 && spot+length < mdataSize) { +			ath_print(common, ATH_DBG_EEPROM, +				  "Restore at %d: spot=%d " +				  "offset=%d length=%d\n", +				   it, spot, offset, length); +			memcpy(&mptr[spot], &block[it+2], length); +			spot += length; +		} else if (length > 0) { +			ath_print(common, ATH_DBG_EEPROM, +				  "Bad restore at %d: spot=%d " +				  "offset=%d length=%d\n", +				  it, spot, offset, length); +			return false; +		} +	} +	return true; +} + +static int ar9300_compress_decision(struct ath_hw *ah, +				    int it, +				    int code, +				    int reference, +				    u8 *mptr, +				    u8 *word, int length, int mdata_size) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	u8 *dptr; + +	switch (code) { +	case _CompressNone: +		if (length != mdata_size) { +			ath_print(common, ATH_DBG_EEPROM, +				  "EEPROM structure size mismatch" +				  "memory=%d eeprom=%d\n", mdata_size, length); +			return -1; +		} +		memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length); +		ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:" +			  " uncompressed, length %d\n", it, length); +		break; +	case _CompressBlock: +		if (reference == 0) { +			dptr = mptr; +		} else { +			if (reference != 2) { +				ath_print(common, ATH_DBG_EEPROM, +					  "cant find reference eeprom" +					  "struct %d\n", reference); +				return -1; +			} +			memcpy(mptr, &ar9300_default, mdata_size); +		} +		ath_print(common, ATH_DBG_EEPROM, +			  "restore eeprom %d: block, reference %d," +			  " length %d\n", it, reference, length); +		ar9300_uncompress_block(ah, mptr, mdata_size, +					(u8 *) (word + COMP_HDR_LEN), length); +		break; +	default: +		ath_print(common, ATH_DBG_EEPROM, "unknown compression" +			  " code %d\n", code); +		return -1; +	} +	return 0; +} + +/* + * Read the configuration data from the eeprom. + * The data can be put in any specified memory buffer. + * + * Returns -1 on error. + * Returns address of next memory location on success. + */ +static int ar9300_eeprom_restore_internal(struct ath_hw *ah, +					  u8 *mptr, int mdata_size) +{ +#define MDEFAULT 15 +#define MSTATE 100 +	int cptr; +	u8 *word; +	int code; +	int reference, length, major, minor; +	int osize; +	int it; +	u16 checksum, mchecksum; +	struct ath_common *common = ath9k_hw_common(ah); + +	word = kzalloc(2048, GFP_KERNEL); +	if (!word) +		return -1; + +	memcpy(mptr, &ar9300_default, mdata_size); + +	cptr = AR9300_BASE_ADDR; +	for (it = 0; it < MSTATE; it++) { +		if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN)) +			goto fail; + +		if ((word[0] == 0 && word[1] == 0 && word[2] == 0 && +		     word[3] == 0) || (word[0] == 0xff && word[1] == 0xff +				       && word[2] == 0xff && word[3] == 0xff)) +			break; + +		ar9300_comp_hdr_unpack(word, &code, &reference, +				       &length, &major, &minor); +		ath_print(common, ATH_DBG_EEPROM, +			  "Found block at %x: code=%d ref=%d" +			  "length=%d major=%d minor=%d\n", cptr, code, +			  reference, length, major, minor); +		if (length >= 1024) { +			ath_print(common, ATH_DBG_EEPROM, +				  "Skipping bad header\n"); +			cptr -= COMP_HDR_LEN; +			continue; +		} + +		osize = length; +		ar9300_read_eeprom(ah, cptr, word, +				   COMP_HDR_LEN + osize + COMP_CKSUM_LEN); +		checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length); +		mchecksum = word[COMP_HDR_LEN + osize] | +		    (word[COMP_HDR_LEN + osize + 1] << 8); +		ath_print(common, ATH_DBG_EEPROM, +			  "checksum %x %x\n", checksum, mchecksum); +		if (checksum == mchecksum) { +			ar9300_compress_decision(ah, it, code, reference, mptr, +						 word, length, mdata_size); +		} else { +			ath_print(common, ATH_DBG_EEPROM, +				  "skipping block with bad checksum\n"); +		} +		cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN); +	} + +	kfree(word); +	return cptr; + +fail: +	kfree(word); +	return -1; +} + +/* + * Restore the configuration structure by reading the eeprom. + * This function destroys any existing in-memory structure + * content. + */ +static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah) +{ +	u8 *mptr = NULL; +	int mdata_size; + +	mptr = (u8 *) &ah->eeprom.ar9300_eep; +	mdata_size = sizeof(struct ar9300_eeprom); + +	if (mptr && mdata_size > 0) { +		/* At this point, mptr points to the eeprom data structure +		 * in it's "default" state. If this is big endian, swap the +		 * data structures back to "little endian" +		 */ +		/* First swap, default to Little Endian */ +#ifdef __BIG_ENDIAN +		ar9300_swap_eeprom((struct ar9300_eeprom *)mptr); +#endif +		if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0) +			return true; + +		/* Second Swap, back to Big Endian */ +#ifdef __BIG_ENDIAN +		ar9300_swap_eeprom((struct ar9300_eeprom *)mptr); +#endif +	} +	return false; +} + +/* XXX: review hardware docs */ +static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah) +{ +	return ah->eeprom.ar9300_eep.eepromVersion; +} + +/* XXX: could be read from the eepromVersion, not sure yet */ +static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah) +{ +	return 0; +} + +static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah, +					     enum ieee80211_band freq_band) +{ +	return 1; +} + +static u16 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah, +						  struct ath9k_channel *chan) +{ +	return -EINVAL; +} + +static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz) +{ +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + +	if (is2ghz) +		return eep->modalHeader2G.xpaBiasLvl; +	else +		return eep->modalHeader5G.xpaBiasLvl; +} + +static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) +{ +	int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz); +	REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3)); +	REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE, +		      ((bias >> 2) & 0x3)); +} + +static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) +{ +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + +	if (is2ghz) +		return eep->modalHeader2G.antCtrlCommon; +	else +		return eep->modalHeader5G.antCtrlCommon; +} + +static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz) +{ +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + +	if (is2ghz) +		return eep->modalHeader2G.antCtrlCommon2; +	else +		return eep->modalHeader5G.antCtrlCommon2; +} + +static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, +					int chain, +					bool is2ghz) +{ +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + +	if (chain >= 0 && chain < AR9300_MAX_CHAINS) { +		if (is2ghz) +			return eep->modalHeader2G.antCtrlChain[chain]; +		else +			return eep->modalHeader5G.antCtrlChain[chain]; +	} + +	return 0; +} + +static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) +{ +	u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); +	REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); + +	value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); +	REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); + +	value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz); +	REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); + +	value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); +	REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value); + +	value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz); +	REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value); +} + +static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) +{ +	int drive_strength; +	unsigned long reg; + +	drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH); + +	if (!drive_strength) +		return; + +	reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS1); +	reg &= ~0x00ffffc0; +	reg |= 0x5 << 21; +	reg |= 0x5 << 18; +	reg |= 0x5 << 15; +	reg |= 0x5 << 12; +	reg |= 0x5 << 9; +	reg |= 0x5 << 6; +	REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS1, reg); + +	reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS2); +	reg &= ~0xffffffe0; +	reg |= 0x5 << 29; +	reg |= 0x5 << 26; +	reg |= 0x5 << 23; +	reg |= 0x5 << 20; +	reg |= 0x5 << 17; +	reg |= 0x5 << 14; +	reg |= 0x5 << 11; +	reg |= 0x5 << 8; +	reg |= 0x5 << 5; +	REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS2, reg); + +	reg = REG_READ(ah, AR_PHY_65NM_CH0_BIAS4); +	reg &= ~0xff800000; +	reg |= 0x5 << 29; +	reg |= 0x5 << 26; +	reg |= 0x5 << 23; +	REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg); +} + +static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah) +{ +	int internal_regulator = +		ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR); + +	if (internal_regulator) { +		/* Internal regulator is ON. Write swreg register. */ +		int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG); +		REG_WRITE(ah, AR_RTC_REG_CONTROL1, +		REG_READ(ah, AR_RTC_REG_CONTROL1) & +			 (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM)); +		REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg); +		/* Set REG_CONTROL1.SWREG_PROGRAM */ +		REG_WRITE(ah, AR_RTC_REG_CONTROL1, +			  REG_READ(ah, +				   AR_RTC_REG_CONTROL1) | +				   AR_RTC_REG_CONTROL1_SWREG_PROGRAM); +	} else { +		REG_WRITE(ah, AR_RTC_SLEEP_CLK, +			  (REG_READ(ah, +				    AR_RTC_SLEEP_CLK) | +				    AR_RTC_FORCE_SWREG_PRD)); +	} +} + +static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, +					     struct ath9k_channel *chan) +{ +	ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan)); +	ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); +	ar9003_hw_drive_strength_apply(ah); +	ar9003_hw_internal_regulator_apply(ah); +} + +static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah, +				      struct ath9k_channel *chan) +{ +} + +/* + * Returns the interpolated y value corresponding to the specified x value + * from the np ordered pairs of data (px,py). + * The pairs do not have to be in any order. + * If the specified x value is less than any of the px, + * the returned y value is equal to the py for the lowest px. + * If the specified x value is greater than any of the px, + * the returned y value is equal to the py for the highest px. + */ +static int ar9003_hw_power_interpolate(int32_t x, +				       int32_t *px, int32_t *py, u_int16_t np) +{ +	int ip = 0; +	int lx = 0, ly = 0, lhave = 0; +	int hx = 0, hy = 0, hhave = 0; +	int dx = 0; +	int y = 0; + +	lhave = 0; +	hhave = 0; + +	/* identify best lower and higher x calibration measurement */ +	for (ip = 0; ip < np; ip++) { +		dx = x - px[ip]; + +		/* this measurement is higher than our desired x */ +		if (dx <= 0) { +			if (!hhave || dx > (x - hx)) { +				/* new best higher x measurement */ +				hx = px[ip]; +				hy = py[ip]; +				hhave = 1; +			} +		} +		/* this measurement is lower than our desired x */ +		if (dx >= 0) { +			if (!lhave || dx < (x - lx)) { +				/* new best lower x measurement */ +				lx = px[ip]; +				ly = py[ip]; +				lhave = 1; +			} +		} +	} + +	/* the low x is good */ +	if (lhave) { +		/* so is the high x */ +		if (hhave) { +			/* they're the same, so just pick one */ +			if (hx == lx) +				y = ly; +			else	/* interpolate  */ +				y = ly + (((x - lx) * (hy - ly)) / (hx - lx)); +		} else		/* only low is good, use it */ +			y = ly; +	} else if (hhave)	/* only high is good, use it */ +		y = hy; +	else /* nothing is good,this should never happen unless np=0, ???? */ +		y = -(1 << 30); +	return y; +} + +static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah, +				       u16 rateIndex, u16 freq, bool is2GHz) +{ +	u16 numPiers, i; +	s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS]; +	s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS]; +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; +	struct cal_tgt_pow_legacy *pEepromTargetPwr; +	u8 *pFreqBin; + +	if (is2GHz) { +		numPiers = AR9300_NUM_2G_20_TARGET_POWERS; +		pEepromTargetPwr = eep->calTargetPower2G; +		pFreqBin = eep->calTarget_freqbin_2G; +	} else { +		numPiers = AR9300_NUM_5G_20_TARGET_POWERS; +		pEepromTargetPwr = eep->calTargetPower5G; +		pFreqBin = eep->calTarget_freqbin_5G; +	} + +	/* +	 * create array of channels and targetpower from +	 * targetpower piers stored on eeprom +	 */ +	for (i = 0; i < numPiers; i++) { +		freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz); +		targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; +	} + +	/* interpolate to get target power for given frequency */ +	return (u8) ar9003_hw_power_interpolate((s32) freq, +						 freqArray, +						 targetPowerArray, numPiers); +} + +static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah, +					    u16 rateIndex, +					    u16 freq, bool is2GHz) +{ +	u16 numPiers, i; +	s32 targetPowerArray[AR9300_NUM_5G_20_TARGET_POWERS]; +	s32 freqArray[AR9300_NUM_5G_20_TARGET_POWERS]; +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; +	struct cal_tgt_pow_ht *pEepromTargetPwr; +	u8 *pFreqBin; + +	if (is2GHz) { +		numPiers = AR9300_NUM_2G_20_TARGET_POWERS; +		pEepromTargetPwr = eep->calTargetPower2GHT20; +		pFreqBin = eep->calTarget_freqbin_2GHT20; +	} else { +		numPiers = AR9300_NUM_5G_20_TARGET_POWERS; +		pEepromTargetPwr = eep->calTargetPower5GHT20; +		pFreqBin = eep->calTarget_freqbin_5GHT20; +	} + +	/* +	 * create array of channels and targetpower +	 * from targetpower piers stored on eeprom +	 */ +	for (i = 0; i < numPiers; i++) { +		freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz); +		targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; +	} + +	/* interpolate to get target power for given frequency */ +	return (u8) ar9003_hw_power_interpolate((s32) freq, +						 freqArray, +						 targetPowerArray, numPiers); +} + +static u8 ar9003_hw_eeprom_get_ht40_tgt_pwr(struct ath_hw *ah, +					    u16 rateIndex, +					    u16 freq, bool is2GHz) +{ +	u16 numPiers, i; +	s32 targetPowerArray[AR9300_NUM_5G_40_TARGET_POWERS]; +	s32 freqArray[AR9300_NUM_5G_40_TARGET_POWERS]; +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; +	struct cal_tgt_pow_ht *pEepromTargetPwr; +	u8 *pFreqBin; + +	if (is2GHz) { +		numPiers = AR9300_NUM_2G_40_TARGET_POWERS; +		pEepromTargetPwr = eep->calTargetPower2GHT40; +		pFreqBin = eep->calTarget_freqbin_2GHT40; +	} else { +		numPiers = AR9300_NUM_5G_40_TARGET_POWERS; +		pEepromTargetPwr = eep->calTargetPower5GHT40; +		pFreqBin = eep->calTarget_freqbin_5GHT40; +	} + +	/* +	 * create array of channels and targetpower from +	 * targetpower piers stored on eeprom +	 */ +	for (i = 0; i < numPiers; i++) { +		freqArray[i] = FBIN2FREQ(pFreqBin[i], is2GHz); +		targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; +	} + +	/* interpolate to get target power for given frequency */ +	return (u8) ar9003_hw_power_interpolate((s32) freq, +						 freqArray, +						 targetPowerArray, numPiers); +} + +static u8 ar9003_hw_eeprom_get_cck_tgt_pwr(struct ath_hw *ah, +					   u16 rateIndex, u16 freq) +{ +	u16 numPiers = AR9300_NUM_2G_CCK_TARGET_POWERS, i; +	s32 targetPowerArray[AR9300_NUM_2G_CCK_TARGET_POWERS]; +	s32 freqArray[AR9300_NUM_2G_CCK_TARGET_POWERS]; +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; +	struct cal_tgt_pow_legacy *pEepromTargetPwr = eep->calTargetPowerCck; +	u8 *pFreqBin = eep->calTarget_freqbin_Cck; + +	/* +	 * create array of channels and targetpower from +	 * targetpower piers stored on eeprom +	 */ +	for (i = 0; i < numPiers; i++) { +		freqArray[i] = FBIN2FREQ(pFreqBin[i], 1); +		targetPowerArray[i] = pEepromTargetPwr[i].tPow2x[rateIndex]; +	} + +	/* interpolate to get target power for given frequency */ +	return (u8) ar9003_hw_power_interpolate((s32) freq, +						 freqArray, +						 targetPowerArray, numPiers); +} + +/* Set tx power registers to array of values passed in */ +static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) +{ +#define POW_SM(_r, _s)     (((_r) & 0x3f) << (_s)) +	/* make sure forced gain is not set */ +	REG_WRITE(ah, 0xa458, 0); + +	/* Write the OFDM power per rate set */ + +	/* 6 (LSB), 9, 12, 18 (MSB) */ +	REG_WRITE(ah, 0xa3c0, +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) | +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) | +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0)); + +	/* 24 (LSB), 36, 48, 54 (MSB) */ +	REG_WRITE(ah, 0xa3c4, +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) | +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) | +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0)); + +	/* Write the CCK power per rate set */ + +	/* 1L (LSB), reserved, 2L, 2S (MSB) */ +	REG_WRITE(ah, 0xa3c8, +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) | +		  /* POW_SM(txPowerTimes2,  8) | this is reserved for AR9003 */ +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)); + +	/* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */ +	REG_WRITE(ah, 0xa3cc, +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) | +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) | +		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0) +	    ); + +	/* Write the HT20 power per rate set */ + +	/* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ +	REG_WRITE(ah, 0xa3d0, +		  POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_0_8_16], 0) +	    ); + +	/* 6 (LSB), 7, 12, 13 (MSB) */ +	REG_WRITE(ah, 0xa3d4, +		  POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_6], 0) +	    ); + +	/* 14 (LSB), 15, 20, 21 */ +	REG_WRITE(ah, 0xa3e4, +		  POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_14], 0) +	    ); + +	/* Mixed HT20 and HT40 rates */ + +	/* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */ +	REG_WRITE(ah, 0xa3e8, +		  POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) | +		  POW_SM(pPwrArray[ALL_TARGET_HT20_22], 0) +	    ); + +	/* +	 * Write the HT40 power per rate set +	 * correct PAR difference between HT40 and HT20/LEGACY +	 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) +	 */ +	REG_WRITE(ah, 0xa3d8, +		  POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) | +		  POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) | +		  POW_SM(pPwrArray[ALL_TARGET_HT40_0_8_16], 0) +	    ); + +	/* 6 (LSB), 7, 12, 13 (MSB) */ +	REG_WRITE(ah, 0xa3dc, +		  POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) | +		  POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) | +		  POW_SM(pPwrArray[ALL_TARGET_HT40_6], 0) +	    ); + +	/* 14 (LSB), 15, 20, 21 */ +	REG_WRITE(ah, 0xa3ec, +		  POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) | +		  POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) | +		  POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) | +		  POW_SM(pPwrArray[ALL_TARGET_HT40_14], 0) +	    ); + +	return 0; +#undef POW_SM +} + +static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq) +{ +	u8 targetPowerValT2[ar9300RateSize]; +	/* XXX: hard code for now, need to get from eeprom struct */ +	u8 ht40PowerIncForPdadc = 0; +	bool is2GHz = false; +	unsigned int i = 0; +	struct ath_common *common = ath9k_hw_common(ah); + +	if (freq < 4000) +		is2GHz = true; + +	targetPowerValT2[ALL_TARGET_LEGACY_6_24] = +	    ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_6_24, freq, +					 is2GHz); +	targetPowerValT2[ALL_TARGET_LEGACY_36] = +	    ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_36, freq, +					 is2GHz); +	targetPowerValT2[ALL_TARGET_LEGACY_48] = +	    ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_48, freq, +					 is2GHz); +	targetPowerValT2[ALL_TARGET_LEGACY_54] = +	    ar9003_hw_eeprom_get_tgt_pwr(ah, LEGACY_TARGET_RATE_54, freq, +					 is2GHz); +	targetPowerValT2[ALL_TARGET_LEGACY_1L_5L] = +	    ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_1L_5L, +					     freq); +	targetPowerValT2[ALL_TARGET_LEGACY_5S] = +	    ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_5S, freq); +	targetPowerValT2[ALL_TARGET_LEGACY_11L] = +	    ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11L, freq); +	targetPowerValT2[ALL_TARGET_LEGACY_11S] = +	    ar9003_hw_eeprom_get_cck_tgt_pwr(ah, LEGACY_TARGET_RATE_11S, freq); +	targetPowerValT2[ALL_TARGET_HT20_0_8_16] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_1_3_9_11_17_19] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19, +					      freq, is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_4] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_4, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_5] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_5, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_6] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_6, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_7] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_7, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_12] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_12, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_13] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_13, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_14] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_14, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_15] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_15, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_20] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_20, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_21] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_21, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_22] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_22, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT20_23] = +	    ar9003_hw_eeprom_get_ht20_tgt_pwr(ah, HT_TARGET_RATE_23, freq, +					      is2GHz); +	targetPowerValT2[ALL_TARGET_HT40_0_8_16] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_0_8_16, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_1_3_9_11_17_19] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_1_3_9_11_17_19, +					      freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_4] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_4, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_5] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_5, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_6] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_6, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_7] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_7, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_12] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_12, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_13] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_13, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_14] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_14, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_15] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_15, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_20] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_20, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_21] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_21, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_22] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_22, freq, +					      is2GHz) + ht40PowerIncForPdadc; +	targetPowerValT2[ALL_TARGET_HT40_23] = +	    ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq, +					      is2GHz) + ht40PowerIncForPdadc; + +	while (i < ar9300RateSize) { +		ath_print(common, ATH_DBG_EEPROM, +			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); +		i++; + +		ath_print(common, ATH_DBG_EEPROM, +			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); +		i++; + +		ath_print(common, ATH_DBG_EEPROM, +			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); +		i++; + +		ath_print(common, ATH_DBG_EEPROM, +			  "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); +		i++; +	} + +	/* Write target power array to registers */ +	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); +} + +static int ar9003_hw_cal_pier_get(struct ath_hw *ah, +				  int mode, +				  int ipier, +				  int ichain, +				  int *pfrequency, +				  int *pcorrection, +				  int *ptemperature, int *pvoltage) +{ +	u8 *pCalPier; +	struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct; +	int is2GHz; +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; +	struct ath_common *common = ath9k_hw_common(ah); + +	if (ichain >= AR9300_MAX_CHAINS) { +		ath_print(common, ATH_DBG_EEPROM, +			  "Invalid chain index, must be less than %d\n", +			  AR9300_MAX_CHAINS); +		return -1; +	} + +	if (mode) {		/* 5GHz */ +		if (ipier >= AR9300_NUM_5G_CAL_PIERS) { +			ath_print(common, ATH_DBG_EEPROM, +				  "Invalid 5GHz cal pier index, must " +				  "be less than %d\n", +				  AR9300_NUM_5G_CAL_PIERS); +			return -1; +		} +		pCalPier = &(eep->calFreqPier5G[ipier]); +		pCalPierStruct = &(eep->calPierData5G[ichain][ipier]); +		is2GHz = 0; +	} else { +		if (ipier >= AR9300_NUM_2G_CAL_PIERS) { +			ath_print(common, ATH_DBG_EEPROM, +				  "Invalid 2GHz cal pier index, must " +				  "be less than %d\n", AR9300_NUM_2G_CAL_PIERS); +			return -1; +		} + +		pCalPier = &(eep->calFreqPier2G[ipier]); +		pCalPierStruct = &(eep->calPierData2G[ichain][ipier]); +		is2GHz = 1; +	} + +	*pfrequency = FBIN2FREQ(*pCalPier, is2GHz); +	*pcorrection = pCalPierStruct->refPower; +	*ptemperature = pCalPierStruct->tempMeas; +	*pvoltage = pCalPierStruct->voltMeas; + +	return 0; +} + +static int ar9003_hw_power_control_override(struct ath_hw *ah, +					    int frequency, +					    int *correction, +					    int *voltage, int *temperature) +{ +	int tempSlope = 0; +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + +	REG_RMW(ah, AR_PHY_TPC_11_B0, +		(correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), +		AR_PHY_TPC_OLPC_GAIN_DELTA); +	REG_RMW(ah, AR_PHY_TPC_11_B1, +		(correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), +		AR_PHY_TPC_OLPC_GAIN_DELTA); +	REG_RMW(ah, AR_PHY_TPC_11_B2, +		(correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), +		AR_PHY_TPC_OLPC_GAIN_DELTA); + +	/* enable open loop power control on chip */ +	REG_RMW(ah, AR_PHY_TPC_6_B0, +		(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), +		AR_PHY_TPC_6_ERROR_EST_MODE); +	REG_RMW(ah, AR_PHY_TPC_6_B1, +		(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), +		AR_PHY_TPC_6_ERROR_EST_MODE); +	REG_RMW(ah, AR_PHY_TPC_6_B2, +		(3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), +		AR_PHY_TPC_6_ERROR_EST_MODE); + +	/* +	 * enable temperature compensation +	 * Need to use register names +	 */ +	if (frequency < 4000) +		tempSlope = eep->modalHeader2G.tempSlope; +	else +		tempSlope = eep->modalHeader5G.tempSlope; + +	REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope); +	REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE, +		      temperature[0]); + +	return 0; +} + +/* Apply the recorded correction values. */ +static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) +{ +	int ichain, ipier, npier; +	int mode; +	int lfrequency[AR9300_MAX_CHAINS], +	    lcorrection[AR9300_MAX_CHAINS], +	    ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS]; +	int hfrequency[AR9300_MAX_CHAINS], +	    hcorrection[AR9300_MAX_CHAINS], +	    htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS]; +	int fdiff; +	int correction[AR9300_MAX_CHAINS], +	    voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS]; +	int pfrequency, pcorrection, ptemperature, pvoltage; +	struct ath_common *common = ath9k_hw_common(ah); + +	mode = (frequency >= 4000); +	if (mode) +		npier = AR9300_NUM_5G_CAL_PIERS; +	else +		npier = AR9300_NUM_2G_CAL_PIERS; + +	for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { +		lfrequency[ichain] = 0; +		hfrequency[ichain] = 100000; +	} +	/* identify best lower and higher frequency calibration measurement */ +	for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { +		for (ipier = 0; ipier < npier; ipier++) { +			if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain, +						    &pfrequency, &pcorrection, +						    &ptemperature, &pvoltage)) { +				fdiff = frequency - pfrequency; + +				/* +				 * this measurement is higher than +				 * our desired frequency +				 */ +				if (fdiff <= 0) { +					if (hfrequency[ichain] <= 0 || +					    hfrequency[ichain] >= 100000 || +					    fdiff > +					    (frequency - hfrequency[ichain])) { +						/* +						 * new best higher +						 * frequency measurement +						 */ +						hfrequency[ichain] = pfrequency; +						hcorrection[ichain] = +						    pcorrection; +						htemperature[ichain] = +						    ptemperature; +						hvoltage[ichain] = pvoltage; +					} +				} +				if (fdiff >= 0) { +					if (lfrequency[ichain] <= 0 +					    || fdiff < +					    (frequency - lfrequency[ichain])) { +						/* +						 * new best lower +						 * frequency measurement +						 */ +						lfrequency[ichain] = pfrequency; +						lcorrection[ichain] = +						    pcorrection; +						ltemperature[ichain] = +						    ptemperature; +						lvoltage[ichain] = pvoltage; +					} +				} +			} +		} +	} + +	/* interpolate  */ +	for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { +		ath_print(common, ATH_DBG_EEPROM, +			  "ch=%d f=%d low=%d %d h=%d %d\n", +			  ichain, frequency, lfrequency[ichain], +			  lcorrection[ichain], hfrequency[ichain], +			  hcorrection[ichain]); +		/* they're the same, so just pick one */ +		if (hfrequency[ichain] == lfrequency[ichain]) { +			correction[ichain] = lcorrection[ichain]; +			voltage[ichain] = lvoltage[ichain]; +			temperature[ichain] = ltemperature[ichain]; +		} +		/* the low frequency is good */ +		else if (frequency - lfrequency[ichain] < 1000) { +			/* so is the high frequency, interpolate */ +			if (hfrequency[ichain] - frequency < 1000) { + +				correction[ichain] = lcorrection[ichain] + +				    (((frequency - lfrequency[ichain]) * +				      (hcorrection[ichain] - +				       lcorrection[ichain])) / +				     (hfrequency[ichain] - lfrequency[ichain])); + +				temperature[ichain] = ltemperature[ichain] + +				    (((frequency - lfrequency[ichain]) * +				      (htemperature[ichain] - +				       ltemperature[ichain])) / +				     (hfrequency[ichain] - lfrequency[ichain])); + +				voltage[ichain] = +				    lvoltage[ichain] + +				    (((frequency - +				       lfrequency[ichain]) * (hvoltage[ichain] - +							      lvoltage[ichain])) +				     / (hfrequency[ichain] - +					lfrequency[ichain])); +			} +			/* only low is good, use it */ +			else { +				correction[ichain] = lcorrection[ichain]; +				temperature[ichain] = ltemperature[ichain]; +				voltage[ichain] = lvoltage[ichain]; +			} +		} +		/* only high is good, use it */ +		else if (hfrequency[ichain] - frequency < 1000) { +			correction[ichain] = hcorrection[ichain]; +			temperature[ichain] = htemperature[ichain]; +			voltage[ichain] = hvoltage[ichain]; +		} else {	/* nothing is good, presume 0???? */ +			correction[ichain] = 0; +			temperature[ichain] = 0; +			voltage[ichain] = 0; +		} +	} + +	ar9003_hw_power_control_override(ah, frequency, correction, voltage, +					 temperature); + +	ath_print(common, ATH_DBG_EEPROM, +		  "for frequency=%d, calibration correction = %d %d %d\n", +		  frequency, correction[0], correction[1], correction[2]); + +	return 0; +} + +static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, +					struct ath9k_channel *chan, u16 cfgCtl, +					u8 twiceAntennaReduction, +					u8 twiceMaxRegulatoryPower, +					u8 powerLimit) +{ +	ah->txpower_limit = powerLimit; +	ar9003_hw_set_target_power_eeprom(ah, chan->channel); +	ar9003_hw_calibration_apply(ah, chan->channel); +} + +static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah, +					    u16 i, bool is2GHz) +{ +	return AR_NO_SPUR; +} + +s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah) +{ +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + +	return (eep->baseEepHeader.txrxgain >> 4) & 0xf; /* bits 7:4 */ +} + +s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah) +{ +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + +	return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */ +} + +const struct eeprom_ops eep_ar9300_ops = { +	.check_eeprom = ath9k_hw_ar9300_check_eeprom, +	.get_eeprom = ath9k_hw_ar9300_get_eeprom, +	.fill_eeprom = ath9k_hw_ar9300_fill_eeprom, +	.get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver, +	.get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev, +	.get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config, +	.get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg, +	.set_board_values = ath9k_hw_ar9300_set_board_values, +	.set_addac = ath9k_hw_ar9300_set_addac, +	.set_txpower = ath9k_hw_ar9300_set_txpower, +	.get_spur_channel = ath9k_hw_ar9300_get_spur_channel +}; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h new file mode 100644 index 00000000000..d8c0318f416 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -0,0 +1,323 @@ +#ifndef AR9003_EEPROM_H +#define AR9003_EEPROM_H + +#include <linux/types.h> + +#define AR9300_EEP_VER               0xD000 +#define AR9300_EEP_VER_MINOR_MASK    0xFFF +#define AR9300_EEP_MINOR_VER_1       0x1 +#define AR9300_EEP_MINOR_VER         AR9300_EEP_MINOR_VER_1 + +/* 16-bit offset location start of calibration struct */ +#define AR9300_EEP_START_LOC         256 +#define AR9300_NUM_5G_CAL_PIERS      8 +#define AR9300_NUM_2G_CAL_PIERS      3 +#define AR9300_NUM_5G_20_TARGET_POWERS  8 +#define AR9300_NUM_5G_40_TARGET_POWERS  8 +#define AR9300_NUM_2G_CCK_TARGET_POWERS 2 +#define AR9300_NUM_2G_20_TARGET_POWERS  3 +#define AR9300_NUM_2G_40_TARGET_POWERS  3 +/* #define AR9300_NUM_CTLS              21 */ +#define AR9300_NUM_CTLS_5G           9 +#define AR9300_NUM_CTLS_2G           12 +#define AR9300_CTL_MODE_M            0xF +#define AR9300_NUM_BAND_EDGES_5G     8 +#define AR9300_NUM_BAND_EDGES_2G     4 +#define AR9300_NUM_PD_GAINS          4 +#define AR9300_PD_GAINS_IN_MASK      4 +#define AR9300_PD_GAIN_ICEPTS        5 +#define AR9300_EEPROM_MODAL_SPURS    5 +#define AR9300_MAX_RATE_POWER        63 +#define AR9300_NUM_PDADC_VALUES      128 +#define AR9300_NUM_RATES             16 +#define AR9300_BCHAN_UNUSED          0xFF +#define AR9300_MAX_PWR_RANGE_IN_HALF_DB 64 +#define AR9300_OPFLAGS_11A           0x01 +#define AR9300_OPFLAGS_11G           0x02 +#define AR9300_OPFLAGS_5G_HT40       0x04 +#define AR9300_OPFLAGS_2G_HT40       0x08 +#define AR9300_OPFLAGS_5G_HT20       0x10 +#define AR9300_OPFLAGS_2G_HT20       0x20 +#define AR9300_EEPMISC_BIG_ENDIAN    0x01 +#define AR9300_EEPMISC_WOW           0x02 +#define AR9300_CUSTOMER_DATA_SIZE    20 + +#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) +#define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x)) +#define AR9300_MAX_CHAINS            3 +#define AR9300_ANT_16S               25 +#define AR9300_FUTURE_MODAL_SZ       6 + +#define AR9300_NUM_ANT_CHAIN_FIELDS     7 +#define AR9300_NUM_ANT_COMMON_FIELDS    4 +#define AR9300_SIZE_ANT_CHAIN_FIELD     3 +#define AR9300_SIZE_ANT_COMMON_FIELD    4 +#define AR9300_ANT_CHAIN_MASK           0x7 +#define AR9300_ANT_COMMON_MASK          0xf +#define AR9300_CHAIN_0_IDX              0 +#define AR9300_CHAIN_1_IDX              1 +#define AR9300_CHAIN_2_IDX              2 + +#define AR928X_NUM_ANT_CHAIN_FIELDS     6 +#define AR928X_SIZE_ANT_CHAIN_FIELD     2 +#define AR928X_ANT_CHAIN_MASK           0x3 + +/* Delta from which to start power to pdadc table */ +/* This offset is used in both open loop and closed loop power control + * schemes. In open loop power control, it is not really needed, but for + * the "sake of consistency" it was kept. For certain AP designs, this + * value is overwritten by the value in the flag "pwrTableOffset" just + * before writing the pdadc vs pwr into the chip registers. + */ +#define AR9300_PWR_TABLE_OFFSET  0 + +/* enable flags for voltage and temp compensation */ +#define ENABLE_TEMP_COMPENSATION 0x01 +#define ENABLE_VOLT_COMPENSATION 0x02 +/* byte addressable */ +#define AR9300_EEPROM_SIZE (16*1024) +#define FIXED_CCA_THRESHOLD 15 + +#define AR9300_BASE_ADDR 0x3ff + +enum targetPowerHTRates { +	HT_TARGET_RATE_0_8_16, +	HT_TARGET_RATE_1_3_9_11_17_19, +	HT_TARGET_RATE_4, +	HT_TARGET_RATE_5, +	HT_TARGET_RATE_6, +	HT_TARGET_RATE_7, +	HT_TARGET_RATE_12, +	HT_TARGET_RATE_13, +	HT_TARGET_RATE_14, +	HT_TARGET_RATE_15, +	HT_TARGET_RATE_20, +	HT_TARGET_RATE_21, +	HT_TARGET_RATE_22, +	HT_TARGET_RATE_23 +}; + +enum targetPowerLegacyRates { +	LEGACY_TARGET_RATE_6_24, +	LEGACY_TARGET_RATE_36, +	LEGACY_TARGET_RATE_48, +	LEGACY_TARGET_RATE_54 +}; + +enum targetPowerCckRates { +	LEGACY_TARGET_RATE_1L_5L, +	LEGACY_TARGET_RATE_5S, +	LEGACY_TARGET_RATE_11L, +	LEGACY_TARGET_RATE_11S +}; + +enum ar9300_Rates { +	ALL_TARGET_LEGACY_6_24, +	ALL_TARGET_LEGACY_36, +	ALL_TARGET_LEGACY_48, +	ALL_TARGET_LEGACY_54, +	ALL_TARGET_LEGACY_1L_5L, +	ALL_TARGET_LEGACY_5S, +	ALL_TARGET_LEGACY_11L, +	ALL_TARGET_LEGACY_11S, +	ALL_TARGET_HT20_0_8_16, +	ALL_TARGET_HT20_1_3_9_11_17_19, +	ALL_TARGET_HT20_4, +	ALL_TARGET_HT20_5, +	ALL_TARGET_HT20_6, +	ALL_TARGET_HT20_7, +	ALL_TARGET_HT20_12, +	ALL_TARGET_HT20_13, +	ALL_TARGET_HT20_14, +	ALL_TARGET_HT20_15, +	ALL_TARGET_HT20_20, +	ALL_TARGET_HT20_21, +	ALL_TARGET_HT20_22, +	ALL_TARGET_HT20_23, +	ALL_TARGET_HT40_0_8_16, +	ALL_TARGET_HT40_1_3_9_11_17_19, +	ALL_TARGET_HT40_4, +	ALL_TARGET_HT40_5, +	ALL_TARGET_HT40_6, +	ALL_TARGET_HT40_7, +	ALL_TARGET_HT40_12, +	ALL_TARGET_HT40_13, +	ALL_TARGET_HT40_14, +	ALL_TARGET_HT40_15, +	ALL_TARGET_HT40_20, +	ALL_TARGET_HT40_21, +	ALL_TARGET_HT40_22, +	ALL_TARGET_HT40_23, +	ar9300RateSize, +}; + + +struct eepFlags { +	u8 opFlags; +	u8 eepMisc; +} __packed; + +enum CompressAlgorithm { +	_CompressNone = 0, +	_CompressLzma, +	_CompressPairs, +	_CompressBlock, +	_Compress4, +	_Compress5, +	_Compress6, +	_Compress7, +}; + +struct ar9300_base_eep_hdr { +	u16 regDmn[2]; +	/* 4 bits tx and 4 bits rx */ +	u8 txrxMask; +	struct eepFlags opCapFlags; +	u8 rfSilent; +	u8 blueToothOptions; +	u8 deviceCap; +	/* takes lower byte in eeprom location */ +	u8 deviceType; +	/* offset in dB to be added to beginning +	 * of pdadc table in calibration +	 */ +	int8_t pwrTableOffset; +	u8 params_for_tuning_caps[2]; +	/* +	 * bit0 - enable tx temp comp +	 * bit1 - enable tx volt comp +	 * bit2 - enable fastClock - default to 1 +	 * bit3 - enable doubling - default to 1 +	 * bit4 - enable internal regulator - default to 1 +	 */ +	u8 featureEnable; +	/* misc flags: bit0 - turn down drivestrength */ +	u8 miscConfiguration; +	u8 eepromWriteEnableGpio; +	u8 wlanDisableGpio; +	u8 wlanLedGpio; +	u8 rxBandSelectGpio; +	u8 txrxgain; +	/* SW controlled internal regulator fields */ +	u32 swreg; +} __packed; + +struct ar9300_modal_eep_header { +	/* 4 idle, t1, t2, b (4 bits per setting) */ +	u32 antCtrlCommon; +	/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ +	u32 antCtrlCommon2; +	/* 6 idle, t, r, rx1, rx12, b (2 bits each) */ +	u16 antCtrlChain[AR9300_MAX_CHAINS]; +	/* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ +	u8 xatten1DB[AR9300_MAX_CHAINS]; +	/* 3  xatten1_margin for merlin (0xa20c/b20c 16:12 */ +	u8 xatten1Margin[AR9300_MAX_CHAINS]; +	int8_t tempSlope; +	int8_t voltSlope; +	/* spur channels in usual fbin coding format */ +	u8 spurChans[AR9300_EEPROM_MODAL_SPURS]; +	/* 3  Check if the register is per chain */ +	int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS]; +	u8 ob[AR9300_MAX_CHAINS]; +	u8 db_stage2[AR9300_MAX_CHAINS]; +	u8 db_stage3[AR9300_MAX_CHAINS]; +	u8 db_stage4[AR9300_MAX_CHAINS]; +	u8 xpaBiasLvl; +	u8 txFrameToDataStart; +	u8 txFrameToPaOn; +	u8 txClip; +	int8_t antennaGain; +	u8 switchSettling; +	int8_t adcDesiredSize; +	u8 txEndToXpaOff; +	u8 txEndToRxOn; +	u8 txFrameToXpaOn; +	u8 thresh62; +	u8 futureModal[32]; +} __packed; + +struct ar9300_cal_data_per_freq_op_loop { +	int8_t refPower; +	/* pdadc voltage at power measurement */ +	u8 voltMeas; +	/* pcdac used for power measurement   */ +	u8 tempMeas; +	/* range is -60 to -127 create a mapping equation 1db resolution */ +	int8_t rxNoisefloorCal; +	/*range is same as noisefloor */ +	int8_t rxNoisefloorPower; +	/* temp measured when noisefloor cal was performed */ +	u8 rxTempMeas; +} __packed; + +struct cal_tgt_pow_legacy { +	u8 tPow2x[4]; +} __packed; + +struct cal_tgt_pow_ht { +	u8 tPow2x[14]; +} __packed; + +struct cal_ctl_edge_pwr { +	u8 tPower:6, +	   flag:2; +} __packed; + +struct cal_ctl_data_2g { +	struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_2G]; +} __packed; + +struct cal_ctl_data_5g { +	struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G]; +} __packed; + +struct ar9300_eeprom { +	u8 eepromVersion; +	u8 templateVersion; +	u8 macAddr[6]; +	u8 custData[AR9300_CUSTOMER_DATA_SIZE]; + +	struct ar9300_base_eep_hdr baseEepHeader; + +	struct ar9300_modal_eep_header modalHeader2G; +	u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS]; +	struct ar9300_cal_data_per_freq_op_loop +	 calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS]; +	u8 calTarget_freqbin_Cck[AR9300_NUM_2G_CCK_TARGET_POWERS]; +	u8 calTarget_freqbin_2G[AR9300_NUM_2G_20_TARGET_POWERS]; +	u8 calTarget_freqbin_2GHT20[AR9300_NUM_2G_20_TARGET_POWERS]; +	u8 calTarget_freqbin_2GHT40[AR9300_NUM_2G_40_TARGET_POWERS]; +	struct cal_tgt_pow_legacy +	 calTargetPowerCck[AR9300_NUM_2G_CCK_TARGET_POWERS]; +	struct cal_tgt_pow_legacy +	 calTargetPower2G[AR9300_NUM_2G_20_TARGET_POWERS]; +	struct cal_tgt_pow_ht +	 calTargetPower2GHT20[AR9300_NUM_2G_20_TARGET_POWERS]; +	struct cal_tgt_pow_ht +	 calTargetPower2GHT40[AR9300_NUM_2G_40_TARGET_POWERS]; +	u8 ctlIndex_2G[AR9300_NUM_CTLS_2G]; +	u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G]; +	struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G]; +	struct ar9300_modal_eep_header modalHeader5G; +	u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS]; +	struct ar9300_cal_data_per_freq_op_loop +	 calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS]; +	u8 calTarget_freqbin_5G[AR9300_NUM_5G_20_TARGET_POWERS]; +	u8 calTarget_freqbin_5GHT20[AR9300_NUM_5G_20_TARGET_POWERS]; +	u8 calTarget_freqbin_5GHT40[AR9300_NUM_5G_40_TARGET_POWERS]; +	struct cal_tgt_pow_legacy +	 calTargetPower5G[AR9300_NUM_5G_20_TARGET_POWERS]; +	struct cal_tgt_pow_ht +	 calTargetPower5GHT20[AR9300_NUM_5G_20_TARGET_POWERS]; +	struct cal_tgt_pow_ht +	 calTargetPower5GHT40[AR9300_NUM_5G_40_TARGET_POWERS]; +	u8 ctlIndex_5G[AR9300_NUM_CTLS_5G]; +	u8 ctl_freqbin_5G[AR9300_NUM_CTLS_5G][AR9300_NUM_BAND_EDGES_5G]; +	struct cal_ctl_data_5g ctlPowerData_5G[AR9300_NUM_CTLS_5G]; +} __packed; + +s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah); +s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah); + +#endif diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c new file mode 100644 index 00000000000..b15309caf1d --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2008-2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "ar9003_mac.h" +#include "ar9003_initvals.h" + +/* General hardware code for the AR9003 hadware family */ + +static bool ar9003_hw_macversion_supported(u32 macversion) +{ +	switch (macversion) { +	case AR_SREV_VERSION_9300: +		return true; +	default: +		break; +	} +	return false; +} + +/* AR9003 2.0 - new INI format (pre, core, post arrays per subsystem) */ +/* + * XXX: move TX/RX gain INI to its own init_mode_gain_regs after + * ensuring it does not affect hardware bring up + */ +static void ar9003_hw_init_mode_regs(struct ath_hw *ah) +{ +	/* mac */ +	INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); +	INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], +		       ar9300_2p0_mac_core, +		       ARRAY_SIZE(ar9300_2p0_mac_core), 2); +	INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], +		       ar9300_2p0_mac_postamble, +		       ARRAY_SIZE(ar9300_2p0_mac_postamble), 5); + +	/* bb */ +	INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); +	INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], +		       ar9300_2p0_baseband_core, +		       ARRAY_SIZE(ar9300_2p0_baseband_core), 2); +	INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], +		       ar9300_2p0_baseband_postamble, +		       ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5); + +	/* radio */ +	INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); +	INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], +		       ar9300_2p0_radio_core, +		       ARRAY_SIZE(ar9300_2p0_radio_core), 2); +	INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], +		       ar9300_2p0_radio_postamble, +		       ARRAY_SIZE(ar9300_2p0_radio_postamble), 5); + +	/* soc */ +	INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], +		       ar9300_2p0_soc_preamble, +		       ARRAY_SIZE(ar9300_2p0_soc_preamble), 2); +	INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); +	INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], +		       ar9300_2p0_soc_postamble, +		       ARRAY_SIZE(ar9300_2p0_soc_postamble), 5); + +	/* rx/tx gain */ +	INIT_INI_ARRAY(&ah->iniModesRxGain, +		       ar9300Common_rx_gain_table_2p0, +		       ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2); +	INIT_INI_ARRAY(&ah->iniModesTxGain, +		       ar9300Modes_lowest_ob_db_tx_gain_table_2p0, +		       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), +		       5); + +	/* Load PCIE SERDES settings from INI */ + +	/* Awake Setting */ + +	INIT_INI_ARRAY(&ah->iniPcieSerdes, +		       ar9300PciePhy_pll_on_clkreq_disable_L1_2p0, +		       ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0), +		       2); + +	/* Sleep Setting */ + +	INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, +		       ar9300PciePhy_clkreq_enable_L1_2p0, +		       ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0), +		       2); + +	/* Fast clock modal settings */ +	INIT_INI_ARRAY(&ah->iniModesAdditional, +		       ar9300Modes_fast_clock_2p0, +		       ARRAY_SIZE(ar9300Modes_fast_clock_2p0), +		       3); +} + +static void ar9003_tx_gain_table_apply(struct ath_hw *ah) +{ +	switch (ar9003_hw_get_tx_gain_idx(ah)) { +	case 0: +	default: +		INIT_INI_ARRAY(&ah->iniModesTxGain, +			       ar9300Modes_lowest_ob_db_tx_gain_table_2p0, +			       ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), +			       5); +		break; +	case 1: +		INIT_INI_ARRAY(&ah->iniModesTxGain, +			       ar9300Modes_high_ob_db_tx_gain_table_2p0, +			       ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0), +			       5); +		break; +	case 2: +		INIT_INI_ARRAY(&ah->iniModesTxGain, +			       ar9300Modes_low_ob_db_tx_gain_table_2p0, +			       ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0), +			       5); +		break; +	} +} + +static void ar9003_rx_gain_table_apply(struct ath_hw *ah) +{ +	switch (ar9003_hw_get_rx_gain_idx(ah)) { +	case 0: +	default: +		INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_rx_gain_table_2p0, +			       ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), +			       2); +		break; +	case 1: +		INIT_INI_ARRAY(&ah->iniModesRxGain, +			       ar9300Common_wo_xlna_rx_gain_table_2p0, +			       ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0), +			       2); +		break; +	} +} + +/* set gain table pointers according to values read from the eeprom */ +static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah) +{ +	ar9003_tx_gain_table_apply(ah); +	ar9003_rx_gain_table_apply(ah); +} + +/* + * Helper for ASPM support. + * + * Disable PLL when in L0s as well as receiver clock when in L1. + * This power saving option must be enabled through the SerDes. + * + * Programming the SerDes must go through the same 288 bit serial shift + * register as the other analog registers.  Hence the 9 writes. + */ +static void ar9003_hw_configpcipowersave(struct ath_hw *ah, +					 int restore, +					 int power_off) +{ +	if (ah->is_pciexpress != true) +		return; + +	/* Do not touch SerDes registers */ +	if (ah->config.pcie_powersave_enable == 2) +		return; + +	/* Nothing to do on restore for 11N */ +	if (!restore) { +		/* set bit 19 to allow forcing of pcie core into L1 state */ +		REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); + +		/* Several PCIe massages to ensure proper behaviour */ +		if (ah->config.pcie_waen) +			REG_WRITE(ah, AR_WA, ah->config.pcie_waen); +	} +} + +/* Sets up the AR9003 hardware familiy callbacks */ +void ar9003_hw_attach_ops(struct ath_hw *ah) +{ +	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); +	struct ath_hw_ops *ops = ath9k_hw_ops(ah); + +	priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; +	priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; +	priv_ops->macversion_supported = ar9003_hw_macversion_supported; + +	ops->config_pci_powersave = ar9003_hw_configpcipowersave; + +	ar9003_hw_attach_phy_ops(ah); +	ar9003_hw_attach_calib_ops(ah); +	ar9003_hw_attach_mac_ops(ah); +} diff --git a/drivers/net/wireless/ath/ath9k/ar9003_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_initvals.h new file mode 100644 index 00000000000..a131cd10ef2 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_initvals.h @@ -0,0 +1,1784 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_9003_H +#define INITVALS_9003_H + +/* AR9003 2.0 */ + +static const u32 ar9300_2p0_radio_postamble[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, +	{0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, +	{0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, +	{0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, +}; + +static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, +	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, +	{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, +	{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, +	{0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, +	{0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, +	{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, +	{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, +	{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, +	{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, +	{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, +	{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, +	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, +	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, +	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, +	{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, +	{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, +	{0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, +	{0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, +	{0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, +	{0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, +	{0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, +	{0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, +	{0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, +	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, +	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, +	{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, +	{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, +	{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, +	{0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, +	{0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, +	{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, +	{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, +	{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, +	{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, +	{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, +	{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, +	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, +	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, +	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, +	{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, +	{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, +	{0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, +	{0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, +	{0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, +	{0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, +	{0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, +	{0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, +	{0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016048, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61}, +	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016448, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61}, +	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016848, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61}, +	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9300Modes_fast_clock_2p0[][3] = { +	/* Addr      5G_HT20     5G_HT40   */ +	{0x00001030, 0x00000268, 0x000004d0}, +	{0x00001070, 0x0000018c, 0x00000318}, +	{0x000010b0, 0x00000fd0, 0x00001fa0}, +	{0x00008014, 0x044c044c, 0x08980898}, +	{0x0000801c, 0x148ec02b, 0x148ec057}, +	{0x00008318, 0x000044c0, 0x00008980}, +	{0x00009e00, 0x03721821, 0x03721821}, +	{0x0000a230, 0x0000000b, 0x00000016}, +	{0x0000a254, 0x00000898, 0x00001130}, +}; + +static const u32 ar9300_2p0_radio_core[][2] = { +	/* Addr      allmodes  */ +	{0x00016000, 0x36db6db6}, +	{0x00016004, 0x6db6db40}, +	{0x00016008, 0x73f00000}, +	{0x0001600c, 0x00000000}, +	{0x00016040, 0x7f80fff8}, +	{0x0001604c, 0x76d005b5}, +	{0x00016050, 0x556cf031}, +	{0x00016054, 0x43449440}, +	{0x00016058, 0x0c51c92c}, +	{0x0001605c, 0x3db7fffc}, +	{0x00016060, 0xfffffffc}, +	{0x00016064, 0x000f0278}, +	{0x0001606c, 0x6db60000}, +	{0x00016080, 0x00000000}, +	{0x00016084, 0x0e48048c}, +	{0x00016088, 0x54214514}, +	{0x0001608c, 0x119f481e}, +	{0x00016090, 0x24926490}, +	{0x00016098, 0xd2888888}, +	{0x000160a0, 0x0a108ffe}, +	{0x000160a4, 0x812fc370}, +	{0x000160a8, 0x423c8000}, +	{0x000160b4, 0x92480080}, +	{0x000160c0, 0x00adb6d0}, +	{0x000160c4, 0x6db6db60}, +	{0x000160c8, 0x6db6db6c}, +	{0x000160cc, 0x01e6c000}, +	{0x00016100, 0x3fffbe01}, +	{0x00016104, 0xfff80000}, +	{0x00016108, 0x00080010}, +	{0x00016140, 0x10804008}, +	{0x00016144, 0x02084080}, +	{0x00016148, 0x00000000}, +	{0x00016280, 0x058a0001}, +	{0x00016284, 0x3d840208}, +	{0x00016288, 0x01a20408}, +	{0x0001628c, 0x00038c07}, +	{0x00016290, 0x40000004}, +	{0x00016294, 0x458aa14f}, +	{0x00016380, 0x00000000}, +	{0x00016384, 0x00000000}, +	{0x00016388, 0x00800700}, +	{0x0001638c, 0x00800700}, +	{0x00016390, 0x00800700}, +	{0x00016394, 0x00000000}, +	{0x00016398, 0x00000000}, +	{0x0001639c, 0x00000000}, +	{0x000163a0, 0x00000001}, +	{0x000163a4, 0x00000001}, +	{0x000163a8, 0x00000000}, +	{0x000163ac, 0x00000000}, +	{0x000163b0, 0x00000000}, +	{0x000163b4, 0x00000000}, +	{0x000163b8, 0x00000000}, +	{0x000163bc, 0x00000000}, +	{0x000163c0, 0x000000a0}, +	{0x000163c4, 0x000c0000}, +	{0x000163c8, 0x14021402}, +	{0x000163cc, 0x00001402}, +	{0x000163d0, 0x00000000}, +	{0x000163d4, 0x00000000}, +	{0x00016400, 0x36db6db6}, +	{0x00016404, 0x6db6db40}, +	{0x00016408, 0x73f00000}, +	{0x0001640c, 0x00000000}, +	{0x00016440, 0x7f80fff8}, +	{0x0001644c, 0x76d005b5}, +	{0x00016450, 0x556cf031}, +	{0x00016454, 0x43449440}, +	{0x00016458, 0x0c51c92c}, +	{0x0001645c, 0x3db7fffc}, +	{0x00016460, 0xfffffffc}, +	{0x00016464, 0x000f0278}, +	{0x0001646c, 0x6db60000}, +	{0x00016500, 0x3fffbe01}, +	{0x00016504, 0xfff80000}, +	{0x00016508, 0x00080010}, +	{0x00016540, 0x10804008}, +	{0x00016544, 0x02084080}, +	{0x00016548, 0x00000000}, +	{0x00016780, 0x00000000}, +	{0x00016784, 0x00000000}, +	{0x00016788, 0x00800700}, +	{0x0001678c, 0x00800700}, +	{0x00016790, 0x00800700}, +	{0x00016794, 0x00000000}, +	{0x00016798, 0x00000000}, +	{0x0001679c, 0x00000000}, +	{0x000167a0, 0x00000001}, +	{0x000167a4, 0x00000001}, +	{0x000167a8, 0x00000000}, +	{0x000167ac, 0x00000000}, +	{0x000167b0, 0x00000000}, +	{0x000167b4, 0x00000000}, +	{0x000167b8, 0x00000000}, +	{0x000167bc, 0x00000000}, +	{0x000167c0, 0x000000a0}, +	{0x000167c4, 0x000c0000}, +	{0x000167c8, 0x14021402}, +	{0x000167cc, 0x00001402}, +	{0x000167d0, 0x00000000}, +	{0x000167d4, 0x00000000}, +	{0x00016800, 0x36db6db6}, +	{0x00016804, 0x6db6db40}, +	{0x00016808, 0x73f00000}, +	{0x0001680c, 0x00000000}, +	{0x00016840, 0x7f80fff8}, +	{0x0001684c, 0x76d005b5}, +	{0x00016850, 0x556cf031}, +	{0x00016854, 0x43449440}, +	{0x00016858, 0x0c51c92c}, +	{0x0001685c, 0x3db7fffc}, +	{0x00016860, 0xfffffffc}, +	{0x00016864, 0x000f0278}, +	{0x0001686c, 0x6db60000}, +	{0x00016900, 0x3fffbe01}, +	{0x00016904, 0xfff80000}, +	{0x00016908, 0x00080010}, +	{0x00016940, 0x10804008}, +	{0x00016944, 0x02084080}, +	{0x00016948, 0x00000000}, +	{0x00016b80, 0x00000000}, +	{0x00016b84, 0x00000000}, +	{0x00016b88, 0x00800700}, +	{0x00016b8c, 0x00800700}, +	{0x00016b90, 0x00800700}, +	{0x00016b94, 0x00000000}, +	{0x00016b98, 0x00000000}, +	{0x00016b9c, 0x00000000}, +	{0x00016ba0, 0x00000001}, +	{0x00016ba4, 0x00000001}, +	{0x00016ba8, 0x00000000}, +	{0x00016bac, 0x00000000}, +	{0x00016bb0, 0x00000000}, +	{0x00016bb4, 0x00000000}, +	{0x00016bb8, 0x00000000}, +	{0x00016bbc, 0x00000000}, +	{0x00016bc0, 0x000000a0}, +	{0x00016bc4, 0x000c0000}, +	{0x00016bc8, 0x14021402}, +	{0x00016bcc, 0x00001402}, +	{0x00016bd0, 0x00000000}, +	{0x00016bd4, 0x00000000}, +}; + +static const u32 ar9300Common_rx_gain_table_merlin_2p0[][2] = { +	/* Addr      allmodes  */ +	{0x0000a000, 0x02000101}, +	{0x0000a004, 0x02000102}, +	{0x0000a008, 0x02000103}, +	{0x0000a00c, 0x02000104}, +	{0x0000a010, 0x02000200}, +	{0x0000a014, 0x02000201}, +	{0x0000a018, 0x02000202}, +	{0x0000a01c, 0x02000203}, +	{0x0000a020, 0x02000204}, +	{0x0000a024, 0x02000205}, +	{0x0000a028, 0x02000208}, +	{0x0000a02c, 0x02000302}, +	{0x0000a030, 0x02000303}, +	{0x0000a034, 0x02000304}, +	{0x0000a038, 0x02000400}, +	{0x0000a03c, 0x02010300}, +	{0x0000a040, 0x02010301}, +	{0x0000a044, 0x02010302}, +	{0x0000a048, 0x02000500}, +	{0x0000a04c, 0x02010400}, +	{0x0000a050, 0x02020300}, +	{0x0000a054, 0x02020301}, +	{0x0000a058, 0x02020302}, +	{0x0000a05c, 0x02020303}, +	{0x0000a060, 0x02020400}, +	{0x0000a064, 0x02030300}, +	{0x0000a068, 0x02030301}, +	{0x0000a06c, 0x02030302}, +	{0x0000a070, 0x02030303}, +	{0x0000a074, 0x02030400}, +	{0x0000a078, 0x02040300}, +	{0x0000a07c, 0x02040301}, +	{0x0000a080, 0x02040302}, +	{0x0000a084, 0x02040303}, +	{0x0000a088, 0x02030500}, +	{0x0000a08c, 0x02040400}, +	{0x0000a090, 0x02050203}, +	{0x0000a094, 0x02050204}, +	{0x0000a098, 0x02050205}, +	{0x0000a09c, 0x02040500}, +	{0x0000a0a0, 0x02050301}, +	{0x0000a0a4, 0x02050302}, +	{0x0000a0a8, 0x02050303}, +	{0x0000a0ac, 0x02050400}, +	{0x0000a0b0, 0x02050401}, +	{0x0000a0b4, 0x02050402}, +	{0x0000a0b8, 0x02050403}, +	{0x0000a0bc, 0x02050500}, +	{0x0000a0c0, 0x02050501}, +	{0x0000a0c4, 0x02050502}, +	{0x0000a0c8, 0x02050503}, +	{0x0000a0cc, 0x02050504}, +	{0x0000a0d0, 0x02050600}, +	{0x0000a0d4, 0x02050601}, +	{0x0000a0d8, 0x02050602}, +	{0x0000a0dc, 0x02050603}, +	{0x0000a0e0, 0x02050604}, +	{0x0000a0e4, 0x02050700}, +	{0x0000a0e8, 0x02050701}, +	{0x0000a0ec, 0x02050702}, +	{0x0000a0f0, 0x02050703}, +	{0x0000a0f4, 0x02050704}, +	{0x0000a0f8, 0x02050705}, +	{0x0000a0fc, 0x02050708}, +	{0x0000a100, 0x02050709}, +	{0x0000a104, 0x0205070a}, +	{0x0000a108, 0x0205070b}, +	{0x0000a10c, 0x0205070c}, +	{0x0000a110, 0x0205070d}, +	{0x0000a114, 0x02050710}, +	{0x0000a118, 0x02050711}, +	{0x0000a11c, 0x02050712}, +	{0x0000a120, 0x02050713}, +	{0x0000a124, 0x02050714}, +	{0x0000a128, 0x02050715}, +	{0x0000a12c, 0x02050730}, +	{0x0000a130, 0x02050731}, +	{0x0000a134, 0x02050732}, +	{0x0000a138, 0x02050733}, +	{0x0000a13c, 0x02050734}, +	{0x0000a140, 0x02050735}, +	{0x0000a144, 0x02050750}, +	{0x0000a148, 0x02050751}, +	{0x0000a14c, 0x02050752}, +	{0x0000a150, 0x02050753}, +	{0x0000a154, 0x02050754}, +	{0x0000a158, 0x02050755}, +	{0x0000a15c, 0x02050770}, +	{0x0000a160, 0x02050771}, +	{0x0000a164, 0x02050772}, +	{0x0000a168, 0x02050773}, +	{0x0000a16c, 0x02050774}, +	{0x0000a170, 0x02050775}, +	{0x0000a174, 0x00000776}, +	{0x0000a178, 0x00000776}, +	{0x0000a17c, 0x00000776}, +	{0x0000a180, 0x00000776}, +	{0x0000a184, 0x00000776}, +	{0x0000a188, 0x00000776}, +	{0x0000a18c, 0x00000776}, +	{0x0000a190, 0x00000776}, +	{0x0000a194, 0x00000776}, +	{0x0000a198, 0x00000776}, +	{0x0000a19c, 0x00000776}, +	{0x0000a1a0, 0x00000776}, +	{0x0000a1a4, 0x00000776}, +	{0x0000a1a8, 0x00000776}, +	{0x0000a1ac, 0x00000776}, +	{0x0000a1b0, 0x00000776}, +	{0x0000a1b4, 0x00000776}, +	{0x0000a1b8, 0x00000776}, +	{0x0000a1bc, 0x00000776}, +	{0x0000a1c0, 0x00000776}, +	{0x0000a1c4, 0x00000776}, +	{0x0000a1c8, 0x00000776}, +	{0x0000a1cc, 0x00000776}, +	{0x0000a1d0, 0x00000776}, +	{0x0000a1d4, 0x00000776}, +	{0x0000a1d8, 0x00000776}, +	{0x0000a1dc, 0x00000776}, +	{0x0000a1e0, 0x00000776}, +	{0x0000a1e4, 0x00000776}, +	{0x0000a1e8, 0x00000776}, +	{0x0000a1ec, 0x00000776}, +	{0x0000a1f0, 0x00000776}, +	{0x0000a1f4, 0x00000776}, +	{0x0000a1f8, 0x00000776}, +	{0x0000a1fc, 0x00000776}, +	{0x0000b000, 0x02000101}, +	{0x0000b004, 0x02000102}, +	{0x0000b008, 0x02000103}, +	{0x0000b00c, 0x02000104}, +	{0x0000b010, 0x02000200}, +	{0x0000b014, 0x02000201}, +	{0x0000b018, 0x02000202}, +	{0x0000b01c, 0x02000203}, +	{0x0000b020, 0x02000204}, +	{0x0000b024, 0x02000205}, +	{0x0000b028, 0x02000208}, +	{0x0000b02c, 0x02000302}, +	{0x0000b030, 0x02000303}, +	{0x0000b034, 0x02000304}, +	{0x0000b038, 0x02000400}, +	{0x0000b03c, 0x02010300}, +	{0x0000b040, 0x02010301}, +	{0x0000b044, 0x02010302}, +	{0x0000b048, 0x02000500}, +	{0x0000b04c, 0x02010400}, +	{0x0000b050, 0x02020300}, +	{0x0000b054, 0x02020301}, +	{0x0000b058, 0x02020302}, +	{0x0000b05c, 0x02020303}, +	{0x0000b060, 0x02020400}, +	{0x0000b064, 0x02030300}, +	{0x0000b068, 0x02030301}, +	{0x0000b06c, 0x02030302}, +	{0x0000b070, 0x02030303}, +	{0x0000b074, 0x02030400}, +	{0x0000b078, 0x02040300}, +	{0x0000b07c, 0x02040301}, +	{0x0000b080, 0x02040302}, +	{0x0000b084, 0x02040303}, +	{0x0000b088, 0x02030500}, +	{0x0000b08c, 0x02040400}, +	{0x0000b090, 0x02050203}, +	{0x0000b094, 0x02050204}, +	{0x0000b098, 0x02050205}, +	{0x0000b09c, 0x02040500}, +	{0x0000b0a0, 0x02050301}, +	{0x0000b0a4, 0x02050302}, +	{0x0000b0a8, 0x02050303}, +	{0x0000b0ac, 0x02050400}, +	{0x0000b0b0, 0x02050401}, +	{0x0000b0b4, 0x02050402}, +	{0x0000b0b8, 0x02050403}, +	{0x0000b0bc, 0x02050500}, +	{0x0000b0c0, 0x02050501}, +	{0x0000b0c4, 0x02050502}, +	{0x0000b0c8, 0x02050503}, +	{0x0000b0cc, 0x02050504}, +	{0x0000b0d0, 0x02050600}, +	{0x0000b0d4, 0x02050601}, +	{0x0000b0d8, 0x02050602}, +	{0x0000b0dc, 0x02050603}, +	{0x0000b0e0, 0x02050604}, +	{0x0000b0e4, 0x02050700}, +	{0x0000b0e8, 0x02050701}, +	{0x0000b0ec, 0x02050702}, +	{0x0000b0f0, 0x02050703}, +	{0x0000b0f4, 0x02050704}, +	{0x0000b0f8, 0x02050705}, +	{0x0000b0fc, 0x02050708}, +	{0x0000b100, 0x02050709}, +	{0x0000b104, 0x0205070a}, +	{0x0000b108, 0x0205070b}, +	{0x0000b10c, 0x0205070c}, +	{0x0000b110, 0x0205070d}, +	{0x0000b114, 0x02050710}, +	{0x0000b118, 0x02050711}, +	{0x0000b11c, 0x02050712}, +	{0x0000b120, 0x02050713}, +	{0x0000b124, 0x02050714}, +	{0x0000b128, 0x02050715}, +	{0x0000b12c, 0x02050730}, +	{0x0000b130, 0x02050731}, +	{0x0000b134, 0x02050732}, +	{0x0000b138, 0x02050733}, +	{0x0000b13c, 0x02050734}, +	{0x0000b140, 0x02050735}, +	{0x0000b144, 0x02050750}, +	{0x0000b148, 0x02050751}, +	{0x0000b14c, 0x02050752}, +	{0x0000b150, 0x02050753}, +	{0x0000b154, 0x02050754}, +	{0x0000b158, 0x02050755}, +	{0x0000b15c, 0x02050770}, +	{0x0000b160, 0x02050771}, +	{0x0000b164, 0x02050772}, +	{0x0000b168, 0x02050773}, +	{0x0000b16c, 0x02050774}, +	{0x0000b170, 0x02050775}, +	{0x0000b174, 0x00000776}, +	{0x0000b178, 0x00000776}, +	{0x0000b17c, 0x00000776}, +	{0x0000b180, 0x00000776}, +	{0x0000b184, 0x00000776}, +	{0x0000b188, 0x00000776}, +	{0x0000b18c, 0x00000776}, +	{0x0000b190, 0x00000776}, +	{0x0000b194, 0x00000776}, +	{0x0000b198, 0x00000776}, +	{0x0000b19c, 0x00000776}, +	{0x0000b1a0, 0x00000776}, +	{0x0000b1a4, 0x00000776}, +	{0x0000b1a8, 0x00000776}, +	{0x0000b1ac, 0x00000776}, +	{0x0000b1b0, 0x00000776}, +	{0x0000b1b4, 0x00000776}, +	{0x0000b1b8, 0x00000776}, +	{0x0000b1bc, 0x00000776}, +	{0x0000b1c0, 0x00000776}, +	{0x0000b1c4, 0x00000776}, +	{0x0000b1c8, 0x00000776}, +	{0x0000b1cc, 0x00000776}, +	{0x0000b1d0, 0x00000776}, +	{0x0000b1d4, 0x00000776}, +	{0x0000b1d8, 0x00000776}, +	{0x0000b1dc, 0x00000776}, +	{0x0000b1e0, 0x00000776}, +	{0x0000b1e4, 0x00000776}, +	{0x0000b1e8, 0x00000776}, +	{0x0000b1ec, 0x00000776}, +	{0x0000b1f0, 0x00000776}, +	{0x0000b1f4, 0x00000776}, +	{0x0000b1f8, 0x00000776}, +	{0x0000b1fc, 0x00000776}, +}; + +static const u32 ar9300_2p0_mac_postamble[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, +	{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, +	{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, +	{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, +	{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, +	{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, +	{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, +	{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, +}; + +static const u32 ar9300_2p0_soc_postamble[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x00007010, 0x00000023, 0x00000023, 0x00000022, 0x00000022}, +}; + +static const u32 ar9200_merlin_2p0_radio_core[][2] = { +	/* Addr      allmodes  */ +	{0x00007800, 0x00040000}, +	{0x00007804, 0xdb005012}, +	{0x00007808, 0x04924914}, +	{0x0000780c, 0x21084210}, +	{0x00007810, 0x6d801300}, +	{0x00007814, 0x0019beff}, +	{0x00007818, 0x07e41000}, +	{0x0000781c, 0x00392000}, +	{0x00007820, 0x92592480}, +	{0x00007824, 0x00040000}, +	{0x00007828, 0xdb005012}, +	{0x0000782c, 0x04924914}, +	{0x00007830, 0x21084210}, +	{0x00007834, 0x6d801300}, +	{0x00007838, 0x0019beff}, +	{0x0000783c, 0x07e40000}, +	{0x00007840, 0x00392000}, +	{0x00007844, 0x92592480}, +	{0x00007848, 0x00100000}, +	{0x0000784c, 0x773f0567}, +	{0x00007850, 0x54214514}, +	{0x00007854, 0x12035828}, +	{0x00007858, 0x92592692}, +	{0x0000785c, 0x00000000}, +	{0x00007860, 0x56400000}, +	{0x00007864, 0x0a8e370e}, +	{0x00007868, 0xc0102850}, +	{0x0000786c, 0x812d4000}, +	{0x00007870, 0x807ec400}, +	{0x00007874, 0x001b6db0}, +	{0x00007878, 0x00376b63}, +	{0x0000787c, 0x06db6db6}, +	{0x00007880, 0x006d8000}, +	{0x00007884, 0xffeffffe}, +	{0x00007888, 0xffeffffe}, +	{0x0000788c, 0x00010000}, +	{0x00007890, 0x02060aeb}, +	{0x00007894, 0x5a108000}, +}; + +static const u32 ar9300_2p0_baseband_postamble[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, +	{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, +	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, +	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, +	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, +	{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, +	{0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044}, +	{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, +	{0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, +	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, +	{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, +	{0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, +	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, +	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, +	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, +	{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, +	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, +	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, +	{0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, +	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, +	{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, +	{0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, +	{0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, +	{0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, +	{0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, +	{0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, +	{0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, +	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, +	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, +	{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, +	{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, +	{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, +	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, +	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, +	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, +	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, +	{0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, +	{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, +	{0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, +	{0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, +	{0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, +	{0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, +	{0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, +	{0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, +	{0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, +}; + +static const u32 ar9300_2p0_baseband_core[][2] = { +	/* Addr      allmodes  */ +	{0x00009800, 0xafe68e30}, +	{0x00009804, 0xfd14e000}, +	{0x00009808, 0x9c0a9f6b}, +	{0x0000980c, 0x04900000}, +	{0x00009814, 0x9280c00a}, +	{0x00009818, 0x00000000}, +	{0x0000981c, 0x00020028}, +	{0x00009834, 0x5f3ca3de}, +	{0x00009838, 0x0108ecff}, +	{0x0000983c, 0x14750600}, +	{0x00009880, 0x201fff00}, +	{0x00009884, 0x00001042}, +	{0x000098a4, 0x00200400}, +	{0x000098b0, 0x52440bbe}, +	{0x000098d0, 0x004b6a8e}, +	{0x000098d4, 0x00000820}, +	{0x000098dc, 0x00000000}, +	{0x000098f0, 0x00000000}, +	{0x000098f4, 0x00000000}, +	{0x00009c04, 0xff55ff55}, +	{0x00009c08, 0x0320ff55}, +	{0x00009c0c, 0x00000000}, +	{0x00009c10, 0x00000000}, +	{0x00009c14, 0x00046384}, +	{0x00009c18, 0x05b6b440}, +	{0x00009c1c, 0x00b6b440}, +	{0x00009d00, 0xc080a333}, +	{0x00009d04, 0x40206c10}, +	{0x00009d08, 0x009c4060}, +	{0x00009d0c, 0x9883800a}, +	{0x00009d10, 0x01834061}, +	{0x00009d14, 0x00c0040b}, +	{0x00009d18, 0x00000000}, +	{0x00009e08, 0x0038233c}, +	{0x00009e24, 0x990bb515}, +	{0x00009e28, 0x0c6f0000}, +	{0x00009e30, 0x06336f77}, +	{0x00009e34, 0x6af6532f}, +	{0x00009e38, 0x0cc80c00}, +	{0x00009e3c, 0xcf946222}, +	{0x00009e40, 0x0d261820}, +	{0x00009e4c, 0x00001004}, +	{0x00009e50, 0x00ff03f1}, +	{0x00009e54, 0x00000000}, +	{0x00009fc0, 0x803e4788}, +	{0x00009fc4, 0x0001efb5}, +	{0x00009fcc, 0x40000014}, +	{0x00009fd0, 0x01193b93}, +	{0x0000a20c, 0x00000000}, +	{0x0000a220, 0x00000000}, +	{0x0000a224, 0x00000000}, +	{0x0000a228, 0x10002310}, +	{0x0000a22c, 0x01036a1e}, +	{0x0000a234, 0x10000fff}, +	{0x0000a23c, 0x00000000}, +	{0x0000a244, 0x0c000000}, +	{0x0000a2a0, 0x00000001}, +	{0x0000a2c0, 0x00000001}, +	{0x0000a2c8, 0x00000000}, +	{0x0000a2cc, 0x18c43433}, +	{0x0000a2d4, 0x00000000}, +	{0x0000a2dc, 0x00000000}, +	{0x0000a2e0, 0x00000000}, +	{0x0000a2e4, 0x00000000}, +	{0x0000a2e8, 0x00000000}, +	{0x0000a2ec, 0x00000000}, +	{0x0000a2f0, 0x00000000}, +	{0x0000a2f4, 0x00000000}, +	{0x0000a2f8, 0x00000000}, +	{0x0000a344, 0x00000000}, +	{0x0000a34c, 0x00000000}, +	{0x0000a350, 0x0000a000}, +	{0x0000a364, 0x00000000}, +	{0x0000a370, 0x00000000}, +	{0x0000a390, 0x00000001}, +	{0x0000a394, 0x00000444}, +	{0x0000a398, 0x001f0e0f}, +	{0x0000a39c, 0x0075393f}, +	{0x0000a3a0, 0xb79f6427}, +	{0x0000a3a4, 0x00000000}, +	{0x0000a3a8, 0xaaaaaaaa}, +	{0x0000a3ac, 0x3c466478}, +	{0x0000a3c0, 0x20202020}, +	{0x0000a3c4, 0x22222220}, +	{0x0000a3c8, 0x20200020}, +	{0x0000a3cc, 0x20202020}, +	{0x0000a3d0, 0x20202020}, +	{0x0000a3d4, 0x20202020}, +	{0x0000a3d8, 0x20202020}, +	{0x0000a3dc, 0x20202020}, +	{0x0000a3e0, 0x20202020}, +	{0x0000a3e4, 0x20202020}, +	{0x0000a3e8, 0x20202020}, +	{0x0000a3ec, 0x20202020}, +	{0x0000a3f0, 0x00000000}, +	{0x0000a3f4, 0x00000246}, +	{0x0000a3f8, 0x0cdbd380}, +	{0x0000a3fc, 0x000f0f01}, +	{0x0000a400, 0x8fa91f01}, +	{0x0000a404, 0x00000000}, +	{0x0000a408, 0x0e79e5c6}, +	{0x0000a40c, 0x00820820}, +	{0x0000a414, 0x1ce739ce}, +	{0x0000a418, 0x7d001dce}, +	{0x0000a41c, 0x1ce739ce}, +	{0x0000a420, 0x000001ce}, +	{0x0000a424, 0x1ce739ce}, +	{0x0000a428, 0x000001ce}, +	{0x0000a42c, 0x1ce739ce}, +	{0x0000a430, 0x1ce739ce}, +	{0x0000a434, 0x00000000}, +	{0x0000a438, 0x00001801}, +	{0x0000a43c, 0x00000000}, +	{0x0000a440, 0x00000000}, +	{0x0000a444, 0x00000000}, +	{0x0000a448, 0x07000080}, +	{0x0000a44c, 0x00000001}, +	{0x0000a450, 0x00010000}, +	{0x0000a458, 0x00000000}, +	{0x0000a600, 0x00000000}, +	{0x0000a604, 0x00000000}, +	{0x0000a608, 0x00000000}, +	{0x0000a60c, 0x00000000}, +	{0x0000a610, 0x00000000}, +	{0x0000a614, 0x00000000}, +	{0x0000a618, 0x00000000}, +	{0x0000a61c, 0x00000000}, +	{0x0000a620, 0x00000000}, +	{0x0000a624, 0x00000000}, +	{0x0000a628, 0x00000000}, +	{0x0000a62c, 0x00000000}, +	{0x0000a630, 0x00000000}, +	{0x0000a634, 0x00000000}, +	{0x0000a638, 0x00000000}, +	{0x0000a63c, 0x00000000}, +	{0x0000a640, 0x00000000}, +	{0x0000a644, 0x3ffd9d74}, +	{0x0000a648, 0x0048060a}, +	{0x0000a64c, 0x00000637}, +	{0x0000a670, 0x03020100}, +	{0x0000a674, 0x09080504}, +	{0x0000a678, 0x0d0c0b0a}, +	{0x0000a67c, 0x13121110}, +	{0x0000a680, 0x31301514}, +	{0x0000a684, 0x35343332}, +	{0x0000a688, 0x00000036}, +	{0x0000a690, 0x00000838}, +	{0x0000a7c0, 0x00000000}, +	{0x0000a7c4, 0xfffffffc}, +	{0x0000a7c8, 0x00000000}, +	{0x0000a7cc, 0x00000000}, +	{0x0000a7d0, 0x00000000}, +	{0x0000a7d4, 0x00000004}, +	{0x0000a7dc, 0x00000001}, +	{0x0000a8d0, 0x004b6a8e}, +	{0x0000a8d4, 0x00000820}, +	{0x0000a8dc, 0x00000000}, +	{0x0000a8f0, 0x00000000}, +	{0x0000a8f4, 0x00000000}, +	{0x0000b2d0, 0x00000080}, +	{0x0000b2d4, 0x00000000}, +	{0x0000b2dc, 0x00000000}, +	{0x0000b2e0, 0x00000000}, +	{0x0000b2e4, 0x00000000}, +	{0x0000b2e8, 0x00000000}, +	{0x0000b2ec, 0x00000000}, +	{0x0000b2f0, 0x00000000}, +	{0x0000b2f4, 0x00000000}, +	{0x0000b2f8, 0x00000000}, +	{0x0000b408, 0x0e79e5c0}, +	{0x0000b40c, 0x00820820}, +	{0x0000b420, 0x00000000}, +	{0x0000b8d0, 0x004b6a8e}, +	{0x0000b8d4, 0x00000820}, +	{0x0000b8dc, 0x00000000}, +	{0x0000b8f0, 0x00000000}, +	{0x0000b8f4, 0x00000000}, +	{0x0000c2d0, 0x00000080}, +	{0x0000c2d4, 0x00000000}, +	{0x0000c2dc, 0x00000000}, +	{0x0000c2e0, 0x00000000}, +	{0x0000c2e4, 0x00000000}, +	{0x0000c2e8, 0x00000000}, +	{0x0000c2ec, 0x00000000}, +	{0x0000c2f0, 0x00000000}, +	{0x0000c2f4, 0x00000000}, +	{0x0000c2f8, 0x00000000}, +	{0x0000c408, 0x0e79e5c0}, +	{0x0000c40c, 0x00820820}, +	{0x0000c420, 0x00000000}, +}; + +static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0000a410, 0x000050db, 0x000050db, 0x000050d9, 0x000050d9}, +	{0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000}, +	{0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, +	{0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, +	{0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, +	{0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, +	{0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, +	{0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, +	{0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, +	{0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, +	{0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, +	{0x0000a530, 0x34043643, 0x34043643, 0x2a000e20, 0x2a000e20}, +	{0x0000a534, 0x38043a44, 0x38043a44, 0x2e000e22, 0x2e000e22}, +	{0x0000a538, 0x3b043e45, 0x3b043e45, 0x31000e24, 0x31000e24}, +	{0x0000a53c, 0x40063e46, 0x40063e46, 0x34001640, 0x34001640}, +	{0x0000a540, 0x44083e46, 0x44083e46, 0x38001660, 0x38001660}, +	{0x0000a544, 0x46083e66, 0x46083e66, 0x3b001861, 0x3b001861}, +	{0x0000a548, 0x4b0a3e69, 0x4b0a3e69, 0x3e001a81, 0x3e001a81}, +	{0x0000a54c, 0x4f0a5e66, 0x4f0a5e66, 0x42001a83, 0x42001a83}, +	{0x0000a550, 0x540a7e66, 0x540a7e66, 0x44001c84, 0x44001c84}, +	{0x0000a554, 0x570a7e89, 0x570a7e89, 0x48001ce3, 0x48001ce3}, +	{0x0000a558, 0x5c0e7e8a, 0x5c0e7e8a, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a55c, 0x60127e8b, 0x60127e8b, 0x50001ce9, 0x50001ce9}, +	{0x0000a560, 0x65127ecc, 0x65127ecc, 0x54001ceb, 0x54001ceb}, +	{0x0000a564, 0x6b169ecd, 0x6b169ecd, 0x56001eec, 0x56001eec}, +	{0x0000a568, 0x70169f0e, 0x70169f0e, 0x56001eec, 0x56001eec}, +	{0x0000a56c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, +	{0x0000a570, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, +	{0x0000a574, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, +	{0x0000a578, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, +	{0x0000a57c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, +	{0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000}, +	{0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002}, +	{0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, +	{0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, +	{0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, +	{0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, +	{0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, +	{0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, +	{0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, +	{0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, +	{0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, +	{0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, +	{0x0000a5b0, 0x34843643, 0x34843643, 0x2a800e20, 0x2a800e20}, +	{0x0000a5b4, 0x38843a44, 0x38843a44, 0x2e800e22, 0x2e800e22}, +	{0x0000a5b8, 0x3b843e45, 0x3b843e45, 0x31800e24, 0x31800e24}, +	{0x0000a5bc, 0x40863e46, 0x40863e46, 0x34801640, 0x34801640}, +	{0x0000a5c0, 0x4c8a3065, 0x44883e46, 0x44883e46, 0x38801660}, +	{0x0000a5c4, 0x46883e66, 0x46883e66, 0x3b801861, 0x3b801861}, +	{0x0000a5c8, 0x4b8a3e69, 0x4b8a3e69, 0x3e801a81, 0x3e801a81}, +	{0x0000a5cc, 0x4f8a5e66, 0x4f8a5e66, 0x42801a83, 0x42801a83}, +	{0x0000a5d0, 0x548a7e66, 0x548a7e66, 0x44801c84, 0x44801c84}, +	{0x0000a5d4, 0x578a7e89, 0x578a7e89, 0x48801ce3, 0x48801ce3}, +	{0x0000a5d8, 0x5c8e7e8a, 0x5c8e7e8a, 0x4c801ce5, 0x4c801ce5}, +	{0x0000a5dc, 0x60927e8b, 0x60927e8b, 0x50801ce9, 0x50801ce9}, +	{0x0000a5e0, 0x65927ecc, 0x65927ecc, 0x54801ceb, 0x54801ceb}, +	{0x0000a5e4, 0x6b969ecd, 0x6b969ecd, 0x56801eec, 0x56801eec}, +	{0x0000a5e8, 0x70969f0e, 0x70969f0e, 0x56801eec, 0x56801eec}, +	{0x0000a5ec, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, +	{0x0000a5f0, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, +	{0x0000a5f4, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, +	{0x0000a5f8, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, +	{0x0000a5fc, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, +	{0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, +	{0x00016048, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61}, +	{0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, +	{0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, +	{0x00016448, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61}, +	{0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, +	{0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, +	{0x00016848, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61}, +	{0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, +}; + +static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0000a410, 0x000050db, 0x000050db, 0x000050d9, 0x000050d9}, +	{0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000}, +	{0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200}, +	{0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202}, +	{0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400}, +	{0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402}, +	{0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404}, +	{0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603}, +	{0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02}, +	{0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04}, +	{0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20}, +	{0x0000a530, 0x34043643, 0x34043643, 0x2a000e20, 0x2a000e20}, +	{0x0000a534, 0x38043a44, 0x38043a44, 0x2e000e22, 0x2e000e22}, +	{0x0000a538, 0x3b043e45, 0x3b043e45, 0x31000e24, 0x31000e24}, +	{0x0000a53c, 0x40063e46, 0x40063e46, 0x34001640, 0x34001640}, +	{0x0000a540, 0x44083e46, 0x44083e46, 0x38001660, 0x38001660}, +	{0x0000a544, 0x46083e66, 0x46083e66, 0x3b001861, 0x3b001861}, +	{0x0000a548, 0x4b0a3e69, 0x4b0a3e69, 0x3e001a81, 0x3e001a81}, +	{0x0000a54c, 0x4f0a5e66, 0x4f0a5e66, 0x42001a83, 0x42001a83}, +	{0x0000a550, 0x540a7e66, 0x540a7e66, 0x44001c84, 0x44001c84}, +	{0x0000a554, 0x570a7e89, 0x570a7e89, 0x48001ce3, 0x48001ce3}, +	{0x0000a558, 0x5c0e7e8a, 0x5c0e7e8a, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a55c, 0x60127e8b, 0x60127e8b, 0x50001ce9, 0x50001ce9}, +	{0x0000a560, 0x65127ecc, 0x65127ecc, 0x54001ceb, 0x54001ceb}, +	{0x0000a564, 0x6b169ecd, 0x6b169ecd, 0x56001eec, 0x56001eec}, +	{0x0000a568, 0x70169f0e, 0x70169f0e, 0x56001eec, 0x56001eec}, +	{0x0000a56c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, +	{0x0000a570, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, +	{0x0000a574, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, +	{0x0000a578, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, +	{0x0000a57c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec}, +	{0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000}, +	{0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002}, +	{0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004}, +	{0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200}, +	{0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202}, +	{0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400}, +	{0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402}, +	{0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404}, +	{0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603}, +	{0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02}, +	{0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04}, +	{0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20}, +	{0x0000a5b0, 0x34843643, 0x34843643, 0x2a800e20, 0x2a800e20}, +	{0x0000a5b4, 0x38843a44, 0x38843a44, 0x2e800e22, 0x2e800e22}, +	{0x0000a5b8, 0x3b843e45, 0x3b843e45, 0x31800e24, 0x31800e24}, +	{0x0000a5bc, 0x40863e46, 0x40863e46, 0x34801640, 0x34801640}, +	{0x0000a5c0, 0x44883e46, 0x44883e46, 0x38801660, 0x38801660}, +	{0x0000a5c4, 0x46883e66, 0x46883e66, 0x3b801861, 0x3b801861}, +	{0x0000a5c8, 0x4b8a3e69, 0x4b8a3e69, 0x3e801a81, 0x3e801a81}, +	{0x0000a5cc, 0x4f8a5e66, 0x4f8a5e66, 0x42801a83, 0x42801a83}, +	{0x0000a5d0, 0x548a7e66, 0x548a7e66, 0x44801c84, 0x44801c84}, +	{0x0000a5d4, 0x578a7e89, 0x578a7e89, 0x48801ce3, 0x48801ce3}, +	{0x0000a5d8, 0x5c8e7e8a, 0x5c8e7e8a, 0x4c801ce5, 0x4c801ce5}, +	{0x0000a5dc, 0x60927e8b, 0x60927e8b, 0x50801ce9, 0x50801ce9}, +	{0x0000a5e0, 0x65927ecc, 0x65927ecc, 0x54801ceb, 0x54801ceb}, +	{0x0000a5e4, 0x6b969ecd, 0x6b969ecd, 0x56801eec, 0x56801eec}, +	{0x0000a5e8, 0x70969f0e, 0x70969f0e, 0x56801eec, 0x56801eec}, +	{0x0000a5ec, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, +	{0x0000a5f0, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, +	{0x0000a5f4, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, +	{0x0000a5f8, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, +	{0x0000a5fc, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec}, +	{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, +	{0x00016048, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61}, +	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, +	{0x00016448, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61}, +	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, +	{0x00016848, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61}, +	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9300Common_rx_gain_table_2p0[][2] = { +	/* Addr      allmodes  */ +	{0x0000a000, 0x00010000}, +	{0x0000a004, 0x00030002}, +	{0x0000a008, 0x00050004}, +	{0x0000a00c, 0x00810080}, +	{0x0000a010, 0x01800082}, +	{0x0000a014, 0x01820181}, +	{0x0000a018, 0x01840183}, +	{0x0000a01c, 0x01880185}, +	{0x0000a020, 0x018a0189}, +	{0x0000a024, 0x02850284}, +	{0x0000a028, 0x02890288}, +	{0x0000a02c, 0x028b028a}, +	{0x0000a030, 0x028d028c}, +	{0x0000a034, 0x02910290}, +	{0x0000a038, 0x02930292}, +	{0x0000a03c, 0x03910390}, +	{0x0000a040, 0x03930392}, +	{0x0000a044, 0x03950394}, +	{0x0000a048, 0x00000396}, +	{0x0000a04c, 0x00000000}, +	{0x0000a050, 0x00000000}, +	{0x0000a054, 0x00000000}, +	{0x0000a058, 0x00000000}, +	{0x0000a05c, 0x00000000}, +	{0x0000a060, 0x00000000}, +	{0x0000a064, 0x00000000}, +	{0x0000a068, 0x00000000}, +	{0x0000a06c, 0x00000000}, +	{0x0000a070, 0x00000000}, +	{0x0000a074, 0x00000000}, +	{0x0000a078, 0x00000000}, +	{0x0000a07c, 0x00000000}, +	{0x0000a080, 0x28282828}, +	{0x0000a084, 0x21212128}, +	{0x0000a088, 0x21212121}, +	{0x0000a08c, 0x1c1c1c21}, +	{0x0000a090, 0x1c1c1c1c}, +	{0x0000a094, 0x17171c1c}, +	{0x0000a098, 0x02020212}, +	{0x0000a09c, 0x02020202}, +	{0x0000a0a0, 0x00000000}, +	{0x0000a0a4, 0x00000000}, +	{0x0000a0a8, 0x00000000}, +	{0x0000a0ac, 0x00000000}, +	{0x0000a0b0, 0x00000000}, +	{0x0000a0b4, 0x00000000}, +	{0x0000a0b8, 0x00000000}, +	{0x0000a0bc, 0x00000000}, +	{0x0000a0c0, 0x001f0000}, +	{0x0000a0c4, 0x011f0100}, +	{0x0000a0c8, 0x011d011e}, +	{0x0000a0cc, 0x011b011c}, +	{0x0000a0d0, 0x02030204}, +	{0x0000a0d4, 0x02010202}, +	{0x0000a0d8, 0x021f0200}, +	{0x0000a0dc, 0x021d021e}, +	{0x0000a0e0, 0x03010302}, +	{0x0000a0e4, 0x031f0300}, +	{0x0000a0e8, 0x0402031e}, +	{0x0000a0ec, 0x04000401}, +	{0x0000a0f0, 0x041e041f}, +	{0x0000a0f4, 0x05010502}, +	{0x0000a0f8, 0x051f0500}, +	{0x0000a0fc, 0x0602051e}, +	{0x0000a100, 0x06000601}, +	{0x0000a104, 0x061e061f}, +	{0x0000a108, 0x0703061d}, +	{0x0000a10c, 0x07010702}, +	{0x0000a110, 0x00000700}, +	{0x0000a114, 0x00000000}, +	{0x0000a118, 0x00000000}, +	{0x0000a11c, 0x00000000}, +	{0x0000a120, 0x00000000}, +	{0x0000a124, 0x00000000}, +	{0x0000a128, 0x00000000}, +	{0x0000a12c, 0x00000000}, +	{0x0000a130, 0x00000000}, +	{0x0000a134, 0x00000000}, +	{0x0000a138, 0x00000000}, +	{0x0000a13c, 0x00000000}, +	{0x0000a140, 0x001f0000}, +	{0x0000a144, 0x011f0100}, +	{0x0000a148, 0x011d011e}, +	{0x0000a14c, 0x011b011c}, +	{0x0000a150, 0x02030204}, +	{0x0000a154, 0x02010202}, +	{0x0000a158, 0x021f0200}, +	{0x0000a15c, 0x021d021e}, +	{0x0000a160, 0x03010302}, +	{0x0000a164, 0x031f0300}, +	{0x0000a168, 0x0402031e}, +	{0x0000a16c, 0x04000401}, +	{0x0000a170, 0x041e041f}, +	{0x0000a174, 0x05010502}, +	{0x0000a178, 0x051f0500}, +	{0x0000a17c, 0x0602051e}, +	{0x0000a180, 0x06000601}, +	{0x0000a184, 0x061e061f}, +	{0x0000a188, 0x0703061d}, +	{0x0000a18c, 0x07010702}, +	{0x0000a190, 0x00000700}, +	{0x0000a194, 0x00000000}, +	{0x0000a198, 0x00000000}, +	{0x0000a19c, 0x00000000}, +	{0x0000a1a0, 0x00000000}, +	{0x0000a1a4, 0x00000000}, +	{0x0000a1a8, 0x00000000}, +	{0x0000a1ac, 0x00000000}, +	{0x0000a1b0, 0x00000000}, +	{0x0000a1b4, 0x00000000}, +	{0x0000a1b8, 0x00000000}, +	{0x0000a1bc, 0x00000000}, +	{0x0000a1c0, 0x00000000}, +	{0x0000a1c4, 0x00000000}, +	{0x0000a1c8, 0x00000000}, +	{0x0000a1cc, 0x00000000}, +	{0x0000a1d0, 0x00000000}, +	{0x0000a1d4, 0x00000000}, +	{0x0000a1d8, 0x00000000}, +	{0x0000a1dc, 0x00000000}, +	{0x0000a1e0, 0x00000000}, +	{0x0000a1e4, 0x00000000}, +	{0x0000a1e8, 0x00000000}, +	{0x0000a1ec, 0x00000000}, +	{0x0000a1f0, 0x00000396}, +	{0x0000a1f4, 0x00000396}, +	{0x0000a1f8, 0x00000396}, +	{0x0000a1fc, 0x00000196}, +	{0x0000b000, 0x00010000}, +	{0x0000b004, 0x00030002}, +	{0x0000b008, 0x00050004}, +	{0x0000b00c, 0x00810080}, +	{0x0000b010, 0x00830082}, +	{0x0000b014, 0x01810180}, +	{0x0000b018, 0x01830182}, +	{0x0000b01c, 0x01850184}, +	{0x0000b020, 0x02810280}, +	{0x0000b024, 0x02830282}, +	{0x0000b028, 0x02850284}, +	{0x0000b02c, 0x02890288}, +	{0x0000b030, 0x028b028a}, +	{0x0000b034, 0x0388028c}, +	{0x0000b038, 0x038a0389}, +	{0x0000b03c, 0x038c038b}, +	{0x0000b040, 0x0390038d}, +	{0x0000b044, 0x03920391}, +	{0x0000b048, 0x03940393}, +	{0x0000b04c, 0x03960395}, +	{0x0000b050, 0x00000000}, +	{0x0000b054, 0x00000000}, +	{0x0000b058, 0x00000000}, +	{0x0000b05c, 0x00000000}, +	{0x0000b060, 0x00000000}, +	{0x0000b064, 0x00000000}, +	{0x0000b068, 0x00000000}, +	{0x0000b06c, 0x00000000}, +	{0x0000b070, 0x00000000}, +	{0x0000b074, 0x00000000}, +	{0x0000b078, 0x00000000}, +	{0x0000b07c, 0x00000000}, +	{0x0000b080, 0x32323232}, +	{0x0000b084, 0x2f2f3232}, +	{0x0000b088, 0x23282a2d}, +	{0x0000b08c, 0x1c1e2123}, +	{0x0000b090, 0x14171919}, +	{0x0000b094, 0x0e0e1214}, +	{0x0000b098, 0x03050707}, +	{0x0000b09c, 0x00030303}, +	{0x0000b0a0, 0x00000000}, +	{0x0000b0a4, 0x00000000}, +	{0x0000b0a8, 0x00000000}, +	{0x0000b0ac, 0x00000000}, +	{0x0000b0b0, 0x00000000}, +	{0x0000b0b4, 0x00000000}, +	{0x0000b0b8, 0x00000000}, +	{0x0000b0bc, 0x00000000}, +	{0x0000b0c0, 0x003f0020}, +	{0x0000b0c4, 0x00400041}, +	{0x0000b0c8, 0x0140005f}, +	{0x0000b0cc, 0x0160015f}, +	{0x0000b0d0, 0x017e017f}, +	{0x0000b0d4, 0x02410242}, +	{0x0000b0d8, 0x025f0240}, +	{0x0000b0dc, 0x027f0260}, +	{0x0000b0e0, 0x0341027e}, +	{0x0000b0e4, 0x035f0340}, +	{0x0000b0e8, 0x037f0360}, +	{0x0000b0ec, 0x04400441}, +	{0x0000b0f0, 0x0460045f}, +	{0x0000b0f4, 0x0541047f}, +	{0x0000b0f8, 0x055f0540}, +	{0x0000b0fc, 0x057f0560}, +	{0x0000b100, 0x06400641}, +	{0x0000b104, 0x0660065f}, +	{0x0000b108, 0x067e067f}, +	{0x0000b10c, 0x07410742}, +	{0x0000b110, 0x075f0740}, +	{0x0000b114, 0x077f0760}, +	{0x0000b118, 0x07800781}, +	{0x0000b11c, 0x07a0079f}, +	{0x0000b120, 0x07c107bf}, +	{0x0000b124, 0x000007c0}, +	{0x0000b128, 0x00000000}, +	{0x0000b12c, 0x00000000}, +	{0x0000b130, 0x00000000}, +	{0x0000b134, 0x00000000}, +	{0x0000b138, 0x00000000}, +	{0x0000b13c, 0x00000000}, +	{0x0000b140, 0x003f0020}, +	{0x0000b144, 0x00400041}, +	{0x0000b148, 0x0140005f}, +	{0x0000b14c, 0x0160015f}, +	{0x0000b150, 0x017e017f}, +	{0x0000b154, 0x02410242}, +	{0x0000b158, 0x025f0240}, +	{0x0000b15c, 0x027f0260}, +	{0x0000b160, 0x0341027e}, +	{0x0000b164, 0x035f0340}, +	{0x0000b168, 0x037f0360}, +	{0x0000b16c, 0x04400441}, +	{0x0000b170, 0x0460045f}, +	{0x0000b174, 0x0541047f}, +	{0x0000b178, 0x055f0540}, +	{0x0000b17c, 0x057f0560}, +	{0x0000b180, 0x06400641}, +	{0x0000b184, 0x0660065f}, +	{0x0000b188, 0x067e067f}, +	{0x0000b18c, 0x07410742}, +	{0x0000b190, 0x075f0740}, +	{0x0000b194, 0x077f0760}, +	{0x0000b198, 0x07800781}, +	{0x0000b19c, 0x07a0079f}, +	{0x0000b1a0, 0x07c107bf}, +	{0x0000b1a4, 0x000007c0}, +	{0x0000b1a8, 0x00000000}, +	{0x0000b1ac, 0x00000000}, +	{0x0000b1b0, 0x00000000}, +	{0x0000b1b4, 0x00000000}, +	{0x0000b1b8, 0x00000000}, +	{0x0000b1bc, 0x00000000}, +	{0x0000b1c0, 0x00000000}, +	{0x0000b1c4, 0x00000000}, +	{0x0000b1c8, 0x00000000}, +	{0x0000b1cc, 0x00000000}, +	{0x0000b1d0, 0x00000000}, +	{0x0000b1d4, 0x00000000}, +	{0x0000b1d8, 0x00000000}, +	{0x0000b1dc, 0x00000000}, +	{0x0000b1e0, 0x00000000}, +	{0x0000b1e4, 0x00000000}, +	{0x0000b1e8, 0x00000000}, +	{0x0000b1ec, 0x00000000}, +	{0x0000b1f0, 0x00000396}, +	{0x0000b1f4, 0x00000396}, +	{0x0000b1f8, 0x00000396}, +	{0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, +	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, +	{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, +	{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, +	{0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, +	{0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, +	{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, +	{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, +	{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, +	{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, +	{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, +	{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, +	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, +	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, +	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, +	{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, +	{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, +	{0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, +	{0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, +	{0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, +	{0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, +	{0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, +	{0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, +	{0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, +	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, +	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, +	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, +	{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, +	{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, +	{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, +	{0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, +	{0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, +	{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, +	{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, +	{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, +	{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, +	{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, +	{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, +	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, +	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, +	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, +	{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, +	{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, +	{0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, +	{0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, +	{0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, +	{0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, +	{0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, +	{0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, +	{0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, +	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016048, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61}, +	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016448, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61}, +	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016848, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61}, +	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9300_2p0_mac_core[][2] = { +	/* Addr      allmodes  */ +	{0x00000008, 0x00000000}, +	{0x00000030, 0x00020085}, +	{0x00000034, 0x00000005}, +	{0x00000040, 0x00000000}, +	{0x00000044, 0x00000000}, +	{0x00000048, 0x00000008}, +	{0x0000004c, 0x00000010}, +	{0x00000050, 0x00000000}, +	{0x00001040, 0x002ffc0f}, +	{0x00001044, 0x002ffc0f}, +	{0x00001048, 0x002ffc0f}, +	{0x0000104c, 0x002ffc0f}, +	{0x00001050, 0x002ffc0f}, +	{0x00001054, 0x002ffc0f}, +	{0x00001058, 0x002ffc0f}, +	{0x0000105c, 0x002ffc0f}, +	{0x00001060, 0x002ffc0f}, +	{0x00001064, 0x002ffc0f}, +	{0x000010f0, 0x00000100}, +	{0x00001270, 0x00000000}, +	{0x000012b0, 0x00000000}, +	{0x000012f0, 0x00000000}, +	{0x0000143c, 0x00000000}, +	{0x0000147c, 0x00000000}, +	{0x00008000, 0x00000000}, +	{0x00008004, 0x00000000}, +	{0x00008008, 0x00000000}, +	{0x0000800c, 0x00000000}, +	{0x00008018, 0x00000000}, +	{0x00008020, 0x00000000}, +	{0x00008038, 0x00000000}, +	{0x0000803c, 0x00000000}, +	{0x00008040, 0x00000000}, +	{0x00008044, 0x00000000}, +	{0x00008048, 0x00000000}, +	{0x0000804c, 0xffffffff}, +	{0x00008054, 0x00000000}, +	{0x00008058, 0x00000000}, +	{0x0000805c, 0x000fc78f}, +	{0x00008060, 0x0000000f}, +	{0x00008064, 0x00000000}, +	{0x00008070, 0x00000310}, +	{0x00008074, 0x00000020}, +	{0x00008078, 0x00000000}, +	{0x0000809c, 0x0000000f}, +	{0x000080a0, 0x00000000}, +	{0x000080a4, 0x02ff0000}, +	{0x000080a8, 0x0e070605}, +	{0x000080ac, 0x0000000d}, +	{0x000080b0, 0x00000000}, +	{0x000080b4, 0x00000000}, +	{0x000080b8, 0x00000000}, +	{0x000080bc, 0x00000000}, +	{0x000080c0, 0x2a800000}, +	{0x000080c4, 0x06900168}, +	{0x000080c8, 0x13881c20}, +	{0x000080cc, 0x01f40000}, +	{0x000080d0, 0x00252500}, +	{0x000080d4, 0x00a00000}, +	{0x000080d8, 0x00400000}, +	{0x000080dc, 0x00000000}, +	{0x000080e0, 0xffffffff}, +	{0x000080e4, 0x0000ffff}, +	{0x000080e8, 0x3f3f3f3f}, +	{0x000080ec, 0x00000000}, +	{0x000080f0, 0x00000000}, +	{0x000080f4, 0x00000000}, +	{0x000080fc, 0x00020000}, +	{0x00008100, 0x00000000}, +	{0x00008108, 0x00000052}, +	{0x0000810c, 0x00000000}, +	{0x00008110, 0x00000000}, +	{0x00008114, 0x000007ff}, +	{0x00008118, 0x000000aa}, +	{0x0000811c, 0x00003210}, +	{0x00008124, 0x00000000}, +	{0x00008128, 0x00000000}, +	{0x0000812c, 0x00000000}, +	{0x00008130, 0x00000000}, +	{0x00008134, 0x00000000}, +	{0x00008138, 0x00000000}, +	{0x0000813c, 0x0000ffff}, +	{0x00008144, 0xffffffff}, +	{0x00008168, 0x00000000}, +	{0x0000816c, 0x00000000}, +	{0x00008170, 0x18486200}, +	{0x00008174, 0x33332210}, +	{0x00008178, 0x00000000}, +	{0x0000817c, 0x00020000}, +	{0x000081c0, 0x00000000}, +	{0x000081c4, 0x33332210}, +	{0x000081c8, 0x00000000}, +	{0x000081cc, 0x00000000}, +	{0x000081d4, 0x00000000}, +	{0x000081ec, 0x00000000}, +	{0x000081f0, 0x00000000}, +	{0x000081f4, 0x00000000}, +	{0x000081f8, 0x00000000}, +	{0x000081fc, 0x00000000}, +	{0x00008240, 0x00100000}, +	{0x00008244, 0x0010f424}, +	{0x00008248, 0x00000800}, +	{0x0000824c, 0x0001e848}, +	{0x00008250, 0x00000000}, +	{0x00008254, 0x00000000}, +	{0x00008258, 0x00000000}, +	{0x0000825c, 0x40000000}, +	{0x00008260, 0x00080922}, +	{0x00008264, 0x98a00010}, +	{0x00008268, 0xffffffff}, +	{0x0000826c, 0x0000ffff}, +	{0x00008270, 0x00000000}, +	{0x00008274, 0x40000000}, +	{0x00008278, 0x003e4180}, +	{0x0000827c, 0x00000004}, +	{0x00008284, 0x0000002c}, +	{0x00008288, 0x0000002c}, +	{0x0000828c, 0x000000ff}, +	{0x00008294, 0x00000000}, +	{0x00008298, 0x00000000}, +	{0x0000829c, 0x00000000}, +	{0x00008300, 0x00000140}, +	{0x00008314, 0x00000000}, +	{0x0000831c, 0x0000010d}, +	{0x00008328, 0x00000000}, +	{0x0000832c, 0x00000007}, +	{0x00008330, 0x00000302}, +	{0x00008334, 0x00000700}, +	{0x00008338, 0x00ff0000}, +	{0x0000833c, 0x02400000}, +	{0x00008340, 0x000107ff}, +	{0x00008344, 0xaa48105b}, +	{0x00008348, 0x008f0000}, +	{0x0000835c, 0x00000000}, +	{0x00008360, 0xffffffff}, +	{0x00008364, 0xffffffff}, +	{0x00008368, 0x00000000}, +	{0x00008370, 0x00000000}, +	{0x00008374, 0x000000ff}, +	{0x00008378, 0x00000000}, +	{0x0000837c, 0x00000000}, +	{0x00008380, 0xffffffff}, +	{0x00008384, 0xffffffff}, +	{0x00008390, 0xffffffff}, +	{0x00008394, 0xffffffff}, +	{0x00008398, 0x00000000}, +	{0x0000839c, 0x00000000}, +	{0x000083a0, 0x00000000}, +	{0x000083a4, 0x0000fa14}, +	{0x000083a8, 0x000f0c00}, +	{0x000083ac, 0x33332210}, +	{0x000083b0, 0x33332210}, +	{0x000083b4, 0x33332210}, +	{0x000083b8, 0x33332210}, +	{0x000083bc, 0x00000000}, +	{0x000083c0, 0x00000000}, +	{0x000083c4, 0x00000000}, +	{0x000083c8, 0x00000000}, +	{0x000083cc, 0x00000200}, +	{0x000083d0, 0x000301ff}, +}; + +static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = { +	/* Addr      allmodes  */ +	{0x0000a000, 0x00010000}, +	{0x0000a004, 0x00030002}, +	{0x0000a008, 0x00050004}, +	{0x0000a00c, 0x00810080}, +	{0x0000a010, 0x01800082}, +	{0x0000a014, 0x01820181}, +	{0x0000a018, 0x01840183}, +	{0x0000a01c, 0x01880185}, +	{0x0000a020, 0x018a0189}, +	{0x0000a024, 0x02850284}, +	{0x0000a028, 0x02890288}, +	{0x0000a02c, 0x03850384}, +	{0x0000a030, 0x03890388}, +	{0x0000a034, 0x038b038a}, +	{0x0000a038, 0x038d038c}, +	{0x0000a03c, 0x03910390}, +	{0x0000a040, 0x03930392}, +	{0x0000a044, 0x03950394}, +	{0x0000a048, 0x00000396}, +	{0x0000a04c, 0x00000000}, +	{0x0000a050, 0x00000000}, +	{0x0000a054, 0x00000000}, +	{0x0000a058, 0x00000000}, +	{0x0000a05c, 0x00000000}, +	{0x0000a060, 0x00000000}, +	{0x0000a064, 0x00000000}, +	{0x0000a068, 0x00000000}, +	{0x0000a06c, 0x00000000}, +	{0x0000a070, 0x00000000}, +	{0x0000a074, 0x00000000}, +	{0x0000a078, 0x00000000}, +	{0x0000a07c, 0x00000000}, +	{0x0000a080, 0x28282828}, +	{0x0000a084, 0x28282828}, +	{0x0000a088, 0x28282828}, +	{0x0000a08c, 0x28282828}, +	{0x0000a090, 0x28282828}, +	{0x0000a094, 0x21212128}, +	{0x0000a098, 0x171c1c1c}, +	{0x0000a09c, 0x02020212}, +	{0x0000a0a0, 0x00000202}, +	{0x0000a0a4, 0x00000000}, +	{0x0000a0a8, 0x00000000}, +	{0x0000a0ac, 0x00000000}, +	{0x0000a0b0, 0x00000000}, +	{0x0000a0b4, 0x00000000}, +	{0x0000a0b8, 0x00000000}, +	{0x0000a0bc, 0x00000000}, +	{0x0000a0c0, 0x001f0000}, +	{0x0000a0c4, 0x011f0100}, +	{0x0000a0c8, 0x011d011e}, +	{0x0000a0cc, 0x011b011c}, +	{0x0000a0d0, 0x02030204}, +	{0x0000a0d4, 0x02010202}, +	{0x0000a0d8, 0x021f0200}, +	{0x0000a0dc, 0x021d021e}, +	{0x0000a0e0, 0x03010302}, +	{0x0000a0e4, 0x031f0300}, +	{0x0000a0e8, 0x0402031e}, +	{0x0000a0ec, 0x04000401}, +	{0x0000a0f0, 0x041e041f}, +	{0x0000a0f4, 0x05010502}, +	{0x0000a0f8, 0x051f0500}, +	{0x0000a0fc, 0x0602051e}, +	{0x0000a100, 0x06000601}, +	{0x0000a104, 0x061e061f}, +	{0x0000a108, 0x0703061d}, +	{0x0000a10c, 0x07010702}, +	{0x0000a110, 0x00000700}, +	{0x0000a114, 0x00000000}, +	{0x0000a118, 0x00000000}, +	{0x0000a11c, 0x00000000}, +	{0x0000a120, 0x00000000}, +	{0x0000a124, 0x00000000}, +	{0x0000a128, 0x00000000}, +	{0x0000a12c, 0x00000000}, +	{0x0000a130, 0x00000000}, +	{0x0000a134, 0x00000000}, +	{0x0000a138, 0x00000000}, +	{0x0000a13c, 0x00000000}, +	{0x0000a140, 0x001f0000}, +	{0x0000a144, 0x011f0100}, +	{0x0000a148, 0x011d011e}, +	{0x0000a14c, 0x011b011c}, +	{0x0000a150, 0x02030204}, +	{0x0000a154, 0x02010202}, +	{0x0000a158, 0x021f0200}, +	{0x0000a15c, 0x021d021e}, +	{0x0000a160, 0x03010302}, +	{0x0000a164, 0x031f0300}, +	{0x0000a168, 0x0402031e}, +	{0x0000a16c, 0x04000401}, +	{0x0000a170, 0x041e041f}, +	{0x0000a174, 0x05010502}, +	{0x0000a178, 0x051f0500}, +	{0x0000a17c, 0x0602051e}, +	{0x0000a180, 0x06000601}, +	{0x0000a184, 0x061e061f}, +	{0x0000a188, 0x0703061d}, +	{0x0000a18c, 0x07010702}, +	{0x0000a190, 0x00000700}, +	{0x0000a194, 0x00000000}, +	{0x0000a198, 0x00000000}, +	{0x0000a19c, 0x00000000}, +	{0x0000a1a0, 0x00000000}, +	{0x0000a1a4, 0x00000000}, +	{0x0000a1a8, 0x00000000}, +	{0x0000a1ac, 0x00000000}, +	{0x0000a1b0, 0x00000000}, +	{0x0000a1b4, 0x00000000}, +	{0x0000a1b8, 0x00000000}, +	{0x0000a1bc, 0x00000000}, +	{0x0000a1c0, 0x00000000}, +	{0x0000a1c4, 0x00000000}, +	{0x0000a1c8, 0x00000000}, +	{0x0000a1cc, 0x00000000}, +	{0x0000a1d0, 0x00000000}, +	{0x0000a1d4, 0x00000000}, +	{0x0000a1d8, 0x00000000}, +	{0x0000a1dc, 0x00000000}, +	{0x0000a1e0, 0x00000000}, +	{0x0000a1e4, 0x00000000}, +	{0x0000a1e8, 0x00000000}, +	{0x0000a1ec, 0x00000000}, +	{0x0000a1f0, 0x00000396}, +	{0x0000a1f4, 0x00000396}, +	{0x0000a1f8, 0x00000396}, +	{0x0000a1fc, 0x00000296}, +	{0x0000b000, 0x00010000}, +	{0x0000b004, 0x00030002}, +	{0x0000b008, 0x00050004}, +	{0x0000b00c, 0x00810080}, +	{0x0000b010, 0x00830082}, +	{0x0000b014, 0x01810180}, +	{0x0000b018, 0x01830182}, +	{0x0000b01c, 0x01850184}, +	{0x0000b020, 0x02810280}, +	{0x0000b024, 0x02830282}, +	{0x0000b028, 0x02850284}, +	{0x0000b02c, 0x02890288}, +	{0x0000b030, 0x028b028a}, +	{0x0000b034, 0x0388028c}, +	{0x0000b038, 0x038a0389}, +	{0x0000b03c, 0x038c038b}, +	{0x0000b040, 0x0390038d}, +	{0x0000b044, 0x03920391}, +	{0x0000b048, 0x03940393}, +	{0x0000b04c, 0x03960395}, +	{0x0000b050, 0x00000000}, +	{0x0000b054, 0x00000000}, +	{0x0000b058, 0x00000000}, +	{0x0000b05c, 0x00000000}, +	{0x0000b060, 0x00000000}, +	{0x0000b064, 0x00000000}, +	{0x0000b068, 0x00000000}, +	{0x0000b06c, 0x00000000}, +	{0x0000b070, 0x00000000}, +	{0x0000b074, 0x00000000}, +	{0x0000b078, 0x00000000}, +	{0x0000b07c, 0x00000000}, +	{0x0000b080, 0x32323232}, +	{0x0000b084, 0x2f2f3232}, +	{0x0000b088, 0x23282a2d}, +	{0x0000b08c, 0x1c1e2123}, +	{0x0000b090, 0x14171919}, +	{0x0000b094, 0x0e0e1214}, +	{0x0000b098, 0x03050707}, +	{0x0000b09c, 0x00030303}, +	{0x0000b0a0, 0x00000000}, +	{0x0000b0a4, 0x00000000}, +	{0x0000b0a8, 0x00000000}, +	{0x0000b0ac, 0x00000000}, +	{0x0000b0b0, 0x00000000}, +	{0x0000b0b4, 0x00000000}, +	{0x0000b0b8, 0x00000000}, +	{0x0000b0bc, 0x00000000}, +	{0x0000b0c0, 0x003f0020}, +	{0x0000b0c4, 0x00400041}, +	{0x0000b0c8, 0x0140005f}, +	{0x0000b0cc, 0x0160015f}, +	{0x0000b0d0, 0x017e017f}, +	{0x0000b0d4, 0x02410242}, +	{0x0000b0d8, 0x025f0240}, +	{0x0000b0dc, 0x027f0260}, +	{0x0000b0e0, 0x0341027e}, +	{0x0000b0e4, 0x035f0340}, +	{0x0000b0e8, 0x037f0360}, +	{0x0000b0ec, 0x04400441}, +	{0x0000b0f0, 0x0460045f}, +	{0x0000b0f4, 0x0541047f}, +	{0x0000b0f8, 0x055f0540}, +	{0x0000b0fc, 0x057f0560}, +	{0x0000b100, 0x06400641}, +	{0x0000b104, 0x0660065f}, +	{0x0000b108, 0x067e067f}, +	{0x0000b10c, 0x07410742}, +	{0x0000b110, 0x075f0740}, +	{0x0000b114, 0x077f0760}, +	{0x0000b118, 0x07800781}, +	{0x0000b11c, 0x07a0079f}, +	{0x0000b120, 0x07c107bf}, +	{0x0000b124, 0x000007c0}, +	{0x0000b128, 0x00000000}, +	{0x0000b12c, 0x00000000}, +	{0x0000b130, 0x00000000}, +	{0x0000b134, 0x00000000}, +	{0x0000b138, 0x00000000}, +	{0x0000b13c, 0x00000000}, +	{0x0000b140, 0x003f0020}, +	{0x0000b144, 0x00400041}, +	{0x0000b148, 0x0140005f}, +	{0x0000b14c, 0x0160015f}, +	{0x0000b150, 0x017e017f}, +	{0x0000b154, 0x02410242}, +	{0x0000b158, 0x025f0240}, +	{0x0000b15c, 0x027f0260}, +	{0x0000b160, 0x0341027e}, +	{0x0000b164, 0x035f0340}, +	{0x0000b168, 0x037f0360}, +	{0x0000b16c, 0x04400441}, +	{0x0000b170, 0x0460045f}, +	{0x0000b174, 0x0541047f}, +	{0x0000b178, 0x055f0540}, +	{0x0000b17c, 0x057f0560}, +	{0x0000b180, 0x06400641}, +	{0x0000b184, 0x0660065f}, +	{0x0000b188, 0x067e067f}, +	{0x0000b18c, 0x07410742}, +	{0x0000b190, 0x075f0740}, +	{0x0000b194, 0x077f0760}, +	{0x0000b198, 0x07800781}, +	{0x0000b19c, 0x07a0079f}, +	{0x0000b1a0, 0x07c107bf}, +	{0x0000b1a4, 0x000007c0}, +	{0x0000b1a8, 0x00000000}, +	{0x0000b1ac, 0x00000000}, +	{0x0000b1b0, 0x00000000}, +	{0x0000b1b4, 0x00000000}, +	{0x0000b1b8, 0x00000000}, +	{0x0000b1bc, 0x00000000}, +	{0x0000b1c0, 0x00000000}, +	{0x0000b1c4, 0x00000000}, +	{0x0000b1c8, 0x00000000}, +	{0x0000b1cc, 0x00000000}, +	{0x0000b1d0, 0x00000000}, +	{0x0000b1d4, 0x00000000}, +	{0x0000b1d8, 0x00000000}, +	{0x0000b1dc, 0x00000000}, +	{0x0000b1e0, 0x00000000}, +	{0x0000b1e4, 0x00000000}, +	{0x0000b1e8, 0x00000000}, +	{0x0000b1ec, 0x00000000}, +	{0x0000b1f0, 0x00000396}, +	{0x0000b1f4, 0x00000396}, +	{0x0000b1f8, 0x00000396}, +	{0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9300_2p0_soc_preamble[][2] = { +	/* Addr      allmodes  */ +	{0x000040a4, 0x00a0c1c9}, +	{0x00007008, 0x00000000}, +	{0x00007020, 0x00000000}, +	{0x00007034, 0x00000002}, +	{0x00007038, 0x000004c2}, +}; + +static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0[][2] = { +	/* Addr      allmodes  */ +	{0x00004040, 0x08212e5e}, +	{0x00004040, 0x0008003b}, +	{0x00004044, 0x00000000}, +}; + +static const u32 ar9300PciePhy_clkreq_enable_L1_2p0[][2] = { +	/* Addr      allmodes  */ +	{0x00004040, 0x08253e5e}, +	{0x00004040, 0x0008003b}, +	{0x00004044, 0x00000000}, +}; + +static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = { +	/* Addr      allmodes  */ +	{0x00004040, 0x08213e5e}, +	{0x00004040, 0x0008003b}, +	{0x00004044, 0x00000000}, +}; + +#endif /* INITVALS_9003_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c new file mode 100644 index 00000000000..37ba37481a4 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -0,0 +1,614 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "hw.h" +#include "ar9003_mac.h" + +static void ar9003_hw_rx_enable(struct ath_hw *hw) +{ +	REG_WRITE(hw, AR_CR, 0); +} + +static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) +{ +	int checksum; + +	checksum = ads->info + ads->link +		+ ads->data0 + ads->ctl3 +		+ ads->data1 + ads->ctl5 +		+ ads->data2 + ads->ctl7 +		+ ads->data3 + ads->ctl9; + +	return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum; +} + +static void ar9003_hw_set_desc_link(void *ds, u32 ds_link) +{ +	struct ar9003_txc *ads = ds; + +	ads->link = ds_link; +	ads->ctl10 &= ~AR_TxPtrChkSum; +	ads->ctl10 |= ar9003_calc_ptr_chksum(ads); +} + +static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link) +{ +	struct ar9003_txc *ads = ds; + +	*ds_link = &ads->link; +} + +static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) +{ +	u32 isr = 0; +	u32 mask2 = 0; +	struct ath9k_hw_capabilities *pCap = &ah->caps; +	u32 sync_cause = 0; +	struct ath_common *common = ath9k_hw_common(ah); + +	if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { +		if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) +				== AR_RTC_STATUS_ON) +			isr = REG_READ(ah, AR_ISR); +	} + +	sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; + +	*masked = 0; + +	if (!isr && !sync_cause) +		return false; + +	if (isr) { +		if (isr & AR_ISR_BCNMISC) { +			u32 isr2; +			isr2 = REG_READ(ah, AR_ISR_S2); + +			mask2 |= ((isr2 & AR_ISR_S2_TIM) >> +				  MAP_ISR_S2_TIM); +			mask2 |= ((isr2 & AR_ISR_S2_DTIM) >> +				  MAP_ISR_S2_DTIM); +			mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >> +				  MAP_ISR_S2_DTIMSYNC); +			mask2 |= ((isr2 & AR_ISR_S2_CABEND) >> +				  MAP_ISR_S2_CABEND); +			mask2 |= ((isr2 & AR_ISR_S2_GTT) << +				  MAP_ISR_S2_GTT); +			mask2 |= ((isr2 & AR_ISR_S2_CST) << +				  MAP_ISR_S2_CST); +			mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> +				  MAP_ISR_S2_TSFOOR); + +			if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { +				REG_WRITE(ah, AR_ISR_S2, isr2); +				isr &= ~AR_ISR_BCNMISC; +			} +		} + +		if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) +			isr = REG_READ(ah, AR_ISR_RAC); + +		if (isr == 0xffffffff) { +			*masked = 0; +			return false; +		} + +		*masked = isr & ATH9K_INT_COMMON; + +		if (ah->config.rx_intr_mitigation) +			if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) +				*masked |= ATH9K_INT_RXLP; + +		if (ah->config.tx_intr_mitigation) +			if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM)) +				*masked |= ATH9K_INT_TX; + +		if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR)) +			*masked |= ATH9K_INT_RXLP; + +		if (isr & AR_ISR_HP_RXOK) +			*masked |= ATH9K_INT_RXHP; + +		if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) { +			*masked |= ATH9K_INT_TX; + +			if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { +				u32 s0, s1; +				s0 = REG_READ(ah, AR_ISR_S0); +				REG_WRITE(ah, AR_ISR_S0, s0); +				s1 = REG_READ(ah, AR_ISR_S1); +				REG_WRITE(ah, AR_ISR_S1, s1); + +				isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR | +					 AR_ISR_TXEOL); +			} +		} + +		if (isr & AR_ISR_GENTMR) { +			u32 s5; + +			if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) +				s5 = REG_READ(ah, AR_ISR_S5_S); +			else +				s5 = REG_READ(ah, AR_ISR_S5); + +			ah->intr_gen_timer_trigger = +				MS(s5, AR_ISR_S5_GENTIMER_TRIG); + +			ah->intr_gen_timer_thresh = +				MS(s5, AR_ISR_S5_GENTIMER_THRESH); + +			if (ah->intr_gen_timer_trigger) +				*masked |= ATH9K_INT_GENTIMER; + +			if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { +				REG_WRITE(ah, AR_ISR_S5, s5); +				isr &= ~AR_ISR_GENTMR; +			} + +		} + +		*masked |= mask2; + +		if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { +			REG_WRITE(ah, AR_ISR, isr); + +			(void) REG_READ(ah, AR_ISR); +		} +	} + +	if (sync_cause) { +		if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { +			REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); +			REG_WRITE(ah, AR_RC, 0); +			*masked |= ATH9K_INT_FATAL; +		} + +		if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) +			ath_print(common, ATH_DBG_INTERRUPT, +				  "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); + +			REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); +		(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); + +	} +	return true; +} + +static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen, +				  bool is_firstseg, bool is_lastseg, +				  const void *ds0, dma_addr_t buf_addr, +				  unsigned int qcu) +{ +	struct ar9003_txc *ads = (struct ar9003_txc *) ds; +	unsigned int descid = 0; + +	ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) | +				     (1 << AR_TxRxDesc_S) | +				     (1 << AR_CtrlStat_S) | +				     (qcu << AR_TxQcuNum_S) | 0x17; + +	ads->data0 = buf_addr; +	ads->data1 = 0; +	ads->data2 = 0; +	ads->data3 = 0; + +	ads->ctl3 = (seglen << AR_BufLen_S); +	ads->ctl3 &= AR_BufLen; + +	/* Fill in pointer checksum and descriptor id */ +	ads->ctl10 = ar9003_calc_ptr_chksum(ads); +	ads->ctl10 |= (descid << AR_TxDescId_S); + +	if (is_firstseg) { +		ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore); +	} else if (is_lastseg) { +		ads->ctl11 = 0; +		ads->ctl12 = 0; +		ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13; +		ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14; +	} else { +		/* XXX Intermediate descriptor in a multi-descriptor frame.*/ +		ads->ctl11 = 0; +		ads->ctl12 = AR_TxMore; +		ads->ctl13 = 0; +		ads->ctl14 = 0; +	} +} + +static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, +				 struct ath_tx_status *ts) +{ +	struct ar9003_txs *ads; + +	ads = &ah->ts_ring[ah->ts_tail]; + +	if ((ads->status8 & AR_TxDone) == 0) +		return -EINPROGRESS; + +	ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; + +	if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || +	    (MS(ads->ds_info, AR_TxRxDesc) != 1)) { +		ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, +			  "Tx Descriptor error %x\n", ads->ds_info); +		memset(ads, 0, sizeof(*ads)); +		return -EIO; +	} + +	ts->qid = MS(ads->ds_info, AR_TxQcuNum); +	ts->desc_id = MS(ads->status1, AR_TxDescId); +	ts->ts_seqnum = MS(ads->status8, AR_SeqNum); +	ts->ts_tstamp = ads->status4; +	ts->ts_status = 0; +	ts->ts_flags  = 0; + +	if (ads->status3 & AR_ExcessiveRetries) +		ts->ts_status |= ATH9K_TXERR_XRETRY; +	if (ads->status3 & AR_Filtered) +		ts->ts_status |= ATH9K_TXERR_FILT; +	if (ads->status3 & AR_FIFOUnderrun) { +		ts->ts_status |= ATH9K_TXERR_FIFO; +		ath9k_hw_updatetxtriglevel(ah, true); +	} +	if (ads->status8 & AR_TxOpExceeded) +		ts->ts_status |= ATH9K_TXERR_XTXOP; +	if (ads->status3 & AR_TxTimerExpired) +		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; + +	if (ads->status3 & AR_DescCfgErr) +		ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; +	if (ads->status3 & AR_TxDataUnderrun) { +		ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; +		ath9k_hw_updatetxtriglevel(ah, true); +	} +	if (ads->status3 & AR_TxDelimUnderrun) { +		ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; +		ath9k_hw_updatetxtriglevel(ah, true); +	} +	if (ads->status2 & AR_TxBaStatus) { +		ts->ts_flags |= ATH9K_TX_BA; +		ts->ba_low = ads->status5; +		ts->ba_high = ads->status6; +	} + +	ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx); + +	ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined); +	ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00); +	ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01); +	ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02); +	ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10); +	ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11); +	ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12); +	ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt); +	ts->ts_longretry = MS(ads->status3, AR_DataFailCnt); +	ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt); +	ts->ts_antenna = 0; + +	ts->tid = MS(ads->status8, AR_TxTid); + +	memset(ads, 0, sizeof(*ads)); + +	return 0; +} + +static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, +		u32 pktlen, enum ath9k_pkt_type type, u32 txpower, +		u32 keyIx, enum ath9k_key_type keyType, u32 flags) +{ +	struct ar9003_txc *ads = (struct ar9003_txc *) ds; + +	if (txpower > ah->txpower_limit) +		txpower = ah->txpower_limit; + +	txpower += ah->txpower_indexoffset; +	if (txpower > 63) +		txpower = 63; + +	ads->ctl11 = (pktlen & AR_FrameLen) +		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) +		| SM(txpower, AR_XmitPower) +		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) +		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) +		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) +		| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); + +	ads->ctl12 = +		(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) +		| SM(type, AR_FrameType) +		| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) +		| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) +		| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); + +	ads->ctl17 = SM(keyType, AR_EncrType) | +		     (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0); +	ads->ctl18 = 0; +	ads->ctl19 = AR_Not_Sounding; + +	ads->ctl20 = 0; +	ads->ctl21 = 0; +	ads->ctl22 = 0; +} + +static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, +					  void *lastds, +					  u32 durUpdateEn, u32 rtsctsRate, +					  u32 rtsctsDuration, +					  struct ath9k_11n_rate_series series[], +					  u32 nseries, u32 flags) +{ +	struct ar9003_txc *ads = (struct ar9003_txc *) ds; +	struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds; +	u_int32_t ctl11; + +	if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { +		ctl11 = ads->ctl11; + +		if (flags & ATH9K_TXDESC_RTSENA) { +			ctl11 &= ~AR_CTSEnable; +			ctl11 |= AR_RTSEnable; +		} else { +			ctl11 &= ~AR_RTSEnable; +			ctl11 |= AR_CTSEnable; +		} + +		ads->ctl11 = ctl11; +	} else { +		ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable)); +	} + +	ads->ctl13 = set11nTries(series, 0) +		|  set11nTries(series, 1) +		|  set11nTries(series, 2) +		|  set11nTries(series, 3) +		|  (durUpdateEn ? AR_DurUpdateEna : 0) +		|  SM(0, AR_BurstDur); + +	ads->ctl14 = set11nRate(series, 0) +		|  set11nRate(series, 1) +		|  set11nRate(series, 2) +		|  set11nRate(series, 3); + +	ads->ctl15 = set11nPktDurRTSCTS(series, 0) +		|  set11nPktDurRTSCTS(series, 1); + +	ads->ctl16 = set11nPktDurRTSCTS(series, 2) +		|  set11nPktDurRTSCTS(series, 3); + +	ads->ctl18 = set11nRateFlags(series, 0) +		|  set11nRateFlags(series, 1) +		|  set11nRateFlags(series, 2) +		|  set11nRateFlags(series, 3) +		| SM(rtsctsRate, AR_RTSCTSRate); +	ads->ctl19 = AR_Not_Sounding; + +	last_ads->ctl13 = ads->ctl13; +	last_ads->ctl14 = ads->ctl14; +} + +static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, +					u32 aggrLen) +{ +	struct ar9003_txc *ads = (struct ar9003_txc *) ds; + +	ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); + +	ads->ctl17 &= ~AR_AggrLen; +	ads->ctl17 |= SM(aggrLen, AR_AggrLen); +} + +static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, +					 u32 numDelims) +{ +	struct ar9003_txc *ads = (struct ar9003_txc *) ds; +	unsigned int ctl17; + +	ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); + +	/* +	 * We use a stack variable to manipulate ctl6 to reduce uncached +	 * read modify, modfiy, write. +	 */ +	ctl17 = ads->ctl17; +	ctl17 &= ~AR_PadDelim; +	ctl17 |= SM(numDelims, AR_PadDelim); +	ads->ctl17 = ctl17; +} + +static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) +{ +	struct ar9003_txc *ads = (struct ar9003_txc *) ds; + +	ads->ctl12 |= AR_IsAggr; +	ads->ctl12 &= ~AR_MoreAggr; +	ads->ctl17 &= ~AR_PadDelim; +} + +static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds) +{ +	struct ar9003_txc *ads = (struct ar9003_txc *) ds; + +	ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr); +} + +static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds, +					   u32 burstDuration) +{ +	struct ar9003_txc *ads = (struct ar9003_txc *) ds; + +	ads->ctl13 &= ~AR_BurstDur; +	ads->ctl13 |= SM(burstDuration, AR_BurstDur); + +} + +static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, +					     u32 vmf) +{ +	struct ar9003_txc *ads = (struct ar9003_txc *) ds; + +	if (vmf) +		ads->ctl11 |=  AR_VirtMoreFrag; +	else +		ads->ctl11 &= ~AR_VirtMoreFrag; +} + +void ar9003_hw_attach_mac_ops(struct ath_hw *hw) +{ +	struct ath_hw_ops *ops = ath9k_hw_ops(hw); + +	ops->rx_enable = ar9003_hw_rx_enable; +	ops->set_desc_link = ar9003_hw_set_desc_link; +	ops->get_desc_link = ar9003_hw_get_desc_link; +	ops->get_isr = ar9003_hw_get_isr; +	ops->fill_txdesc = ar9003_hw_fill_txdesc; +	ops->proc_txdesc = ar9003_hw_proc_txdesc; +	ops->set11n_txdesc = ar9003_hw_set11n_txdesc; +	ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario; +	ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first; +	ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; +	ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; +	ops->clr11n_aggr = ar9003_hw_clr11n_aggr; +	ops->set11n_burstduration = ar9003_hw_set11n_burstduration; +	ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag; +} + +void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) +{ +	REG_WRITE(ah, AR_DATABUF_SIZE, buf_size & AR_DATABUF_SIZE_MASK); +} +EXPORT_SYMBOL(ath9k_hw_set_rx_bufsize); + +void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp, +			    enum ath9k_rx_qtype qtype) +{ +	if (qtype == ATH9K_RX_QUEUE_HP) +		REG_WRITE(ah, AR_HP_RXDP, rxdp); +	else +		REG_WRITE(ah, AR_LP_RXDP, rxdp); +} +EXPORT_SYMBOL(ath9k_hw_addrxbuf_edma); + +int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, +				 void *buf_addr) +{ +	struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr; +	unsigned int phyerr; + +	/* TODO: byte swap on big endian for ar9300_10 */ + +	if ((rxsp->status11 & AR_RxDone) == 0) +		return -EINPROGRESS; + +	if (MS(rxsp->ds_info, AR_DescId) != 0x168c) +		return -EINVAL; + +	if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) +		return -EINPROGRESS; + +	if (!rxs) +		return 0; + +	rxs->rs_status = 0; +	rxs->rs_flags =  0; + +	rxs->rs_datalen = rxsp->status2 & AR_DataLen; +	rxs->rs_tstamp =  rxsp->status3; + +	/* XXX: Keycache */ +	rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined); +	rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00); +	rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01); +	rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02); +	rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10); +	rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11); +	rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12); + +	if (rxsp->status11 & AR_RxKeyIdxValid) +		rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx); +	else +		rxs->rs_keyix = ATH9K_RXKEYIX_INVALID; + +	rxs->rs_rate = MS(rxsp->status1, AR_RxRate); +	rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0; + +	rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0; +	rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0; +	rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7); +	rxs->rs_flags  = (rxsp->status4 & AR_GI) ? ATH9K_RX_GI : 0; +	rxs->rs_flags  |= (rxsp->status4 & AR_2040) ? ATH9K_RX_2040 : 0; + +	rxs->evm0 = rxsp->status6; +	rxs->evm1 = rxsp->status7; +	rxs->evm2 = rxsp->status8; +	rxs->evm3 = rxsp->status9; +	rxs->evm4 = (rxsp->status10 & 0xffff); + +	if (rxsp->status11 & AR_PreDelimCRCErr) +		rxs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE; + +	if (rxsp->status11 & AR_PostDelimCRCErr) +		rxs->rs_flags |= ATH9K_RX_DELIM_CRC_POST; + +	if (rxsp->status11 & AR_DecryptBusyErr) +		rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; + +	if ((rxsp->status11 & AR_RxFrameOK) == 0) { +		if (rxsp->status11 & AR_CRCErr) { +			rxs->rs_status |= ATH9K_RXERR_CRC; +		} else if (rxsp->status11 & AR_PHYErr) { +			rxs->rs_status |= ATH9K_RXERR_PHY; +			phyerr = MS(rxsp->status11, AR_PHYErrCode); +			rxs->rs_phyerr = phyerr; +		} else if (rxsp->status11 & AR_DecryptCRCErr) { +			rxs->rs_status |= ATH9K_RXERR_DECRYPT; +		} else if (rxsp->status11 & AR_MichaelErr) { +			rxs->rs_status |= ATH9K_RXERR_MIC; +		} +	} + +	return 0; +} +EXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma); + +void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) +{ +	ah->ts_tail = 0; + +	memset((void *) ah->ts_ring, 0, +		ah->ts_size * sizeof(struct ar9003_txs)); + +	ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, +		  "TS Start 0x%x End 0x%x Virt %p, Size %d\n", +		   ah->ts_paddr_start, ah->ts_paddr_end, +		   ah->ts_ring, ah->ts_size); + +	REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start); +	REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end); +} + +void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start, +			       u32 ts_paddr_start, +			       u8 size) +{ + +	ah->ts_paddr_start = ts_paddr_start; +	ah->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9003_txs)); +	ah->ts_size = size; +	ah->ts_ring = (struct ar9003_txs *) ts_start; + +	ath9k_hw_reset_txstatus_ring(ah); +} +EXPORT_SYMBOL(ath9k_hw_setup_statusring); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h new file mode 100644 index 00000000000..f17558b1453 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef AR9003_MAC_H +#define AR9003_MAC_H + +#define AR_DescId	0xffff0000 +#define AR_DescId_S	16 +#define AR_CtrlStat	0x00004000 +#define AR_CtrlStat_S	14 +#define AR_TxRxDesc	0x00008000 +#define AR_TxRxDesc_S	15 +#define AR_TxQcuNum	0x00000f00 +#define AR_TxQcuNum_S	8 + +#define AR_BufLen	0x0fff0000 +#define AR_BufLen_S	16 + +#define AR_TxDescId	0xffff0000 +#define AR_TxDescId_S	16 +#define AR_TxPtrChkSum	0x0000ffff + +#define AR_TxTid	0xf0000000 +#define AR_TxTid_S	28 + +#define AR_LowRxChain	0x00004000 + +#define AR_Not_Sounding	0x20000000 + +#define MAP_ISR_S2_CST          6 +#define MAP_ISR_S2_GTT          6 +#define MAP_ISR_S2_TIM          3 +#define MAP_ISR_S2_CABEND       0 +#define MAP_ISR_S2_DTIMSYNC     7 +#define MAP_ISR_S2_DTIM         7 +#define MAP_ISR_S2_TSFOOR       4 + +#define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds) + +struct ar9003_rxs { +	u32 ds_info; +	u32 status1; +	u32 status2; +	u32 status3; +	u32 status4; +	u32 status5; +	u32 status6; +	u32 status7; +	u32 status8; +	u32 status9; +	u32 status10; +	u32 status11; +} __packed; + +/* Transmit Control Descriptor */ +struct ar9003_txc { +	u32 info;   /* descriptor information */ +	u32 link;   /* link pointer */ +	u32 data0;  /* data pointer to 1st buffer */ +	u32 ctl3;   /* DMA control 3  */ +	u32 data1;  /* data pointer to 2nd buffer */ +	u32 ctl5;   /* DMA control 5  */ +	u32 data2;  /* data pointer to 3rd buffer */ +	u32 ctl7;   /* DMA control 7  */ +	u32 data3;  /* data pointer to 4th buffer */ +	u32 ctl9;   /* DMA control 9  */ +	u32 ctl10;  /* DMA control 10 */ +	u32 ctl11;  /* DMA control 11 */ +	u32 ctl12;  /* DMA control 12 */ +	u32 ctl13;  /* DMA control 13 */ +	u32 ctl14;  /* DMA control 14 */ +	u32 ctl15;  /* DMA control 15 */ +	u32 ctl16;  /* DMA control 16 */ +	u32 ctl17;  /* DMA control 17 */ +	u32 ctl18;  /* DMA control 18 */ +	u32 ctl19;  /* DMA control 19 */ +	u32 ctl20;  /* DMA control 20 */ +	u32 ctl21;  /* DMA control 21 */ +	u32 ctl22;  /* DMA control 22 */ +	u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */ +} __packed; + +struct ar9003_txs { +	u32 ds_info; +	u32 status1; +	u32 status2; +	u32 status3; +	u32 status4; +	u32 status5; +	u32 status6; +	u32 status7; +	u32 status8; +} __packed; + +void ar9003_hw_attach_mac_ops(struct ath_hw *hw); +void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size); +void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp, +			    enum ath9k_rx_qtype qtype); + +int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, +				 struct ath_rx_status *rxs, +				 void *buf_addr); +void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah); +void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start, +			       u32 ts_paddr_start, +			       u8 size); +#endif diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c new file mode 100644 index 00000000000..80431a2f6dc --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -0,0 +1,1134 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "hw.h" +#include "ar9003_phy.h" + +/** + * ar9003_hw_set_channel - set channel on single-chip device + * @ah: atheros hardware structure + * @chan: + * + * This is the function to change channel on single-chip devices, that is + * all devices after ar9280. + * + * This function takes the channel value in MHz and sets + * hardware channel value. Assumes writes have been enabled to analog bus. + * + * Actual Expression, + * + * For 2GHz channel, + * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + * + * For 5GHz channel, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) + * (freq_ref = 40MHz/(24>>amodeRefSel)) + * + * For 5GHz channels which are 5MHz spaced, + * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) + * (freq_ref = 40MHz) + */ +static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) +{ +	u16 bMode, fracMode = 0, aModeRefSel = 0; +	u32 freq, channelSel = 0, reg32 = 0; +	struct chan_centers centers; +	int loadSynthChannel; + +	ath9k_hw_get_channel_centers(ah, chan, ¢ers); +	freq = centers.synth_center; + +	if (freq < 4800) {     /* 2 GHz, fractional mode */ +		channelSel = CHANSEL_2G(freq); +		/* Set to 2G mode */ +		bMode = 1; +	} else { +		channelSel = CHANSEL_5G(freq); +		/* Doubler is ON, so, divide channelSel by 2. */ +		channelSel >>= 1; +		/* Set to 5G mode */ +		bMode = 0; +	} + +	/* Enable fractional mode for all channels */ +	fracMode = 1; +	aModeRefSel = 0; +	loadSynthChannel = 0; + +	reg32 = (bMode << 29); +	REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); + +	/* Enable Long shift Select for Synthesizer */ +	REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH4, +		      AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1); + +	/* Program Synth. setting */ +	reg32 = (channelSel << 2) | (fracMode << 30) | +		(aModeRefSel << 28) | (loadSynthChannel << 31); +	REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); + +	/* Toggle Load Synth channel bit */ +	loadSynthChannel = 1; +	reg32 = (channelSel << 2) | (fracMode << 30) | +		(aModeRefSel << 28) | (loadSynthChannel << 31); +	REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); + +	ah->curchan = chan; +	ah->curchan_rad_index = -1; + +	return 0; +} + +/** + * ar9003_hw_spur_mitigate - convert baseband spur frequency + * @ah: atheros hardware structure + * @chan: + * + * For single-chip solutions. Converts to baseband spur frequency given the + * input channel frequency and compute register settings below. + * + * Spur mitigation for MRC CCK + */ +static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, +					    struct ath9k_channel *chan) +{ +	u32 spur_freq[4] = { 2420, 2440, 2464, 2480 }; +	int cur_bb_spur, negative = 0, cck_spur_freq; +	int i; + +	/* +	 * Need to verify range +/- 10 MHz in control channel, otherwise spur +	 * is out-of-band and can be ignored. +	 */ + +	for (i = 0; i < 4; i++) { +		negative = 0; +		cur_bb_spur = spur_freq[i] - chan->channel; + +		if (cur_bb_spur < 0) { +			negative = 1; +			cur_bb_spur = -cur_bb_spur; +		} +		if (cur_bb_spur < 10) { +			cck_spur_freq = (int)((cur_bb_spur << 19) / 11); + +			if (negative == 1) +				cck_spur_freq = -cck_spur_freq; + +			cck_spur_freq = cck_spur_freq & 0xfffff; + +			REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL, +				      AR_PHY_AGC_CONTROL_YCOK_MAX, 0x7); +			REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, +				      AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR, 0x7f); +			REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, +				      AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE, +				      0x2); +			REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, +				      AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, +				      0x1); +			REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, +				      AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, +				      cck_spur_freq); + +			return; +		} +	} + +	REG_RMW_FIELD(ah, AR_PHY_AGC_CONTROL, +		      AR_PHY_AGC_CONTROL_YCOK_MAX, 0x5); +	REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, +		      AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT, 0x0); +	REG_RMW_FIELD(ah, AR_PHY_CCK_SPUR_MIT, +		      AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, 0x0); +} + +/* Clean all spur register fields */ +static void ar9003_hw_spur_ofdm_clear(struct ath_hw *ah) +{ +	REG_RMW_FIELD(ah, AR_PHY_TIMING4, +		      AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0); +	REG_RMW_FIELD(ah, AR_PHY_TIMING11, +		      AR_PHY_TIMING11_SPUR_FREQ_SD, 0); +	REG_RMW_FIELD(ah, AR_PHY_TIMING11, +		      AR_PHY_TIMING11_SPUR_DELTA_PHASE, 0); +	REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +		      AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, 0); +	REG_RMW_FIELD(ah, AR_PHY_TIMING11, +		      AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0); +	REG_RMW_FIELD(ah, AR_PHY_TIMING11, +		      AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0); +	REG_RMW_FIELD(ah, AR_PHY_TIMING4, +		      AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0); +	REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, +		      AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 0); +	REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, +		      AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 0); + +	REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, +		      AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0); +	REG_RMW_FIELD(ah, AR_PHY_TIMING4, +		      AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0); +	REG_RMW_FIELD(ah, AR_PHY_TIMING4, +		      AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0); +	REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, +		      AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, 0); +	REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, +		      AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, 0); +	REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, +		      AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, 0); +	REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, +		      AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0); +	REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, +		      AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0); +	REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, +		      AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0); +	REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, +		      AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0); +} + +static void ar9003_hw_spur_ofdm(struct ath_hw *ah, +				int freq_offset, +				int spur_freq_sd, +				int spur_delta_phase, +				int spur_subchannel_sd) +{ +	int mask_index = 0; + +	/* OFDM Spur mitigation */ +	REG_RMW_FIELD(ah, AR_PHY_TIMING4, +		 AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0x1); +	REG_RMW_FIELD(ah, AR_PHY_TIMING11, +		      AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd); +	REG_RMW_FIELD(ah, AR_PHY_TIMING11, +		      AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase); +	REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +		      AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, spur_subchannel_sd); +	REG_RMW_FIELD(ah, AR_PHY_TIMING11, +		      AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0x1); +	REG_RMW_FIELD(ah, AR_PHY_TIMING11, +		      AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0x1); +	REG_RMW_FIELD(ah, AR_PHY_TIMING4, +		      AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1); +	REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, +		      AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, 34); +	REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, +		      AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1); + +	if (REG_READ_FIELD(ah, AR_PHY_MODE, +			   AR_PHY_MODE_DYNAMIC) == 0x1) +		REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, +			      AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1); + +	mask_index = (freq_offset << 4) / 5; +	if (mask_index < 0) +		mask_index = mask_index - 1; + +	mask_index = mask_index & 0x7f; + +	REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, +		      AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0x1); +	REG_RMW_FIELD(ah, AR_PHY_TIMING4, +		      AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0x1); +	REG_RMW_FIELD(ah, AR_PHY_TIMING4, +		      AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0x1); +	REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, +		      AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, mask_index); +	REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, +		      AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, mask_index); +	REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, +		      AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, mask_index); +	REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, +		      AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0xc); +	REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, +		      AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0xc); +	REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, +		      AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0); +	REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, +		      AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff); +} + +static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah, +				     struct ath9k_channel *chan, +				     int freq_offset) +{ +	int spur_freq_sd = 0; +	int spur_subchannel_sd = 0; +	int spur_delta_phase = 0; + +	if (IS_CHAN_HT40(chan)) { +		if (freq_offset < 0) { +			if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, +					   AR_PHY_GC_DYN2040_PRI_CH) == 0x0) +				spur_subchannel_sd = 1; +			else +				spur_subchannel_sd = 0; + +			spur_freq_sd = ((freq_offset + 10) << 9) / 11; + +		} else { +			if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, +			    AR_PHY_GC_DYN2040_PRI_CH) == 0x0) +				spur_subchannel_sd = 0; +			else +				spur_subchannel_sd = 1; + +			spur_freq_sd = ((freq_offset - 10) << 9) / 11; + +		} + +		spur_delta_phase = (freq_offset << 17) / 5; + +	} else { +		spur_subchannel_sd = 0; +		spur_freq_sd = (freq_offset << 9) /11; +		spur_delta_phase = (freq_offset << 18) / 5; +	} + +	spur_freq_sd = spur_freq_sd & 0x3ff; +	spur_delta_phase = spur_delta_phase & 0xfffff; + +	ar9003_hw_spur_ofdm(ah, +			    freq_offset, +			    spur_freq_sd, +			    spur_delta_phase, +			    spur_subchannel_sd); +} + +/* Spur mitigation for OFDM */ +static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah, +					 struct ath9k_channel *chan) +{ +	int synth_freq; +	int range = 10; +	int freq_offset = 0; +	int mode; +	u8* spurChansPtr; +	unsigned int i; +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + +	if (IS_CHAN_5GHZ(chan)) { +		spurChansPtr = &(eep->modalHeader5G.spurChans[0]); +		mode = 0; +	} +	else { +		spurChansPtr = &(eep->modalHeader2G.spurChans[0]); +		mode = 1; +	} + +	if (spurChansPtr[0] == 0) +		return; /* No spur in the mode */ + +	if (IS_CHAN_HT40(chan)) { +		range = 19; +		if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, +				   AR_PHY_GC_DYN2040_PRI_CH) == 0x0) +			synth_freq = chan->channel - 10; +		else +			synth_freq = chan->channel + 10; +	} else { +		range = 10; +		synth_freq = chan->channel; +	} + +	ar9003_hw_spur_ofdm_clear(ah); + +	for (i = 0; spurChansPtr[i] && i < 5; i++) { +		freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq; +		if (abs(freq_offset) < range) { +			ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); +			break; +		} +	} +} + +static void ar9003_hw_spur_mitigate(struct ath_hw *ah, +				    struct ath9k_channel *chan) +{ +	ar9003_hw_spur_mitigate_mrc_cck(ah, chan); +	ar9003_hw_spur_mitigate_ofdm(ah, chan); +} + +static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah, +					 struct ath9k_channel *chan) +{ +	u32 pll; + +	pll = SM(0x5, AR_RTC_9300_PLL_REFDIV); + +	if (chan && IS_CHAN_HALF_RATE(chan)) +		pll |= SM(0x1, AR_RTC_9300_PLL_CLKSEL); +	else if (chan && IS_CHAN_QUARTER_RATE(chan)) +		pll |= SM(0x2, AR_RTC_9300_PLL_CLKSEL); + +	pll |= SM(0x2c, AR_RTC_9300_PLL_DIV); + +	return pll; +} + +static void ar9003_hw_set_channel_regs(struct ath_hw *ah, +				       struct ath9k_channel *chan) +{ +	u32 phymode; +	u32 enableDacFifo = 0; + +	enableDacFifo = +		(REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO); + +	/* Enable 11n HT, 20 MHz */ +	phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH | +		  AR_PHY_GC_SHORT_GI_40 | enableDacFifo; + +	/* Configure baseband for dynamic 20/40 operation */ +	if (IS_CHAN_HT40(chan)) { +		phymode |= AR_PHY_GC_DYN2040_EN; +		/* Configure control (primary) channel at +-10MHz */ +		if ((chan->chanmode == CHANNEL_A_HT40PLUS) || +		    (chan->chanmode == CHANNEL_G_HT40PLUS)) +			phymode |= AR_PHY_GC_DYN2040_PRI_CH; + +	} + +	/* make sure we preserve INI settings */ +	phymode |= REG_READ(ah, AR_PHY_GEN_CTRL); +	/* turn off Green Field detection for STA for now */ +	phymode &= ~AR_PHY_GC_GF_DETECT_EN; + +	REG_WRITE(ah, AR_PHY_GEN_CTRL, phymode); + +	/* Configure MAC for 20/40 operation */ +	ath9k_hw_set11nmac2040(ah); + +	/* global transmit timeout (25 TUs default)*/ +	REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); +	/* carrier sense timeout */ +	REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); +} + +static void ar9003_hw_init_bb(struct ath_hw *ah, +			      struct ath9k_channel *chan) +{ +	u32 synthDelay; + +	/* +	 * Wait for the frequency synth to settle (synth goes on +	 * via AR_PHY_ACTIVE_EN).  Read the phy active delay register. +	 * Value is in 100ns increments. +	 */ +	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; +	if (IS_CHAN_B(chan)) +		synthDelay = (4 * synthDelay) / 22; +	else +		synthDelay /= 10; + +	/* Activate the PHY (includes baseband activate + synthesizer on) */ +	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + +	/* +	 * There is an issue if the AP starts the calibration before +	 * the base band timeout completes.  This could result in the +	 * rx_clear false triggering.  As a workaround we add delay an +	 * extra BASE_ACTIVATE_DELAY usecs to ensure this condition +	 * does not happen. +	 */ +	udelay(synthDelay + BASE_ACTIVATE_DELAY); +} + +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) +{ +	switch (rx) { +	case 0x5: +		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, +			    AR_PHY_SWAP_ALT_CHAIN); +	case 0x3: +	case 0x1: +	case 0x2: +	case 0x7: +		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); +		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); +		break; +	default: +		break; +	} + +	REG_WRITE(ah, AR_SELFGEN_MASK, tx); +	if (tx == 0x5) { +		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, +			    AR_PHY_SWAP_ALT_CHAIN); +	} +} + +/* + * Override INI values with chip specific configuration. + */ +static void ar9003_hw_override_ini(struct ath_hw *ah) +{ +	u32 val; + +	/* +	 * Set the RX_ABORT and RX_DIS and clear it only after +	 * RXE is set for MAC. This prevents frames with +	 * corrupted descriptor status. +	 */ +	REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); + +	/* +	 * For AR9280 and above, there is a new feature that allows +	 * Multicast search based on both MAC Address and Key ID. By default, +	 * this feature is enabled. But since the driver is not using this +	 * feature, we switch it off; otherwise multicast search based on +	 * MAC addr only will fail. +	 */ +	val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE); +	REG_WRITE(ah, AR_PCU_MISC_MODE2, +		  val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE); +} + +static void ar9003_hw_prog_ini(struct ath_hw *ah, +			       struct ar5416IniArray *iniArr, +			       int column) +{ +	unsigned int i, regWrites = 0; + +	/* New INI format: Array may be undefined (pre, core, post arrays) */ +	if (!iniArr->ia_array) +		return; + +	/* +	 * New INI format: Pre, core, and post arrays for a given subsystem +	 * may be modal (> 2 columns) or non-modal (2 columns). Determine if +	 * the array is non-modal and force the column to 1. +	 */ +	if (column >= iniArr->ia_columns) +		column = 1; + +	for (i = 0; i < iniArr->ia_rows; i++) { +		u32 reg = INI_RA(iniArr, i, 0); +		u32 val = INI_RA(iniArr, i, column); + +		REG_WRITE(ah, reg, val); + +		/* +		 * Determine if this is a shift register value, and insert the +		 * configured delay if so. +		 */ +		if (reg >= 0x16000 && reg < 0x17000 +		    && ah->config.analog_shiftreg) +			udelay(100); + +		DO_DELAY(regWrites); +	} +} + +static int ar9003_hw_process_ini(struct ath_hw *ah, +				 struct ath9k_channel *chan) +{ +	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); +	unsigned int regWrites = 0, i; +	struct ieee80211_channel *channel = chan->chan; +	u32 modesIndex, freqIndex; + +	switch (chan->chanmode) { +	case CHANNEL_A: +	case CHANNEL_A_HT20: +		modesIndex = 1; +		freqIndex = 1; +		break; +	case CHANNEL_A_HT40PLUS: +	case CHANNEL_A_HT40MINUS: +		modesIndex = 2; +		freqIndex = 1; +		break; +	case CHANNEL_G: +	case CHANNEL_G_HT20: +	case CHANNEL_B: +		modesIndex = 4; +		freqIndex = 2; +		break; +	case CHANNEL_G_HT40PLUS: +	case CHANNEL_G_HT40MINUS: +		modesIndex = 3; +		freqIndex = 2; +		break; + +	default: +		return -EINVAL; +	} + +	for (i = 0; i < ATH_INI_NUM_SPLIT; i++) { +		ar9003_hw_prog_ini(ah, &ah->iniSOC[i], modesIndex); +		ar9003_hw_prog_ini(ah, &ah->iniMac[i], modesIndex); +		ar9003_hw_prog_ini(ah, &ah->iniBB[i], modesIndex); +		ar9003_hw_prog_ini(ah, &ah->iniRadio[i], modesIndex); +	} + +	REG_WRITE_ARRAY(&ah->iniModesRxGain, 1, regWrites); +	REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); + +	/* +	 * For 5GHz channels requiring Fast Clock, apply +	 * different modal values. +	 */ +	if (IS_CHAN_A_FAST_CLOCK(ah, chan)) +		REG_WRITE_ARRAY(&ah->iniModesAdditional, +				modesIndex, regWrites); + +	ar9003_hw_override_ini(ah); +	ar9003_hw_set_channel_regs(ah, chan); +	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); + +	/* Set TX power */ +	ah->eep_ops->set_txpower(ah, chan, +				 ath9k_regd_get_ctl(regulatory, chan), +				 channel->max_antenna_gain * 2, +				 channel->max_power * 2, +				 min((u32) MAX_RATE_POWER, +				 (u32) regulatory->power_limit)); + +	return 0; +} + +static void ar9003_hw_set_rfmode(struct ath_hw *ah, +				 struct ath9k_channel *chan) +{ +	u32 rfMode = 0; + +	if (chan == NULL) +		return; + +	rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) +		? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; + +	if (IS_CHAN_A_FAST_CLOCK(ah, chan)) +		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); + +	REG_WRITE(ah, AR_PHY_MODE, rfMode); +} + +static void ar9003_hw_mark_phy_inactive(struct ath_hw *ah) +{ +	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); +} + +static void ar9003_hw_set_delta_slope(struct ath_hw *ah, +				      struct ath9k_channel *chan) +{ +	u32 coef_scaled, ds_coef_exp, ds_coef_man; +	u32 clockMhzScaled = 0x64000000; +	struct chan_centers centers; + +	/* +	 * half and quarter rate can divide the scaled clock by 2 or 4 +	 * scale for selected channel bandwidth +	 */ +	if (IS_CHAN_HALF_RATE(chan)) +		clockMhzScaled = clockMhzScaled >> 1; +	else if (IS_CHAN_QUARTER_RATE(chan)) +		clockMhzScaled = clockMhzScaled >> 2; + +	/* +	 * ALGO -> coef = 1e8/fcarrier*fclock/40; +	 * scaled coef to provide precision for this floating calculation +	 */ +	ath9k_hw_get_channel_centers(ah, chan, ¢ers); +	coef_scaled = clockMhzScaled / centers.synth_center; + +	ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, +				      &ds_coef_exp); + +	REG_RMW_FIELD(ah, AR_PHY_TIMING3, +		      AR_PHY_TIMING3_DSC_MAN, ds_coef_man); +	REG_RMW_FIELD(ah, AR_PHY_TIMING3, +		      AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); + +	/* +	 * For Short GI, +	 * scaled coeff is 9/10 that of normal coeff +	 */ +	coef_scaled = (9 * coef_scaled) / 10; + +	ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, +				      &ds_coef_exp); + +	/* for short gi */ +	REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA, +		      AR_PHY_SGI_DSC_MAN, ds_coef_man); +	REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA, +		      AR_PHY_SGI_DSC_EXP, ds_coef_exp); +} + +static bool ar9003_hw_rfbus_req(struct ath_hw *ah) +{ +	REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); +	return ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, +			     AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT); +} + +/* + * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN). + * Read the phy active delay register. Value is in 100ns increments. + */ +static void ar9003_hw_rfbus_done(struct ath_hw *ah) +{ +	u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; +	if (IS_CHAN_B(ah->curchan)) +		synthDelay = (4 * synthDelay) / 22; +	else +		synthDelay /= 10; + +	udelay(synthDelay + BASE_ACTIVATE_DELAY); + +	REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); +} + +/* + * Set the interrupt and GPIO values so the ISR can disable RF + * on a switch signal.  Assumes GPIO port and interrupt polarity + * are set prior to call. + */ +static void ar9003_hw_enable_rfkill(struct ath_hw *ah) +{ +	/* Connect rfsilent_bb_l to baseband */ +	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, +		    AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); +	/* Set input mux for rfsilent_bb_l to GPIO #0 */ +	REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, +		    AR_GPIO_INPUT_MUX2_RFSILENT); + +	/* +	 * Configure the desired GPIO port for input and +	 * enable baseband rf silence. +	 */ +	ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); +	REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); +} + +static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) +{ +	u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); +	if (value) +		v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; +	else +		v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; +	REG_WRITE(ah, AR_PHY_CCK_DETECT, v); +} + +static bool ar9003_hw_ani_control(struct ath_hw *ah, +				  enum ath9k_ani_cmd cmd, int param) +{ +	struct ar5416AniState *aniState = ah->curani; +	struct ath_common *common = ath9k_hw_common(ah); + +	switch (cmd & ah->ani_function) { +	case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ +		u32 level = param; + +		if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { +			ath_print(common, ATH_DBG_ANI, +				  "level out of range (%u > %u)\n", +				  level, +				  (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); +			return false; +		} + +		REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, +			      AR_PHY_DESIRED_SZ_TOT_DES, +			      ah->totalSizeDesired[level]); +		REG_RMW_FIELD(ah, AR_PHY_AGC, +			      AR_PHY_AGC_COARSE_LOW, +			      ah->coarse_low[level]); +		REG_RMW_FIELD(ah, AR_PHY_AGC, +			      AR_PHY_AGC_COARSE_HIGH, +			      ah->coarse_high[level]); +		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, +			      AR_PHY_FIND_SIG_FIRPWR, ah->firpwr[level]); + +		if (level > aniState->noiseImmunityLevel) +			ah->stats.ast_ani_niup++; +		else if (level < aniState->noiseImmunityLevel) +			ah->stats.ast_ani_nidown++; +		aniState->noiseImmunityLevel = level; +		break; +	} +	case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ +		const int m1ThreshLow[] = { 127, 50 }; +		const int m2ThreshLow[] = { 127, 40 }; +		const int m1Thresh[] = { 127, 0x4d }; +		const int m2Thresh[] = { 127, 0x40 }; +		const int m2CountThr[] = { 31, 16 }; +		const int m2CountThrLow[] = { 63, 48 }; +		u32 on = param ? 1 : 0; + +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +			      AR_PHY_SFCORR_LOW_M1_THRESH_LOW, +			      m1ThreshLow[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +			      AR_PHY_SFCORR_LOW_M2_THRESH_LOW, +			      m2ThreshLow[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR, +			      AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR, +			      AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR, +			      AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, +			      AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, +			      m2CountThrLow[on]); + +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +			      AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +			      AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +			      AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]); +		REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, +			      AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]); + +		if (on) +			REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, +				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); +		else +			REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, +				    AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); + +		if (!on != aniState->ofdmWeakSigDetectOff) { +			if (on) +				ah->stats.ast_ani_ofdmon++; +			else +				ah->stats.ast_ani_ofdmoff++; +			aniState->ofdmWeakSigDetectOff = !on; +		} +		break; +	} +	case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ +		const int weakSigThrCck[] = { 8, 6 }; +		u32 high = param ? 1 : 0; + +		REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, +			      AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, +			      weakSigThrCck[high]); +		if (high != aniState->cckWeakSigThreshold) { +			if (high) +				ah->stats.ast_ani_cckhigh++; +			else +				ah->stats.ast_ani_ccklow++; +			aniState->cckWeakSigThreshold = high; +		} +		break; +	} +	case ATH9K_ANI_FIRSTEP_LEVEL:{ +		const int firstep[] = { 0, 4, 8 }; +		u32 level = param; + +		if (level >= ARRAY_SIZE(firstep)) { +			ath_print(common, ATH_DBG_ANI, +				  "level out of range (%u > %u)\n", +				  level, +				  (unsigned) ARRAY_SIZE(firstep)); +			return false; +		} +		REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, +			      AR_PHY_FIND_SIG_FIRSTEP, +			      firstep[level]); +		if (level > aniState->firstepLevel) +			ah->stats.ast_ani_stepup++; +		else if (level < aniState->firstepLevel) +			ah->stats.ast_ani_stepdown++; +		aniState->firstepLevel = level; +		break; +	} +	case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ +		const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; +		u32 level = param; + +		if (level >= ARRAY_SIZE(cycpwrThr1)) { +			ath_print(common, ATH_DBG_ANI, +				  "level out of range (%u > %u)\n", +				  level, +				  (unsigned) ARRAY_SIZE(cycpwrThr1)); +			return false; +		} +		REG_RMW_FIELD(ah, AR_PHY_TIMING5, +			      AR_PHY_TIMING5_CYCPWR_THR1, +			      cycpwrThr1[level]); +		if (level > aniState->spurImmunityLevel) +			ah->stats.ast_ani_spurup++; +		else if (level < aniState->spurImmunityLevel) +			ah->stats.ast_ani_spurdown++; +		aniState->spurImmunityLevel = level; +		break; +	} +	case ATH9K_ANI_PRESENT: +		break; +	default: +		ath_print(common, ATH_DBG_ANI, +			  "invalid cmd %u\n", cmd); +		return false; +	} + +	ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); +	ath_print(common, ATH_DBG_ANI, +		  "noiseImmunityLevel=%d, spurImmunityLevel=%d, " +		  "ofdmWeakSigDetectOff=%d\n", +		  aniState->noiseImmunityLevel, +		  aniState->spurImmunityLevel, +		  !aniState->ofdmWeakSigDetectOff); +	ath_print(common, ATH_DBG_ANI, +		  "cckWeakSigThreshold=%d, " +		  "firstepLevel=%d, listenTime=%d\n", +		  aniState->cckWeakSigThreshold, +		  aniState->firstepLevel, +		  aniState->listenTime); +	ath_print(common, ATH_DBG_ANI, +		"cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", +		aniState->cycleCount, +		aniState->ofdmPhyErrCount, +		aniState->cckPhyErrCount); + +	return true; +} + +static void ar9003_hw_nf_sanitize_2g(struct ath_hw *ah, s16 *nf) +{ +	struct ath_common *common = ath9k_hw_common(ah); + +	if (*nf > ah->nf_2g_max) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "2 GHz NF (%d) > MAX (%d), " +			  "correcting to MAX", +			  *nf, ah->nf_2g_max); +		*nf = ah->nf_2g_max; +	} else if (*nf < ah->nf_2g_min) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "2 GHz NF (%d) < MIN (%d), " +			  "correcting to MIN", +			  *nf, ah->nf_2g_min); +		*nf = ah->nf_2g_min; +	} +} + +static void ar9003_hw_nf_sanitize_5g(struct ath_hw *ah, s16 *nf) +{ +	struct ath_common *common = ath9k_hw_common(ah); + +	if (*nf > ah->nf_5g_max) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "5 GHz NF (%d) > MAX (%d), " +			  "correcting to MAX", +			  *nf, ah->nf_5g_max); +		*nf = ah->nf_5g_max; +	} else if (*nf < ah->nf_5g_min) { +		ath_print(common, ATH_DBG_CALIBRATE, +			  "5 GHz NF (%d) < MIN (%d), " +			  "correcting to MIN", +			  *nf, ah->nf_5g_min); +		*nf = ah->nf_5g_min; +	} +} + +static void ar9003_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) +{ +	if (IS_CHAN_2GHZ(ah->curchan)) +		ar9003_hw_nf_sanitize_2g(ah, nf); +	else +		ar9003_hw_nf_sanitize_5g(ah, nf); +} + +static void ar9003_hw_do_getnf(struct ath_hw *ah, +			      int16_t nfarray[NUM_NF_READINGS]) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	int16_t nf; + +	nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ar9003_hw_nf_sanitize(ah, &nf); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ctl] [chain 0] is %d\n", nf); +	nfarray[0] = nf; + +	nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ar9003_hw_nf_sanitize(ah, &nf); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ctl] [chain 1] is %d\n", nf); +	nfarray[1] = nf; + +	nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ar9003_hw_nf_sanitize(ah, &nf); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ctl] [chain 2] is %d\n", nf); +	nfarray[2] = nf; + +	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ar9003_hw_nf_sanitize(ah, &nf); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ext] [chain 0] is %d\n", nf); +	nfarray[3] = nf; + +	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ar9003_hw_nf_sanitize(ah, &nf); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ext] [chain 1] is %d\n", nf); +	nfarray[4] = nf; + +	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR); +	if (nf & 0x100) +		nf = 0 - ((nf ^ 0x1ff) + 1); +	ar9003_hw_nf_sanitize(ah, &nf); +	ath_print(common, ATH_DBG_CALIBRATE, +		  "NF calibrated [ext] [chain 2] is %d\n", nf); +	nfarray[5] = nf; +} + +void ar9003_hw_set_nf_limits(struct ath_hw *ah) +{ +	ah->nf_2g_max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ; +	ah->nf_2g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ; +	ah->nf_5g_max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ; +	ah->nf_5g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ; +} + +/* + * Find out which of the RX chains are enabled + */ +static u32 ar9003_hw_get_rx_chainmask(struct ath_hw *ah) +{ +	u32 chain = REG_READ(ah, AR_PHY_RX_CHAINMASK); +	/* +	 * The bits [2:0] indicate the rx chain mask and are to be +	 * interpreted as follows: +	 * 00x => Only chain 0 is enabled +	 * 01x => Chain 1 and 0 enabled +	 * 1xx => Chain 2,1 and 0 enabled +	 */ +	return chain & 0x7; +} + +static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) +{ +	struct ath9k_nfcal_hist *h; +	unsigned i, j; +	int32_t val; +	const u32 ar9300_cca_regs[6] = { +		AR_PHY_CCA_0, +		AR_PHY_CCA_1, +		AR_PHY_CCA_2, +		AR_PHY_EXT_CCA, +		AR_PHY_EXT_CCA_1, +		AR_PHY_EXT_CCA_2, +	}; +	u8 chainmask, rx_chain_status; +	struct ath_common *common = ath9k_hw_common(ah); + +	rx_chain_status = ar9003_hw_get_rx_chainmask(ah); + +	chainmask = 0x3F; +	h = ah->nfCalHist; + +	for (i = 0; i < NUM_NF_READINGS; i++) { +		if (chainmask & (1 << i)) { +			val = REG_READ(ah, ar9300_cca_regs[i]); +			val &= 0xFFFFFE00; +			val |= (((u32) (h[i].privNF) << 1) & 0x1ff); +			REG_WRITE(ah, ar9300_cca_regs[i], val); +		} +	} + +	/* +	 * Load software filtered NF value into baseband internal minCCApwr +	 * variable. +	 */ +	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, +		    AR_PHY_AGC_CONTROL_ENABLE_NF); +	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, +		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF); +	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); + +	/* +	 * Wait for load to complete, should be fast, a few 10s of us. +	 * The max delay was changed from an original 250us to 10000us +	 * since 250us often results in NF load timeout and causes deaf +	 * condition during stress testing 12/12/2009 +	 */ +	for (j = 0; j < 1000; j++) { +		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & +		     AR_PHY_AGC_CONTROL_NF) == 0) +			break; +		udelay(10); +	} + +	/* +	 * We timed out waiting for the noisefloor to load, probably due to an +	 * in-progress rx. Simply return here and allow the load plenty of time +	 * to complete before the next calibration interval.  We need to avoid +	 * trying to load -50 (which happens below) while the previous load is +	 * still in progress as this can cause rx deafness. Instead by returning +	 * here, the baseband nf cal will just be capped by our present +	 * noisefloor until the next calibration timer. +	 */ +	if (j == 1000) { +		ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf " +			  "to load: AR_PHY_AGC_CONTROL=0x%x\n", +			  REG_READ(ah, AR_PHY_AGC_CONTROL)); +		return; +	} + +	/* +	 * Restore maxCCAPower register parameter again so that we're not capped +	 * by the median we just loaded.  This will be initial (and max) value +	 * of next noise floor calibration the baseband does. +	 */ +	for (i = 0; i < NUM_NF_READINGS; i++) { +		if (chainmask & (1 << i)) { +			val = REG_READ(ah, ar9300_cca_regs[i]); +			val &= 0xFFFFFE00; +			val |= (((u32) (-50) << 1) & 0x1ff); +			REG_WRITE(ah, ar9300_cca_regs[i], val); +		} +	} +} + +void ar9003_hw_attach_phy_ops(struct ath_hw *ah) +{ +	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + +	priv_ops->rf_set_freq = ar9003_hw_set_channel; +	priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate; +	priv_ops->compute_pll_control = ar9003_hw_compute_pll_control; +	priv_ops->set_channel_regs = ar9003_hw_set_channel_regs; +	priv_ops->init_bb = ar9003_hw_init_bb; +	priv_ops->process_ini = ar9003_hw_process_ini; +	priv_ops->set_rfmode = ar9003_hw_set_rfmode; +	priv_ops->mark_phy_inactive = ar9003_hw_mark_phy_inactive; +	priv_ops->set_delta_slope = ar9003_hw_set_delta_slope; +	priv_ops->rfbus_req = ar9003_hw_rfbus_req; +	priv_ops->rfbus_done = ar9003_hw_rfbus_done; +	priv_ops->enable_rfkill = ar9003_hw_enable_rfkill; +	priv_ops->set_diversity = ar9003_hw_set_diversity; +	priv_ops->ani_control = ar9003_hw_ani_control; +	priv_ops->do_getnf = ar9003_hw_do_getnf; +	priv_ops->loadnf = ar9003_hw_loadnf; +} diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h new file mode 100644 index 00000000000..f08cc8bda00 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -0,0 +1,847 @@ +/* + * Copyright (c) 2002-2010 Atheros Communications, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef AR9003_PHY_H +#define AR9003_PHY_H + +/* + * Channel Register Map + */ +#define AR_CHAN_BASE	0x9800 + +#define AR_PHY_TIMING1      (AR_CHAN_BASE + 0x0) +#define AR_PHY_TIMING2      (AR_CHAN_BASE + 0x4) +#define AR_PHY_TIMING3      (AR_CHAN_BASE + 0x8) +#define AR_PHY_TIMING4      (AR_CHAN_BASE + 0xc) +#define AR_PHY_TIMING5      (AR_CHAN_BASE + 0x10) +#define AR_PHY_TIMING6      (AR_CHAN_BASE + 0x14) +#define AR_PHY_TIMING11     (AR_CHAN_BASE + 0x18) +#define AR_PHY_SPUR_REG     (AR_CHAN_BASE + 0x1c) +#define AR_PHY_RX_IQCAL_CORR_B0    (AR_CHAN_BASE + 0xdc) +#define AR_PHY_TX_IQCAL_CONTROL_3  (AR_CHAN_BASE + 0xb0) + +#define AR_PHY_TIMING11_SPUR_FREQ_SD    0x3FF00000 +#define AR_PHY_TIMING11_SPUR_FREQ_SD_S  20 + +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF +#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 + +#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC 0x40000000 +#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC_S 30 + +#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR 0x80000000 +#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR_S 31 + +#define AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT         0x4000000 +#define AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT_S       26 + +#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM                         0x20000     /* bins move with freq offset */ +#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM_S                       17 +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH            0x000000FF +#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S          0 +#define AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI                        0x00000100 +#define AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI_S                      8 +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL                          0x03FC0000 +#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S			18 + +#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN   0x20000000 +#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN_S         29 + +#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN   0x80000000 +#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN_S         31 + +#define AR_PHY_FIND_SIG_LOW  (AR_CHAN_BASE + 0x20) + +#define AR_PHY_SFCORR           (AR_CHAN_BASE + 0x24) +#define AR_PHY_SFCORR_LOW       (AR_CHAN_BASE + 0x28) +#define AR_PHY_SFCORR_EXT       (AR_CHAN_BASE + 0x2c) + +#define AR_PHY_EXT_CCA              (AR_CHAN_BASE + 0x30) +#define AR_PHY_RADAR_0              (AR_CHAN_BASE + 0x34) +#define AR_PHY_RADAR_1              (AR_CHAN_BASE + 0x38) +#define AR_PHY_RADAR_EXT            (AR_CHAN_BASE + 0x3c) +#define AR_PHY_MULTICHAIN_CTRL      (AR_CHAN_BASE + 0x80) +#define AR_PHY_PERCHAIN_CSD         (AR_CHAN_BASE + 0x84) + +#define AR_PHY_TX_PHASE_RAMP_0      (AR_CHAN_BASE + 0xd0) +#define AR_PHY_ADC_GAIN_DC_CORR_0   (AR_CHAN_BASE + 0xd4) +#define AR_PHY_IQ_ADC_MEAS_0_B0     (AR_CHAN_BASE + 0xc0) +#define AR_PHY_IQ_ADC_MEAS_1_B0     (AR_CHAN_BASE + 0xc4) +#define AR_PHY_IQ_ADC_MEAS_2_B0     (AR_CHAN_BASE + 0xc8) +#define AR_PHY_IQ_ADC_MEAS_3_B0     (AR_CHAN_BASE + 0xcc) + +/* The following registers changed position from AR9300 1.0 to AR9300 2.0 */ +#define AR_PHY_TX_PHASE_RAMP_0_9300_10      (AR_CHAN_BASE + 0xd0 - 0x10) +#define AR_PHY_ADC_GAIN_DC_CORR_0_9300_10   (AR_CHAN_BASE + 0xd4 - 0x10) +#define AR_PHY_IQ_ADC_MEAS_0_B0_9300_10     (AR_CHAN_BASE + 0xc0 + 0x8) +#define AR_PHY_IQ_ADC_MEAS_1_B0_9300_10     (AR_CHAN_BASE + 0xc4 + 0x8) +#define AR_PHY_IQ_ADC_MEAS_2_B0_9300_10     (AR_CHAN_BASE + 0xc8 + 0x8) +#define AR_PHY_IQ_ADC_MEAS_3_B0_9300_10     (AR_CHAN_BASE + 0xcc + 0x8) + +#define AR_PHY_TX_CRC               (AR_CHAN_BASE + 0xa0) +#define AR_PHY_TST_DAC_CONST        (AR_CHAN_BASE + 0xa4) +#define AR_PHY_SPUR_REPORT_0        (AR_CHAN_BASE + 0xa8) +#define AR_PHY_CHAN_INFO_TAB_0      (AR_CHAN_BASE + 0x300) + +/* + * Channel Field Definitions + */ +#define AR_PHY_TIMING2_USE_FORCE_PPM    0x00001000 +#define AR_PHY_TIMING2_FORCE_PPM_VAL    0x00000fff +#define AR_PHY_TIMING3_DSC_MAN      0xFFFE0000 +#define AR_PHY_TIMING3_DSC_MAN_S    17 +#define AR_PHY_TIMING3_DSC_EXP      0x0001E000 +#define AR_PHY_TIMING3_DSC_EXP_S    13 +#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX 0xF000 +#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX_S   12 +#define AR_PHY_TIMING4_DO_CAL    0x10000 + +#define AR_PHY_TIMING4_ENABLE_PILOT_MASK        0x10000000 +#define AR_PHY_TIMING4_ENABLE_PILOT_MASK_S      28 +#define AR_PHY_TIMING4_ENABLE_CHAN_MASK         0x20000000 +#define AR_PHY_TIMING4_ENABLE_CHAN_MASK_S       29 + +#define AR_PHY_TIMING4_ENABLE_SPUR_FILTER 0x40000000 +#define AR_PHY_TIMING4_ENABLE_SPUR_FILTER_S 30 +#define AR_PHY_TIMING4_ENABLE_SPUR_RSSI 0x80000000 +#define AR_PHY_TIMING4_ENABLE_SPUR_RSSI_S 31 + +#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 +#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 +#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW  0x00000001 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW    0x00003F00 +#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S  8 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW      0x001FC000 +#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S    14 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW      0x0FE00000 +#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S    21 +#define AR_PHY_SFCORR_M2COUNT_THR    0x0000001F +#define AR_PHY_SFCORR_M2COUNT_THR_S  0 +#define AR_PHY_SFCORR_M1_THRESH      0x00FE0000 +#define AR_PHY_SFCORR_M1_THRESH_S    17 +#define AR_PHY_SFCORR_M2_THRESH      0x7F000000 +#define AR_PHY_SFCORR_M2_THRESH_S    24 +#define AR_PHY_SFCORR_EXT_M1_THRESH       0x0000007F +#define AR_PHY_SFCORR_EXT_M1_THRESH_S     0 +#define AR_PHY_SFCORR_EXT_M2_THRESH       0x00003F80 +#define AR_PHY_SFCORR_EXT_M2_THRESH_S     7 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW   0x001FC000 +#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW   0x0FE00000 +#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 +#define AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD 0x10000000 +#define AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD_S 28 +#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S   28 +#define AR_PHY_EXT_CCA_THRESH62 0x007F0000 +#define AR_PHY_EXT_CCA_THRESH62_S       16 +#define AR_PHY_EXT_MINCCA_PWR   0x01FF0000 +#define AR_PHY_EXT_MINCCA_PWR_S 16 +#define AR_PHY_TIMING5_CYCPWR_THR1  0x000000FE +#define AR_PHY_TIMING5_CYCPWR_THR1_S    1 +#define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE  0x00000001 +#define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE_S    0 +#define AR_PHY_TIMING5_CYCPWR_THR1A  0x007F0000 +#define AR_PHY_TIMING5_CYCPWR_THR1A_S    16 +#define AR_PHY_TIMING5_RSSI_THR1A     (0x7F << 16) +#define AR_PHY_TIMING5_RSSI_THR1A_S   16 +#define AR_PHY_TIMING5_RSSI_THR1A_ENA (0x1 << 15) +#define AR_PHY_RADAR_0_ENA  0x00000001 +#define AR_PHY_RADAR_0_FFT_ENA  0x80000000 +#define AR_PHY_RADAR_0_INBAND   0x0000003e +#define AR_PHY_RADAR_0_INBAND_S 1 +#define AR_PHY_RADAR_0_PRSSI    0x00000FC0 +#define AR_PHY_RADAR_0_PRSSI_S  6 +#define AR_PHY_RADAR_0_HEIGHT   0x0003F000 +#define AR_PHY_RADAR_0_HEIGHT_S 12 +#define AR_PHY_RADAR_0_RRSSI    0x00FC0000 +#define AR_PHY_RADAR_0_RRSSI_S  18 +#define AR_PHY_RADAR_0_FIRPWR   0x7F000000 +#define AR_PHY_RADAR_0_FIRPWR_S 24 +#define AR_PHY_RADAR_1_RELPWR_ENA       0x00800000 +#define AR_PHY_RADAR_1_USE_FIR128       0x00400000 +#define AR_PHY_RADAR_1_RELPWR_THRESH    0x003F0000 +#define AR_PHY_RADAR_1_RELPWR_THRESH_S  16 +#define AR_PHY_RADAR_1_BLOCK_CHECK      0x00008000 +#define AR_PHY_RADAR_1_MAX_RRSSI        0x00004000 +#define AR_PHY_RADAR_1_RELSTEP_CHECK    0x00002000 +#define AR_PHY_RADAR_1_RELSTEP_THRESH   0x00001F00 +#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 +#define AR_PHY_RADAR_1_MAXLEN           0x000000FF +#define AR_PHY_RADAR_1_MAXLEN_S         0 +#define AR_PHY_RADAR_EXT_ENA            0x00004000 +#define AR_PHY_RADAR_DC_PWR_THRESH      0x007f8000 +#define AR_PHY_RADAR_DC_PWR_THRESH_S    15 +#define AR_PHY_RADAR_LB_DC_CAP          0x7f800000 +#define AR_PHY_RADAR_LB_DC_CAP_S        23 +#define AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW (0x3f << 6) +#define AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW_S   6 +#define AR_PHY_FIND_SIG_LOW_FIRPWR      (0x7f << 12) +#define AR_PHY_FIND_SIG_LOW_FIRPWR_S    12 +#define AR_PHY_FIND_SIG_LOW_FIRPWR_SIGN_BIT 19 +#define AR_PHY_FIND_SIG_LOW_RELSTEP     0x1f +#define AR_PHY_FIND_SIG_LOW_RELSTEP_S   0 +#define AR_PHY_FIND_SIG_LOW_RELSTEP_SIGN_BIT 5 +#define AR_PHY_CHAN_INFO_TAB_S2_READ    0x00000008 +#define AR_PHY_CHAN_INFO_TAB_S2_READ_S           3 +#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF 0x0000007F +#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF_S   0 +#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF 0x00003F80 +#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF_S   7 +#define AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE   0x00004000 +#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF   0x003f8000 +#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF_S 15 +#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF   0x1fc00000 +#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF_S 22 + +/* + * MRC Register Map + */ +#define AR_MRC_BASE	0x9c00 + +#define AR_PHY_TIMING_3A       (AR_MRC_BASE + 0x0) +#define AR_PHY_LDPC_CNTL1      (AR_MRC_BASE + 0x4) +#define AR_PHY_LDPC_CNTL2      (AR_MRC_BASE + 0x8) +#define AR_PHY_PILOT_SPUR_MASK (AR_MRC_BASE + 0xc) +#define AR_PHY_CHAN_SPUR_MASK  (AR_MRC_BASE + 0x10) +#define AR_PHY_SGI_DELTA       (AR_MRC_BASE + 0x14) +#define AR_PHY_ML_CNTL_1       (AR_MRC_BASE + 0x18) +#define AR_PHY_ML_CNTL_2       (AR_MRC_BASE + 0x1c) +#define AR_PHY_TST_ADC         (AR_MRC_BASE + 0x20) + +#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A              0x00000FE0 +#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A_S    5 +#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A                  0x1F +#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A_S                0 + +#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A        0x00000FE0 +#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A_S      5 +#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A            0x1F +#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A_S		0 + +/* + * MRC Feild Definitions + */ +#define AR_PHY_SGI_DSC_MAN   0x0007FFF0 +#define AR_PHY_SGI_DSC_MAN_S 4 +#define AR_PHY_SGI_DSC_EXP   0x0000000F +#define AR_PHY_SGI_DSC_EXP_S 0 +/* + * BBB Register Map + */ +#define AR_BBB_BASE	0x9d00 + +/* + * AGC Register Map + */ +#define AR_AGC_BASE	0x9e00 + +#define AR_PHY_SETTLING         (AR_AGC_BASE + 0x0) +#define AR_PHY_FORCEMAX_GAINS_0 (AR_AGC_BASE + 0x4) +#define AR_PHY_GAINS_MINOFF0    (AR_AGC_BASE + 0x8) +#define AR_PHY_DESIRED_SZ       (AR_AGC_BASE + 0xc) +#define AR_PHY_FIND_SIG         (AR_AGC_BASE + 0x10) +#define AR_PHY_AGC              (AR_AGC_BASE + 0x14) +#define AR_PHY_EXT_ATTEN_CTL_0  (AR_AGC_BASE + 0x18) +#define AR_PHY_CCA_0            (AR_AGC_BASE + 0x1c) +#define AR_PHY_EXT_CCA0         (AR_AGC_BASE + 0x20) +#define AR_PHY_RESTART          (AR_AGC_BASE + 0x24) +#define AR_PHY_MC_GAIN_CTRL     (AR_AGC_BASE + 0x28) +#define AR_PHY_EXTCHN_PWRTHR1   (AR_AGC_BASE + 0x2c) +#define AR_PHY_EXT_CHN_WIN      (AR_AGC_BASE + 0x30) +#define AR_PHY_20_40_DET_THR    (AR_AGC_BASE + 0x34) +#define AR_PHY_RIFS_SRCH        (AR_AGC_BASE + 0x38) +#define AR_PHY_PEAK_DET_CTRL_1  (AR_AGC_BASE + 0x3c) +#define AR_PHY_PEAK_DET_CTRL_2  (AR_AGC_BASE + 0x40) +#define AR_PHY_RX_GAIN_BOUNDS_1 (AR_AGC_BASE + 0x44) +#define AR_PHY_RX_GAIN_BOUNDS_2 (AR_AGC_BASE + 0x48) +#define AR_PHY_RSSI_0           (AR_AGC_BASE + 0x180) +#define AR_PHY_SPUR_CCK_REP0    (AR_AGC_BASE + 0x184) +#define AR_PHY_CCK_DETECT       (AR_AGC_BASE + 0x1c0) +#define AR_PHY_DAG_CTRLCCK      (AR_AGC_BASE + 0x1c4) +#define AR_PHY_IQCORR_CTRL_CCK  (AR_AGC_BASE + 0x1c8) + +#define AR_PHY_CCK_SPUR_MIT     (AR_AGC_BASE + 0x1cc) +#define AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR                           0x000001fe +#define AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR_S                                  1 +#define AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE                        0x60000000 +#define AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE_S                              29 +#define AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT                        0x00000001 +#define AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT_S                               0 +#define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ                           0x1ffffe00 +#define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ_S                                  9 + +#define AR_PHY_RX_OCGAIN        (AR_AGC_BASE + 0x200) + +#define AR_PHY_CCA_NOM_VAL_9300_2GHZ          -110 +#define AR_PHY_CCA_NOM_VAL_9300_5GHZ          -115 +#define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ     -125 +#define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ     -125 +#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -95 +#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -100 + +/* + * AGC Field Definitions + */ +#define AR_PHY_EXT_ATTEN_CTL_RXTX_MARGIN    0x00FC0000 +#define AR_PHY_EXT_ATTEN_CTL_RXTX_MARGIN_S  18 +#define AR_PHY_EXT_ATTEN_CTL_BSW_MARGIN     0x00003C00 +#define AR_PHY_EXT_ATTEN_CTL_BSW_MARGIN_S   10 +#define AR_PHY_EXT_ATTEN_CTL_BSW_ATTEN      0x0000001F +#define AR_PHY_EXT_ATTEN_CTL_BSW_ATTEN_S    0 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_MARGIN     0x003E0000 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_MARGIN_S   17 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN     0x0001F000 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN_S   12 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_DB         0x00000FC0 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_DB_S       6 +#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB         0x0000003F +#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB_S       0 +#define AR_PHY_RXGAIN_TXRX_ATTEN    0x0003F000 +#define AR_PHY_RXGAIN_TXRX_ATTEN_S  12 +#define AR_PHY_RXGAIN_TXRX_RF_MAX   0x007C0000 +#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN    0x00003F80 +#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S  7 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN   0x001FC000 +#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 +#define AR_PHY_SETTLING_SWITCH  0x00003F80 +#define AR_PHY_SETTLING_SWITCH_S    7 +#define AR_PHY_DESIRED_SZ_ADC       0x000000FF +#define AR_PHY_DESIRED_SZ_ADC_S     0 +#define AR_PHY_DESIRED_SZ_PGA       0x0000FF00 +#define AR_PHY_DESIRED_SZ_PGA_S     8 +#define AR_PHY_DESIRED_SZ_TOT_DES   0x0FF00000 +#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 +#define AR_PHY_MINCCA_PWR       0x1FF00000 +#define AR_PHY_MINCCA_PWR_S     20 +#define AR_PHY_CCA_THRESH62     0x0007F000 +#define AR_PHY_CCA_THRESH62_S   12 +#define AR9280_PHY_MINCCA_PWR       0x1FF00000 +#define AR9280_PHY_MINCCA_PWR_S     20 +#define AR9280_PHY_CCA_THRESH62     0x000FF000 +#define AR9280_PHY_CCA_THRESH62_S   12 +#define AR_PHY_EXT_CCA0_THRESH62    0x000000FF +#define AR_PHY_EXT_CCA0_THRESH62_S  0 +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK          0x0000003F +#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S        0 +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME           0x00001FC0 +#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S         6 +#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV    0x2000 + +#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR  0x00000200 +#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR_S  9 +#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 +#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S   10 + +#define AR_PHY_RIFS_INIT_DELAY         0x3ff0000 +#define AR_PHY_AGC_COARSE_LOW       0x00007F80 +#define AR_PHY_AGC_COARSE_LOW_S     7 +#define AR_PHY_AGC_COARSE_HIGH      0x003F8000 +#define AR_PHY_AGC_COARSE_HIGH_S    15 +#define AR_PHY_AGC_COARSE_PWR_CONST 0x0000007F +#define AR_PHY_AGC_COARSE_PWR_CONST_S   0 +#define AR_PHY_FIND_SIG_FIRSTEP  0x0003F000 +#define AR_PHY_FIND_SIG_FIRSTEP_S        12 +#define AR_PHY_FIND_SIG_FIRPWR   0x03FC0000 +#define AR_PHY_FIND_SIG_FIRPWR_S         18 +#define AR_PHY_FIND_SIG_FIRPWR_SIGN_BIT  25 +#define AR_PHY_FIND_SIG_RELPWR   (0x1f << 6) +#define AR_PHY_FIND_SIG_RELPWR_S          6 +#define AR_PHY_FIND_SIG_RELPWR_SIGN_BIT  11 +#define AR_PHY_FIND_SIG_RELSTEP        0x1f +#define AR_PHY_FIND_SIG_RELSTEP_S         0 +#define AR_PHY_FIND_SIG_RELSTEP_SIGN_BIT  5 +#define AR_PHY_RESTART_DIV_GC   0x001C0000 +#define AR_PHY_RESTART_DIV_GC_S 18 +#define AR_PHY_RESTART_ENA      0x01 +#define AR_PHY_DC_RESTART_DIS   0x40000000 + +#define AR_PHY_TPC_OLPC_GAIN_DELTA_PAL_ON       0xFF000000 +#define AR_PHY_TPC_OLPC_GAIN_DELTA_PAL_ON_S     24 +#define AR_PHY_TPC_OLPC_GAIN_DELTA              0x00FF0000 +#define AR_PHY_TPC_OLPC_GAIN_DELTA_S            16 + +#define AR_PHY_TPC_6_ERROR_EST_MODE             0x03000000 +#define AR_PHY_TPC_6_ERROR_EST_MODE_S           24 + +/* + * SM Register Map + */ +#define AR_SM_BASE	0xa200 + +#define AR_PHY_D2_CHIP_ID        (AR_SM_BASE + 0x0) +#define AR_PHY_GEN_CTRL          (AR_SM_BASE + 0x4) +#define AR_PHY_MODE              (AR_SM_BASE + 0x8) +#define AR_PHY_ACTIVE            (AR_SM_BASE + 0xc) +#define AR_PHY_SPUR_MASK_A       (AR_SM_BASE + 0x20) +#define AR_PHY_SPUR_MASK_B       (AR_SM_BASE + 0x24) +#define AR_PHY_SPECTRAL_SCAN     (AR_SM_BASE + 0x28) +#define AR_PHY_RADAR_BW_FILTER   (AR_SM_BASE + 0x2c) +#define AR_PHY_SEARCH_START_DELAY (AR_SM_BASE + 0x30) +#define AR_PHY_MAX_RX_LEN        (AR_SM_BASE + 0x34) +#define AR_PHY_FRAME_CTL         (AR_SM_BASE + 0x38) +#define AR_PHY_RFBUS_REQ         (AR_SM_BASE + 0x3c) +#define AR_PHY_RFBUS_GRANT       (AR_SM_BASE + 0x40) +#define AR_PHY_RIFS              (AR_SM_BASE + 0x44) +#define AR_PHY_RX_CLR_DELAY      (AR_SM_BASE + 0x50) +#define AR_PHY_RX_DELAY          (AR_SM_BASE + 0x54) + +#define AR_PHY_XPA_TIMING_CTL    (AR_SM_BASE + 0x64) +#define AR_PHY_MISC_PA_CTL       (AR_SM_BASE + 0x80) +#define AR_PHY_SWITCH_CHAIN_0    (AR_SM_BASE + 0x84) +#define AR_PHY_SWITCH_COM        (AR_SM_BASE + 0x88) +#define AR_PHY_SWITCH_COM_2      (AR_SM_BASE + 0x8c) +#define AR_PHY_RX_CHAINMASK      (AR_SM_BASE + 0xa0) +#define AR_PHY_CAL_CHAINMASK     (AR_SM_BASE + 0xc0) +#define AR_PHY_CALMODE           (AR_SM_BASE + 0xc8) +#define AR_PHY_FCAL_1            (AR_SM_BASE + 0xcc) +#define AR_PHY_FCAL_2_0          (AR_SM_BASE + 0xd0) +#define AR_PHY_DFT_TONE_CTL_0    (AR_SM_BASE + 0xd4) +#define AR_PHY_CL_CAL_CTL        (AR_SM_BASE + 0xd8) +#define AR_PHY_CL_TAB_0          (AR_SM_BASE + 0x100) +#define AR_PHY_SYNTH_CONTROL     (AR_SM_BASE + 0x140) +#define AR_PHY_ADDAC_CLK_SEL     (AR_SM_BASE + 0x144) +#define AR_PHY_PLL_CTL           (AR_SM_BASE + 0x148) +#define AR_PHY_ANALOG_SWAP       (AR_SM_BASE + 0x14c) +#define AR_PHY_ADDAC_PARA_CTL    (AR_SM_BASE + 0x150) +#define AR_PHY_XPA_CFG           (AR_SM_BASE + 0x158) + +#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A           0x0001FC00 +#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A_S         10 +#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A                       0x3FF +#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A_S                     0 + +#define AR_PHY_TEST              (AR_SM_BASE + 0x160) + +#define AR_PHY_TEST_BBB_OBS_SEL       0x780000 +#define AR_PHY_TEST_BBB_OBS_SEL_S     19 + +#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23 +#define AR_PHY_TEST_RX_OBS_SEL_BIT5   (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S) + +#define AR_PHY_TEST_CHAIN_SEL      0xC0000000 +#define AR_PHY_TEST_CHAIN_SEL_S    30 + +#define AR_PHY_TEST_CTL_STATUS   (AR_SM_BASE + 0x164) +#define AR_PHY_TEST_CTL_TSTDAC_EN         0x1 +#define AR_PHY_TEST_CTL_TSTDAC_EN_S       0 +#define AR_PHY_TEST_CTL_TX_OBS_SEL        0x1C +#define AR_PHY_TEST_CTL_TX_OBS_SEL_S      2 +#define AR_PHY_TEST_CTL_TX_OBS_MUX_SEL    0x60 +#define AR_PHY_TEST_CTL_TX_OBS_MUX_SEL_S  5 +#define AR_PHY_TEST_CTL_TSTADC_EN         0x100 +#define AR_PHY_TEST_CTL_TSTADC_EN_S       8 +#define AR_PHY_TEST_CTL_RX_OBS_SEL        0x3C00 +#define AR_PHY_TEST_CTL_RX_OBS_SEL_S      10 + + +#define AR_PHY_TSTDAC            (AR_SM_BASE + 0x168) + +#define AR_PHY_CHAN_STATUS       (AR_SM_BASE + 0x16c) +#define AR_PHY_CHAN_INFO_MEMORY  (AR_SM_BASE + 0x170) +#define AR_PHY_CHNINFO_NOISEPWR  (AR_SM_BASE + 0x174) +#define AR_PHY_CHNINFO_GAINDIFF  (AR_SM_BASE + 0x178) +#define AR_PHY_CHNINFO_FINETIM   (AR_SM_BASE + 0x17c) +#define AR_PHY_CHAN_INFO_GAIN_0  (AR_SM_BASE + 0x180) +#define AR_PHY_SCRAMBLER_SEED    (AR_SM_BASE + 0x190) +#define AR_PHY_CCK_TX_CTRL       (AR_SM_BASE + 0x194) + +#define AR_PHY_HEAVYCLIP_CTL     (AR_SM_BASE + 0x1a4) +#define AR_PHY_HEAVYCLIP_20      (AR_SM_BASE + 0x1a8) +#define AR_PHY_HEAVYCLIP_40      (AR_SM_BASE + 0x1ac) +#define AR_PHY_ILLEGAL_TXRATE    (AR_SM_BASE + 0x1b0) + +#define AR_PHY_PWRTX_MAX         (AR_SM_BASE + 0x1f0) +#define AR_PHY_POWER_TX_SUB      (AR_SM_BASE + 0x1f4) + +#define AR_PHY_TPC_4_B0          (AR_SM_BASE + 0x204) +#define AR_PHY_TPC_5_B0          (AR_SM_BASE + 0x208) +#define AR_PHY_TPC_6_B0          (AR_SM_BASE + 0x20c) +#define AR_PHY_TPC_11_B0         (AR_SM_BASE + 0x220) +#define AR_PHY_TPC_18            (AR_SM_BASE + 0x23c) +#define AR_PHY_TPC_19            (AR_SM_BASE + 0x240) + +#define AR_PHY_TX_FORCED_GAIN    (AR_SM_BASE + 0x258) + +#define AR_PHY_PDADC_TAB_0       (AR_SM_BASE + 0x280) + +#define AR_PHY_TX_IQCAL_CONTROL_1   (AR_SM_BASE + 0x448) +#define AR_PHY_TX_IQCAL_START       (AR_SM_BASE + 0x440) +#define AR_PHY_TX_IQCAL_STATUS_B0   (AR_SM_BASE + 0x48c) +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0    (AR_SM_BASE + 0x450) + +#define AR_PHY_PANIC_WD_STATUS      (AR_SM_BASE + 0x5c0) +#define AR_PHY_PANIC_WD_CTL_1       (AR_SM_BASE + 0x5c4) +#define AR_PHY_PANIC_WD_CTL_2       (AR_SM_BASE + 0x5c8) +#define AR_PHY_BT_CTL               (AR_SM_BASE + 0x5cc) +#define AR_PHY_ONLY_WARMRESET       (AR_SM_BASE + 0x5d0) +#define AR_PHY_ONLY_CTL             (AR_SM_BASE + 0x5d4) +#define AR_PHY_ECO_CTRL             (AR_SM_BASE + 0x5dc) +#define AR_PHY_BB_THERM_ADC_1       (AR_SM_BASE + 0x248) + +#define AR_PHY_65NM_CH0_SYNTH4      0x1608c +#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   0x00000002 +#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S 1 +#define AR_PHY_65NM_CH0_SYNTH7      0x16098 +#define AR_PHY_65NM_CH0_BIAS1       0x160c0 +#define AR_PHY_65NM_CH0_BIAS2       0x160c4 +#define AR_PHY_65NM_CH0_BIAS4       0x160cc +#define AR_PHY_65NM_CH0_RXTX4       0x1610c +#define AR_PHY_65NM_CH0_THERM       0x16290 + +#define AR_PHY_65NM_CH0_THERM_LOCAL   0x80000000 +#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 +#define AR_PHY_65NM_CH0_THERM_START   0x20000000 +#define AR_PHY_65NM_CH0_THERM_START_S 29 +#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT   0x0000ff00 +#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8 + +#define AR_PHY_65NM_CH0_RXTX1       0x16100 +#define AR_PHY_65NM_CH0_RXTX2       0x16104 +#define AR_PHY_65NM_CH1_RXTX1       0x16500 +#define AR_PHY_65NM_CH1_RXTX2       0x16504 +#define AR_PHY_65NM_CH2_RXTX1       0x16900 +#define AR_PHY_65NM_CH2_RXTX2       0x16904 + +#define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT		0x00380000 +#define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT_S	19 +#define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT		0x00c00000 +#define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT_S	22 +#define AR_PHY_LNAGAIN_LONG_SHIFT		0xe0000000 +#define AR_PHY_LNAGAIN_LONG_SHIFT_S		29 +#define AR_PHY_MXRGAIN_LONG_SHIFT		0x03000000 +#define AR_PHY_MXRGAIN_LONG_SHIFT_S		24 +#define AR_PHY_VGAGAIN_LONG_SHIFT		0x1c000000 +#define AR_PHY_VGAGAIN_LONG_SHIFT_S		26 +#define AR_PHY_SCFIR_GAIN_LONG_SHIFT		0x00000001 +#define AR_PHY_SCFIR_GAIN_LONG_SHIFT_S		0 +#define AR_PHY_MANRXGAIN_LONG_SHIFT		0x00000002 +#define AR_PHY_MANRXGAIN_LONG_SHIFT_S		1 + +/* + * SM Field Definitions + */ +#define AR_PHY_CL_CAL_ENABLE          0x00000002 +#define AR_PHY_PARALLEL_CAL_ENABLE    0x00000001 +#define AR_PHY_TPCRG1_PD_CAL_ENABLE   0x00400000 +#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 + +#define AR_PHY_ADDAC_PARACTL_OFF_PWDADC 0x00008000 + +#define AR_PHY_FCAL20_CAP_STATUS_0    0x01f00000 +#define AR_PHY_FCAL20_CAP_STATUS_0_S  20 + +#define AR_PHY_RFBUS_REQ_EN     0x00000001  /* request for RF bus */ +#define AR_PHY_RFBUS_GRANT_EN   0x00000001  /* RF bus granted */ +#define AR_PHY_GC_TURBO_MODE       0x00000001  /* set turbo mode bits */ +#define AR_PHY_GC_TURBO_SHORT      0x00000002  /* set short symbols to turbo mode setting */ +#define AR_PHY_GC_DYN2040_EN       0x00000004  /* enable dyn 20/40 mode */ +#define AR_PHY_GC_DYN2040_PRI_ONLY 0x00000008  /* dyn 20/40 - primary only */ +#define AR_PHY_GC_DYN2040_PRI_CH   0x00000010  /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/ +#define AR_PHY_GC_DYN2040_PRI_CH_S 4 +#define AR_PHY_GC_DYN2040_EXT_CH   0x00000020  /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */ +#define AR_PHY_GC_HT_EN            0x00000040  /* ht enable */ +#define AR_PHY_GC_SHORT_GI_40      0x00000080  /* allow short GI for HT 40 */ +#define AR_PHY_GC_WALSH            0x00000100  /* walsh spatial spreading for 2 chains,2 streams TX */ +#define AR_PHY_GC_SINGLE_HT_LTF1   0x00000200  /* single length (4us) 1st HT long training symbol */ +#define AR_PHY_GC_GF_DETECT_EN     0x00000400  /* enable Green Field detection. Only affects rx, not tx */ +#define AR_PHY_GC_ENABLE_DAC_FIFO  0x00000800  /* fifo between bb and dac */ +#define AR_PHY_RX_DELAY_DELAY      0x00003FFF  /* delay from wakeup to rx ena */ + +#define AR_PHY_CALMODE_IQ           0x00000000 +#define AR_PHY_CALMODE_ADC_GAIN     0x00000001 +#define AR_PHY_CALMODE_ADC_DC_PER   0x00000002 +#define AR_PHY_CALMODE_ADC_DC_INIT  0x00000003 +#define AR_PHY_SWAP_ALT_CHAIN       0x00000040 +#define AR_PHY_MODE_OFDM            0x00000000 +#define AR_PHY_MODE_CCK             0x00000001 +#define AR_PHY_MODE_DYNAMIC         0x00000004 +#define AR_PHY_MODE_DYNAMIC_S       2 +#define AR_PHY_MODE_HALF            0x00000020 +#define AR_PHY_MODE_QUARTER         0x00000040 +#define AR_PHY_MAC_CLK_MODE         0x00000080 +#define AR_PHY_MODE_DYN_CCK_DISABLE 0x00000100 +#define AR_PHY_MODE_SVD_HALF        0x00000200 +#define AR_PHY_ACTIVE_EN    0x00000001 +#define AR_PHY_ACTIVE_DIS   0x00000000 +#define AR_PHY_FORCE_XPA_CFG    0x000000001 +#define AR_PHY_FORCE_XPA_CFG_S  0 +#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF    0xFF000000 +#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF_S  24 +#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF    0x00FF0000 +#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF_S  16 +#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON      0x0000FF00 +#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON_S    8 +#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON      0x000000FF +#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON_S    0 +#define AR_PHY_TX_END_TO_A2_RX_ON       0x00FF0000 +#define AR_PHY_TX_END_TO_A2_RX_ON_S     16 +#define AR_PHY_TX_END_DATA_START  0x000000FF +#define AR_PHY_TX_END_DATA_START_S  0 +#define AR_PHY_TX_END_PA_ON       0x0000FF00 +#define AR_PHY_TX_END_PA_ON_S       8 +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP   0x0000000F +#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S     0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1    0x000003F0 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S  4 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2    0x0000FC00 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S  10 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3    0x003F0000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S  16 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4    0x0FC00000 +#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S  22 +#define AR_PHY_TPCRG1_NUM_PD_GAIN   0x0000c000 +#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 +#define AR_PHY_TPCRG1_PD_GAIN_1    0x00030000 +#define AR_PHY_TPCRG1_PD_GAIN_1_S  16 +#define AR_PHY_TPCRG1_PD_GAIN_2    0x000C0000 +#define AR_PHY_TPCRG1_PD_GAIN_2_S  18 +#define AR_PHY_TPCRG1_PD_GAIN_3    0x00300000 +#define AR_PHY_TPCRG1_PD_GAIN_3_S  20 +#define AR_PHY_TPCGR1_FORCED_DAC_GAIN   0x0000003e +#define AR_PHY_TPCGR1_FORCED_DAC_GAIN_S 1 +#define AR_PHY_TPCGR1_FORCE_DAC_GAIN    0x00000001 +#define AR_PHY_TXGAIN_FORCE               0x00000001 +#define AR_PHY_TXGAIN_FORCED_PADVGNRA     0x00003c00 +#define AR_PHY_TXGAIN_FORCED_PADVGNRA_S   10 +#define AR_PHY_TXGAIN_FORCED_PADVGNRB     0x0003c000 +#define AR_PHY_TXGAIN_FORCED_PADVGNRB_S   14 +#define AR_PHY_TXGAIN_FORCED_PADVGNRD     0x00c00000 +#define AR_PHY_TXGAIN_FORCED_PADVGNRD_S   22 +#define AR_PHY_TXGAIN_FORCED_TXMXRGAIN    0x000003c0 +#define AR_PHY_TXGAIN_FORCED_TXMXRGAIN_S  6 +#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN  0x0000000e +#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN_S 1 + +#define AR_PHY_POWER_TX_RATE1   0x9934 +#define AR_PHY_POWER_TX_RATE2   0x9938 +#define AR_PHY_POWER_TX_RATE_MAX    0x993c +#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 +#define PHY_AGC_CLR             0x10000000 +#define RFSILENT_BB             0x00002000 +#define AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_MASK          0xFFF +#define AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_SIGNED_BIT    0x800 +#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT         320 +#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK         0x0001 +#define AR_PHY_RX_DELAY_DELAY   0x00003FFF +#define AR_PHY_CCK_TX_CTRL_JAPAN    0x00000010 +#define AR_PHY_SPECTRAL_SCAN_ENABLE         0x00000001 +#define AR_PHY_SPECTRAL_SCAN_ENABLE_S       0 +#define AR_PHY_SPECTRAL_SCAN_ACTIVE         0x00000002 +#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S       1 +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD     0x000000F0 +#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S   4 +#define AR_PHY_SPECTRAL_SCAN_PERIOD         0x0000FF00 +#define AR_PHY_SPECTRAL_SCAN_PERIOD_S       8 +#define AR_PHY_SPECTRAL_SCAN_COUNT          0x00FF0000 +#define AR_PHY_SPECTRAL_SCAN_COUNT_S        16 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT   0x01000000 +#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 +#define AR_PHY_CHANNEL_STATUS_RX_CLEAR      0x00000004 +#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT             0x01fc0000 +#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S                   18 +#define AR_PHY_TX_IQCAL_START_DO_CAL        0x00000001 +#define AR_PHY_TX_IQCAL_START_DO_CAL_S      0 + +#define AR_PHY_TX_IQCAL_STATUS_FAILED    0x00000001 +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE      0x00003fff +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S    0 + +#define AR_PHY_TPC_18_THERM_CAL_VALUE           0xff +#define AR_PHY_TPC_18_THERM_CAL_VALUE_S         0 +#define AR_PHY_TPC_19_ALPHA_THERM               0xff +#define AR_PHY_TPC_19_ALPHA_THERM_S             0 + +#define AR_PHY_65NM_CH0_RXTX4_THERM_ON          0x10000000 +#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S        28 + +#define AR_PHY_BB_THERM_ADC_1_INIT_THERM        0x000000ff +#define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S      0 + +/* + * Channel 1 Register Map + */ +#define AR_CHAN1_BASE	0xa800 + +#define AR_PHY_EXT_CCA_1            (AR_CHAN1_BASE + 0x30) +#define AR_PHY_TX_PHASE_RAMP_1      (AR_CHAN1_BASE + 0xd0) +#define AR_PHY_ADC_GAIN_DC_CORR_1   (AR_CHAN1_BASE + 0xd4) + +#define AR_PHY_SPUR_REPORT_1        (AR_CHAN1_BASE + 0xa8) +#define AR_PHY_CHAN_INFO_TAB_1      (AR_CHAN1_BASE + 0x300) +#define AR_PHY_RX_IQCAL_CORR_B1     (AR_CHAN1_BASE + 0xdc) + +/* + * Channel 1 Field Definitions + */ +#define AR_PHY_CH1_EXT_MINCCA_PWR   0x01FF0000 +#define AR_PHY_CH1_EXT_MINCCA_PWR_S 16 + +/* + * AGC 1 Register Map + */ +#define AR_AGC1_BASE	0xae00 + +#define AR_PHY_FORCEMAX_GAINS_1      (AR_AGC1_BASE + 0x4) +#define AR_PHY_EXT_ATTEN_CTL_1       (AR_AGC1_BASE + 0x18) +#define AR_PHY_CCA_1                 (AR_AGC1_BASE + 0x1c) +#define AR_PHY_CCA_CTRL_1            (AR_AGC1_BASE + 0x20) +#define AR_PHY_RSSI_1                (AR_AGC1_BASE + 0x180) +#define AR_PHY_SPUR_CCK_REP_1        (AR_AGC1_BASE + 0x184) +#define AR_PHY_RX_OCGAIN_2           (AR_AGC1_BASE + 0x200) + +/* + * AGC 1 Field Definitions + */ +#define AR_PHY_CH1_MINCCA_PWR   0x1FF00000 +#define AR_PHY_CH1_MINCCA_PWR_S 20 + +/* + * SM 1 Register Map + */ +#define AR_SM1_BASE	0xb200 + +#define AR_PHY_SWITCH_CHAIN_1    (AR_SM1_BASE + 0x84) +#define AR_PHY_FCAL_2_1          (AR_SM1_BASE + 0xd0) +#define AR_PHY_DFT_TONE_CTL_1    (AR_SM1_BASE + 0xd4) +#define AR_PHY_CL_TAB_1          (AR_SM1_BASE + 0x100) +#define AR_PHY_CHAN_INFO_GAIN_1  (AR_SM1_BASE + 0x180) +#define AR_PHY_TPC_4_B1          (AR_SM1_BASE + 0x204) +#define AR_PHY_TPC_5_B1          (AR_SM1_BASE + 0x208) +#define AR_PHY_TPC_6_B1          (AR_SM1_BASE + 0x20c) +#define AR_PHY_TPC_11_B1         (AR_SM1_BASE + 0x220) +#define AR_PHY_PDADC_TAB_1       (AR_SM1_BASE + 0x240) +#define AR_PHY_TX_IQCAL_STATUS_B1   (AR_SM1_BASE + 0x48c) +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B1    (AR_SM1_BASE + 0x450) + +/* + * Channel 2 Register Map + */ +#define AR_CHAN2_BASE	0xb800 + +#define AR_PHY_EXT_CCA_2            (AR_CHAN2_BASE + 0x30) +#define AR_PHY_TX_PHASE_RAMP_2      (AR_CHAN2_BASE + 0xd0) +#define AR_PHY_ADC_GAIN_DC_CORR_2   (AR_CHAN2_BASE + 0xd4) + +#define AR_PHY_SPUR_REPORT_2        (AR_CHAN2_BASE + 0xa8) +#define AR_PHY_CHAN_INFO_TAB_2      (AR_CHAN2_BASE + 0x300) +#define AR_PHY_RX_IQCAL_CORR_B2     (AR_CHAN2_BASE + 0xdc) + +/* + * Channel 2 Field Definitions + */ +#define AR_PHY_CH2_EXT_MINCCA_PWR   0x01FF0000 +#define AR_PHY_CH2_EXT_MINCCA_PWR_S 16 +/* + * AGC 2 Register Map + */ +#define AR_AGC2_BASE	0xbe00 + +#define AR_PHY_FORCEMAX_GAINS_2      (AR_AGC2_BASE + 0x4) +#define AR_PHY_EXT_ATTEN_CTL_2       (AR_AGC2_BASE + 0x18) +#define AR_PHY_CCA_2                 (AR_AGC2_BASE + 0x1c) +#define AR_PHY_CCA_CTRL_2            (AR_AGC2_BASE + 0x20) +#define AR_PHY_RSSI_2                (AR_AGC2_BASE + 0x180) + +/* + * AGC 2 Field Definitions + */ +#define AR_PHY_CH2_MINCCA_PWR   0x1FF00000 +#define AR_PHY_CH2_MINCCA_PWR_S 20 + +/* + * SM 2 Register Map + */ +#define AR_SM2_BASE	0xc200 + +#define AR_PHY_SWITCH_CHAIN_2    (AR_SM2_BASE + 0x84) +#define AR_PHY_FCAL_2_2          (AR_SM2_BASE + 0xd0) +#define AR_PHY_DFT_TONE_CTL_2    (AR_SM2_BASE + 0xd4) +#define AR_PHY_CL_TAB_2          (AR_SM2_BASE + 0x100) +#define AR_PHY_CHAN_INFO_GAIN_2  (AR_SM2_BASE + 0x180) +#define AR_PHY_TPC_4_B2          (AR_SM2_BASE + 0x204) +#define AR_PHY_TPC_5_B2          (AR_SM2_BASE + 0x208) +#define AR_PHY_TPC_6_B2          (AR_SM2_BASE + 0x20c) +#define AR_PHY_TPC_11_B2         (AR_SM2_BASE + 0x220) +#define AR_PHY_PDADC_TAB_2       (AR_SM2_BASE + 0x240) +#define AR_PHY_TX_IQCAL_STATUS_B2   (AR_SM2_BASE + 0x48c) +#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B2    (AR_SM2_BASE + 0x450) + +#define AR_PHY_TX_IQCAL_STATUS_B2_FAILED    0x00000001 + +/* + * AGC 3 Register Map + */ +#define AR_AGC3_BASE	0xce00 + +#define AR_PHY_RSSI_3            (AR_AGC3_BASE + 0x180) + +/* + * Misc helper defines + */ +#define AR_PHY_CHAIN_OFFSET     (AR_CHAN1_BASE - AR_CHAN_BASE) + +#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (AR_PHY_ADC_GAIN_DC_CORR_0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_NEW_ADC_DC_GAIN_CORR_9300_10(_i) (AR_PHY_ADC_GAIN_DC_CORR_0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_SWITCH_CHAIN(_i)     (AR_PHY_SWITCH_CHAIN_0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_EXT_ATTEN_CTL(_i)    (AR_PHY_EXT_ATTEN_CTL_0 + (AR_PHY_CHAIN_OFFSET * (_i))) + +#define AR_PHY_RXGAIN(_i)           (AR_PHY_FORCEMAX_GAINS_0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_TPCRG5(_i)           (AR_PHY_TPC_5_B0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_PDADC_TAB(_i)        (AR_PHY_PDADC_TAB_0 + (AR_PHY_CHAIN_OFFSET * (_i))) + +#define AR_PHY_CAL_MEAS_0(_i)       (AR_PHY_IQ_ADC_MEAS_0_B0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_1(_i)       (AR_PHY_IQ_ADC_MEAS_1_B0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_2(_i)       (AR_PHY_IQ_ADC_MEAS_2_B0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_3(_i)       (AR_PHY_IQ_ADC_MEAS_3_B0 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_0_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_0_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_1_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_1_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) +#define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) + +#define AR_PHY_BB_PANIC_NON_IDLE_ENABLE 0x00000001 +#define AR_PHY_BB_PANIC_IDLE_ENABLE     0x00000002 +#define AR_PHY_BB_PANIC_IDLE_MASK       0xFFFF0000 +#define AR_PHY_BB_PANIC_NON_IDLE_MASK   0x0000FFFC + +#define AR_PHY_BB_PANIC_RST_ENABLE      0x00000002 +#define AR_PHY_BB_PANIC_IRQ_ENABLE      0x00000004 +#define AR_PHY_BB_PANIC_CNTL2_MASK      0xFFFFFFF9 + +#define AR_PHY_BB_WD_STATUS             0x00000007 +#define AR_PHY_BB_WD_STATUS_S           0 +#define AR_PHY_BB_WD_DET_HANG           0x00000008 +#define AR_PHY_BB_WD_DET_HANG_S         3 +#define AR_PHY_BB_WD_RADAR_SM           0x000000F0 +#define AR_PHY_BB_WD_RADAR_SM_S         4 +#define AR_PHY_BB_WD_RX_OFDM_SM         0x00000F00 +#define AR_PHY_BB_WD_RX_OFDM_SM_S       8 +#define AR_PHY_BB_WD_RX_CCK_SM          0x0000F000 +#define AR_PHY_BB_WD_RX_CCK_SM_S        12 +#define AR_PHY_BB_WD_TX_OFDM_SM         0x000F0000 +#define AR_PHY_BB_WD_TX_OFDM_SM_S       16 +#define AR_PHY_BB_WD_TX_CCK_SM          0x00F00000 +#define AR_PHY_BB_WD_TX_CCK_SM_S        20 +#define AR_PHY_BB_WD_AGC_SM             0x0F000000 +#define AR_PHY_BB_WD_AGC_SM_S           24 +#define AR_PHY_BB_WD_SRCH_SM            0xF0000000 +#define AR_PHY_BB_WD_SRCH_SM_S          28 + +#define AR_PHY_BB_WD_STATUS_CLR         0x00000008 + +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); + +#endif  /* AR9003_PHY_H */ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bdcd257ca7a..fbb7dec6dde 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -114,8 +114,10 @@ enum buffer_type {  #define bf_isretried(bf)	(bf->bf_state.bf_type & BUF_RETRY)  #define bf_isxretried(bf)	(bf->bf_state.bf_type & BUF_XRETRY) +#define ATH_TXSTATUS_RING_SIZE 64 +  struct ath_descdma { -	struct ath_desc *dd_desc; +	void *dd_desc;  	dma_addr_t dd_desc_paddr;  	u32 dd_desc_len;  	struct ath_buf *dd_bufptr; @@ -123,7 +125,7 @@ struct ath_descdma {  int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  		      struct list_head *head, const char *name, -		      int nbuf, int ndesc); +		      int nbuf, int ndesc, bool is_tx);  void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,  			 struct list_head *head); @@ -188,6 +190,7 @@ enum ATH_AGGR_STATUS {  	ATH_AGGR_LIMITED,  }; +#define ATH_TXFIFO_DEPTH 8  struct ath_txq {  	u32 axq_qnum;  	u32 *axq_link; @@ -197,6 +200,10 @@ struct ath_txq {  	bool stopped;  	bool axq_tx_inprogress;  	struct list_head axq_acq; +	struct list_head txq_fifo[ATH_TXFIFO_DEPTH]; +	struct list_head txq_fifo_pending; +	u8 txq_headidx; +	u8 txq_tailidx;  };  #define AGGR_CLEANUP         BIT(1) @@ -223,6 +230,12 @@ struct ath_tx {  	struct ath_descdma txdma;  }; +struct ath_rx_edma { +	struct sk_buff_head rx_fifo; +	struct sk_buff_head rx_buffers; +	u32 rx_fifo_hwsize; +}; +  struct ath_rx {  	u8 defant;  	u8 rxotherant; @@ -232,6 +245,8 @@ struct ath_rx {  	spinlock_t rxbuflock;  	struct list_head rxbuf;  	struct ath_descdma rxdma; +	struct ath_buf *rx_bufptr; +	struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];  };  int ath_startrecv(struct ath_softc *sc); @@ -240,7 +255,7 @@ void ath_flushrecv(struct ath_softc *sc);  u32 ath_calcrxfilter(struct ath_softc *sc);  int ath_rx_init(struct ath_softc *sc, int nbufs);  void ath_rx_cleanup(struct ath_softc *sc); -int ath_rx_tasklet(struct ath_softc *sc, int flush); +int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);  struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);  void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);  int ath_tx_setup(struct ath_softc *sc, int haltype); @@ -258,6 +273,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum,  int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,  		 struct ath_tx_control *txctl);  void ath_tx_tasklet(struct ath_softc *sc); +void ath_tx_edma_tasklet(struct ath_softc *sc);  void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);  bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);  void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, @@ -507,6 +523,8 @@ struct ath_softc {  	struct ath_beacon_config cur_beacon_conf;  	struct delayed_work tx_complete_work;  	struct ath_btcoex btcoex; + +	struct ath_descdma txsdma;  };  struct ath_wiphy { diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 22375a75471..c8a4558f79b 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -93,8 +93,6 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,  		antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);  	} -	ds->ds_data = bf->bf_buf_addr; -  	sband = &sc->sbands[common->hw->conf.channel->band];  	rate = sband->bitrates[rateidx].hw_value;  	if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) @@ -109,7 +107,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,  	/* NB: beacon's BufLen must be a multiple of 4 bytes */  	ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), -			    true, true, ds); +			    true, true, ds, bf->bf_buf_addr, +			    sc->beacon.beaconq);  	memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);  	series[0].Tries = 1; diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 064f5b51dfc..6982577043b 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -15,10 +15,12 @@   */  #include "hw.h" +#include "hw-ops.h" + +/* Common calibration code */  /* We can tune this as we go by monitoring really low values */  #define ATH9K_NF_TOO_LOW	-60 -#define AR9285_CLCAL_REDO_THRESH    1  /* AR5416 may return very high value (like -31 dBm), in those cases the nf   * is incorrect and we should use the static NF value. Later we can try to @@ -87,98 +89,9 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,  	return;  } -static void ath9k_hw_do_getnf(struct ath_hw *ah, -			      int16_t nfarray[NUM_NF_READINGS]) -{ -	struct ath_common *common = ath9k_hw_common(ah); -	int16_t nf; - -	if (AR_SREV_9280_10_OR_LATER(ah)) -		nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); -	else -		nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); - -	if (nf & 0x100) -		nf = 0 - ((nf ^ 0x1ff) + 1); -	ath_print(common, ATH_DBG_CALIBRATE, -		  "NF calibrated [ctl] [chain 0] is %d\n", nf); - -	if (AR_SREV_9271(ah) && (nf >= -114)) -		nf = -116; - -	nfarray[0] = nf; - -	if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { -		if (AR_SREV_9280_10_OR_LATER(ah)) -			nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), -					AR9280_PHY_CH1_MINCCA_PWR); -		else -			nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), -					AR_PHY_CH1_MINCCA_PWR); - -		if (nf & 0x100) -			nf = 0 - ((nf ^ 0x1ff) + 1); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "NF calibrated [ctl] [chain 1] is %d\n", nf); -		nfarray[1] = nf; - -		if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { -			nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), -					AR_PHY_CH2_MINCCA_PWR); -			if (nf & 0x100) -				nf = 0 - ((nf ^ 0x1ff) + 1); -			ath_print(common, ATH_DBG_CALIBRATE, -				  "NF calibrated [ctl] [chain 2] is %d\n", nf); -			nfarray[2] = nf; -		} -	} - -	if (AR_SREV_9280_10_OR_LATER(ah)) -		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), -			AR9280_PHY_EXT_MINCCA_PWR); -	else -		nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), -			AR_PHY_EXT_MINCCA_PWR); - -	if (nf & 0x100) -		nf = 0 - ((nf ^ 0x1ff) + 1); -	ath_print(common, ATH_DBG_CALIBRATE, -		  "NF calibrated [ext] [chain 0] is %d\n", nf); - -	if (AR_SREV_9271(ah) && (nf >= -114)) -		nf = -116; - -	nfarray[3] = nf; - -	if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) { -		if (AR_SREV_9280_10_OR_LATER(ah)) -			nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), -					AR9280_PHY_CH1_EXT_MINCCA_PWR); -		else -			nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), -					AR_PHY_CH1_EXT_MINCCA_PWR); - -		if (nf & 0x100) -			nf = 0 - ((nf ^ 0x1ff) + 1); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "NF calibrated [ext] [chain 1] is %d\n", nf); -		nfarray[4] = nf; - -		if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { -			nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), -					AR_PHY_CH2_EXT_MINCCA_PWR); -			if (nf & 0x100) -				nf = 0 - ((nf ^ 0x1ff) + 1); -			ath_print(common, ATH_DBG_CALIBRATE, -				  "NF calibrated [ext] [chain 2] is %d\n", nf); -			nfarray[5] = nf; -		} -	} -} - -static bool getNoiseFloorThresh(struct ath_hw *ah, -				enum ieee80211_band band, -				int16_t *nft) +static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, +				   enum ieee80211_band band, +				   int16_t *nft)  {  	switch (band) {  	case IEEE80211_BAND_5GHZ: @@ -195,44 +108,8 @@ static bool getNoiseFloorThresh(struct ath_hw *ah,  	return true;  } -static void ath9k_hw_setup_calibration(struct ath_hw *ah, -				       struct ath9k_cal_list *currCal) -{ -	struct ath_common *common = ath9k_hw_common(ah); - -	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), -		      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, -		      currCal->calData->calCountMax); - -	switch (currCal->calData->calType) { -	case IQ_MISMATCH_CAL: -		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "starting IQ Mismatch Calibration\n"); -		break; -	case ADC_GAIN_CAL: -		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "starting ADC Gain Calibration\n"); -		break; -	case ADC_DC_CAL: -		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "starting ADC DC Calibration\n"); -		break; -	case ADC_DC_INIT_CAL: -		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "starting Init ADC DC Calibration\n"); -		break; -	} - -	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), -		    AR_PHY_TIMING_CTRL4_DO_CAL); -} - -static void ath9k_hw_reset_calibration(struct ath_hw *ah, -				       struct ath9k_cal_list *currCal) +void ath9k_hw_reset_calibration(struct ath_hw *ah, +				struct ath9k_cal_list *currCal)  {  	int i; @@ -250,324 +127,6 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah,  	ah->cal_samples = 0;  } -static bool ath9k_hw_per_calibration(struct ath_hw *ah, -				     struct ath9k_channel *ichan, -				     u8 rxchainmask, -				     struct ath9k_cal_list *currCal) -{ -	bool iscaldone = false; - -	if (currCal->calState == CAL_RUNNING) { -		if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & -		      AR_PHY_TIMING_CTRL4_DO_CAL)) { - -			currCal->calData->calCollect(ah); -			ah->cal_samples++; - -			if (ah->cal_samples >= currCal->calData->calNumSamples) { -				int i, numChains = 0; -				for (i = 0; i < AR5416_MAX_CHAINS; i++) { -					if (rxchainmask & (1 << i)) -						numChains++; -				} - -				currCal->calData->calPostProc(ah, numChains); -				ichan->CalValid |= currCal->calData->calType; -				currCal->calState = CAL_DONE; -				iscaldone = true; -			} else { -				ath9k_hw_setup_calibration(ah, currCal); -			} -		} -	} else if (!(ichan->CalValid & currCal->calData->calType)) { -		ath9k_hw_reset_calibration(ah, currCal); -	} - -	return iscaldone; -} - -/* Assumes you are talking about the currently configured channel */ -static bool ath9k_hw_iscal_supported(struct ath_hw *ah, -				     enum ath9k_cal_types calType) -{ -	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; - -	switch (calType & ah->supp_cals) { -	case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ -		return true; -	case ADC_GAIN_CAL: -	case ADC_DC_CAL: -		if (!(conf->channel->band == IEEE80211_BAND_2GHZ && -		      conf_is_ht20(conf))) -			return true; -		break; -	} -	return false; -} - -static void ath9k_hw_iqcal_collect(struct ath_hw *ah) -{ -	int i; - -	for (i = 0; i < AR5416_MAX_CHAINS; i++) { -		ah->totalPowerMeasI[i] += -			REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); -		ah->totalPowerMeasQ[i] += -			REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); -		ah->totalIqCorrMeas[i] += -			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); -		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, -			  "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", -			  ah->cal_samples, i, ah->totalPowerMeasI[i], -			  ah->totalPowerMeasQ[i], -			  ah->totalIqCorrMeas[i]); -	} -} - -static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah) -{ -	int i; - -	for (i = 0; i < AR5416_MAX_CHAINS; i++) { -		ah->totalAdcIOddPhase[i] += -			REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); -		ah->totalAdcIEvenPhase[i] += -			REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); -		ah->totalAdcQOddPhase[i] += -			REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); -		ah->totalAdcQEvenPhase[i] += -			REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - -		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, -			  "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " -			  "oddq=0x%08x; evenq=0x%08x;\n", -			  ah->cal_samples, i, -			  ah->totalAdcIOddPhase[i], -			  ah->totalAdcIEvenPhase[i], -			  ah->totalAdcQOddPhase[i], -			  ah->totalAdcQEvenPhase[i]); -	} -} - -static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah) -{ -	int i; - -	for (i = 0; i < AR5416_MAX_CHAINS; i++) { -		ah->totalAdcDcOffsetIOddPhase[i] += -			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); -		ah->totalAdcDcOffsetIEvenPhase[i] += -			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); -		ah->totalAdcDcOffsetQOddPhase[i] += -			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); -		ah->totalAdcDcOffsetQEvenPhase[i] += -			(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - -		ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, -			  "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " -			  "oddq=0x%08x; evenq=0x%08x;\n", -			  ah->cal_samples, i, -			  ah->totalAdcDcOffsetIOddPhase[i], -			  ah->totalAdcDcOffsetIEvenPhase[i], -			  ah->totalAdcDcOffsetQOddPhase[i], -			  ah->totalAdcDcOffsetQEvenPhase[i]); -	} -} - -static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) -{ -	struct ath_common *common = ath9k_hw_common(ah); -	u32 powerMeasQ, powerMeasI, iqCorrMeas; -	u32 qCoffDenom, iCoffDenom; -	int32_t qCoff, iCoff; -	int iqCorrNeg, i; - -	for (i = 0; i < numChains; i++) { -		powerMeasI = ah->totalPowerMeasI[i]; -		powerMeasQ = ah->totalPowerMeasQ[i]; -		iqCorrMeas = ah->totalIqCorrMeas[i]; - -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Starting IQ Cal and Correction for Chain %d\n", -			  i); - -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Orignal: Chn %diq_corr_meas = 0x%08x\n", -			  i, ah->totalIqCorrMeas[i]); - -		iqCorrNeg = 0; - -		if (iqCorrMeas > 0x80000000) { -			iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; -			iqCorrNeg = 1; -		} - -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); -		ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", -			  iqCorrNeg); - -		iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; -		qCoffDenom = powerMeasQ / 64; - -		if ((powerMeasQ != 0) && (iCoffDenom != 0) && -		    (qCoffDenom != 0)) { -			iCoff = iqCorrMeas / iCoffDenom; -			qCoff = powerMeasI / qCoffDenom - 64; -			ath_print(common, ATH_DBG_CALIBRATE, -				  "Chn %d iCoff = 0x%08x\n", i, iCoff); -			ath_print(common, ATH_DBG_CALIBRATE, -				  "Chn %d qCoff = 0x%08x\n", i, qCoff); - -			iCoff = iCoff & 0x3f; -			ath_print(common, ATH_DBG_CALIBRATE, -				  "New: Chn %d iCoff = 0x%08x\n", i, iCoff); -			if (iqCorrNeg == 0x0) -				iCoff = 0x40 - iCoff; - -			if (qCoff > 15) -				qCoff = 15; -			else if (qCoff <= -16) -				qCoff = 16; - -			ath_print(common, ATH_DBG_CALIBRATE, -				  "Chn %d : iCoff = 0x%x  qCoff = 0x%x\n", -				  i, iCoff, qCoff); - -			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), -				      AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, -				      iCoff); -			REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), -				      AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, -				      qCoff); -			ath_print(common, ATH_DBG_CALIBRATE, -				  "IQ Cal and Correction done for Chain %d\n", -				  i); -		} -	} - -	REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), -		    AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); -} - -static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) -{ -	struct ath_common *common = ath9k_hw_common(ah); -	u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; -	u32 qGainMismatch, iGainMismatch, val, i; - -	for (i = 0; i < numChains; i++) { -		iOddMeasOffset = ah->totalAdcIOddPhase[i]; -		iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; -		qOddMeasOffset = ah->totalAdcQOddPhase[i]; -		qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; - -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Starting ADC Gain Cal for Chain %d\n", i); - -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d pwr_meas_odd_i = 0x%08x\n", i, -			  iOddMeasOffset); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d pwr_meas_even_i = 0x%08x\n", i, -			  iEvenMeasOffset); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d pwr_meas_odd_q = 0x%08x\n", i, -			  qOddMeasOffset); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d pwr_meas_even_q = 0x%08x\n", i, -			  qEvenMeasOffset); - -		if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { -			iGainMismatch = -				((iEvenMeasOffset * 32) / -				 iOddMeasOffset) & 0x3f; -			qGainMismatch = -				((qOddMeasOffset * 32) / -				 qEvenMeasOffset) & 0x3f; - -			ath_print(common, ATH_DBG_CALIBRATE, -				  "Chn %d gain_mismatch_i = 0x%08x\n", i, -				  iGainMismatch); -			ath_print(common, ATH_DBG_CALIBRATE, -				  "Chn %d gain_mismatch_q = 0x%08x\n", i, -				  qGainMismatch); - -			val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); -			val &= 0xfffff000; -			val |= (qGainMismatch) | (iGainMismatch << 6); -			REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - -			ath_print(common, ATH_DBG_CALIBRATE, -				  "ADC Gain Cal done for Chain %d\n", i); -		} -	} - -	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), -		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | -		  AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); -} - -static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) -{ -	struct ath_common *common = ath9k_hw_common(ah); -	u32 iOddMeasOffset, iEvenMeasOffset, val, i; -	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; -	const struct ath9k_percal_data *calData = -		ah->cal_list_curr->calData; -	u32 numSamples = -		(1 << (calData->calCountMax + 5)) * calData->calNumSamples; - -	for (i = 0; i < numChains; i++) { -		iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; -		iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; -		qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; -		qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; - -		ath_print(common, ATH_DBG_CALIBRATE, -			   "Starting ADC DC Offset Cal for Chain %d\n", i); - -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d pwr_meas_odd_i = %d\n", i, -			  iOddMeasOffset); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d pwr_meas_even_i = %d\n", i, -			  iEvenMeasOffset); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d pwr_meas_odd_q = %d\n", i, -			  qOddMeasOffset); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d pwr_meas_even_q = %d\n", i, -			  qEvenMeasOffset); - -		iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / -			       numSamples) & 0x1ff; -		qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / -			       numSamples) & 0x1ff; - -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, -			  iDcMismatch); -		ath_print(common, ATH_DBG_CALIBRATE, -			  "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, -			  qDcMismatch); - -		val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); -		val &= 0xc0000fff; -		val |= (qDcMismatch << 12) | (iDcMismatch << 21); -		REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - -		ath_print(common, ATH_DBG_CALIBRATE, -			  "ADC DC Offset Cal done for Chain %d\n", i); -	} - -	REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), -		  REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | -		  AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); -} -  /* This is done for the currently configured channel */  bool ath9k_hw_reset_calvalid(struct ath_hw *ah)  { @@ -614,72 +173,6 @@ void ath9k_hw_start_nfcal(struct ath_hw *ah)  	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);  } -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) -{ -	struct ath9k_nfcal_hist *h; -	int i, j; -	int32_t val; -	const u32 ar5416_cca_regs[6] = { -		AR_PHY_CCA, -		AR_PHY_CH1_CCA, -		AR_PHY_CH2_CCA, -		AR_PHY_EXT_CCA, -		AR_PHY_CH1_EXT_CCA, -		AR_PHY_CH2_EXT_CCA -	}; -	u8 chainmask, rx_chain_status; - -	rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); -	if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) -		chainmask = 0x9; -	else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { -		if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) -			chainmask = 0x1B; -		else -			chainmask = 0x09; -	} else { -		if (rx_chain_status & 0x4) -			chainmask = 0x3F; -		else if (rx_chain_status & 0x2) -			chainmask = 0x1B; -		else -			chainmask = 0x09; -	} - -	h = ah->nfCalHist; - -	for (i = 0; i < NUM_NF_READINGS; i++) { -		if (chainmask & (1 << i)) { -			val = REG_READ(ah, ar5416_cca_regs[i]); -			val &= 0xFFFFFE00; -			val |= (((u32) (h[i].privNF) << 1) & 0x1ff); -			REG_WRITE(ah, ar5416_cca_regs[i], val); -		} -	} - -	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, -		    AR_PHY_AGC_CONTROL_ENABLE_NF); -	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, -		    AR_PHY_AGC_CONTROL_NO_UPDATE_NF); -	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); - -	for (j = 0; j < 5; j++) { -		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & -		     AR_PHY_AGC_CONTROL_NF) == 0) -			break; -		udelay(50); -	} - -	for (i = 0; i < NUM_NF_READINGS; i++) { -		if (chainmask & (1 << i)) { -			val = REG_READ(ah, ar5416_cca_regs[i]); -			val &= 0xFFFFFE00; -			val |= (((u32) (-50) << 1) & 0x1ff); -			REG_WRITE(ah, ar5416_cca_regs[i], val); -		} -	} -} -  int16_t ath9k_hw_getnf(struct ath_hw *ah,  		       struct ath9k_channel *chan)  { @@ -699,7 +192,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,  	} else {  		ath9k_hw_do_getnf(ah, nfarray);  		nf = nfarray[0]; -		if (getNoiseFloorThresh(ah, c->band, &nfThresh) +		if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)  		    && nf > nfThresh) {  			ath_print(common, ATH_DBG_CALIBRATE,  				  "noise floor failed detected; " @@ -757,567 +250,3 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)  	return nf;  }  EXPORT_SYMBOL(ath9k_hw_getchan_noise); - -static void ath9k_olc_temp_compensation_9287(struct ath_hw *ah) -{ -	u32 rddata; -	int32_t delta, currPDADC, slope; - -	rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); -	currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); - -	if (ah->initPDADC == 0 || currPDADC == 0) { -		/* -		 * Zero value indicates that no frames have been transmitted yet, -		 * can't do temperature compensation until frames are transmitted. -		 */ -		return; -	} else { -		slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); - -		if (slope == 0) { /* to avoid divide by zero case */ -			delta = 0; -		} else { -			delta = ((currPDADC - ah->initPDADC)*4) / slope; -		} -		REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, -			      AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); -		REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, -			      AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); -	} -} - -static void ath9k_olc_temp_compensation(struct ath_hw *ah) -{ -	u32 rddata, i; -	int delta, currPDADC, regval; - -	if (OLC_FOR_AR9287_10_LATER) { -		ath9k_olc_temp_compensation_9287(ah); -	} else { -		rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); -		currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); - -		if (ah->initPDADC == 0 || currPDADC == 0) { -			return; -		} else { -			if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) -				delta = (currPDADC - ah->initPDADC + 4) / 8; -			else -				delta = (currPDADC - ah->initPDADC + 5) / 10; - -			if (delta != ah->PDADCdelta) { -				ah->PDADCdelta = delta; -				for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { -					regval = ah->originalGain[i] - delta; -					if (regval < 0) -						regval = 0; - -					REG_RMW_FIELD(ah, -						      AR_PHY_TX_GAIN_TBL1 + i * 4, -						      AR_PHY_TX_GAIN, regval); -				} -			} -		} -	} -} - -static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset) -{ -	u32 regVal; -	unsigned int i; -	u32 regList [][2] = { -		{ 0x786c, 0 }, -		{ 0x7854, 0 }, -		{ 0x7820, 0 }, -		{ 0x7824, 0 }, -		{ 0x7868, 0 }, -		{ 0x783c, 0 }, -		{ 0x7838, 0 } , -		{ 0x7828, 0 } , -	}; - -	for (i = 0; i < ARRAY_SIZE(regList); i++) -		regList[i][1] = REG_READ(ah, regList[i][0]); - -	regVal = REG_READ(ah, 0x7834); -	regVal &= (~(0x1)); -	REG_WRITE(ah, 0x7834, regVal); -	regVal = REG_READ(ah, 0x9808); -	regVal |= (0x1 << 27); -	REG_WRITE(ah, 0x9808, regVal); - -	/* 786c,b23,1, pwddac=1 */ -	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); -	/* 7854, b5,1, pdrxtxbb=1 */ -	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); -	/* 7854, b7,1, pdv2i=1 */ -	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); -	/* 7854, b8,1, pddacinterface=1 */ -	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); -	/* 7824,b12,0, offcal=0 */ -	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); -	/* 7838, b1,0, pwddb=0 */ -	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); -	/* 7820,b11,0, enpacal=0 */ -	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); -	/* 7820,b25,1, pdpadrv1=0 */ -	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); -	/* 7820,b24,0, pdpadrv2=0 */ -	REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0); -	/* 7820,b23,0, pdpaout=0 */ -	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); -	/* 783c,b14-16,7, padrvgn2tab_0=7 */ -	REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7); -	/* -	 * 7838,b29-31,0, padrvgn1tab_0=0 -	 * does not matter since we turn it off -	 */ -	REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0); - -	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); - -	/* Set: -	 * localmode=1,bmode=1,bmoderxtx=1,synthon=1, -	 * txon=1,paon=1,oscon=1,synthon_force=1 -	 */ -	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); -	udelay(30); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); - -	/* find off_6_1; */ -	for (i = 6; i > 0; i--) { -		regVal = REG_READ(ah, 0x7834); -		regVal |= (1 << (20 + i)); -		REG_WRITE(ah, 0x7834, regVal); -		udelay(1); -		//regVal = REG_READ(ah, 0x7834); -		regVal &= (~(0x1 << (20 + i))); -		regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) -			    << (20 + i)); -		REG_WRITE(ah, 0x7834, regVal); -	} - -	regVal = (regVal >>20) & 0x7f; - -	/* Update PA cal info */ -	if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) { -		if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) -			ah->pacal_info.max_skipcount = -				2 * ah->pacal_info.max_skipcount; -		ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; -	} else { -		ah->pacal_info.max_skipcount = 1; -		ah->pacal_info.skipcount = 0; -		ah->pacal_info.prev_offset = regVal; -	} - -	regVal = REG_READ(ah, 0x7834); -	regVal |= 0x1; -	REG_WRITE(ah, 0x7834, regVal); -	regVal = REG_READ(ah, 0x9808); -	regVal &= (~(0x1 << 27)); -	REG_WRITE(ah, 0x9808, regVal); - -	for (i = 0; i < ARRAY_SIZE(regList); i++) -		REG_WRITE(ah, regList[i][0], regList[i][1]); -} - -static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) -{ -	struct ath_common *common = ath9k_hw_common(ah); -	u32 regVal; -	int i, offset, offs_6_1, offs_0; -	u32 ccomp_org, reg_field; -	u32 regList[][2] = { -		{ 0x786c, 0 }, -		{ 0x7854, 0 }, -		{ 0x7820, 0 }, -		{ 0x7824, 0 }, -		{ 0x7868, 0 }, -		{ 0x783c, 0 }, -		{ 0x7838, 0 }, -	}; - -	ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); - -	/* PA CAL is not needed for high power solution */ -	if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == -	    AR5416_EEP_TXGAIN_HIGH_POWER) -		return; - -	if (AR_SREV_9285_11(ah)) { -		REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); -		udelay(10); -	} - -	for (i = 0; i < ARRAY_SIZE(regList); i++) -		regList[i][1] = REG_READ(ah, regList[i][0]); - -	regVal = REG_READ(ah, 0x7834); -	regVal &= (~(0x1)); -	REG_WRITE(ah, 0x7834, regVal); -	regVal = REG_READ(ah, 0x9808); -	regVal |= (0x1 << 27); -	REG_WRITE(ah, 0x9808, regVal); - -	REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); -	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); -	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); -	REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); -	ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); - -	REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); -	udelay(30); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); - -	for (i = 6; i > 0; i--) { -		regVal = REG_READ(ah, 0x7834); -		regVal |= (1 << (19 + i)); -		REG_WRITE(ah, 0x7834, regVal); -		udelay(1); -		regVal = REG_READ(ah, 0x7834); -		regVal &= (~(0x1 << (19 + i))); -		reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); -		regVal |= (reg_field << (19 + i)); -		REG_WRITE(ah, 0x7834, regVal); -	} - -	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); -	udelay(1); -	reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); -	offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); -	offs_0   = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); - -	offset = (offs_6_1<<1) | offs_0; -	offset = offset - 0; -	offs_6_1 = offset>>1; -	offs_0 = offset & 1; - -	if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) { -		if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) -			ah->pacal_info.max_skipcount = -				2 * ah->pacal_info.max_skipcount; -		ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; -	} else { -		ah->pacal_info.max_skipcount = 1; -		ah->pacal_info.skipcount = 0; -		ah->pacal_info.prev_offset = offset; -	} - -	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); -	REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); - -	regVal = REG_READ(ah, 0x7834); -	regVal |= 0x1; -	REG_WRITE(ah, 0x7834, regVal); -	regVal = REG_READ(ah, 0x9808); -	regVal &= (~(0x1 << 27)); -	REG_WRITE(ah, 0x9808, regVal); - -	for (i = 0; i < ARRAY_SIZE(regList); i++) -		REG_WRITE(ah, regList[i][0], regList[i][1]); - -	REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); - -	if (AR_SREV_9285_11(ah)) -		REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); - -} - -bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, -			u8 rxchainmask, bool longcal) -{ -	bool iscaldone = true; -	struct ath9k_cal_list *currCal = ah->cal_list_curr; - -	if (currCal && -	    (currCal->calState == CAL_RUNNING || -	     currCal->calState == CAL_WAITING)) { -		iscaldone = ath9k_hw_per_calibration(ah, chan, -						     rxchainmask, currCal); -		if (iscaldone) { -			ah->cal_list_curr = currCal = currCal->calNext; - -			if (currCal->calState == CAL_WAITING) { -				iscaldone = false; -				ath9k_hw_reset_calibration(ah, currCal); -			} -		} -	} - -	/* Do NF cal only at longer intervals */ -	if (longcal) { -		/* Do periodic PAOffset Cal */ -		if (AR_SREV_9271(ah)) { -			if (!ah->pacal_info.skipcount) -				ath9k_hw_9271_pa_cal(ah, false); -			else -				ah->pacal_info.skipcount--; -		} else if (AR_SREV_9285_11_OR_LATER(ah)) { -			if (!ah->pacal_info.skipcount) -				ath9k_hw_9285_pa_cal(ah, false); -			else -				ah->pacal_info.skipcount--; -		} - -		if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) -			ath9k_olc_temp_compensation(ah); - -		/* Get the value from the previous NF cal and update history buffer */ -		ath9k_hw_getnf(ah, chan); - -		/* -		 * Load the NF from history buffer of the current channel. -		 * NF is slow time-variant, so it is OK to use a historical value. -		 */ -		ath9k_hw_loadnf(ah, ah->curchan); - -		ath9k_hw_start_nfcal(ah); -	} - -	return iscaldone; -} -EXPORT_SYMBOL(ath9k_hw_calibrate); - -/* Carrier leakage Calibration fix */ -static bool ar9285_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) -{ -	struct ath_common *common = ath9k_hw_common(ah); - -	REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); -	if (IS_CHAN_HT20(chan)) { -		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); -		REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); -		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, -			    AR_PHY_AGC_CONTROL_FLTR_CAL); -		REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); -		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); -		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, -				  AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { -			ath_print(common, ATH_DBG_CALIBRATE, "offset " -				  "calibration failed to complete in " -				  "1ms; noisy ??\n"); -			return false; -		} -		REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); -		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); -		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); -	} -	REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); -	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); -	REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); -	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); -	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, -			  0, AH_WAIT_TIMEOUT)) { -		ath_print(common, ATH_DBG_CALIBRATE, "offset calibration " -			  "failed to complete in 1ms; noisy ??\n"); -		return false; -	} - -	REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); -	REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); -	REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - -	return true; -} - -static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) -{ -	int i; -	u_int32_t txgain_max; -	u_int32_t clc_gain, gain_mask = 0, clc_num = 0; -	u_int32_t reg_clc_I0, reg_clc_Q0; -	u_int32_t i0_num = 0; -	u_int32_t q0_num = 0; -	u_int32_t total_num = 0; -	u_int32_t reg_rf2g5_org; -	bool retv = true; - -	if (!(ar9285_cl_cal(ah, chan))) -		return false; - -	txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7), -			AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); - -	for (i = 0; i < (txgain_max+1); i++) { -		clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & -			   AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; -		if (!(gain_mask & (1 << clc_gain))) { -			gain_mask |= (1 << clc_gain); -			clc_num++; -		} -	} - -	for (i = 0; i < clc_num; i++) { -		reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) -			      & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; -		reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) -			      & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; -		if (reg_clc_I0 == 0) -			i0_num++; - -		if (reg_clc_Q0 == 0) -			q0_num++; -	} -	total_num = i0_num + q0_num; -	if (total_num > AR9285_CLCAL_REDO_THRESH) { -		reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5); -		if (AR_SREV_9285E_20(ah)) { -			REG_WRITE(ah, AR9285_RF2G5, -				  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | -				  AR9285_RF2G5_IC50TX_XE_SET); -		} else { -			REG_WRITE(ah, AR9285_RF2G5, -				  (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | -				  AR9285_RF2G5_IC50TX_SET); -		} -		retv = ar9285_cl_cal(ah, chan); -		REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); -	} -	return retv; -} - -bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) -{ -	struct ath_common *common = ath9k_hw_common(ah); - -	if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { -		if (!ar9285_clc(ah, chan)) -			return false; -	} else { -		if (AR_SREV_9280_10_OR_LATER(ah)) { -			if (!AR_SREV_9287_10_OR_LATER(ah)) -				REG_CLR_BIT(ah, AR_PHY_ADC_CTL, -					    AR_PHY_ADC_CTL_OFF_PWDADC); -			REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, -				    AR_PHY_AGC_CONTROL_FLTR_CAL); -		} - -		/* Calibrate the AGC */ -		REG_WRITE(ah, AR_PHY_AGC_CONTROL, -			  REG_READ(ah, AR_PHY_AGC_CONTROL) | -			  AR_PHY_AGC_CONTROL_CAL); - -		/* Poll for offset calibration complete */ -		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, -				   0, AH_WAIT_TIMEOUT)) { -			ath_print(common, ATH_DBG_CALIBRATE, -				  "offset calibration failed to " -				  "complete in 1ms; noisy environment?\n"); -			return false; -		} - -		if (AR_SREV_9280_10_OR_LATER(ah)) { -			if (!AR_SREV_9287_10_OR_LATER(ah)) -				REG_SET_BIT(ah, AR_PHY_ADC_CTL, -					    AR_PHY_ADC_CTL_OFF_PWDADC); -			REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, -				    AR_PHY_AGC_CONTROL_FLTR_CAL); -		} -	} - -	/* Do PA Calibration */ -	if (AR_SREV_9271(ah)) -		ath9k_hw_9271_pa_cal(ah, true); -	else if (AR_SREV_9285_11_OR_LATER(ah)) -		ath9k_hw_9285_pa_cal(ah, true); - -	/* Do NF Calibration after DC offset and other calibrations */ -	REG_WRITE(ah, AR_PHY_AGC_CONTROL, -		  REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); - -	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; - -	/* Enable IQ, ADC Gain and ADC DC offset CALs */ -	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { -		if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { -			INIT_CAL(&ah->adcgain_caldata); -			INSERT_CAL(ah, &ah->adcgain_caldata); -			ath_print(common, ATH_DBG_CALIBRATE, -				  "enabling ADC Gain Calibration.\n"); -		} -		if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { -			INIT_CAL(&ah->adcdc_caldata); -			INSERT_CAL(ah, &ah->adcdc_caldata); -			ath_print(common, ATH_DBG_CALIBRATE, -				  "enabling ADC DC Calibration.\n"); -		} -		if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { -			INIT_CAL(&ah->iq_caldata); -			INSERT_CAL(ah, &ah->iq_caldata); -			ath_print(common, ATH_DBG_CALIBRATE, -				  "enabling IQ Calibration.\n"); -		} - -		ah->cal_list_curr = ah->cal_list; - -		if (ah->cal_list_curr) -			ath9k_hw_reset_calibration(ah, ah->cal_list_curr); -	} - -	chan->CalValid = 0; - -	return true; -} - -const struct ath9k_percal_data iq_cal_multi_sample = { -	IQ_MISMATCH_CAL, -	MAX_CAL_SAMPLES, -	PER_MIN_LOG_COUNT, -	ath9k_hw_iqcal_collect, -	ath9k_hw_iqcalibrate -}; -const struct ath9k_percal_data iq_cal_single_sample = { -	IQ_MISMATCH_CAL, -	MIN_CAL_SAMPLES, -	PER_MAX_LOG_COUNT, -	ath9k_hw_iqcal_collect, -	ath9k_hw_iqcalibrate -}; -const struct ath9k_percal_data adc_gain_cal_multi_sample = { -	ADC_GAIN_CAL, -	MAX_CAL_SAMPLES, -	PER_MIN_LOG_COUNT, -	ath9k_hw_adc_gaincal_collect, -	ath9k_hw_adc_gaincal_calibrate -}; -const struct ath9k_percal_data adc_gain_cal_single_sample = { -	ADC_GAIN_CAL, -	MIN_CAL_SAMPLES, -	PER_MAX_LOG_COUNT, -	ath9k_hw_adc_gaincal_collect, -	ath9k_hw_adc_gaincal_calibrate -}; -const struct ath9k_percal_data adc_dc_cal_multi_sample = { -	ADC_DC_CAL, -	MAX_CAL_SAMPLES, -	PER_MIN_LOG_COUNT, -	ath9k_hw_adc_dccal_collect, -	ath9k_hw_adc_dccal_calibrate -}; -const struct ath9k_percal_data adc_dc_cal_single_sample = { -	ADC_DC_CAL, -	MIN_CAL_SAMPLES, -	PER_MAX_LOG_COUNT, -	ath9k_hw_adc_dccal_collect, -	ath9k_hw_adc_dccal_calibrate -}; -const struct ath9k_percal_data adc_init_dc_cal = { -	ADC_DC_INIT_CAL, -	MIN_CAL_SAMPLES, -	INIT_LOG_COUNT, -	ath9k_hw_adc_dccal_collect, -	ath9k_hw_adc_dccal_calibrate -}; diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index b2c873e9748..24538bdb912 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -19,14 +19,6 @@  #include "hw.h" -extern const struct ath9k_percal_data iq_cal_multi_sample; -extern const struct ath9k_percal_data iq_cal_single_sample; -extern const struct ath9k_percal_data adc_gain_cal_multi_sample; -extern const struct ath9k_percal_data adc_gain_cal_single_sample; -extern const struct ath9k_percal_data adc_dc_cal_multi_sample; -extern const struct ath9k_percal_data adc_dc_cal_single_sample; -extern const struct ath9k_percal_data adc_init_dc_cal; -  #define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE	-85  #define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE	-112  #define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE	-118 @@ -76,7 +68,8 @@ enum ath9k_cal_types {  	ADC_DC_INIT_CAL = 0x1,  	ADC_GAIN_CAL = 0x2,  	ADC_DC_CAL = 0x4, -	IQ_MISMATCH_CAL = 0x8 +	IQ_MISMATCH_CAL = 0x8, +	TEMP_COMP_CAL = 0x10,  };  enum ath9k_cal_state { @@ -122,14 +115,12 @@ struct ath9k_pacal_info{  bool ath9k_hw_reset_calvalid(struct ath_hw *ah);  void ath9k_hw_start_nfcal(struct ath_hw *ah); -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);  int16_t ath9k_hw_getnf(struct ath_hw *ah,  		       struct ath9k_channel *chan);  void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah);  s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); -bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, -			u8 rxchainmask, bool longcal); -bool ath9k_hw_init_cal(struct ath_hw *ah, -		       struct ath9k_channel *chan); +void ath9k_hw_reset_calibration(struct ath_hw *ah, +				struct ath9k_cal_list *currCal); +  #endif /* CALIB_H */ diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 09effdedc8c..b4424a623cf 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -212,7 +212,6 @@ int ath9k_cmn_rx_skb_preprocess(struct ath_common *common,  	rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp);  	rx_status->band = hw->conf.channel->band;  	rx_status->freq = hw->conf.channel->center_freq; -	rx_status->noise = common->ani.noise_floor;  	rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;  	rx_status->antenna = rx_stats->rs_antenna;  	rx_status->flag |= RX_FLAG_TSFT; diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 72a835d9e97..e08f7e5a26e 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -20,6 +20,7 @@  #include "../debug.h"  #include "hw.h" +#include "hw-ops.h"  /* Common header for Atheros 802.11n base driver cores */ @@ -76,11 +77,12 @@ struct ath_buf {  					   an aggregate) */  	struct ath_buf *bf_next;	/* next subframe in the aggregate */  	struct sk_buff *bf_mpdu;	/* enclosing frame structure */ -	struct ath_desc *bf_desc;	/* virtual addr of desc */ +	void *bf_desc;			/* virtual addr of desc */  	dma_addr_t bf_daddr;		/* physical addr of desc */  	dma_addr_t bf_buf_addr;		/* physical addr of data buffer */  	bool bf_stale;  	bool bf_isnullfunc; +	bool bf_tx_aborted;  	u16 bf_flags;  	struct ath_buf_state bf_state;  	dma_addr_t bf_dmacontext; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 9a8e419398f..64e30cd45d0 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -180,8 +180,15 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)  {  	if (status)  		sc->debug.stats.istats.total++; -	if (status & ATH9K_INT_RX) -		sc->debug.stats.istats.rxok++; +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +		if (status & ATH9K_INT_RXLP) +			sc->debug.stats.istats.rxlp++; +		if (status & ATH9K_INT_RXHP) +			sc->debug.stats.istats.rxhp++; +	} else { +		if (status & ATH9K_INT_RX) +			sc->debug.stats.istats.rxok++; +	}  	if (status & ATH9K_INT_RXEOL)  		sc->debug.stats.istats.rxeol++;  	if (status & ATH9K_INT_RXORN) @@ -223,8 +230,15 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,  	char buf[512];  	unsigned int len = 0; -	len += snprintf(buf + len, sizeof(buf) - len, -		"%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +		len += snprintf(buf + len, sizeof(buf) - len, +			"%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp); +		len += snprintf(buf + len, sizeof(buf) - len, +			"%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp); +	} else { +		len += snprintf(buf + len, sizeof(buf) - len, +			"%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); +	}  	len += snprintf(buf + len, sizeof(buf) - len,  		"%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);  	len += snprintf(buf + len, sizeof(buf) - len, diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index b2af9de755e..c545960e7ec 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -35,6 +35,8 @@ struct ath_buf;   * struct ath_interrupt_stats - Contains statistics about interrupts   * @total: Total no. of interrupts generated so far   * @rxok: RX with no errors + * @rxlp: RX with low priority RX + * @rxhp: RX with high priority, uapsd only   * @rxeol: RX with no more RXDESC available   * @rxorn: RX FIFO overrun   * @txok: TX completed at the requested rate @@ -55,6 +57,8 @@ struct ath_buf;  struct ath_interrupt_stats {  	u32 total;  	u32 rxok; +	u32 rxlp; +	u32 rxhp;  	u32 rxeol;  	u32 rxorn;  	u32 txok; diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index dacaae93414..bd9dff3293d 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c @@ -256,14 +256,13 @@ int ath9k_hw_eeprom_init(struct ath_hw *ah)  {  	int status; -	if (AR_SREV_9287(ah)) { -		ah->eep_map = EEP_MAP_AR9287; -		ah->eep_ops = &eep_AR9287_ops; +	if (AR_SREV_9300_20_OR_LATER(ah)) +		ah->eep_ops = &eep_ar9300_ops; +	else if (AR_SREV_9287(ah)) { +		ah->eep_ops = &eep_ar9287_ops;  	} else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { -		ah->eep_map = EEP_MAP_4KBITS;  		ah->eep_ops = &eep_4k_ops;  	} else { -		ah->eep_map = EEP_MAP_DEFAULT;  		ah->eep_ops = &eep_def_ops;  	} diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 2f2993b50e2..21354c15a9a 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -19,6 +19,7 @@  #include "../ath.h"  #include <net/cfg80211.h> +#include "ar9003_eeprom.h"  #define AH_USE_EEPROM   0x1 @@ -93,7 +94,6 @@   */  #define AR9285_RDEXT_DEFAULT    0x1F -#define AR_EEPROM_MAC(i)	(0x1d+(i))  #define ATH9K_POW_SM(_r, _s)	(((_r) & 0x3f) << (_s))  #define FREQ2FBIN(x, y)		((y) ? ((x) - 2300) : (((x) - 4800) / 5))  #define ath9k_hw_use_flash(_ah)	(!(_ah->ah_flags & AH_USE_EEPROM)) @@ -155,6 +155,7 @@  #define AR5416_BCHAN_UNUSED             0xFF  #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64  #define AR5416_MAX_CHAINS               3 +#define AR9300_MAX_CHAINS		3  #define AR5416_PWR_TABLE_OFFSET_DB     -5  /* Rx gain type values */ @@ -249,16 +250,20 @@ enum eeprom_param {  	EEP_MINOR_REV,  	EEP_TX_MASK,  	EEP_RX_MASK, +	EEP_FSTCLK_5G,  	EEP_RXGAIN_TYPE, -	EEP_TXGAIN_TYPE,  	EEP_OL_PWRCTRL, +	EEP_TXGAIN_TYPE,  	EEP_RC_CHAIN_MASK,  	EEP_DAC_HPWR_5G,  	EEP_FRAC_N_5G,  	EEP_DEV_TYPE,  	EEP_TEMPSENSE_SLOPE,  	EEP_TEMPSENSE_SLOPE_PAL_ON, -	EEP_PWR_TABLE_OFFSET +	EEP_PWR_TABLE_OFFSET, +	EEP_DRIVE_STRENGTH, +	EEP_INTERNAL_REGULATOR, +	EEP_SWREG  };  enum ar5416_rates { @@ -295,7 +300,8 @@ struct base_eep_header {  	u32 binBuildNumber;  	u8 deviceType;  	u8 pwdclkind; -	u8 futureBase_1[2]; +	u8 fastClk5g; +	u8 divChain;  	u8 rxGainType;  	u8 dacHiPwrMode_5G;  	u8 openLoopPwrCntl; @@ -656,13 +662,6 @@ struct ath9k_country_entry {  	u8 iso[3];  }; -enum ath9k_eep_map { -	EEP_MAP_DEFAULT = 0x0, -	EEP_MAP_4KBITS, -	EEP_MAP_AR9287, -	EEP_MAP_MAX -}; -  struct eeprom_ops {  	int (*check_eeprom)(struct ath_hw *hw);  	u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param); @@ -713,6 +712,8 @@ int ath9k_hw_eeprom_init(struct ath_hw *ah);  extern const struct eeprom_ops eep_def_ops;  extern const struct eeprom_ops eep_4k_ops; -extern const struct eeprom_ops eep_AR9287_ops; +extern const struct eeprom_ops eep_ar9287_ops; +extern const struct eeprom_ops eep_ar9287_ops; +extern const struct eeprom_ops eep_ar9300_ops;  #endif /* EEPROM_H */ diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 0354fe50f8e..41a77d1bd43 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -15,6 +15,7 @@   */  #include "hw.h" +#include "ar9002_phy.h"  static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)  { @@ -182,11 +183,11 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,  	switch (param) {  	case EEP_NFTHRESH_2:  		return pModal->noiseFloorThreshCh[0]; -	case AR_EEPROM_MAC(0): +	case EEP_MAC_LSW:  		return pBase->macAddr[0] << 8 | pBase->macAddr[1]; -	case AR_EEPROM_MAC(1): +	case EEP_MAC_MID:  		return pBase->macAddr[2] << 8 | pBase->macAddr[3]; -	case AR_EEPROM_MAC(2): +	case EEP_MAC_MSW:  		return pBase->macAddr[4] << 8 | pBase->macAddr[5];  	case EEP_REG_0:  		return pBase->regDmn[0]; @@ -453,6 +454,8 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,  					    &tMinCalPower, gainBoundaries,  					    pdadcValues, numXpdGain); +			ENABLE_REGWRITE_BUFFER(ah); +  			if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {  				REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,  					  SM(pdGainOverlap_t2, @@ -493,6 +496,9 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,  				regOffset += 4;  			} + +			REGWRITE_BUFFER_FLUSH(ah); +			DISABLE_REGWRITE_BUFFER(ah);  		}  	} @@ -758,6 +764,8 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,  			ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;  	} +	ENABLE_REGWRITE_BUFFER(ah); +  	/* OFDM power per rate */  	REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,  		  ATH9K_POW_SM(ratesArray[rate18mb], 24) @@ -820,6 +828,9 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,  			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)  			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));  	} + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah);  }  static void ath9k_hw_4k_set_addac(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index d8ca94c3fa0..b471db5fb82 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -15,6 +15,7 @@   */  #include "hw.h" +#include "ar9002_phy.h"  static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah)  { @@ -172,11 +173,11 @@ static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah,  	switch (param) {  	case EEP_NFTHRESH_2:  		return pModal->noiseFloorThreshCh[0]; -	case AR_EEPROM_MAC(0): +	case EEP_MAC_LSW:  		return pBase->macAddr[0] << 8 | pBase->macAddr[1]; -	case AR_EEPROM_MAC(1): +	case EEP_MAC_MID:  		return pBase->macAddr[2] << 8 | pBase->macAddr[3]; -	case AR_EEPROM_MAC(2): +	case EEP_MAC_MSW:  		return pBase->macAddr[4] << 8 | pBase->macAddr[5];  	case EEP_REG_0:  		return pBase->regDmn[0]; @@ -1169,7 +1170,7 @@ static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah,  #undef EEP_MAP9287_SPURCHAN  } -const struct eeprom_ops eep_AR9287_ops = { +const struct eeprom_ops eep_ar9287_ops = {  	.check_eeprom		= ath9k_hw_AR9287_check_eeprom,  	.get_eeprom		= ath9k_hw_AR9287_get_eeprom,  	.fill_eeprom		= ath9k_hw_AR9287_fill_eeprom, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 404a0341242..e591ad6016e 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -15,6 +15,7 @@   */  #include "hw.h" +#include "ar9002_phy.h"  static void ath9k_get_txgain_index(struct ath_hw *ah,  		struct ath9k_channel *chan, @@ -222,6 +223,12 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)  		return -EINVAL;  	} +	/* Enable fixup for AR_AN_TOP2 if necessary */ +	if (AR_SREV_9280_10_OR_LATER(ah) && +	    (eep->baseEepHeader.version & 0xff) > 0x0a && +	    eep->baseEepHeader.pwdclkind == 0) +		ah->need_an_top2_fixup = 1; +  	return 0;  } @@ -237,11 +244,11 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,  		return pModal[0].noiseFloorThreshCh[0];  	case EEP_NFTHRESH_2:  		return pModal[1].noiseFloorThreshCh[0]; -	case AR_EEPROM_MAC(0): +	case EEP_MAC_LSW:  		return pBase->macAddr[0] << 8 | pBase->macAddr[1]; -	case AR_EEPROM_MAC(1): +	case EEP_MAC_MID:  		return pBase->macAddr[2] << 8 | pBase->macAddr[3]; -	case AR_EEPROM_MAC(2): +	case EEP_MAC_MSW:  		return pBase->macAddr[4] << 8 | pBase->macAddr[5];  	case EEP_REG_0:  		return pBase->regDmn[0]; @@ -267,6 +274,8 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,  		return pBase->txMask;  	case EEP_RX_MASK:  		return pBase->rxMask; +	case EEP_FSTCLK_5G: +		return pBase->fastClk5g;  	case EEP_RXGAIN_TYPE:  		return pBase->rxGainType;  	case EEP_TXGAIN_TYPE: diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index fe994e22989..74872ca76f9 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -93,14 +93,24 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,  	return ret;  } +static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, +					 struct sk_buff_head *list) +{ +	struct sk_buff *skb; + +	while ((skb = __skb_dequeue(list)) != NULL) { +		dev_kfree_skb_any(skb); +		TX_STAT_INC(skb_dropped); +	} +} +  static void hif_usb_tx_cb(struct urb *urb)  {  	struct tx_buf *tx_buf = (struct tx_buf *) urb->context;  	struct hif_device_usb *hif_dev = tx_buf->hif_dev;  	struct sk_buff *skb; -	bool drop, flush; -	if (!hif_dev) +	if (!hif_dev || !tx_buf)  		return;  	switch (urb->status) { @@ -108,52 +118,47 @@ static void hif_usb_tx_cb(struct urb *urb)  		break;  	case -ENOENT:  	case -ECONNRESET: -		break;  	case -ENODEV:  	case -ESHUTDOWN: +		/* +		 * The URB has been killed, free the SKBs +		 * and return. +		 */ +		ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);  		return;  	default:  		break;  	} -	if (tx_buf) { -		spin_lock(&hif_dev->tx.tx_lock); -		drop = !!(hif_dev->tx.flags & HIF_USB_TX_STOP); -		flush = !!(hif_dev->tx.flags & HIF_USB_TX_FLUSH); +	/* Check if TX has been stopped */ +	spin_lock(&hif_dev->tx.tx_lock); +	if (hif_dev->tx.flags & HIF_USB_TX_STOP) {  		spin_unlock(&hif_dev->tx.tx_lock); +		ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); +		goto add_free; +	} +	spin_unlock(&hif_dev->tx.tx_lock); -		while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { -			if (!drop && !flush) { -				ath9k_htc_txcompletion_cb(hif_dev->htc_handle, -							  skb, 1); -				TX_STAT_INC(skb_completed); -			} else { -				dev_kfree_skb_any(skb); -			} -		} - -		if (flush) -			return; - -		tx_buf->len = tx_buf->offset = 0; -		__skb_queue_head_init(&tx_buf->skb_queue); - -		spin_lock(&hif_dev->tx.tx_lock); -		list_del(&tx_buf->list); -		list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf); -		hif_dev->tx.tx_buf_cnt++; -		if (!drop) -			__hif_usb_tx(hif_dev); /* Check for pending SKBs */ -		TX_STAT_INC(buf_completed); -		spin_unlock(&hif_dev->tx.tx_lock); +	/* Complete the queued SKBs. */ +	while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { +		ath9k_htc_txcompletion_cb(hif_dev->htc_handle, +					  skb, 1); +		TX_STAT_INC(skb_completed);  	} -} -static inline void ath9k_skb_queue_purge(struct sk_buff_head *list) -{ -	struct sk_buff *skb; -	while ((skb = __skb_dequeue(list)) != NULL) -		dev_kfree_skb_any(skb); +add_free: +	/* Re-initialize the SKB queue */ +	tx_buf->len = tx_buf->offset = 0; +	__skb_queue_head_init(&tx_buf->skb_queue); + +	/* Add this TX buffer to the free list */ +	spin_lock(&hif_dev->tx.tx_lock); +	list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); +	hif_dev->tx.tx_buf_cnt++; +	if (!(hif_dev->tx.flags & HIF_USB_TX_STOP)) +		__hif_usb_tx(hif_dev); /* Check for pending SKBs */ +	TX_STAT_INC(buf_completed); +	spin_unlock(&hif_dev->tx.tx_lock);  }  /* TX lock has to be taken */ @@ -173,8 +178,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)  		return 0;  	tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list); -	list_del(&tx_buf->list); -	list_add_tail(&tx_buf->list, &hif_dev->tx.tx_pending); +	list_move_tail(&tx_buf->list, &hif_dev->tx.tx_pending);  	hif_dev->tx.tx_buf_cnt--;  	tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM); @@ -214,7 +218,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)  	ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC);  	if (ret) {  		tx_buf->len = tx_buf->offset = 0; -		ath9k_skb_queue_purge(&tx_buf->skb_queue); +		ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);  		__skb_queue_head_init(&tx_buf->skb_queue);  		list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);  		hif_dev->tx.tx_buf_cnt++; @@ -281,7 +285,7 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id)  	unsigned long flags;  	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); -	ath9k_skb_queue_purge(&hif_dev->tx.tx_skb_queue); +	ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue);  	hif_dev->tx.tx_skb_cnt = 0;  	hif_dev->tx.flags |= HIF_USB_TX_STOP;  	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); @@ -506,9 +510,18 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)  	if (likely(urb->actual_length != 0)) {  		skb_put(skb, urb->actual_length); +		/* Process the command first */ +		ath9k_htc_rx_msg(hif_dev->htc_handle, skb, +				 skb->len, USB_REG_IN_PIPE); + +  		nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); -		if (!nskb) -			goto resubmit; +		if (!nskb) { +			dev_err(&hif_dev->udev->dev, +				"ath9k_htc: REG_IN memory allocation failure\n"); +			urb->context = NULL; +			return; +		}  		usb_fill_int_urb(urb, hif_dev->udev,  				 usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), @@ -518,12 +531,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)  		ret = usb_submit_urb(urb, GFP_ATOMIC);  		if (ret) {  			kfree_skb(nskb); -			goto free; +			urb->context = NULL;  		} -		ath9k_htc_rx_msg(hif_dev->htc_handle, skb, -				 skb->len, USB_REG_IN_PIPE); -  		return;  	} @@ -543,20 +553,17 @@ free:  static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)  { -	unsigned long flags;  	struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; -	list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_buf, list) { +	list_for_each_entry_safe(tx_buf, tx_buf_tmp, +				 &hif_dev->tx.tx_buf, list) { +		usb_kill_urb(tx_buf->urb);  		list_del(&tx_buf->list);  		usb_free_urb(tx_buf->urb);  		kfree(tx_buf->buf);  		kfree(tx_buf);  	} -	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); -	hif_dev->tx.flags |= HIF_USB_TX_FLUSH; -	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); -  	list_for_each_entry_safe(tx_buf, tx_buf_tmp,  				 &hif_dev->tx.tx_pending, list) {  		usb_kill_urb(tx_buf->urb); @@ -565,10 +572,6 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)  		kfree(tx_buf->buf);  		kfree(tx_buf);  	} - -	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); -	hif_dev->tx.flags &= ~HIF_USB_TX_FLUSH; -	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);  }  static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) @@ -892,6 +895,26 @@ err_alloc:  	return ret;  } +static void ath9k_hif_usb_reboot(struct usb_device *udev) +{ +	u32 reboot_cmd = 0xffffffff; +	void *buf; +	int ret; + +	buf = kmalloc(4, GFP_KERNEL); +	if (!buf) +		return; + +	memcpy(buf, &reboot_cmd, 4); + +	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE), +			   buf, 4, NULL, HZ); +	if (ret) +		dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n"); + +	kfree(buf); +} +  static void ath9k_hif_usb_disconnect(struct usb_interface *interface)  {  	struct usb_device *udev = interface_to_usbdev(interface); @@ -899,14 +922,15 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)  		(struct hif_device_usb *) usb_get_intfdata(interface);  	if (hif_dev) { -		ath9k_htc_hw_deinit(hif_dev->htc_handle, true); +		ath9k_htc_hw_deinit(hif_dev->htc_handle, +		    (udev->state == USB_STATE_NOTATTACHED) ? true : false);  		ath9k_htc_hw_free(hif_dev->htc_handle);  		ath9k_hif_usb_dev_deinit(hif_dev);  		usb_set_intfdata(interface, NULL);  	}  	if (hif_dev->flags & HIF_USB_START) -		usb_reset_device(udev); +		ath9k_hif_usb_reboot(udev);  	kfree(hif_dev);  	dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n"); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 7d49a8af420..0aca49b6fcb 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h @@ -61,7 +61,6 @@ struct tx_buf {  };  #define HIF_USB_TX_STOP  BIT(0) -#define HIF_USB_TX_FLUSH BIT(1)  struct hif_usb_tx {  	u8 flags; diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 78213fc71b0..1ae18bbc4d9 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h @@ -124,13 +124,13 @@ struct ath9k_htc_cap_target {  struct ath9k_htc_target_vif {  	u8 index;  	u8 des_bssid[ETH_ALEN]; -	enum htc_opmode opmode; +	__be32 opmode;  	u8 myaddr[ETH_ALEN];  	u8 bssid[ETH_ALEN];  	u32 flags;  	u32 flags_ext;  	u16 ps_sta; -	u16 rtsthreshold; +	__be16 rtsthreshold;  	u8 ath_cap;  	u8 node;  	s8 mcast_rate; @@ -151,7 +151,7 @@ struct ath9k_htc_target_sta {  	u8 sta_index;  	u8 vif_index;  	u8 vif_sta; -	u16 flags; /* ATH_HTC_STA_* */ +	__be16 flags; /* ATH_HTC_STA_* */  	u16 htcap;  	u8 valid;  	u16 capinfo; @@ -191,16 +191,16 @@ struct ath9k_htc_rate {  struct ath9k_htc_target_rate {  	u8 sta_index;  	u8 isnew; -	u32 capflags; +	__be32 capflags;  	struct ath9k_htc_rate rates;  };  struct ath9k_htc_target_stats { -	u32 tx_shortretry; -	u32 tx_longretry; -	u32 tx_xretries; -	u32 ht_txunaggr_xretry; -	u32 ht_tx_xretries; +	__be32 tx_shortretry; +	__be32 tx_longretry; +	__be32 tx_xretries; +	__be32 ht_txunaggr_xretry; +	__be32 ht_tx_xretries;  } __packed;  struct ath9k_htc_vif { @@ -261,6 +261,7 @@ struct ath_tx_stats {  	u32 buf_completed;  	u32 skb_queued;  	u32 skb_completed; +	u32 skb_dropped;  };  struct ath_rx_stats { @@ -328,6 +329,7 @@ struct htc_beacon_config {  #define OP_ASSOCIATED     BIT(8)  #define OP_ENABLE_BEACON  BIT(9)  #define OP_LED_DEINIT     BIT(10) +#define OP_UNPLUGGED      BIT(11)  struct ath9k_htc_priv {  	struct device *dev; @@ -377,6 +379,7 @@ struct ath9k_htc_priv {  	struct mutex htc_pm_lock;  	unsigned long ps_usecount;  	bool ps_enabled; +	bool ps_idle;  	struct ath_led radio_led;  	struct ath_led assoc_led; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 5e21f4d92ff..7cb55f5b071 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -26,7 +26,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,  	enum ath9k_int imask = 0;  	int dtimperiod, dtimcount, sleepduration;  	int cfpperiod, cfpcount, bmiss_timeout; -	u32 nexttbtt = 0, intval, tsftu, htc_imask = 0; +	u32 nexttbtt = 0, intval, tsftu; +	__be32 htc_imask = 0;  	u64 tsf;  	int num_beacons, offset, dtim_dec_count, cfp_dec_count;  	int ret; @@ -142,7 +143,8 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,  {  	struct ath_common *common = ath9k_hw_common(priv->ah);  	enum ath9k_int imask = 0; -	u32 nexttbtt, intval, htc_imask = 0; +	u32 nexttbtt, intval; +	__be32 htc_imask = 0;  	int ret;  	u8 cmd_rsp; @@ -244,25 +246,20 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,  			     struct ieee80211_vif *vif)  {  	struct ath_common *common = ath9k_hw_common(priv->ah); -	enum nl80211_iftype iftype;  	struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; +	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; -	if (vif) { -		struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; -		iftype = vif->type; -		cur_conf->beacon_interval = bss_conf->beacon_int; -		cur_conf->dtim_period = bss_conf->dtim_period; -		cur_conf->listen_interval = 1; -		cur_conf->dtim_count = 1; -		cur_conf->bmiss_timeout = -			ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; -	} else -		iftype = priv->ah->opmode; - +	cur_conf->beacon_interval = bss_conf->beacon_int;  	if (cur_conf->beacon_interval == 0)  		cur_conf->beacon_interval = 100; -	switch (iftype) { +	cur_conf->dtim_period = bss_conf->dtim_period; +	cur_conf->listen_interval = 1; +	cur_conf->dtim_count = 1; +	cur_conf->bmiss_timeout = +		ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; + +	switch (vif->type) {  	case NL80211_IFTYPE_STATION:  		ath9k_htc_beacon_config_sta(priv, cur_conf);  		break; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index aed53573c54..701f2ef5a44 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -213,7 +213,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,  				      ath9k_hw_regulatory(priv->ah));  } -static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) +static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)  {  	struct ath_hw *ah = (struct ath_hw *) hw_priv;  	struct ath_common *common = ath9k_hw_common(ah); @@ -235,7 +235,7 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)  	return be32_to_cpu(val);  } -static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) +static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)  {  	struct ath_hw *ah = (struct ath_hw *) hw_priv;  	struct ath_common *common = ath9k_hw_common(ah); @@ -257,9 +257,105 @@ static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)  	}  } +static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset) +{ +	struct ath_hw *ah = (struct ath_hw *) hw_priv; +	struct ath_common *common = ath9k_hw_common(ah); +	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; +	u32 rsp_status; +	int r; + +	mutex_lock(&priv->wmi->multi_write_mutex); + +	/* Store the register/value */ +	priv->wmi->multi_write[priv->wmi->multi_write_idx].reg = +		cpu_to_be32(reg_offset); +	priv->wmi->multi_write[priv->wmi->multi_write_idx].val = +		cpu_to_be32(val); + +	priv->wmi->multi_write_idx++; + +	/* If the buffer is full, send it out. */ +	if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) { +		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, +			  (u8 *) &priv->wmi->multi_write, +			  sizeof(struct register_write) * priv->wmi->multi_write_idx, +			  (u8 *) &rsp_status, sizeof(rsp_status), +			  100); +		if (unlikely(r)) { +			ath_print(common, ATH_DBG_WMI, +				  "REGISTER WRITE FAILED, multi len: %d\n", +				  priv->wmi->multi_write_idx); +		} +		priv->wmi->multi_write_idx = 0; +	} + +	mutex_unlock(&priv->wmi->multi_write_mutex); +} + +static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset) +{ +	struct ath_hw *ah = (struct ath_hw *) hw_priv; +	struct ath_common *common = ath9k_hw_common(ah); +	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + +	if (atomic_read(&priv->wmi->mwrite_cnt)) +		ath9k_regwrite_buffer(hw_priv, val, reg_offset); +	else +		ath9k_regwrite_single(hw_priv, val, reg_offset); +} + +static void ath9k_enable_regwrite_buffer(void *hw_priv) +{ +	struct ath_hw *ah = (struct ath_hw *) hw_priv; +	struct ath_common *common = ath9k_hw_common(ah); +	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + +	atomic_inc(&priv->wmi->mwrite_cnt); +} + +static void ath9k_disable_regwrite_buffer(void *hw_priv) +{ +	struct ath_hw *ah = (struct ath_hw *) hw_priv; +	struct ath_common *common = ath9k_hw_common(ah); +	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; + +	atomic_dec(&priv->wmi->mwrite_cnt); +} + +static void ath9k_regwrite_flush(void *hw_priv) +{ +	struct ath_hw *ah = (struct ath_hw *) hw_priv; +	struct ath_common *common = ath9k_hw_common(ah); +	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; +	u32 rsp_status; +	int r; + +	mutex_lock(&priv->wmi->multi_write_mutex); + +	if (priv->wmi->multi_write_idx) { +		r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID, +			  (u8 *) &priv->wmi->multi_write, +			  sizeof(struct register_write) * priv->wmi->multi_write_idx, +			  (u8 *) &rsp_status, sizeof(rsp_status), +			  100); +		if (unlikely(r)) { +			ath_print(common, ATH_DBG_WMI, +				  "REGISTER WRITE FAILED, multi len: %d\n", +				  priv->wmi->multi_write_idx); +		} +		priv->wmi->multi_write_idx = 0; +	} + +	mutex_unlock(&priv->wmi->multi_write_mutex); +} +  static const struct ath_ops ath9k_common_ops = { -	.read = ath9k_ioread32, -	.write = ath9k_iowrite32, +	.read = ath9k_regread, +	.write = ath9k_regwrite, +	.enable_write_buffer = ath9k_enable_regwrite_buffer, +	.disable_write_buffer = ath9k_disable_regwrite_buffer, +	.write_flush = ath9k_regwrite_flush,  };  static void ath_usb_read_cachesize(struct ath_common *common, int *csz) @@ -648,6 +744,9 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,  	if (ret)  		goto err_init; +	/* The device may have been unplugged earlier. */ +	priv->op_flags &= ~OP_UNPLUGGED; +  	ret = ath9k_init_device(priv, devid);  	if (ret)  		goto err_init; @@ -664,6 +763,11 @@ err_free:  void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)  {  	if (htc_handle->drv_priv) { + +		/* Check if the device has been yanked out. */ +		if (hotunplug) +			htc_handle->drv_priv->op_flags |= OP_UNPLUGGED; +  		ath9k_deinit_device(htc_handle->drv_priv);  		ath9k_deinit_wmi(htc_handle->drv_priv);  		ieee80211_free_hw(htc_handle->drv_priv->hw); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index eb7722b2cfc..ca7f3a78eb1 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -94,8 +94,11 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)  	if (--priv->ps_usecount != 0)  		goto unlock; -	if (priv->ps_enabled) +	if (priv->ps_idle) +		ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP); +	else if (priv->ps_enabled)  		ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); +  unlock:  	mutex_unlock(&priv->htc_pm_lock);  } @@ -125,7 +128,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,  	bool fastcc = true;  	struct ieee80211_channel *channel = hw->conf.channel;  	enum htc_phymode mode; -	u16 htc_mode; +	__be16 htc_mode;  	u8 cmd_rsp;  	int ret; @@ -153,7 +156,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,  		ath_print(common, ATH_DBG_FATAL,  			  "Unable to reset channel (%u Mhz) "  			  "reset status %d\n", channel->center_freq, ret); -		ath9k_htc_ps_restore(priv);  		goto err;  	} @@ -378,7 +380,7 @@ static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv,  	priv->tgt_rate.sta_index = ista->index;  	priv->tgt_rate.isnew = 1;  	trate = priv->tgt_rate; -	priv->tgt_rate.capflags = caps; +	priv->tgt_rate.capflags = cpu_to_be32(caps);  	trate.capflags = cpu_to_be32(caps);  	WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate); @@ -426,6 +428,7 @@ static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40)  	struct ath9k_htc_target_rate trate;  	struct ath_common *common = ath9k_hw_common(priv->ah);  	int ret; +	u32 caps = be32_to_cpu(priv->tgt_rate.capflags);  	u8 cmd_rsp;  	memset(&trate, 0, sizeof(trate)); @@ -433,11 +436,12 @@ static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40)  	trate = priv->tgt_rate;  	if (is_cw40) -		priv->tgt_rate.capflags |= WLAN_RC_40_FLAG; +		caps |= WLAN_RC_40_FLAG;  	else -		priv->tgt_rate.capflags &= ~WLAN_RC_40_FLAG; +		caps &= ~WLAN_RC_40_FLAG; -	trate.capflags = cpu_to_be32(priv->tgt_rate.capflags); +	priv->tgt_rate.capflags = cpu_to_be32(caps); +	trate.capflags = cpu_to_be32(caps);  	WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate);  	if (ret) { @@ -609,6 +613,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,  	len += snprintf(buf + len, sizeof(buf) - len,  			"%20s : %10u\n", "SKBs completed",  			priv->debug.tx_stats.skb_completed); +	len += snprintf(buf + len, sizeof(buf) - len, +			"%20s : %10u\n", "SKBs dropped", +			priv->debug.tx_stats.skb_dropped);  	return simple_read_from_buffer(user_buf, count, ppos, buf, len);  } @@ -960,7 +967,6 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv)  	ath9k_unregister_led(&priv->tx_led);  	ath9k_unregister_led(&priv->rx_led);  	ath9k_unregister_led(&priv->radio_led); -	ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);  }  void ath9k_init_leds(struct ath9k_htc_priv *priv) @@ -1093,7 +1099,7 @@ fail_tx:  	return 0;  } -static int ath9k_htc_start(struct ieee80211_hw *hw) +static int ath9k_htc_radio_enable(struct ieee80211_hw *hw)  {  	struct ath9k_htc_priv *priv = hw->priv;  	struct ath_hw *ah = priv->ah; @@ -1102,15 +1108,13 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)  	struct ath9k_channel *init_channel;  	int ret = 0;  	enum htc_phymode mode; -	u16 htc_mode; +	__be16 htc_mode;  	u8 cmd_rsp;  	ath_print(common, ATH_DBG_CONFIG,  		  "Starting driver with initial channel: %d MHz\n",  		  curchan->center_freq); -	mutex_lock(&priv->mutex); -  	/* setup initial channel */  	init_channel = ath9k_cmn_get_curchannel(hw, ah); @@ -1123,7 +1127,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)  		ath_print(common, ATH_DBG_FATAL,  			  "Unable to reset hardware; reset status %d "  			  "(freq %u MHz)\n", ret, curchan->center_freq); -		goto mutex_unlock; +		return ret;  	}  	ath_update_txpow(priv); @@ -1131,16 +1135,8 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)  	mode = ath9k_htc_get_curmode(priv, init_channel);  	htc_mode = cpu_to_be16(mode);  	WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); -	if (ret) -		goto mutex_unlock; -  	WMI_CMD(WMI_ATH_INIT_CMDID); -	if (ret) -		goto mutex_unlock; -  	WMI_CMD(WMI_START_RECV_CMDID); -	if (ret) -		goto mutex_unlock;  	ath9k_host_rx_init(priv); @@ -1153,12 +1149,22 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)  	ieee80211_wake_queues(hw); -mutex_unlock: +	return ret; +} + +static int ath9k_htc_start(struct ieee80211_hw *hw) +{ +	struct ath9k_htc_priv *priv = hw->priv; +	int ret = 0; + +	mutex_lock(&priv->mutex); +	ret = ath9k_htc_radio_enable(hw);  	mutex_unlock(&priv->mutex); +  	return ret;  } -static void ath9k_htc_stop(struct ieee80211_hw *hw) +static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)  {  	struct ath9k_htc_priv *priv = hw->priv;  	struct ath_hw *ah = priv->ah; @@ -1166,14 +1172,18 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)  	int ret = 0;  	u8 cmd_rsp; -	mutex_lock(&priv->mutex); -  	if (priv->op_flags & OP_INVALID) {  		ath_print(common, ATH_DBG_ANY, "Device not present\n"); -		mutex_unlock(&priv->mutex);  		return;  	} +	/* Cancel all the running timers/work .. */ +	cancel_work_sync(&priv->ps_work); +	cancel_delayed_work_sync(&priv->ath9k_ani_work); +	cancel_delayed_work_sync(&priv->ath9k_aggr_work); +	cancel_delayed_work_sync(&priv->ath9k_led_blink_work); +	ath9k_led_stop_brightness(priv); +  	ath9k_htc_ps_wakeup(priv);  	htc_stop(priv->htc);  	WMI_CMD(WMI_DISABLE_INTR_CMDID); @@ -1185,11 +1195,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)  	ath9k_htc_ps_restore(priv);  	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); -	cancel_work_sync(&priv->ps_work); -	cancel_delayed_work_sync(&priv->ath9k_ani_work); -	cancel_delayed_work_sync(&priv->ath9k_aggr_work); -	cancel_delayed_work_sync(&priv->ath9k_led_blink_work); -	ath9k_led_stop_brightness(priv);  	skb_queue_purge(&priv->tx_queue);  	/* Remove monitor interface here */ @@ -1203,11 +1208,20 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)  	}  	priv->op_flags |= OP_INVALID; -	mutex_unlock(&priv->mutex);  	ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");  } +static void ath9k_htc_stop(struct ieee80211_hw *hw) +{ +	struct ath9k_htc_priv *priv = hw->priv; + +	mutex_lock(&priv->mutex); +	ath9k_htc_radio_disable(hw); +	mutex_unlock(&priv->mutex); +} + +  static int ath9k_htc_add_interface(struct ieee80211_hw *hw,  				   struct ieee80211_vif *vif)  { @@ -1321,6 +1335,23 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)  	mutex_lock(&priv->mutex); +	if (changed & IEEE80211_CONF_CHANGE_IDLE) { +		bool enable_radio = false; +		bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); + +		if (!idle && priv->ps_idle) +			enable_radio = true; + +		priv->ps_idle = idle; + +		if (enable_radio) { +			ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); +			ath9k_htc_radio_enable(hw); +			ath_print(common, ATH_DBG_CONFIG, +				  "not-idle: enabling radio\n"); +		} +	} +  	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {  		struct ieee80211_channel *curchan = hw->conf.channel;  		int pos = curchan->hw_value; @@ -1364,6 +1395,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)  		}  	} +	if (priv->ps_idle) { +		ath_print(common, ATH_DBG_CONFIG, +			  "idle: disabling radio\n"); +		ath9k_htc_radio_disable(hw); +	} + +  	mutex_unlock(&priv->mutex);  	return 0; @@ -1687,7 +1725,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)  	spin_unlock_bh(&priv->beacon_lock);  	priv->op_flags |= OP_FULL_RESET;  	if (priv->op_flags & OP_ASSOCIATED) -		ath9k_htc_beacon_config(priv, NULL); +		ath9k_htc_beacon_config(priv, priv->vif);  	ath_start_ani(priv);  	mutex_unlock(&priv->mutex);  	ath9k_htc_ps_restore(priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 0a7cb30af5b..28abc7d5e90 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -244,16 +244,25 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,  		    enum htc_endpoint_id ep_id, bool txok)  {  	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; +	struct ath_common *common = ath9k_hw_common(priv->ah);  	struct ieee80211_tx_info *tx_info;  	if (!skb)  		return; -	if (ep_id == priv->mgmt_ep) +	if (ep_id == priv->mgmt_ep) {  		skb_pull(skb, sizeof(struct tx_mgmt_hdr)); -	else -		/* TODO: Check for cab/uapsd/data */ +	} else if ((ep_id == priv->data_bk_ep) || +		   (ep_id == priv->data_be_ep) || +		   (ep_id == priv->data_vi_ep) || +		   (ep_id == priv->data_vo_ep)) {  		skb_pull(skb, sizeof(struct tx_frame_hdr)); +	} else { +		ath_print(common, ATH_DBG_FATAL, +			  "Unsupported TX EPID: %d\n", ep_id); +		dev_kfree_skb_any(skb); +		return; +	}  	tx_info = IEEE80211_SKB_CB(skb); @@ -439,10 +448,32 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,  	struct ieee80211_hw *hw = priv->hw;  	struct sk_buff *skb = rxbuf->skb;  	struct ath_common *common = ath9k_hw_common(priv->ah); +	struct ath_htc_rx_status *rxstatus;  	int hdrlen, padpos, padsize;  	int last_rssi = ATH_RSSI_DUMMY_MARKER;  	__le16 fc; +	if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) { +		ath_print(common, ATH_DBG_FATAL, +			  "Corrupted RX frame, dropping\n"); +		goto rx_next; +	} + +	rxstatus = (struct ath_htc_rx_status *)skb->data; + +	if (be16_to_cpu(rxstatus->rs_datalen) - +	    (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) { +		ath_print(common, ATH_DBG_FATAL, +			  "Corrupted RX data len, dropping " +			  "(dlen: %d, skblen: %d)\n", +			  rxstatus->rs_datalen, skb->len); +		goto rx_next; +	} + +	/* Get the RX status information */ +	memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); +	skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); +  	hdr = (struct ieee80211_hdr *)skb->data;  	fc = hdr->frame_control;  	hdrlen = ieee80211_get_hdrlen_from_skb(skb); @@ -530,7 +561,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,  			priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;  	} -	rx_status->mactime = rxbuf->rxstatus.rs_tstamp; +	rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);  	rx_status->band = hw->conf.channel->band;  	rx_status->freq = hw->conf.channel->center_freq;  	rx_status->signal =  rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; @@ -607,8 +638,6 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,  	struct ath_hw *ah = priv->ah;  	struct ath_common *common = ath9k_hw_common(ah);  	struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; -	struct ath_htc_rx_status *rxstatus; -	u32 len = 0;  	spin_lock(&priv->rx.rxbuflock);  	list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { @@ -625,32 +654,7 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,  		goto err;  	} -	len = skb->len; -	if (len <= HTC_RX_FRAME_HEADER_SIZE) { -		ath_print(common, ATH_DBG_FATAL, -			  "Corrupted RX frame, dropping\n"); -		goto err; -	} - -	rxstatus = (struct ath_htc_rx_status *)skb->data; - -	rxstatus->rs_tstamp = be64_to_cpu(rxstatus->rs_tstamp); -	rxstatus->rs_datalen = be16_to_cpu(rxstatus->rs_datalen); -	rxstatus->evm0 = be32_to_cpu(rxstatus->evm0); -	rxstatus->evm1 = be32_to_cpu(rxstatus->evm1); -	rxstatus->evm2 = be32_to_cpu(rxstatus->evm2); - -	if (rxstatus->rs_datalen - (len - HTC_RX_FRAME_HEADER_SIZE) != 0) { -		ath_print(common, ATH_DBG_FATAL, -			  "Corrupted RX data len, dropping " -			  "(epid: %d, dlen: %d, skblen: %d)\n", -			  ep_id, rxstatus->rs_datalen, len); -		goto err; -	} -  	spin_lock(&priv->rx.rxbuflock); -	memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); -	skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);  	rxbuf->skb = skb;  	rxbuf->in_process = true;  	spin_unlock(&priv->rx.rxbuflock); diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 587d98ed098..7bf6ce1e7e2 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -341,8 +341,9 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,  		skb_pull(skb, sizeof(struct htc_frame_hdr));  		if (endpoint->ep_callbacks.tx) { -			endpoint->ep_callbacks.tx(htc_handle->drv_priv, skb, -						  htc_hdr->endpoint_id, txok); +			endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, +						  skb, htc_hdr->endpoint_id, +						  txok);  		}  	} @@ -368,7 +369,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,  	struct htc_frame_hdr *htc_hdr;  	enum htc_endpoint_id epid;  	struct htc_endpoint *endpoint; -	u16 *msg_id; +	__be16 *msg_id;  	if (!htc_handle || !skb)  		return; @@ -388,14 +389,14 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,  		/* Handle trailer */  		if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { -			if (be32_to_cpu(*(u32 *) skb->data) == 0x00C60000) +			if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000)  				/* Move past the Watchdog pattern */  				htc_hdr = (struct htc_frame_hdr *)(skb->data + 4);  		}  		/* Get the message ID */ -		msg_id = (u16 *) ((void *) htc_hdr + -					   sizeof(struct htc_frame_hdr)); +		msg_id = (__be16 *) ((void *) htc_hdr + +				     sizeof(struct htc_frame_hdr));  		/* Now process HTC messages */  		switch (be16_to_cpu(*msg_id)) { diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index cd7048ffd23..ea50ab032d2 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h @@ -59,20 +59,20 @@ enum htc_endpoint_id {  struct htc_frame_hdr {  	u8 endpoint_id;  	u8 flags; -	u16 payload_len; +	__be16 payload_len;  	u8 control[4];  } __packed;  struct htc_ready_msg { -	u16 message_id; -	u16 credits; -	u16 credit_size; +	__be16 message_id; +	__be16 credits; +	__be16 credit_size;  	u8 max_endpoints;  	u8 pad;  } __packed;  struct htc_config_pipe_msg { -	u16 message_id; +	__be16 message_id;  	u8 pipe_id;  	u8 credits;  } __packed; @@ -192,9 +192,9 @@ enum htc_service_group_ids{  #define WMI_DATA_BK_SVC   MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 8)  struct htc_conn_svc_msg { -	u16 msg_id; -	u16 service_id; -	u16 con_flags; +	__be16 msg_id; +	__be16 service_id; +	__be16 con_flags;  	u8 dl_pipeid;  	u8 ul_pipeid;  	u8 svc_meta_len; @@ -209,17 +209,17 @@ struct htc_conn_svc_msg {  #define HTC_SERVICE_NO_MORE_EP   4  struct htc_conn_svc_rspmsg { -	u16 msg_id; -	u16 service_id; +	__be16 msg_id; +	__be16 service_id;  	u8 status;  	u8 endpoint_id; -	u16 max_msg_len; +	__be16 max_msg_len;  	u8 svc_meta_len;  	u8 pad;  } __packed;  struct htc_comp_msg { -	u16 msg_id; +	__be16 msg_id;  } __packed;  int htc_init(struct htc_target *target); diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h new file mode 100644 index 00000000000..624422a8169 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef ATH9K_HW_OPS_H +#define ATH9K_HW_OPS_H + +#include "hw.h" + +/* Hardware core and driver accessible callbacks */ + +static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah, +					       int restore, +					       int power_off) +{ +	ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off); +} + +static inline void ath9k_hw_rxena(struct ath_hw *ah) +{ +	ath9k_hw_ops(ah)->rx_enable(ah); +} + +static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds, +					  u32 link) +{ +	ath9k_hw_ops(ah)->set_desc_link(ds, link); +} + +static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds, +					  u32 **link) +{ +	ath9k_hw_ops(ah)->get_desc_link(ds, link); +} +static inline bool ath9k_hw_calibrate(struct ath_hw *ah, +				      struct ath9k_channel *chan, +				      u8 rxchainmask, +				      bool longcal) +{ +	return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal); +} + +static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) +{ +	return ath9k_hw_ops(ah)->get_isr(ah, masked); +} + +static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen, +				  bool is_firstseg, bool is_lastseg, +				  const void *ds0, dma_addr_t buf_addr, +				  unsigned int qcu) +{ +	ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg, +				      ds0, buf_addr, qcu); +} + +static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds, +				      struct ath_tx_status *ts) +{ +	return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts); +} + +static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds, +					  u32 pktLen, enum ath9k_pkt_type type, +					  u32 txPower, u32 keyIx, +					  enum ath9k_key_type keyType, +					  u32 flags) +{ +	ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx, +				      keyType, flags); +} + +static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, +					void *lastds, +					u32 durUpdateEn, u32 rtsctsRate, +					u32 rtsctsDuration, +					struct ath9k_11n_rate_series series[], +					u32 nseries, u32 flags) +{ +	ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn, +					    rtsctsRate, rtsctsDuration, series, +					    nseries, flags); +} + +static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, +					u32 aggrLen) +{ +	ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen); +} + +static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, +					       u32 numDelims) +{ +	ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims); +} + +static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds) +{ +	ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds); +} + +static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds) +{ +	ath9k_hw_ops(ah)->clr11n_aggr(ah, ds); +} + +static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds, +						 u32 burstDuration) +{ +	ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); +} + +static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, +						   u32 vmf) +{ +	ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); +} + +/* Private hardware call ops */ + +/* PHY ops */ + +static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah, +				       struct ath9k_channel *chan) +{ +	return ath9k_hw_private_ops(ah)->rf_set_freq(ah, chan); +} + +static inline void ath9k_hw_spur_mitigate_freq(struct ath_hw *ah, +					       struct ath9k_channel *chan) +{ +	ath9k_hw_private_ops(ah)->spur_mitigate_freq(ah, chan); +} + +static inline int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah) +{ +	if (!ath9k_hw_private_ops(ah)->rf_alloc_ext_banks) +		return 0; + +	return ath9k_hw_private_ops(ah)->rf_alloc_ext_banks(ah); +} + +static inline void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah) +{ +	if (!ath9k_hw_private_ops(ah)->rf_free_ext_banks) +		return; + +	ath9k_hw_private_ops(ah)->rf_free_ext_banks(ah); +} + +static inline bool ath9k_hw_set_rf_regs(struct ath_hw *ah, +					struct ath9k_channel *chan, +					u16 modesIndex) +{ +	if (!ath9k_hw_private_ops(ah)->set_rf_regs) +		return true; + +	return ath9k_hw_private_ops(ah)->set_rf_regs(ah, chan, modesIndex); +} + +static inline void ath9k_hw_init_bb(struct ath_hw *ah, +				    struct ath9k_channel *chan) +{ +	return ath9k_hw_private_ops(ah)->init_bb(ah, chan); +} + +static inline void ath9k_hw_set_channel_regs(struct ath_hw *ah, +					     struct ath9k_channel *chan) +{ +	return ath9k_hw_private_ops(ah)->set_channel_regs(ah, chan); +} + +static inline int ath9k_hw_process_ini(struct ath_hw *ah, +					struct ath9k_channel *chan) +{ +	return ath9k_hw_private_ops(ah)->process_ini(ah, chan); +} + +static inline void ath9k_olc_init(struct ath_hw *ah) +{ +	if (!ath9k_hw_private_ops(ah)->olc_init) +		return; + +	return ath9k_hw_private_ops(ah)->olc_init(ah); +} + +static inline void ath9k_hw_set_rfmode(struct ath_hw *ah, +				       struct ath9k_channel *chan) +{ +	return ath9k_hw_private_ops(ah)->set_rfmode(ah, chan); +} + +static inline void ath9k_hw_mark_phy_inactive(struct ath_hw *ah) +{ +	return ath9k_hw_private_ops(ah)->mark_phy_inactive(ah); +} + +static inline void ath9k_hw_set_delta_slope(struct ath_hw *ah, +					    struct ath9k_channel *chan) +{ +	return ath9k_hw_private_ops(ah)->set_delta_slope(ah, chan); +} + +static inline bool ath9k_hw_rfbus_req(struct ath_hw *ah) +{ +	return ath9k_hw_private_ops(ah)->rfbus_req(ah); +} + +static inline void ath9k_hw_rfbus_done(struct ath_hw *ah) +{ +	return ath9k_hw_private_ops(ah)->rfbus_done(ah); +} + +static inline void ath9k_enable_rfkill(struct ath_hw *ah) +{ +	return ath9k_hw_private_ops(ah)->enable_rfkill(ah); +} + +static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah) +{ +	if (!ath9k_hw_private_ops(ah)->restore_chainmask) +		return; + +	return ath9k_hw_private_ops(ah)->restore_chainmask(ah); +} + +static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value) +{ +	return ath9k_hw_private_ops(ah)->set_diversity(ah, value); +} + +static inline bool ath9k_hw_ani_control(struct ath_hw *ah, +					enum ath9k_ani_cmd cmd, int param) +{ +	return ath9k_hw_private_ops(ah)->ani_control(ah, cmd, param); +} + +static inline void ath9k_hw_do_getnf(struct ath_hw *ah, +				     int16_t nfarray[NUM_NF_READINGS]) +{ +	ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray); +} + +static inline void ath9k_hw_loadnf(struct ath_hw *ah, +				   struct ath9k_channel *chan) +{ +	ath9k_hw_private_ops(ah)->loadnf(ah, chan); +} + +static inline bool ath9k_hw_init_cal(struct ath_hw *ah, +				     struct ath9k_channel *chan) +{ +	return ath9k_hw_private_ops(ah)->init_cal(ah, chan); +} + +static inline void ath9k_hw_setup_calibration(struct ath_hw *ah, +					      struct ath9k_cal_list *currCal) +{ +	ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal); +} + +static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah, +					    enum ath9k_cal_types calType) +{ +	return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType); +} + +#endif /* ATH9K_HW_OPS_H */ diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index af730c7d50e..559019262d3 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2010 Atheros Communications Inc.   *   * Permission to use, copy, modify, and/or distribute this software for any   * purpose with or without fee is hereby granted, provided that the above @@ -19,15 +19,16 @@  #include <asm/unaligned.h>  #include "hw.h" +#include "hw-ops.h"  #include "rc.h" -#include "initvals.h" +#include "ar9003_mac.h"  #define ATH9K_CLOCK_RATE_CCK		22  #define ATH9K_CLOCK_RATE_5GHZ_OFDM	40  #define ATH9K_CLOCK_RATE_2GHZ_OFDM	44 +#define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44  static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); -static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan);  MODULE_AUTHOR("Atheros Communications");  MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); @@ -46,6 +47,39 @@ static void __exit ath9k_exit(void)  }  module_exit(ath9k_exit); +/* Private hardware callbacks */ + +static void ath9k_hw_init_cal_settings(struct ath_hw *ah) +{ +	ath9k_hw_private_ops(ah)->init_cal_settings(ah); +} + +static void ath9k_hw_init_mode_regs(struct ath_hw *ah) +{ +	ath9k_hw_private_ops(ah)->init_mode_regs(ah); +} + +static bool ath9k_hw_macversion_supported(struct ath_hw *ah) +{ +	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); + +	return priv_ops->macversion_supported(ah->hw_version.macVersion); +} + +static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, +					struct ath9k_channel *chan) +{ +	return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan); +} + +static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) +{ +	if (!ath9k_hw_private_ops(ah)->init_mode_gain_regs) +		return; + +	ath9k_hw_private_ops(ah)->init_mode_gain_regs(ah); +} +  /********************/  /* Helper Functions */  /********************/ @@ -58,7 +92,11 @@ static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)  		return usecs *ATH9K_CLOCK_RATE_CCK;  	if (conf->channel->band == IEEE80211_BAND_2GHZ)  		return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM; -	return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM; + +	if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) +		return usecs * ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; +	else +		return usecs * ATH9K_CLOCK_RATE_5GHZ_OFDM;  }  static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) @@ -233,21 +271,6 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)  	}  } -static int ath9k_hw_get_radiorev(struct ath_hw *ah) -{ -	u32 val; -	int i; - -	REG_WRITE(ah, AR_PHY(0x36), 0x00007058); - -	for (i = 0; i < 8; i++) -		REG_WRITE(ah, AR_PHY(0x20), 0x00010000); -	val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; -	val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); - -	return ath9k_hw_reverse_bits(val, 8); -} -  /************************************/  /* HW Attach, Detach, Init Routines */  /************************************/ @@ -257,6 +280,8 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah)  	if (AR_SREV_9100(ah))  		return; +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);  	REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);  	REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); @@ -268,20 +293,30 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah)  	REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);  	REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah);  } +/* This should work for all families including legacy */  static bool ath9k_hw_chip_test(struct ath_hw *ah)  {  	struct ath_common *common = ath9k_hw_common(ah); -	u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) }; +	u32 regAddr[2] = { AR_STA_ID0 };  	u32 regHold[2];  	u32 patternData[4] = { 0x55555555,  			       0xaaaaaaaa,  			       0x66666666,  			       0x99999999 }; -	int i, j; +	int i, j, loop_max; -	for (i = 0; i < 2; i++) { +	if (!AR_SREV_9300_20_OR_LATER(ah)) { +		loop_max = 2; +		regAddr[1] = AR_PHY_BASE + (8 << 2); +	} else +		loop_max = 1; + +	for (i = 0; i < loop_max; i++) {  		u32 addr = regAddr[i];  		u32 wrData, rdData; @@ -336,7 +371,13 @@ static void ath9k_hw_init_config(struct ath_hw *ah)  	ah->config.ofdm_trig_high = 500;  	ah->config.cck_trig_high = 200;  	ah->config.cck_trig_low = 100; -	ah->config.enable_ani = 1; + +	/* +	 * For now ANI is disabled for AR9003, it is still +	 * being tested. +	 */ +	if (!AR_SREV_9300_20_OR_LATER(ah)) +		ah->config.enable_ani = 1;  	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {  		ah->config.spurchans[i][0] = AR_NO_SPUR; @@ -351,6 +392,12 @@ static void ath9k_hw_init_config(struct ath_hw *ah)  	ah->config.rx_intr_mitigation = true;  	/* +	 * Tx IQ Calibration (ah->config.tx_iq_calibration) is only +	 * used by AR9003, but it is showing reliability issues. +	 * It will take a while to fix so this is currently disabled. +	 */ + +	/*  	 * We need this for PCI devices only (Cardbus, PCI, miniPCI)  	 * _and_ if on non-uniprocessor systems (Multiprocessor/HT).  	 * This means we use it for all AR5416 devices, and the few @@ -369,7 +416,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)  	if (num_possible_cpus() > 1)  		ah->config.serialize_regmode = SER_REG_MODE_AUTO;  } -EXPORT_SYMBOL(ath9k_hw_init);  static void ath9k_hw_init_defaults(struct ath_hw *ah)  { @@ -383,8 +429,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)  	ah->hw_version.subvendorid = 0;  	ah->ah_flags = 0; -	if (ah->hw_version.devid == AR5416_AR9100_DEVID) -		ah->hw_version.macVersion = AR_SREV_VERSION_9100;  	if (!AR_SREV_9100(ah))  		ah->ah_flags = AH_USE_EEPROM; @@ -397,44 +441,17 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)  	ah->power_mode = ATH9K_PM_UNDEFINED;  } -static int ath9k_hw_rf_claim(struct ath_hw *ah) -{ -	u32 val; - -	REG_WRITE(ah, AR_PHY(0), 0x00000007); - -	val = ath9k_hw_get_radiorev(ah); -	switch (val & AR_RADIO_SREV_MAJOR) { -	case 0: -		val = AR_RAD5133_SREV_MAJOR; -		break; -	case AR_RAD5133_SREV_MAJOR: -	case AR_RAD5122_SREV_MAJOR: -	case AR_RAD2133_SREV_MAJOR: -	case AR_RAD2122_SREV_MAJOR: -		break; -	default: -		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, -			  "Radio Chip Rev 0x%02X not supported\n", -			  val & AR_RADIO_SREV_MAJOR); -		return -EOPNOTSUPP; -	} - -	ah->hw_version.analog5GhzRev = val; - -	return 0; -} -  static int ath9k_hw_init_macaddr(struct ath_hw *ah)  {  	struct ath_common *common = ath9k_hw_common(ah);  	u32 sum;  	int i;  	u16 eeval; +	u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW };  	sum = 0;  	for (i = 0; i < 3; i++) { -		eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i)); +		eeval = ah->eep_ops->get_eeprom(ah, EEP_MAC[i]);  		sum += eeval;  		common->macaddr[2 * i] = eeval >> 8;  		common->macaddr[2 * i + 1] = eeval & 0xff; @@ -445,54 +462,6 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah)  	return 0;  } -static void ath9k_hw_init_rxgain_ini(struct ath_hw *ah) -{ -	u32 rxgain_type; - -	if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) { -		rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); - -		if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) -			INIT_INI_ARRAY(&ah->iniModesRxGain, -			ar9280Modes_backoff_13db_rxgain_9280_2, -			ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); -		else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) -			INIT_INI_ARRAY(&ah->iniModesRxGain, -			ar9280Modes_backoff_23db_rxgain_9280_2, -			ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); -		else -			INIT_INI_ARRAY(&ah->iniModesRxGain, -			ar9280Modes_original_rxgain_9280_2, -			ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); -	} else { -		INIT_INI_ARRAY(&ah->iniModesRxGain, -			ar9280Modes_original_rxgain_9280_2, -			ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); -	} -} - -static void ath9k_hw_init_txgain_ini(struct ath_hw *ah) -{ -	u32 txgain_type; - -	if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) { -		txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); - -		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) -			INIT_INI_ARRAY(&ah->iniModesTxGain, -			ar9280Modes_high_power_tx_gain_9280_2, -			ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); -		else -			INIT_INI_ARRAY(&ah->iniModesTxGain, -			ar9280Modes_original_tx_gain_9280_2, -			ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); -	} else { -		INIT_INI_ARRAY(&ah->iniModesTxGain, -		ar9280Modes_original_tx_gain_9280_2, -		ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); -	} -} -  static int ath9k_hw_post_init(struct ath_hw *ah)  {  	int ecode; @@ -502,9 +471,11 @@ static int ath9k_hw_post_init(struct ath_hw *ah)  			return -ENODEV;  	} -	ecode = ath9k_hw_rf_claim(ah); -	if (ecode != 0) -		return ecode; +	if (!AR_SREV_9300_20_OR_LATER(ah)) { +		ecode = ar9002_hw_rf_claim(ah); +		if (ecode != 0) +			return ecode; +	}  	ecode = ath9k_hw_eeprom_init(ah);  	if (ecode != 0) @@ -515,14 +486,12 @@ static int ath9k_hw_post_init(struct ath_hw *ah)  		  ah->eep_ops->get_eeprom_ver(ah),  		  ah->eep_ops->get_eeprom_rev(ah)); -        if (!AR_SREV_9280_10_OR_LATER(ah)) { -		ecode = ath9k_hw_rf_alloc_ext_banks(ah); -		if (ecode) { -			ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, -				  "Failed allocating banks for " -				  "external radio\n"); -			return ecode; -		} +	ecode = ath9k_hw_rf_alloc_ext_banks(ah); +	if (ecode) { +		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, +			  "Failed allocating banks for " +			  "external radio\n"); +		return ecode;  	}  	if (!AR_SREV_9100(ah)) { @@ -533,344 +502,22 @@ static int ath9k_hw_post_init(struct ath_hw *ah)  	return 0;  } -static bool ath9k_hw_devid_supported(u16 devid) -{ -	switch (devid) { -	case AR5416_DEVID_PCI: -	case AR5416_DEVID_PCIE: -	case AR5416_AR9100_DEVID: -	case AR9160_DEVID_PCI: -	case AR9280_DEVID_PCI: -	case AR9280_DEVID_PCIE: -	case AR9285_DEVID_PCIE: -	case AR5416_DEVID_AR9287_PCI: -	case AR5416_DEVID_AR9287_PCIE: -	case AR2427_DEVID_PCIE: -		return true; -	default: -		break; -	} -	return false; -} - -static bool ath9k_hw_macversion_supported(u32 macversion) -{ -	switch (macversion) { -	case AR_SREV_VERSION_5416_PCI: -	case AR_SREV_VERSION_5416_PCIE: -	case AR_SREV_VERSION_9160: -	case AR_SREV_VERSION_9100: -	case AR_SREV_VERSION_9280: -	case AR_SREV_VERSION_9285: -	case AR_SREV_VERSION_9287: -	case AR_SREV_VERSION_9271: -		return true; -	default: -		break; -	} -	return false; -} - -static void ath9k_hw_init_cal_settings(struct ath_hw *ah) -{ -	if (AR_SREV_9160_10_OR_LATER(ah)) { -		if (AR_SREV_9280_10_OR_LATER(ah)) { -			ah->iq_caldata.calData = &iq_cal_single_sample; -			ah->adcgain_caldata.calData = -				&adc_gain_cal_single_sample; -			ah->adcdc_caldata.calData = -				&adc_dc_cal_single_sample; -			ah->adcdc_calinitdata.calData = -				&adc_init_dc_cal; -		} else { -			ah->iq_caldata.calData = &iq_cal_multi_sample; -			ah->adcgain_caldata.calData = -				&adc_gain_cal_multi_sample; -			ah->adcdc_caldata.calData = -				&adc_dc_cal_multi_sample; -			ah->adcdc_calinitdata.calData = -				&adc_init_dc_cal; -		} -		ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; -	} -} - -static void ath9k_hw_init_mode_regs(struct ath_hw *ah) -{ -	if (AR_SREV_9271(ah)) { -		INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271, -			       ARRAY_SIZE(ar9271Modes_9271), 6); -		INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, -			       ARRAY_SIZE(ar9271Common_9271), 2); -		INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271, -			       ar9271Common_normal_cck_fir_coeff_9271, -			       ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2); -		INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271, -			       ar9271Common_japan_2484_cck_fir_coeff_9271, -			       ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2); -		INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only, -			       ar9271Modes_9271_1_0_only, -			       ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6); -		INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg, -			       ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6); -		INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271, -			       ar9271Modes_high_power_tx_gain_9271, -			       ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6); -		INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, -			       ar9271Modes_normal_power_tx_gain_9271, -			       ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6); -		return; -	} - -	if (AR_SREV_9287_11_OR_LATER(ah)) { -		INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, -				ARRAY_SIZE(ar9287Modes_9287_1_1), 6); -		INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1, -				ARRAY_SIZE(ar9287Common_9287_1_1), 2); -		if (ah->config.pcie_clock_req) -			INIT_INI_ARRAY(&ah->iniPcieSerdes, -			ar9287PciePhy_clkreq_off_L1_9287_1_1, -			ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2); -		else -			INIT_INI_ARRAY(&ah->iniPcieSerdes, -			ar9287PciePhy_clkreq_always_on_L1_9287_1_1, -			ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1), -					2); -	} else if (AR_SREV_9287_10_OR_LATER(ah)) { -		INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0, -				ARRAY_SIZE(ar9287Modes_9287_1_0), 6); -		INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0, -				ARRAY_SIZE(ar9287Common_9287_1_0), 2); - -		if (ah->config.pcie_clock_req) -			INIT_INI_ARRAY(&ah->iniPcieSerdes, -			ar9287PciePhy_clkreq_off_L1_9287_1_0, -			ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2); -		else -			INIT_INI_ARRAY(&ah->iniPcieSerdes, -			ar9287PciePhy_clkreq_always_on_L1_9287_1_0, -			ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0), -				  2); -	} else if (AR_SREV_9285_12_OR_LATER(ah)) { - - -		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, -			       ARRAY_SIZE(ar9285Modes_9285_1_2), 6); -		INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, -			       ARRAY_SIZE(ar9285Common_9285_1_2), 2); - -		if (ah->config.pcie_clock_req) { -			INIT_INI_ARRAY(&ah->iniPcieSerdes, -			ar9285PciePhy_clkreq_off_L1_9285_1_2, -			ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2); -		} else { -			INIT_INI_ARRAY(&ah->iniPcieSerdes, -			ar9285PciePhy_clkreq_always_on_L1_9285_1_2, -			ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2), -				  2); -		} -	} else if (AR_SREV_9285_10_OR_LATER(ah)) { -		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285, -			       ARRAY_SIZE(ar9285Modes_9285), 6); -		INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285, -			       ARRAY_SIZE(ar9285Common_9285), 2); - -		if (ah->config.pcie_clock_req) { -			INIT_INI_ARRAY(&ah->iniPcieSerdes, -			ar9285PciePhy_clkreq_off_L1_9285, -			ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2); -		} else { -			INIT_INI_ARRAY(&ah->iniPcieSerdes, -			ar9285PciePhy_clkreq_always_on_L1_9285, -			ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2); -		} -	} else if (AR_SREV_9280_20_OR_LATER(ah)) { -		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, -			       ARRAY_SIZE(ar9280Modes_9280_2), 6); -		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, -			       ARRAY_SIZE(ar9280Common_9280_2), 2); - -		if (ah->config.pcie_clock_req) { -			INIT_INI_ARRAY(&ah->iniPcieSerdes, -			       ar9280PciePhy_clkreq_off_L1_9280, -			       ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2); -		} else { -			INIT_INI_ARRAY(&ah->iniPcieSerdes, -			       ar9280PciePhy_clkreq_always_on_L1_9280, -			       ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2); -		} -		INIT_INI_ARRAY(&ah->iniModesAdditional, -			       ar9280Modes_fast_clock_9280_2, -			       ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); -	} else if (AR_SREV_9280_10_OR_LATER(ah)) { -		INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280, -			       ARRAY_SIZE(ar9280Modes_9280), 6); -		INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280, -			       ARRAY_SIZE(ar9280Common_9280), 2); -	} else if (AR_SREV_9160_10_OR_LATER(ah)) { -		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, -			       ARRAY_SIZE(ar5416Modes_9160), 6); -		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160, -			       ARRAY_SIZE(ar5416Common_9160), 2); -		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160, -			       ARRAY_SIZE(ar5416Bank0_9160), 2); -		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160, -			       ARRAY_SIZE(ar5416BB_RfGain_9160), 3); -		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160, -			       ARRAY_SIZE(ar5416Bank1_9160), 2); -		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160, -			       ARRAY_SIZE(ar5416Bank2_9160), 2); -		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160, -			       ARRAY_SIZE(ar5416Bank3_9160), 3); -		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160, -			       ARRAY_SIZE(ar5416Bank6_9160), 3); -		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160, -			       ARRAY_SIZE(ar5416Bank6TPC_9160), 3); -		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160, -			       ARRAY_SIZE(ar5416Bank7_9160), 2); -		if (AR_SREV_9160_11(ah)) { -			INIT_INI_ARRAY(&ah->iniAddac, -				       ar5416Addac_91601_1, -				       ARRAY_SIZE(ar5416Addac_91601_1), 2); -		} else { -			INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160, -				       ARRAY_SIZE(ar5416Addac_9160), 2); -		} -	} else if (AR_SREV_9100_OR_LATER(ah)) { -		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100, -			       ARRAY_SIZE(ar5416Modes_9100), 6); -		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100, -			       ARRAY_SIZE(ar5416Common_9100), 2); -		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100, -			       ARRAY_SIZE(ar5416Bank0_9100), 2); -		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100, -			       ARRAY_SIZE(ar5416BB_RfGain_9100), 3); -		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100, -			       ARRAY_SIZE(ar5416Bank1_9100), 2); -		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100, -			       ARRAY_SIZE(ar5416Bank2_9100), 2); -		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100, -			       ARRAY_SIZE(ar5416Bank3_9100), 3); -		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100, -			       ARRAY_SIZE(ar5416Bank6_9100), 3); -		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100, -			       ARRAY_SIZE(ar5416Bank6TPC_9100), 3); -		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100, -			       ARRAY_SIZE(ar5416Bank7_9100), 2); -		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100, -			       ARRAY_SIZE(ar5416Addac_9100), 2); -	} else { -		INIT_INI_ARRAY(&ah->iniModes, ar5416Modes, -			       ARRAY_SIZE(ar5416Modes), 6); -		INIT_INI_ARRAY(&ah->iniCommon, ar5416Common, -			       ARRAY_SIZE(ar5416Common), 2); -		INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0, -			       ARRAY_SIZE(ar5416Bank0), 2); -		INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain, -			       ARRAY_SIZE(ar5416BB_RfGain), 3); -		INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1, -			       ARRAY_SIZE(ar5416Bank1), 2); -		INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2, -			       ARRAY_SIZE(ar5416Bank2), 2); -		INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3, -			       ARRAY_SIZE(ar5416Bank3), 3); -		INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6, -			       ARRAY_SIZE(ar5416Bank6), 3); -		INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC, -			       ARRAY_SIZE(ar5416Bank6TPC), 3); -		INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7, -			       ARRAY_SIZE(ar5416Bank7), 2); -		INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, -			       ARRAY_SIZE(ar5416Addac), 2); -	} -} - -static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) -{ -	if (AR_SREV_9287_11_OR_LATER(ah)) -		INIT_INI_ARRAY(&ah->iniModesRxGain, -		ar9287Modes_rx_gain_9287_1_1, -		ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); -	else if (AR_SREV_9287_10(ah)) -		INIT_INI_ARRAY(&ah->iniModesRxGain, -		ar9287Modes_rx_gain_9287_1_0, -		ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6); -	else if (AR_SREV_9280_20(ah)) -		ath9k_hw_init_rxgain_ini(ah); - -	if (AR_SREV_9287_11_OR_LATER(ah)) { -		INIT_INI_ARRAY(&ah->iniModesTxGain, -		ar9287Modes_tx_gain_9287_1_1, -		ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); -	} else if (AR_SREV_9287_10(ah)) { -		INIT_INI_ARRAY(&ah->iniModesTxGain, -		ar9287Modes_tx_gain_9287_1_0, -		ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6); -	} else if (AR_SREV_9280_20(ah)) { -		ath9k_hw_init_txgain_ini(ah); -	} else if (AR_SREV_9285_12_OR_LATER(ah)) { -		u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); - -		/* txgain table */ -		if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { -			if (AR_SREV_9285E_20(ah)) { -				INIT_INI_ARRAY(&ah->iniModesTxGain, -				ar9285Modes_XE2_0_high_power, -				ARRAY_SIZE( -				  ar9285Modes_XE2_0_high_power), 6); -			} else { -				INIT_INI_ARRAY(&ah->iniModesTxGain, -				ar9285Modes_high_power_tx_gain_9285_1_2, -				ARRAY_SIZE( -				  ar9285Modes_high_power_tx_gain_9285_1_2), 6); -			} -		} else { -			if (AR_SREV_9285E_20(ah)) { -				INIT_INI_ARRAY(&ah->iniModesTxGain, -				ar9285Modes_XE2_0_normal_power, -				ARRAY_SIZE( -				  ar9285Modes_XE2_0_normal_power), 6); -			} else { -				INIT_INI_ARRAY(&ah->iniModesTxGain, -				ar9285Modes_original_tx_gain_9285_1_2, -				ARRAY_SIZE( -				  ar9285Modes_original_tx_gain_9285_1_2), 6); -			} -		} -	} -} - -static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) +static void ath9k_hw_attach_ops(struct ath_hw *ah)  { -	struct base_eep_header *pBase = &(ah->eeprom.def.baseEepHeader); -	struct ath_common *common = ath9k_hw_common(ah); - -	ah->need_an_top2_fixup = (ah->hw_version.devid == AR9280_DEVID_PCI) && -				 (ah->eep_map != EEP_MAP_4KBITS) && -				 ((pBase->version & 0xff) > 0x0a) && -				 (pBase->pwdclkind == 0); - -	if (ah->need_an_top2_fixup) -		ath_print(common, ATH_DBG_EEPROM, -			  "needs fixup for AR_AN_TOP2 register\n"); +	if (AR_SREV_9300_20_OR_LATER(ah)) +		ar9003_hw_attach_ops(ah); +	else +		ar9002_hw_attach_ops(ah);  } -int ath9k_hw_init(struct ath_hw *ah) +/* Called for all hardware families */ +static int __ath9k_hw_init(struct ath_hw *ah)  {  	struct ath_common *common = ath9k_hw_common(ah);  	int r = 0; -	if (common->bus_ops->ath_bus_type != ATH_USB) { -		if (!ath9k_hw_devid_supported(ah->hw_version.devid)) { -			ath_print(common, ATH_DBG_FATAL, -				  "Unsupported device ID: 0x%0x\n", -				  ah->hw_version.devid); -			return -EOPNOTSUPP; -		} -	} - -	ath9k_hw_init_defaults(ah); -	ath9k_hw_init_config(ah); +	if (ah->hw_version.devid == AR5416_AR9100_DEVID) +		ah->hw_version.macVersion = AR_SREV_VERSION_9100;  	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {  		ath_print(common, ATH_DBG_FATAL, @@ -878,6 +525,11 @@ int ath9k_hw_init(struct ath_hw *ah)  		return -EIO;  	} +	ath9k_hw_init_defaults(ah); +	ath9k_hw_init_config(ah); + +	ath9k_hw_attach_ops(ah); +  	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {  		ath_print(common, ATH_DBG_FATAL, "Couldn't wakeup chip\n");  		return -EIO; @@ -902,7 +554,7 @@ int ath9k_hw_init(struct ath_hw *ah)  	else  		ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; -	if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { +	if (!ath9k_hw_macversion_supported(ah)) {  		ath_print(common, ATH_DBG_FATAL,  			  "Mac Chip Rev 0x%02x.%x is not supported by "  			  "this driver\n", ah->hw_version.macVersion, @@ -910,28 +562,15 @@ int ath9k_hw_init(struct ath_hw *ah)  		return -EOPNOTSUPP;  	} -	if (AR_SREV_9100(ah)) { -		ah->iq_caldata.calData = &iq_cal_multi_sample; -		ah->supp_cals = IQ_MISMATCH_CAL; -		ah->is_pciexpress = false; -	} - -	if (AR_SREV_9271(ah)) +	if (AR_SREV_9271(ah) || AR_SREV_9100(ah))  		ah->is_pciexpress = false;  	ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); -  	ath9k_hw_init_cal_settings(ah);  	ah->ani_function = ATH9K_ANI_ALL; -	if (AR_SREV_9280_10_OR_LATER(ah)) { +	if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah))  		ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; -		ah->ath9k_hw_rf_set_freq = &ath9k_hw_ar9280_set_channel; -		ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_9280_spur_mitigate; -	} else { -		ah->ath9k_hw_rf_set_freq = &ath9k_hw_set_channel; -		ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_spur_mitigate; -	}  	ath9k_hw_init_mode_regs(ah); @@ -940,15 +579,8 @@ int ath9k_hw_init(struct ath_hw *ah)  	else  		ath9k_hw_disablepcie(ah); -	/* Support for Japan ch.14 (2484) spread */ -	if (AR_SREV_9287_11_OR_LATER(ah)) { -		INIT_INI_ARRAY(&ah->iniCckfirNormal, -		       ar9287Common_normal_cck_fir_coeff_92871_1, -		       ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_92871_1), 2); -		INIT_INI_ARRAY(&ah->iniCckfirJapan2484, -		       ar9287Common_japan_2484_cck_fir_coeff_92871_1, -		       ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_92871_1), 2); -	} +	if (!AR_SREV_9300_20_OR_LATER(ah)) +		ar9002_hw_cck_chan14_spread(ah);  	r = ath9k_hw_post_init(ah);  	if (r) @@ -959,8 +591,6 @@ int ath9k_hw_init(struct ath_hw *ah)  	if (r)  		return r; -	ath9k_hw_init_eeprom_fix(ah); -  	r = ath9k_hw_init_macaddr(ah);  	if (r) {  		ath_print(common, ATH_DBG_FATAL, @@ -973,6 +603,9 @@ int ath9k_hw_init(struct ath_hw *ah)  	else  		ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); +	if (AR_SREV_9300_20_OR_LATER(ah)) +		ar9003_hw_set_nf_limits(ah); +  	ath9k_init_nfcal_hist_buffer(ah);  	common->state = ATH_HW_INITIALIZED; @@ -980,24 +613,50 @@ int ath9k_hw_init(struct ath_hw *ah)  	return 0;  } -static void ath9k_hw_init_bb(struct ath_hw *ah, -			     struct ath9k_channel *chan) +int ath9k_hw_init(struct ath_hw *ah)  { -	u32 synthDelay; +	int ret; +	struct ath_common *common = ath9k_hw_common(ah); -	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; -	if (IS_CHAN_B(chan)) -		synthDelay = (4 * synthDelay) / 22; -	else -		synthDelay /= 10; +	/* These are all the AR5008/AR9001/AR9002 hardware family of chipsets */ +	switch (ah->hw_version.devid) { +	case AR5416_DEVID_PCI: +	case AR5416_DEVID_PCIE: +	case AR5416_AR9100_DEVID: +	case AR9160_DEVID_PCI: +	case AR9280_DEVID_PCI: +	case AR9280_DEVID_PCIE: +	case AR9285_DEVID_PCIE: +	case AR9287_DEVID_PCI: +	case AR9287_DEVID_PCIE: +	case AR2427_DEVID_PCIE: +	case AR9300_DEVID_PCIE: +		break; +	default: +		if (common->bus_ops->ath_bus_type == ATH_USB) +			break; +		ath_print(common, ATH_DBG_FATAL, +			  "Hardware device ID 0x%04x not supported\n", +			  ah->hw_version.devid); +		return -EOPNOTSUPP; +	} -	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); +	ret = __ath9k_hw_init(ah); +	if (ret) { +		ath_print(common, ATH_DBG_FATAL, +			  "Unable to initialize hardware; " +			  "initialization status: %d\n", ret); +		return ret; +	} -	udelay(synthDelay + BASE_ACTIVATE_DELAY); +	return 0;  } +EXPORT_SYMBOL(ath9k_hw_init);  static void ath9k_hw_init_qos(struct ath_hw *ah)  { +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);  	REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); @@ -1011,69 +670,16 @@ static void ath9k_hw_init_qos(struct ath_hw *ah)  	REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);  	REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);  	REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah);  }  static void ath9k_hw_init_pll(struct ath_hw *ah,  			      struct ath9k_channel *chan)  { -	u32 pll; - -	if (AR_SREV_9100(ah)) { -		if (chan && IS_CHAN_5GHZ(chan)) -			pll = 0x1450; -		else -			pll = 0x1458; -	} else { -		if (AR_SREV_9280_10_OR_LATER(ah)) { -			pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); +	u32 pll = ath9k_hw_compute_pll_control(ah, chan); -			if (chan && IS_CHAN_HALF_RATE(chan)) -				pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); -			else if (chan && IS_CHAN_QUARTER_RATE(chan)) -				pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); - -			if (chan && IS_CHAN_5GHZ(chan)) { -				pll |= SM(0x28, AR_RTC_9160_PLL_DIV); - - -				if (AR_SREV_9280_20(ah)) { -					if (((chan->channel % 20) == 0) -					    || ((chan->channel % 10) == 0)) -						pll = 0x2850; -					else -						pll = 0x142c; -				} -			} else { -				pll |= SM(0x2c, AR_RTC_9160_PLL_DIV); -			} - -		} else if (AR_SREV_9160_10_OR_LATER(ah)) { - -			pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); - -			if (chan && IS_CHAN_HALF_RATE(chan)) -				pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); -			else if (chan && IS_CHAN_QUARTER_RATE(chan)) -				pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); - -			if (chan && IS_CHAN_5GHZ(chan)) -				pll |= SM(0x50, AR_RTC_9160_PLL_DIV); -			else -				pll |= SM(0x58, AR_RTC_9160_PLL_DIV); -		} else { -			pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; - -			if (chan && IS_CHAN_HALF_RATE(chan)) -				pll |= SM(0x1, AR_RTC_PLL_CLKSEL); -			else if (chan && IS_CHAN_QUARTER_RATE(chan)) -				pll |= SM(0x2, AR_RTC_PLL_CLKSEL); - -			if (chan && IS_CHAN_5GHZ(chan)) -				pll |= SM(0xa, AR_RTC_PLL_DIV); -			else -				pll |= SM(0xb, AR_RTC_PLL_DIV); -		} -	}  	REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);  	/* Switch the core clock for ar9271 to 117Mhz */ @@ -1087,43 +693,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,  	REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);  } -static void ath9k_hw_init_chain_masks(struct ath_hw *ah) -{ -	int rx_chainmask, tx_chainmask; - -	rx_chainmask = ah->rxchainmask; -	tx_chainmask = ah->txchainmask; - -	switch (rx_chainmask) { -	case 0x5: -		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, -			    AR_PHY_SWAP_ALT_CHAIN); -	case 0x3: -		if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) { -			REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); -			REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); -			break; -		} -	case 0x1: -	case 0x2: -	case 0x7: -		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); -		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); -		break; -	default: -		break; -	} - -	REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); -	if (tx_chainmask == 0x5) { -		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, -			    AR_PHY_SWAP_ALT_CHAIN); -	} -	if (AR_SREV_9100(ah)) -		REG_WRITE(ah, AR_PHY_ANALOG_SWAP, -			  REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); -} -  static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,  					  enum nl80211_iftype opmode)  { @@ -1133,16 +702,30 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,  		AR_IMR_RXORN |  		AR_IMR_BCNMISC; -	if (ah->config.rx_intr_mitigation) -		imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; -	else -		imr_reg |= AR_IMR_RXOK; +	if (AR_SREV_9300_20_OR_LATER(ah)) { +		imr_reg |= AR_IMR_RXOK_HP; +		if (ah->config.rx_intr_mitigation) +			imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; +		else +			imr_reg |= AR_IMR_RXOK_LP; + +	} else { +		if (ah->config.rx_intr_mitigation) +			imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; +		else +			imr_reg |= AR_IMR_RXOK; +	} -	imr_reg |= AR_IMR_TXOK; +	if (ah->config.tx_intr_mitigation) +		imr_reg |= AR_IMR_TXINTM | AR_IMR_TXMINTR; +	else +		imr_reg |= AR_IMR_TXOK;  	if (opmode == NL80211_IFTYPE_AP)  		imr_reg |= AR_IMR_MIB; +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_IMR, imr_reg);  	ah->imrs2_reg |= AR_IMR_S2_GTT;  	REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); @@ -1152,6 +735,16 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,  		REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);  		REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);  	} + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); + +	if (AR_SREV_9300_20_OR_LATER(ah)) { +		REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0); +		REG_WRITE(ah, AR_INTR_PRIO_ASYNC_MASK, 0); +		REG_WRITE(ah, AR_INTR_PRIO_SYNC_ENABLE, 0); +		REG_WRITE(ah, AR_INTR_PRIO_SYNC_MASK, 0); +	}  }  static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us) @@ -1237,14 +830,10 @@ void ath9k_hw_deinit(struct ath_hw *ah)  	if (common->state < ATH_HW_INITIALIZED)  		goto free_hw; -	if (!AR_SREV_9100(ah)) -		ath9k_hw_ani_disable(ah); -  	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);  free_hw: -	if (!AR_SREV_9280_10_OR_LATER(ah)) -		ath9k_hw_rf_free_ext_banks(ah); +	ath9k_hw_rf_free_ext_banks(ah);  }  EXPORT_SYMBOL(ath9k_hw_deinit); @@ -1252,73 +841,7 @@ EXPORT_SYMBOL(ath9k_hw_deinit);  /* INI */  /*******/ -static void ath9k_hw_override_ini(struct ath_hw *ah, -				  struct ath9k_channel *chan) -{ -	u32 val; - -	/* -	 * Set the RX_ABORT and RX_DIS and clear if off only after -	 * RXE is set for MAC. This prevents frames with corrupted -	 * descriptor status. -	 */ -	REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); - -	if (AR_SREV_9280_10_OR_LATER(ah)) { -		val = REG_READ(ah, AR_PCU_MISC_MODE2); - -		if (!AR_SREV_9271(ah)) -			val &= ~AR_PCU_MISC_MODE2_HWWAR1; - -		if (AR_SREV_9287_10_OR_LATER(ah)) -			val = val & (~AR_PCU_MISC_MODE2_HWWAR2); - -		REG_WRITE(ah, AR_PCU_MISC_MODE2, val); -	} - -	if (!AR_SREV_5416_20_OR_LATER(ah) || -	    AR_SREV_9280_10_OR_LATER(ah)) -		return; -	/* -	 * Disable BB clock gating -	 * Necessary to avoid issues on AR5416 2.0 -	 */ -	REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); - -	/* -	 * Disable RIFS search on some chips to avoid baseband -	 * hang issues. -	 */ -	if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { -		val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS); -		val &= ~AR_PHY_RIFS_INIT_DELAY; -		REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); -	} -} - -static void ath9k_olc_init(struct ath_hw *ah) -{ -	u32 i; - -	if (OLC_FOR_AR9287_10_LATER) { -		REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9, -				AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL); -		ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0, -				AR9287_AN_TXPC0_TXPCMODE, -				AR9287_AN_TXPC0_TXPCMODE_S, -				AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE); -		udelay(100); -	} else { -		for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) -			ah->originalGain[i] = -				MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), -						AR_PHY_TX_GAIN); -		ah->PDADCdelta = 0; -	} -} - -static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, -			      struct ath9k_channel *chan) +u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan)  {  	u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); @@ -1332,193 +855,24 @@ static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg,  	return ctl;  } -static int ath9k_hw_process_ini(struct ath_hw *ah, -				struct ath9k_channel *chan) -{ -	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); -	int i, regWrites = 0; -	struct ieee80211_channel *channel = chan->chan; -	u32 modesIndex, freqIndex; - -	switch (chan->chanmode) { -	case CHANNEL_A: -	case CHANNEL_A_HT20: -		modesIndex = 1; -		freqIndex = 1; -		break; -	case CHANNEL_A_HT40PLUS: -	case CHANNEL_A_HT40MINUS: -		modesIndex = 2; -		freqIndex = 1; -		break; -	case CHANNEL_G: -	case CHANNEL_G_HT20: -	case CHANNEL_B: -		modesIndex = 4; -		freqIndex = 2; -		break; -	case CHANNEL_G_HT40PLUS: -	case CHANNEL_G_HT40MINUS: -		modesIndex = 3; -		freqIndex = 2; -		break; - -	default: -		return -EINVAL; -	} - -	/* Set correct baseband to analog shift setting to access analog chips */ -	REG_WRITE(ah, AR_PHY(0), 0x00000007); - -	/* Write ADDAC shifts */ -	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); -	ah->eep_ops->set_addac(ah, chan); - -	if (AR_SREV_5416_22_OR_LATER(ah)) { -		REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); -	} else { -		struct ar5416IniArray temp; -		u32 addacSize = -			sizeof(u32) * ah->iniAddac.ia_rows * -			ah->iniAddac.ia_columns; - -		/* For AR5416 2.0/2.1 */ -		memcpy(ah->addac5416_21, -		       ah->iniAddac.ia_array, addacSize); - -		/* override CLKDRV value at [row, column] = [31, 1] */ -		(ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; - -		temp.ia_array = ah->addac5416_21; -		temp.ia_columns = ah->iniAddac.ia_columns; -		temp.ia_rows = ah->iniAddac.ia_rows; -		REG_WRITE_ARRAY(&temp, 1, regWrites); -	} - -	REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); - -	for (i = 0; i < ah->iniModes.ia_rows; i++) { -		u32 reg = INI_RA(&ah->iniModes, i, 0); -		u32 val = INI_RA(&ah->iniModes, i, modesIndex); - -		if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup) -			val &= ~AR_AN_TOP2_PWDCLKIND; - -		REG_WRITE(ah, reg, val); - -		if (reg >= 0x7800 && reg < 0x78a0 -		    && ah->config.analog_shiftreg) { -			udelay(100); -		} - -		DO_DELAY(regWrites); -	} - -	if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah)) -		REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); - -	if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) || -	    AR_SREV_9287_10_OR_LATER(ah)) -		REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); - -	if (AR_SREV_9271_10(ah)) -		REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, -				modesIndex, regWrites); - -	/* Write common array parameters */ -	for (i = 0; i < ah->iniCommon.ia_rows; i++) { -		u32 reg = INI_RA(&ah->iniCommon, i, 0); -		u32 val = INI_RA(&ah->iniCommon, i, 1); - -		REG_WRITE(ah, reg, val); - -		if (reg >= 0x7800 && reg < 0x78a0 -		    && ah->config.analog_shiftreg) { -			udelay(100); -		} - -		DO_DELAY(regWrites); -	} - -	if (AR_SREV_9271(ah)) { -		if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) -			REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271, -					modesIndex, regWrites); -		else -			REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271, -					modesIndex, regWrites); -	} - -	ath9k_hw_write_regs(ah, freqIndex, regWrites); - -	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { -		REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, -				regWrites); -	} - -	ath9k_hw_override_ini(ah, chan); -	ath9k_hw_set_regs(ah, chan); -	ath9k_hw_init_chain_masks(ah); - -	if (OLC_FOR_AR9280_20_LATER) -		ath9k_olc_init(ah); - -	/* Set TX power */ -	ah->eep_ops->set_txpower(ah, chan, -				 ath9k_regd_get_ctl(regulatory, chan), -				 channel->max_antenna_gain * 2, -				 channel->max_power * 2, -				 min((u32) MAX_RATE_POWER, -				 (u32) regulatory->power_limit)); - -	/* Write analog registers */ -	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { -		ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, -			  "ar5416SetRfRegs failed\n"); -		return -EIO; -	} - -	return 0; -} -  /****************************************/  /* Reset and Channel Switching Routines */  /****************************************/ -static void ath9k_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) -{ -	u32 rfMode = 0; - -	if (chan == NULL) -		return; - -	rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) -		? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; - -	if (!AR_SREV_9280_10_OR_LATER(ah)) -		rfMode |= (IS_CHAN_5GHZ(chan)) ? -			AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; - -	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) -		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); - -	REG_WRITE(ah, AR_PHY_MODE, rfMode); -} - -static void ath9k_hw_mark_phy_inactive(struct ath_hw *ah) -{ -	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); -} -  static inline void ath9k_hw_set_dma(struct ath_hw *ah)  { +	struct ath_common *common = ath9k_hw_common(ah);  	u32 regval; +	ENABLE_REGWRITE_BUFFER(ah); +  	/*  	 * set AHB_MODE not to do cacheline prefetches  	*/ -	regval = REG_READ(ah, AR_AHB_MODE); -	REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); +	if (!AR_SREV_9300_20_OR_LATER(ah)) { +		regval = REG_READ(ah, AR_AHB_MODE); +		REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); +	}  	/*  	 * let mac dma reads be in 128 byte chunks @@ -1526,12 +880,18 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)  	regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;  	REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +  	/*  	 * Restore TX Trigger Level to its pre-reset value.  	 * The initial value depends on whether aggregation is enabled, and is  	 * adjusted whenever underruns are detected.  	 */ -	REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); +	if (!AR_SREV_9300_20_OR_LATER(ah)) +		REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); + +	ENABLE_REGWRITE_BUFFER(ah);  	/*  	 * let mac dma writes be in 128 byte chunks @@ -1544,6 +904,14 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)  	 */  	REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); +	if (AR_SREV_9300_20_OR_LATER(ah)) { +		REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_HP, 0x1); +		REG_RMW_FIELD(ah, AR_RXBP_THRESH, AR_RXBP_THRESH_LP, 0x1); + +		ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - +			ah->caps.rx_status_len); +	} +  	/*  	 * reduce the number of usable entries in PCU TXBUF to avoid  	 * wrap around issues. @@ -1559,6 +927,12 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah)  		REG_WRITE(ah, AR_PCU_TXBUF_CTRL,  			  AR_PCU_TXBUF_CTRL_USABLE_SIZE);  	} + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); + +	if (AR_SREV_9300_20_OR_LATER(ah)) +		ath9k_hw_reset_txstatus_ring(ah);  }  static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) @@ -1586,10 +960,8 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)  	}  } -static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, -						 u32 coef_scaled, -						 u32 *coef_mantissa, -						 u32 *coef_exponent) +void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, +				   u32 *coef_mantissa, u32 *coef_exponent)  {  	u32 coef_exp, coef_man; @@ -1605,40 +977,6 @@ static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah,  	*coef_exponent = coef_exp - 16;  } -static void ath9k_hw_set_delta_slope(struct ath_hw *ah, -				     struct ath9k_channel *chan) -{ -	u32 coef_scaled, ds_coef_exp, ds_coef_man; -	u32 clockMhzScaled = 0x64000000; -	struct chan_centers centers; - -	if (IS_CHAN_HALF_RATE(chan)) -		clockMhzScaled = clockMhzScaled >> 1; -	else if (IS_CHAN_QUARTER_RATE(chan)) -		clockMhzScaled = clockMhzScaled >> 2; - -	ath9k_hw_get_channel_centers(ah, chan, ¢ers); -	coef_scaled = clockMhzScaled / centers.synth_center; - -	ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, -				      &ds_coef_exp); - -	REG_RMW_FIELD(ah, AR_PHY_TIMING3, -		      AR_PHY_TIMING3_DSC_MAN, ds_coef_man); -	REG_RMW_FIELD(ah, AR_PHY_TIMING3, -		      AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); - -	coef_scaled = (9 * coef_scaled) / 10; - -	ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, -				      &ds_coef_exp); - -	REG_RMW_FIELD(ah, AR_PHY_HALFGI, -		      AR_PHY_HALFGI_DSC_MAN, ds_coef_man); -	REG_RMW_FIELD(ah, AR_PHY_HALFGI, -		      AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); -} -  static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)  {  	u32 rst_flags; @@ -1652,6 +990,8 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)  		(void)REG_READ(ah, AR_RTC_DERIVED_CLK);  	} +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |  		  AR_RTC_FORCE_WAKE_ON_INT); @@ -1663,11 +1003,16 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)  		if (tmpReg &  		    (AR_INTR_SYNC_LOCAL_TIMEOUT |  		     AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { +			u32 val;  			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); -			REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); -		} else { + +			val = AR_RC_HOSTIF; +			if (!AR_SREV_9300_20_OR_LATER(ah)) +				val |= AR_RC_AHB; +			REG_WRITE(ah, AR_RC, val); + +		} else if (!AR_SREV_9300_20_OR_LATER(ah))  			REG_WRITE(ah, AR_RC, AR_RC_AHB); -		}  		rst_flags = AR_RTC_RC_MAC_WARM;  		if (type == ATH9K_RESET_COLD) @@ -1675,6 +1020,10 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)  	}  	REG_WRITE(ah, AR_RTC_RC, rst_flags); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +  	udelay(50);  	REG_WRITE(ah, AR_RTC_RC, 0); @@ -1695,16 +1044,23 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)  static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)  { +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |  		  AR_RTC_FORCE_WAKE_ON_INT); -	if (!AR_SREV_9100(ah)) +	if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))  		REG_WRITE(ah, AR_RC, AR_RC_AHB);  	REG_WRITE(ah, AR_RTC_RESET, 0); -	udelay(2); -	if (!AR_SREV_9100(ah)) +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); + +	if (!AR_SREV_9300_20_OR_LATER(ah)) +		udelay(2); + +	if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))  		REG_WRITE(ah, AR_RC, 0);  	REG_WRITE(ah, AR_RTC_RESET, 1); @@ -1740,34 +1096,6 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)  	}  } -static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan) -{ -	u32 phymode; -	u32 enableDacFifo = 0; - -	if (AR_SREV_9285_10_OR_LATER(ah)) -		enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) & -					 AR_PHY_FC_ENABLE_DAC_FIFO); - -	phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 -		| AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo; - -	if (IS_CHAN_HT40(chan)) { -		phymode |= AR_PHY_FC_DYN2040_EN; - -		if ((chan->chanmode == CHANNEL_A_HT40PLUS) || -		    (chan->chanmode == CHANNEL_G_HT40PLUS)) -			phymode |= AR_PHY_FC_DYN2040_PRI_CH; - -	} -	REG_WRITE(ah, AR_PHY_TURBO, phymode); - -	ath9k_hw_set11nmac2040(ah); - -	REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); -	REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); -} -  static bool ath9k_hw_chip_reset(struct ath_hw *ah,  				struct ath9k_channel *chan)  { @@ -1793,7 +1121,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,  	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);  	struct ath_common *common = ath9k_hw_common(ah);  	struct ieee80211_channel *channel = chan->chan; -	u32 synthDelay, qnum; +	u32 qnum;  	int r;  	for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { @@ -1805,17 +1133,15 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,  		}  	} -	REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); -	if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, -			   AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { +	if (!ath9k_hw_rfbus_req(ah)) {  		ath_print(common, ATH_DBG_FATAL,  			  "Could not kill baseband RX\n");  		return false;  	} -	ath9k_hw_set_regs(ah, chan); +	ath9k_hw_set_channel_regs(ah, chan); -	r = ah->ath9k_hw_rf_set_freq(ah, chan); +	r = ath9k_hw_rf_set_freq(ah, chan);  	if (r) {  		ath_print(common, ATH_DBG_FATAL,  			  "Failed to set channel\n"); @@ -1829,20 +1155,12 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,  			     min((u32) MAX_RATE_POWER,  			     (u32) regulatory->power_limit)); -	synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; -	if (IS_CHAN_B(chan)) -		synthDelay = (4 * synthDelay) / 22; -	else -		synthDelay /= 10; - -	udelay(synthDelay + BASE_ACTIVATE_DELAY); - -	REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); +	ath9k_hw_rfbus_done(ah);  	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))  		ath9k_hw_set_delta_slope(ah, chan); -	ah->ath9k_hw_spur_mitigate_freq(ah, chan); +	ath9k_hw_spur_mitigate_freq(ah, chan);  	if (!chan->oneTimeCalsDone)  		chan->oneTimeCalsDone = true; @@ -1850,17 +1168,33 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,  	return true;  } -static void ath9k_enable_rfkill(struct ath_hw *ah) +bool ath9k_hw_check_alive(struct ath_hw *ah)  { -	REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, -		    AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); +	int count = 50; +	u32 reg; + +	if (AR_SREV_9285_10_OR_LATER(ah)) +		return true; + +	do { +		reg = REG_READ(ah, AR_OBS_BUS_1); -	REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, -		    AR_GPIO_INPUT_MUX2_RFSILENT); +		if ((reg & 0x7E7FFFEF) == 0x00702400) +			continue; -	ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); -	REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); +		switch (reg & 0x7E000B00) { +		case 0x1E000000: +		case 0x52000B00: +		case 0x18000B00: +			continue; +		default: +			return true; +		} +	} while (count-- > 0); + +	return false;  } +EXPORT_SYMBOL(ath9k_hw_check_alive);  int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  		    bool bChannelChange) @@ -1871,11 +1205,18 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  	u32 saveDefAntenna;  	u32 macStaId1;  	u64 tsf = 0; -	int i, rx_chainmask, r; +	int i, r;  	ah->txchainmask = common->tx_chainmask;  	ah->rxchainmask = common->rx_chainmask; +	if (!ah->chip_fullsleep) { +		ath9k_hw_abortpcurecv(ah); +		if (!ath9k_hw_stopdmarecv(ah)) +			ath_print(common, ATH_DBG_XMIT, +				"Failed to stop receive dma\n"); +	} +  	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))  		return -EIO; @@ -1888,8 +1229,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  	    (chan->channel != ah->curchan->channel) &&  	    ((chan->channelFlags & CHANNEL_ALL) ==  	     (ah->curchan->channelFlags & CHANNEL_ALL)) && -	     !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) || -	     IS_CHAN_A_5MHZ_SPACED(ah->curchan))) { +	    !AR_SREV_9280(ah)) {  		if (ath9k_hw_channel_change(ah, chan)) {  			ath9k_hw_loadnf(ah, ah->curchan); @@ -1943,16 +1283,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  	if (AR_SREV_9280_10_OR_LATER(ah))  		REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); -	if (AR_SREV_9287_12_OR_LATER(ah)) { -		/* Enable ASYNC FIFO */ -		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, -				AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); -		REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); -		REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, -				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); -		REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, -				AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); -	}  	r = ath9k_hw_process_ini(ah, chan);  	if (r)  		return r; @@ -1977,9 +1307,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  	if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))  		ath9k_hw_set_delta_slope(ah, chan); -	ah->ath9k_hw_spur_mitigate_freq(ah, chan); +	ath9k_hw_spur_mitigate_freq(ah, chan);  	ah->eep_ops->set_board_values(ah, chan); +	ath9k_hw_set_operating_mode(ah, ah->opmode); + +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));  	REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)  		  | macStaId1 @@ -1987,25 +1321,27 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  		  | (ah->config.  		     ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0)  		  | ah->sta_id1_defaults); -	ath9k_hw_set_operating_mode(ah, ah->opmode); -  	ath_hw_setbssidmask(common); -  	REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); -  	ath9k_hw_write_associd(ah); -  	REG_WRITE(ah, AR_ISR, ~0); -  	REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); -	r = ah->ath9k_hw_rf_set_freq(ah, chan); +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); + +	r = ath9k_hw_rf_set_freq(ah, chan);  	if (r)  		return r; +	ENABLE_REGWRITE_BUFFER(ah); +  	for (i = 0; i < AR_NUM_DCU; i++)  		REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +  	ah->intr_txqs = 0;  	for (i = 0; i < ah->caps.total_queues; i++)  		ath9k_hw_resettxqueue(ah, i); @@ -2018,25 +1354,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  	ath9k_hw_init_global_settings(ah); -	if (AR_SREV_9287_12_OR_LATER(ah)) { -		REG_WRITE(ah, AR_D_GBL_IFS_SIFS, -			  AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); -		REG_WRITE(ah, AR_D_GBL_IFS_SLOT, -			  AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR); -		REG_WRITE(ah, AR_D_GBL_IFS_EIFS, -			  AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR); - -		REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR); -		REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR); - -		REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, -			    AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); -		REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, -			      AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); -	} -	if (AR_SREV_9287_12_OR_LATER(ah)) { -		REG_SET_BIT(ah, AR_PCU_MISC_MODE2, -				AR_PCU_MISC_MODE2_ENABLE_AGGWEP); +	if (!AR_SREV_9300_20_OR_LATER(ah)) { +		ar9002_hw_enable_async_fifo(ah); +		ar9002_hw_enable_wep_aggregation(ah);  	}  	REG_WRITE(ah, AR_STA_ID1, @@ -2051,19 +1371,24 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);  	} +	if (ah->config.tx_intr_mitigation) { +		REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300); +		REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750); +	} +  	ath9k_hw_init_bb(ah, chan);  	if (!ath9k_hw_init_cal(ah, chan))  		return -EIO; -	rx_chainmask = ah->rxchainmask; -	if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { -		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); -		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); -	} +	ENABLE_REGWRITE_BUFFER(ah); +	ath9k_hw_restore_chainmask(ah);  	REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +  	/*  	 * For big endian systems turn on swapping for descriptors  	 */ @@ -2093,6 +1418,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  	if (ah->btcoex_hw.enabled)  		ath9k_hw_btcoex_enable(ah); +	if (AR_SREV_9300_20_OR_LATER(ah)) { +		ath9k_hw_loadnf(ah, curchan); +		ath9k_hw_start_nfcal(ah); +	} +  	return 0;  }  EXPORT_SYMBOL(ath9k_hw_reset); @@ -2379,21 +1709,35 @@ EXPORT_SYMBOL(ath9k_hw_keyisvalid);  /* Power Management (Chipset) */  /******************************/ +/* + * Notify Power Mgt is disabled in self-generated frames. + * If requested, force chip to sleep. + */  static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)  {  	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);  	if (setChip) { +		/* +		 * Clear the RTC force wake bit to allow the +		 * mac to go to sleep. +		 */  		REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,  			    AR_RTC_FORCE_WAKE_EN); -		if (!AR_SREV_9100(ah)) +		if (!AR_SREV_9100(ah) && !AR_SREV_9300_20_OR_LATER(ah))  			REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); +		/* Shutdown chip. Active low */  		if (!AR_SREV_5416(ah) && !AR_SREV_9271(ah))  			REG_CLR_BIT(ah, (AR_RTC_RESET),  				    AR_RTC_RESET_EN);  	}  } +/* + * Notify Power Management is enabled in self-generating + * frames. If request, set power mode of chip to + * auto/normal.  Duration in units of 128us (1/8 TU). + */  static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)  {  	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); @@ -2401,9 +1745,14 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)  		struct ath9k_hw_capabilities *pCap = &ah->caps;  		if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { +			/* Set WakeOnInterrupt bit; clear ForceWake bit */  			REG_WRITE(ah, AR_RTC_FORCE_WAKE,  				  AR_RTC_FORCE_WAKE_ON_INT);  		} else { +			/* +			 * Clear the RTC force wake bit to allow the +			 * mac to go to sleep. +			 */  			REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,  				    AR_RTC_FORCE_WAKE_EN);  		} @@ -2422,7 +1771,8 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)  					   ATH9K_RESET_POWER_ON) != true) {  				return false;  			} -			ath9k_hw_init_pll(ah, NULL); +			if (!AR_SREV_9300_20_OR_LATER(ah)) +				ath9k_hw_init_pll(ah, NULL);  		}  		if (AR_SREV_9100(ah))  			REG_SET_BIT(ah, AR_RTC_RESET, @@ -2492,420 +1842,6 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)  }  EXPORT_SYMBOL(ath9k_hw_setpower); -/* - * Helper for ASPM support. - * - * Disable PLL when in L0s as well as receiver clock when in L1. - * This power saving option must be enabled through the SerDes. - * - * Programming the SerDes must go through the same 288 bit serial shift - * register as the other analog registers.  Hence the 9 writes. - */ -void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) -{ -	u8 i; -	u32 val; - -	if (ah->is_pciexpress != true) -		return; - -	/* Do not touch SerDes registers */ -	if (ah->config.pcie_powersave_enable == 2) -		return; - -	/* Nothing to do on restore for 11N */ -	if (!restore) { -		if (AR_SREV_9280_20_OR_LATER(ah)) { -			/* -			 * AR9280 2.0 or later chips use SerDes values from the -			 * initvals.h initialized depending on chipset during -			 * ath9k_hw_init() -			 */ -			for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { -				REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), -					  INI_RA(&ah->iniPcieSerdes, i, 1)); -			} -		} else if (AR_SREV_9280(ah) && -			   (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { -			REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); -			REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - -			/* RX shut off when elecidle is asserted */ -			REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); -			REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); -			REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); - -			/* Shut off CLKREQ active in L1 */ -			if (ah->config.pcie_clock_req) -				REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); -			else -				REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); - -			REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); -			REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); -			REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); - -			/* Load the new settings */ -			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - -		} else { -			REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); -			REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - -			/* RX shut off when elecidle is asserted */ -			REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); -			REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); -			REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); - -			/* -			 * Ignore ah->ah_config.pcie_clock_req setting for -			 * pre-AR9280 11n -			 */ -			REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); - -			REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); -			REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); -			REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); - -			/* Load the new settings */ -			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); -		} - -		udelay(1000); - -		/* set bit 19 to allow forcing of pcie core into L1 state */ -		REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); - -		/* Several PCIe massages to ensure proper behaviour */ -		if (ah->config.pcie_waen) { -			val = ah->config.pcie_waen; -			if (!power_off) -				val &= (~AR_WA_D3_L1_DISABLE); -		} else { -			if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || -			    AR_SREV_9287(ah)) { -				val = AR9285_WA_DEFAULT; -				if (!power_off) -					val &= (~AR_WA_D3_L1_DISABLE); -			} else if (AR_SREV_9280(ah)) { -				/* -				 * On AR9280 chips bit 22 of 0x4004 needs to be -				 * set otherwise card may disappear. -				 */ -				val = AR9280_WA_DEFAULT; -				if (!power_off) -					val &= (~AR_WA_D3_L1_DISABLE); -			} else -				val = AR_WA_DEFAULT; -		} - -		REG_WRITE(ah, AR_WA, val); -	} - -	if (power_off) { -		/* -		 * Set PCIe workaround bits -		 * bit 14 in WA register (disable L1) should only -		 * be set when device enters D3 and be cleared -		 * when device comes back to D0. -		 */ -		if (ah->config.pcie_waen) { -			if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) -				REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); -		} else { -			if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) || -			      AR_SREV_9287(ah)) && -			     (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || -			    (AR_SREV_9280(ah) && -			     (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { -				REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); -			} -		} -	} -} -EXPORT_SYMBOL(ath9k_hw_configpcipowersave); - -/**********************/ -/* Interrupt Handling */ -/**********************/ - -bool ath9k_hw_intrpend(struct ath_hw *ah) -{ -	u32 host_isr; - -	if (AR_SREV_9100(ah)) -		return true; - -	host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); -	if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) -		return true; - -	host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); -	if ((host_isr & AR_INTR_SYNC_DEFAULT) -	    && (host_isr != AR_INTR_SPURIOUS)) -		return true; - -	return false; -} -EXPORT_SYMBOL(ath9k_hw_intrpend); - -bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) -{ -	u32 isr = 0; -	u32 mask2 = 0; -	struct ath9k_hw_capabilities *pCap = &ah->caps; -	u32 sync_cause = 0; -	bool fatal_int = false; -	struct ath_common *common = ath9k_hw_common(ah); - -	if (!AR_SREV_9100(ah)) { -		if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { -			if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) -			    == AR_RTC_STATUS_ON) { -				isr = REG_READ(ah, AR_ISR); -			} -		} - -		sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & -			AR_INTR_SYNC_DEFAULT; - -		*masked = 0; - -		if (!isr && !sync_cause) -			return false; -	} else { -		*masked = 0; -		isr = REG_READ(ah, AR_ISR); -	} - -	if (isr) { -		if (isr & AR_ISR_BCNMISC) { -			u32 isr2; -			isr2 = REG_READ(ah, AR_ISR_S2); -			if (isr2 & AR_ISR_S2_TIM) -				mask2 |= ATH9K_INT_TIM; -			if (isr2 & AR_ISR_S2_DTIM) -				mask2 |= ATH9K_INT_DTIM; -			if (isr2 & AR_ISR_S2_DTIMSYNC) -				mask2 |= ATH9K_INT_DTIMSYNC; -			if (isr2 & (AR_ISR_S2_CABEND)) -				mask2 |= ATH9K_INT_CABEND; -			if (isr2 & AR_ISR_S2_GTT) -				mask2 |= ATH9K_INT_GTT; -			if (isr2 & AR_ISR_S2_CST) -				mask2 |= ATH9K_INT_CST; -			if (isr2 & AR_ISR_S2_TSFOOR) -				mask2 |= ATH9K_INT_TSFOOR; -		} - -		isr = REG_READ(ah, AR_ISR_RAC); -		if (isr == 0xffffffff) { -			*masked = 0; -			return false; -		} - -		*masked = isr & ATH9K_INT_COMMON; - -		if (ah->config.rx_intr_mitigation) { -			if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) -				*masked |= ATH9K_INT_RX; -		} - -		if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) -			*masked |= ATH9K_INT_RX; -		if (isr & -		    (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | -		     AR_ISR_TXEOL)) { -			u32 s0_s, s1_s; - -			*masked |= ATH9K_INT_TX; - -			s0_s = REG_READ(ah, AR_ISR_S0_S); -			ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); -			ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); - -			s1_s = REG_READ(ah, AR_ISR_S1_S); -			ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); -			ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); -		} - -		if (isr & AR_ISR_RXORN) { -			ath_print(common, ATH_DBG_INTERRUPT, -				  "receive FIFO overrun interrupt\n"); -		} - -		if (!AR_SREV_9100(ah)) { -			if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { -				u32 isr5 = REG_READ(ah, AR_ISR_S5_S); -				if (isr5 & AR_ISR_S5_TIM_TIMER) -					*masked |= ATH9K_INT_TIM_TIMER; -			} -		} - -		*masked |= mask2; -	} - -	if (AR_SREV_9100(ah)) -		return true; - -	if (isr & AR_ISR_GENTMR) { -		u32 s5_s; - -		s5_s = REG_READ(ah, AR_ISR_S5_S); -		if (isr & AR_ISR_GENTMR) { -			ah->intr_gen_timer_trigger = -				MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); - -			ah->intr_gen_timer_thresh = -				MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); - -			if (ah->intr_gen_timer_trigger) -				*masked |= ATH9K_INT_GENTIMER; - -		} -	} - -	if (sync_cause) { -		fatal_int = -			(sync_cause & -			 (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) -			? true : false; - -		if (fatal_int) { -			if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { -				ath_print(common, ATH_DBG_ANY, -					  "received PCI FATAL interrupt\n"); -			} -			if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { -				ath_print(common, ATH_DBG_ANY, -					  "received PCI PERR interrupt\n"); -			} -			*masked |= ATH9K_INT_FATAL; -		} -		if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { -			ath_print(common, ATH_DBG_INTERRUPT, -				  "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); -			REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); -			REG_WRITE(ah, AR_RC, 0); -			*masked |= ATH9K_INT_FATAL; -		} -		if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { -			ath_print(common, ATH_DBG_INTERRUPT, -				  "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); -		} - -		REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); -		(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); -	} - -	return true; -} -EXPORT_SYMBOL(ath9k_hw_getisr); - -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) -{ -	enum ath9k_int omask = ah->imask; -	u32 mask, mask2; -	struct ath9k_hw_capabilities *pCap = &ah->caps; -	struct ath_common *common = ath9k_hw_common(ah); - -	ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); - -	if (omask & ATH9K_INT_GLOBAL) { -		ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); -		REG_WRITE(ah, AR_IER, AR_IER_DISABLE); -		(void) REG_READ(ah, AR_IER); -		if (!AR_SREV_9100(ah)) { -			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); -			(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); - -			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); -			(void) REG_READ(ah, AR_INTR_SYNC_ENABLE); -		} -	} - -	mask = ints & ATH9K_INT_COMMON; -	mask2 = 0; - -	if (ints & ATH9K_INT_TX) { -		if (ah->txok_interrupt_mask) -			mask |= AR_IMR_TXOK; -		if (ah->txdesc_interrupt_mask) -			mask |= AR_IMR_TXDESC; -		if (ah->txerr_interrupt_mask) -			mask |= AR_IMR_TXERR; -		if (ah->txeol_interrupt_mask) -			mask |= AR_IMR_TXEOL; -	} -	if (ints & ATH9K_INT_RX) { -		mask |= AR_IMR_RXERR; -		if (ah->config.rx_intr_mitigation) -			mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; -		else -			mask |= AR_IMR_RXOK | AR_IMR_RXDESC; -		if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) -			mask |= AR_IMR_GENTMR; -	} - -	if (ints & (ATH9K_INT_BMISC)) { -		mask |= AR_IMR_BCNMISC; -		if (ints & ATH9K_INT_TIM) -			mask2 |= AR_IMR_S2_TIM; -		if (ints & ATH9K_INT_DTIM) -			mask2 |= AR_IMR_S2_DTIM; -		if (ints & ATH9K_INT_DTIMSYNC) -			mask2 |= AR_IMR_S2_DTIMSYNC; -		if (ints & ATH9K_INT_CABEND) -			mask2 |= AR_IMR_S2_CABEND; -		if (ints & ATH9K_INT_TSFOOR) -			mask2 |= AR_IMR_S2_TSFOOR; -	} - -	if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { -		mask |= AR_IMR_BCNMISC; -		if (ints & ATH9K_INT_GTT) -			mask2 |= AR_IMR_S2_GTT; -		if (ints & ATH9K_INT_CST) -			mask2 |= AR_IMR_S2_CST; -	} - -	ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); -	REG_WRITE(ah, AR_IMR, mask); -	ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | -			   AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | -			   AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); -	ah->imrs2_reg |= mask2; -	REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); - -	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { -		if (ints & ATH9K_INT_TIM_TIMER) -			REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); -		else -			REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); -	} - -	if (ints & ATH9K_INT_GLOBAL) { -		ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); -		REG_WRITE(ah, AR_IER, AR_IER_ENABLE); -		if (!AR_SREV_9100(ah)) { -			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, -				  AR_INTR_MAC_IRQ); -			REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - - -			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, -				  AR_INTR_SYNC_DEFAULT); -			REG_WRITE(ah, AR_INTR_SYNC_MASK, -				  AR_INTR_SYNC_DEFAULT); -		} -		ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", -			  REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); -	} - -	return omask; -} -EXPORT_SYMBOL(ath9k_hw_set_interrupts); -  /*******************/  /* Beacon Handling */  /*******************/ @@ -2916,6 +1852,8 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)  	ah->beacon_interval = beacon_period; +	ENABLE_REGWRITE_BUFFER(ah); +  	switch (ah->opmode) {  	case NL80211_IFTYPE_STATION:  	case NL80211_IFTYPE_MONITOR: @@ -2959,6 +1897,9 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)  	REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period));  	REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +  	beacon_period &= ~ATH9K_BEACON_ENA;  	if (beacon_period & ATH9K_BEACON_RESET_TSF) {  		ath9k_hw_reset_tsf(ah); @@ -2975,6 +1916,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,  	struct ath9k_hw_capabilities *pCap = &ah->caps;  	struct ath_common *common = ath9k_hw_common(ah); +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));  	REG_WRITE(ah, AR_BEACON_PERIOD, @@ -2982,6 +1925,9 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,  	REG_WRITE(ah, AR_DMA_BEACON_PERIOD,  		  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +  	REG_RMW_FIELD(ah, AR_RSSI_THR,  		      AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); @@ -3004,6 +1950,8 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,  	ath_print(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval);  	ath_print(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_NEXT_DTIM,  		  TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));  	REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); @@ -3023,6 +1971,9 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,  	REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));  	REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +  	REG_SET_BIT(ah, AR_TIMER_MODE,  		    AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN |  		    AR_DTIM_TIMER_EN); @@ -3241,6 +2192,26 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)  		btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE;  	} +	if (AR_SREV_9300_20_OR_LATER(ah)) { +		pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC | +				 ATH9K_HW_CAP_FASTCLOCK; +		pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; +		pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH; +		pCap->rx_status_len = sizeof(struct ar9003_rxs); +		pCap->tx_desc_len = sizeof(struct ar9003_txc); +		pCap->txs_len = sizeof(struct ar9003_txs); +	} else { +		pCap->tx_desc_len = sizeof(struct ath_desc); +		if (AR_SREV_9280_20(ah) && +		    ((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <= +		      AR5416_EEP_MINOR_VER_16) || +		     ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G))) +			pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK; +	} + +	if (AR_SREV_9300_20_OR_LATER(ah)) +		pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; +  	return 0;  } @@ -3273,10 +2244,6 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,  	case ATH9K_CAP_TKIP_SPLIT:  		return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ?  			false : true; -	case ATH9K_CAP_DIVERSITY: -		return (REG_READ(ah, AR_PHY_CCK_DETECT) & -			AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ? -			true : false;  	case ATH9K_CAP_MCAST_KEYSRCH:  		switch (capability) {  		case 0: @@ -3319,8 +2286,6 @@ EXPORT_SYMBOL(ath9k_hw_getcapability);  bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,  			    u32 capability, u32 setting, int *status)  { -	u32 v; -  	switch (type) {  	case ATH9K_CAP_TKIP_MIC:  		if (setting) @@ -3330,14 +2295,6 @@ bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,  			ah->sta_id1_defaults &=  				~AR_STA_ID1_CRPT_MIC_ENABLE;  		return true; -	case ATH9K_CAP_DIVERSITY: -		v = REG_READ(ah, AR_PHY_CCK_DETECT); -		if (setting) -			v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; -		else -			v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; -		REG_WRITE(ah, AR_PHY_CCK_DETECT, v); -		return true;  	case ATH9K_CAP_MCAST_KEYSRCH:  		if (setting)  			ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH; @@ -3405,7 +2362,9 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)  	if (gpio >= ah->caps.num_gpio_pins)  		return 0xffffffff; -	if (AR_SREV_9271(ah)) +	if (AR_SREV_9300_20_OR_LATER(ah)) +		return MS_REG_READ(AR9300, gpio) != 0; +	else if (AR_SREV_9271(ah))  		return MS_REG_READ(AR9271, gpio) != 0;  	else if (AR_SREV_9287_10_OR_LATER(ah))  		return MS_REG_READ(AR9287, gpio) != 0; @@ -3478,6 +2437,8 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)  {  	u32 phybits; +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_RX_FILTER, bits);  	phybits = 0; @@ -3493,6 +2454,9 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)  	else  		REG_WRITE(ah, AR_RXCFG,  			  REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah);  }  EXPORT_SYMBOL(ath9k_hw_setrxfilter); @@ -3565,14 +2529,25 @@ void ath9k_hw_write_associd(struct ath_hw *ah)  }  EXPORT_SYMBOL(ath9k_hw_write_associd); +#define ATH9K_MAX_TSF_READ 10 +  u64 ath9k_hw_gettsf64(struct ath_hw *ah)  { -	u64 tsf; +	u32 tsf_lower, tsf_upper1, tsf_upper2; +	int i; + +	tsf_upper1 = REG_READ(ah, AR_TSF_U32); +	for (i = 0; i < ATH9K_MAX_TSF_READ; i++) { +		tsf_lower = REG_READ(ah, AR_TSF_L32); +		tsf_upper2 = REG_READ(ah, AR_TSF_U32); +		if (tsf_upper2 == tsf_upper1) +			break; +		tsf_upper1 = tsf_upper2; +	} -	tsf = REG_READ(ah, AR_TSF_U32); -	tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32); +	WARN_ON( i == ATH9K_MAX_TSF_READ ); -	return tsf; +	return (((u64)tsf_upper1 << 32) | tsf_lower);  }  EXPORT_SYMBOL(ath9k_hw_gettsf64); @@ -3847,6 +2822,7 @@ static struct {  	{ AR_SREV_VERSION_9285,		"9285" },  	{ AR_SREV_VERSION_9287,         "9287" },  	{ AR_SREV_VERSION_9271,         "9271" }, +	{ AR_SREV_VERSION_9300,         "9300" },  };  /* For devices with external radios */ diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index f4821cf33b8..77245dff599 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2008-2009 Atheros Communications Inc. + * Copyright (c) 2008-2010 Atheros Communications Inc.   *   * Permission to use, copy, modify, and/or distribute this software for any   * purpose with or without fee is hereby granted, provided that the above @@ -41,6 +41,9 @@  #define AR9280_DEVID_PCIE	0x002a  #define AR9285_DEVID_PCIE	0x002b  #define AR2427_DEVID_PCIE	0x002c +#define AR9287_DEVID_PCI	0x002d +#define AR9287_DEVID_PCIE	0x002e +#define AR9300_DEVID_PCIE	0x0030  #define AR5416_AR9100_DEVID	0x000b @@ -48,9 +51,6 @@  #define AR_SUBVENDOR_ID_NEW_A	0x7065  #define AR5416_MAGIC		0x19641014 -#define AR5416_DEVID_AR9287_PCI  0x002D -#define AR5416_DEVID_AR9287_PCIE 0x002E -  #define AR9280_COEX2WIRE_SUBSYSID	0x309b  #define AT9285_COEX3WIRE_SA_SUBSYSID	0x30aa  #define AT9285_COEX3WIRE_DA_SUBSYSID	0x30ab @@ -68,6 +68,24 @@  #define REG_READ(_ah, _reg) \  	ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) +#define ENABLE_REGWRITE_BUFFER(_ah)					\ +	do {								\ +		if (AR_SREV_9271(_ah))					\ +			ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \ +	} while (0) + +#define DISABLE_REGWRITE_BUFFER(_ah)					\ +	do {								\ +		if (AR_SREV_9271(_ah))					\ +			ath9k_hw_common(_ah)->ops->disable_write_buffer((_ah)); \ +	} while (0) + +#define REGWRITE_BUFFER_FLUSH(_ah)					\ +	do {								\ +		if (AR_SREV_9271(_ah))					\ +			ath9k_hw_common(_ah)->ops->write_flush((_ah));	\ +	} while (0) +  #define SM(_v, _f)  (((_v) << _f##_S) & _f)  #define MS(_v, _f)  (((_v) & _f) >> _f##_S)  #define REG_RMW(_a, _r, _set, _clr)    \ @@ -75,6 +93,8 @@  #define REG_RMW_FIELD(_a, _r, _f, _v) \  	REG_WRITE(_a, _r, \  	(REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) +#define REG_READ_FIELD(_a, _r, _f) \ +	(((REG_READ(_a, _r) & _f) >> _f##_S))  #define REG_SET_BIT(_a, _r, _f) \  	REG_WRITE(_a, _r, REG_READ(_a, _r) | _f)  #define REG_CLR_BIT(_a, _r, _f) \ @@ -135,6 +155,16 @@  #define TU_TO_USEC(_tu)             ((_tu) << 10) +#define ATH9K_HW_RX_HP_QDEPTH	16 +#define ATH9K_HW_RX_LP_QDEPTH	128 + +enum ath_ini_subsys { +	ATH_INI_PRE = 0, +	ATH_INI_CORE, +	ATH_INI_POST, +	ATH_INI_NUM_SPLIT, +}; +  enum wireless_mode {  	ATH9K_MODE_11A = 0,  	ATH9K_MODE_11G, @@ -165,13 +195,16 @@ enum ath9k_hw_caps {  	ATH9K_HW_CAP_ENHANCEDPM                 = BIT(14),  	ATH9K_HW_CAP_AUTOSLEEP                  = BIT(15),  	ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(16), +	ATH9K_HW_CAP_EDMA			= BIT(17), +	ATH9K_HW_CAP_RAC_SUPPORTED		= BIT(18), +	ATH9K_HW_CAP_LDPC			= BIT(19), +	ATH9K_HW_CAP_FASTCLOCK			= BIT(20),  };  enum ath9k_capability_type {  	ATH9K_CAP_CIPHER = 0,  	ATH9K_CAP_TKIP_MIC,  	ATH9K_CAP_TKIP_SPLIT, -	ATH9K_CAP_DIVERSITY,  	ATH9K_CAP_TXPOW,  	ATH9K_CAP_MCAST_KEYSRCH,  	ATH9K_CAP_DS @@ -192,6 +225,11 @@ struct ath9k_hw_capabilities {  	u8 num_gpio_pins;  	u8 num_antcfg_2ghz;  	u8 num_antcfg_5ghz; +	u8 rx_hp_qdepth; +	u8 rx_lp_qdepth; +	u8 rx_status_len; +	u8 tx_desc_len; +	u8 txs_len;  };  struct ath9k_ops_config { @@ -212,6 +250,7 @@ struct ath9k_ops_config {  	u32 enable_ani;  	int serialize_regmode;  	bool rx_intr_mitigation; +	bool tx_intr_mitigation;  #define SPUR_DISABLE        	0  #define SPUR_ENABLE_IOCTL   	1  #define SPUR_ENABLE_EEPROM  	2 @@ -223,6 +262,7 @@ struct ath9k_ops_config {  #define AR_BASE_FREQ_5GHZ   	4900  #define AR_SPUR_FEEQ_BOUND_HT40 19  #define AR_SPUR_FEEQ_BOUND_HT20 10 +	bool tx_iq_calibration; /* Only available for >= AR9003 */  	int spurmode;  	u16 spurchans[AR_EEPROM_MODAL_SPURS][2];  	u8 max_txtrig_level; @@ -231,6 +271,8 @@ struct ath9k_ops_config {  enum ath9k_int {  	ATH9K_INT_RX = 0x00000001,  	ATH9K_INT_RXDESC = 0x00000002, +	ATH9K_INT_RXHP = 0x00000001, +	ATH9K_INT_RXLP = 0x00000002,  	ATH9K_INT_RXNOFRM = 0x00000008,  	ATH9K_INT_RXEOL = 0x00000010,  	ATH9K_INT_RXORN = 0x00000020, @@ -327,10 +369,9 @@ struct ath9k_channel {  #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)  #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)  #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) -#define IS_CHAN_A_5MHZ_SPACED(_c)			\ +#define IS_CHAN_A_FAST_CLOCK(_ah, _c)			\  	((((_c)->channelFlags & CHANNEL_5GHZ) != 0) &&	\ -	 (((_c)->channel % 20) != 0) &&			\ -	 (((_c)->channel % 10) != 0)) +	 ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK))  /* These macros check chanmode and not channelFlags */  #define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B) @@ -363,6 +404,12 @@ enum ser_reg_mode {  	SER_REG_MODE_AUTO = 2,  }; +enum ath9k_rx_qtype { +	ATH9K_RX_QUEUE_HP, +	ATH9K_RX_QUEUE_LP, +	ATH9K_RX_QUEUE_MAX, +}; +  struct ath9k_beacon_state {  	u32 bs_nexttbtt;  	u32 bs_nextdtim; @@ -440,6 +487,124 @@ struct ath_gen_timer_table {  	} timer_mask;  }; +/** + * struct ath_hw_private_ops - callbacks used internally by hardware code + * + * This structure contains private callbacks designed to only be used internally + * by the hardware core. + * + * @init_cal_settings: setup types of calibrations supported + * @init_cal: starts actual calibration + * + * @init_mode_regs: Initializes mode registers + * @init_mode_gain_regs: Initialize TX/RX gain registers + * @macversion_supported: If this specific mac revision is supported + * + * @rf_set_freq: change frequency + * @spur_mitigate_freq: spur mitigation + * @rf_alloc_ext_banks: + * @rf_free_ext_banks: + * @set_rf_regs: + * @compute_pll_control: compute the PLL control value to use for + *	AR_RTC_PLL_CONTROL for a given channel + * @setup_calibration: set up calibration + * @iscal_supported: used to query if a type of calibration is supported + * @loadnf: load noise floor read from each chain on the CCA registers + */ +struct ath_hw_private_ops { +	/* Calibration ops */ +	void (*init_cal_settings)(struct ath_hw *ah); +	bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan); + +	void (*init_mode_regs)(struct ath_hw *ah); +	void (*init_mode_gain_regs)(struct ath_hw *ah); +	bool (*macversion_supported)(u32 macversion); +	void (*setup_calibration)(struct ath_hw *ah, +				  struct ath9k_cal_list *currCal); +	bool (*iscal_supported)(struct ath_hw *ah, +				enum ath9k_cal_types calType); + +	/* PHY ops */ +	int (*rf_set_freq)(struct ath_hw *ah, +			   struct ath9k_channel *chan); +	void (*spur_mitigate_freq)(struct ath_hw *ah, +				   struct ath9k_channel *chan); +	int (*rf_alloc_ext_banks)(struct ath_hw *ah); +	void (*rf_free_ext_banks)(struct ath_hw *ah); +	bool (*set_rf_regs)(struct ath_hw *ah, +			    struct ath9k_channel *chan, +			    u16 modesIndex); +	void (*set_channel_regs)(struct ath_hw *ah, struct ath9k_channel *chan); +	void (*init_bb)(struct ath_hw *ah, +			struct ath9k_channel *chan); +	int (*process_ini)(struct ath_hw *ah, struct ath9k_channel *chan); +	void (*olc_init)(struct ath_hw *ah); +	void (*set_rfmode)(struct ath_hw *ah, struct ath9k_channel *chan); +	void (*mark_phy_inactive)(struct ath_hw *ah); +	void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan); +	bool (*rfbus_req)(struct ath_hw *ah); +	void (*rfbus_done)(struct ath_hw *ah); +	void (*enable_rfkill)(struct ath_hw *ah); +	void (*restore_chainmask)(struct ath_hw *ah); +	void (*set_diversity)(struct ath_hw *ah, bool value); +	u32 (*compute_pll_control)(struct ath_hw *ah, +				   struct ath9k_channel *chan); +	bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, +			    int param); +	void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); +	void (*loadnf)(struct ath_hw *ah, struct ath9k_channel *chan); +}; + +/** + * struct ath_hw_ops - callbacks used by hardware code and driver code + * + * This structure contains callbacks designed to to be used internally by + * hardware code and also by the lower level driver. + * + * @config_pci_powersave: + * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC + */ +struct ath_hw_ops { +	void (*config_pci_powersave)(struct ath_hw *ah, +				     int restore, +				     int power_off); +	void (*rx_enable)(struct ath_hw *ah); +	void (*set_desc_link)(void *ds, u32 link); +	void (*get_desc_link)(void *ds, u32 **link); +	bool (*calibrate)(struct ath_hw *ah, +			  struct ath9k_channel *chan, +			  u8 rxchainmask, +			  bool longcal); +	bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked); +	void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen, +			    bool is_firstseg, bool is_is_lastseg, +			    const void *ds0, dma_addr_t buf_addr, +			    unsigned int qcu); +	int (*proc_txdesc)(struct ath_hw *ah, void *ds, +			   struct ath_tx_status *ts); +	void (*set11n_txdesc)(struct ath_hw *ah, void *ds, +			      u32 pktLen, enum ath9k_pkt_type type, +			      u32 txPower, u32 keyIx, +			      enum ath9k_key_type keyType, +			      u32 flags); +	void (*set11n_ratescenario)(struct ath_hw *ah, void *ds, +				void *lastds, +				u32 durUpdateEn, u32 rtsctsRate, +				u32 rtsctsDuration, +				struct ath9k_11n_rate_series series[], +				u32 nseries, u32 flags); +	void (*set11n_aggr_first)(struct ath_hw *ah, void *ds, +				  u32 aggrLen); +	void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds, +				   u32 numDelims); +	void (*set11n_aggr_last)(struct ath_hw *ah, void *ds); +	void (*clr11n_aggr)(struct ath_hw *ah, void *ds); +	void (*set11n_burstduration)(struct ath_hw *ah, void *ds, +				     u32 burstDuration); +	void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, +				       u32 vmf); +}; +  struct ath_hw {  	struct ieee80211_hw *hw;  	struct ath_common common; @@ -453,14 +618,18 @@ struct ath_hw {  		struct ar5416_eeprom_def def;  		struct ar5416_eeprom_4k map4k;  		struct ar9287_eeprom map9287; +		struct ar9300_eeprom ar9300_eep;  	} eeprom;  	const struct eeprom_ops *eep_ops; -	enum ath9k_eep_map eep_map;  	bool sw_mgmt_crypto;  	bool is_pciexpress;  	bool need_an_top2_fixup;  	u16 tx_trig_level; +	s16 nf_2g_max; +	s16 nf_2g_min; +	s16 nf_5g_max; +	s16 nf_5g_min;  	u16 rfsilent;  	u32 rfkill_gpio;  	u32 rfkill_polarity; @@ -493,6 +662,7 @@ struct ath_hw {  	struct ath9k_cal_list adcgain_caldata;  	struct ath9k_cal_list adcdc_calinitdata;  	struct ath9k_cal_list adcdc_caldata; +	struct ath9k_cal_list tempCompCalData;  	struct ath9k_cal_list *cal_list;  	struct ath9k_cal_list *cal_list_last;  	struct ath9k_cal_list *cal_list_curr; @@ -533,12 +703,10 @@ struct ath_hw {  		DONT_USE_32KHZ,  	} enable_32kHz_clock; -	/* Callback for radio frequency change */ -	int (*ath9k_hw_rf_set_freq)(struct ath_hw *ah, struct ath9k_channel *chan); - -	/* Callback for baseband spur frequency */ -	void (*ath9k_hw_spur_mitigate_freq)(struct ath_hw *ah, -					    struct ath9k_channel *chan); +	/* Private to hardware code */ +	struct ath_hw_private_ops private_ops; +	/* Accessed by the lower level driver */ +	struct ath_hw_ops ops;  	/* Used to program the radio on non single-chip devices */  	u32 *analogBank0Data; @@ -551,6 +719,7 @@ struct ath_hw {  	u32 *addac5416_21;  	u32 *bank6Temp; +	u8 txpower_limit;  	int16_t txpower_indexoffset;  	int coverage_class;  	u32 beacon_interval; @@ -592,6 +761,7 @@ struct ath_hw {  	struct ar5416IniArray iniBank7;  	struct ar5416IniArray iniAddac;  	struct ar5416IniArray iniPcieSerdes; +	struct ar5416IniArray iniPcieSerdesLowPower;  	struct ar5416IniArray iniModesAdditional;  	struct ar5416IniArray iniModesRxGain;  	struct ar5416IniArray iniModesTxGain; @@ -604,9 +774,21 @@ struct ath_hw {  	struct ar5416IniArray iniModes_high_power_tx_gain_9271;  	struct ar5416IniArray iniModes_normal_power_tx_gain_9271; +	struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT]; +	struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT]; +	struct ar5416IniArray iniRadio[ATH_INI_NUM_SPLIT]; +	struct ar5416IniArray iniSOC[ATH_INI_NUM_SPLIT]; +  	u32 intr_gen_timer_trigger;  	u32 intr_gen_timer_thresh;  	struct ath_gen_timer_table hw_gen_timers; + +	struct ar9003_txs *ts_ring; +	void *ts_start; +	u32 ts_paddr_start; +	u32 ts_paddr_end; +	u16 ts_tail; +	u8 ts_size;  };  static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) @@ -619,6 +801,16 @@ static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)  	return &(ath9k_hw_common(ah)->regulatory);  } +static inline struct ath_hw_private_ops *ath9k_hw_private_ops(struct ath_hw *ah) +{ +	return &ah->private_ops; +} + +static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah) +{ +	return &ah->ops; +} +  /* Initialization, Detach, Reset */  const char *ath9k_hw_probe(u16 vendorid, u16 devid);  void ath9k_hw_deinit(struct ath_hw *ah); @@ -630,6 +822,7 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,  			    u32 capability, u32 *result);  bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,  			    u32 capability, u32 setting, int *status); +u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);  /* Key Cache Management */  bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry); @@ -678,16 +871,10 @@ void ath9k_hw_set11nmac2040(struct ath_hw *ah);  void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);  void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,  				    const struct ath9k_beacon_state *bs); +bool ath9k_hw_check_alive(struct ath_hw *ah);  bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); -void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off); - -/* Interrupt Handling */ -bool ath9k_hw_intrpend(struct ath_hw *ah); -bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked); -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); -  /* Generic hw timer primitives */  struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,  					  void (*trigger)(void *), @@ -709,6 +896,36 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);  /* HTC */  void ath9k_hw_htc_resetinit(struct ath_hw *ah); +/* PHY */ +void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, +				   u32 *coef_mantissa, u32 *coef_exponent); + +/* + * Code Specific to AR5008, AR9001 or AR9002, + * we stuff these here to avoid callbacks for AR9003. + */ +void ar9002_hw_cck_chan14_spread(struct ath_hw *ah); +int ar9002_hw_rf_claim(struct ath_hw *ah); +void ar9002_hw_enable_async_fifo(struct ath_hw *ah); +void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah); + +/* + * Code specifric to AR9003, we stuff these here to avoid callbacks + * for older families + */ +void ar9003_hw_set_nf_limits(struct ath_hw *ah); + +/* Hardware family op attach helpers */ +void ar5008_hw_attach_phy_ops(struct ath_hw *ah); +void ar9002_hw_attach_phy_ops(struct ath_hw *ah); +void ar9003_hw_attach_phy_ops(struct ath_hw *ah); + +void ar9002_hw_attach_calib_ops(struct ath_hw *ah); +void ar9003_hw_attach_calib_ops(struct ath_hw *ah); + +void ar9002_hw_attach_ops(struct ath_hw *ah); +void ar9003_hw_attach_ops(struct ath_hw *ah); +  #define ATH_PCIE_CAP_LINK_CTRL	0x70  #define ATH_PCIE_CAP_LINK_L0S	1  #define ATH_PCIE_CAP_LINK_L1	2 diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index b78308c3c4d..8c795488ebc 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -175,6 +175,18 @@ static const struct ath_ops ath9k_common_ops = {  	.write = ath9k_iowrite32,  }; +static int count_streams(unsigned int chainmask, int max) +{ +	int streams = 0; + +	do { +		if (++streams == max) +			break; +	} while ((chainmask = chainmask & (chainmask - 1))); + +	return streams; +} +  /**************************/  /*     Initialization     */  /**************************/ @@ -182,8 +194,10 @@ static const struct ath_ops ath9k_common_ops = {  static void setup_ht_cap(struct ath_softc *sc,  			 struct ieee80211_sta_ht_cap *ht_info)  { -	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	struct ath_hw *ah = sc->sc_ah; +	struct ath_common *common = ath9k_hw_common(ah);  	u8 tx_streams, rx_streams; +	int i, max_streams;  	ht_info->ht_supported = true;  	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | @@ -191,28 +205,40 @@ static void setup_ht_cap(struct ath_softc *sc,  		       IEEE80211_HT_CAP_SGI_40 |  		       IEEE80211_HT_CAP_DSSSCCK40; +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC) +		ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; +  	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;  	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; +	if (AR_SREV_9300_20_OR_LATER(ah)) +		max_streams = 3; +	else +		max_streams = 2; + +	if (AR_SREV_9280_10_OR_LATER(ah)) { +		if (max_streams >= 2) +			ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; +		ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); +	} +  	/* set up supported mcs set */  	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); -	tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? -		     1 : 2; -	rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? -		     1 : 2; +	tx_streams = count_streams(common->tx_chainmask, max_streams); +	rx_streams = count_streams(common->rx_chainmask, max_streams); + +	ath_print(common, ATH_DBG_CONFIG, +		  "TX streams %d, RX streams: %d\n", +		  tx_streams, rx_streams);  	if (tx_streams != rx_streams) { -		ath_print(common, ATH_DBG_CONFIG, -			  "TX streams %d, RX streams: %d\n", -			  tx_streams, rx_streams);  		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;  		ht_info->mcs.tx_params |= ((tx_streams - 1) <<  				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);  	} -	ht_info->mcs.rx_mask[0] = 0xff; -	if (rx_streams >= 2) -		ht_info->mcs.rx_mask[1] = 0xff; +	for (i = 0; i < rx_streams; i++) +		ht_info->mcs.rx_mask[i] = 0xff;  	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;  } @@ -235,31 +261,37 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,  */  int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  		      struct list_head *head, const char *name, -		      int nbuf, int ndesc) +		      int nbuf, int ndesc, bool is_tx)  {  #define	DS2PHYS(_dd, _ds)						\  	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))  #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)  #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)  	struct ath_common *common = ath9k_hw_common(sc->sc_ah); -	struct ath_desc *ds; +	u8 *ds;  	struct ath_buf *bf; -	int i, bsize, error; +	int i, bsize, error, desc_len;  	ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",  		  name, nbuf, ndesc);  	INIT_LIST_HEAD(head); + +	if (is_tx) +		desc_len = sc->sc_ah->caps.tx_desc_len; +	else +		desc_len = sizeof(struct ath_desc); +  	/* ath_desc must be a multiple of DWORDs */ -	if ((sizeof(struct ath_desc) % 4) != 0) { +	if ((desc_len % 4) != 0) {  		ath_print(common, ATH_DBG_FATAL,  			  "ath_desc not DWORD aligned\n"); -		BUG_ON((sizeof(struct ath_desc) % 4) != 0); +		BUG_ON((desc_len % 4) != 0);  		error = -ENOMEM;  		goto fail;  	} -	dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; +	dd->dd_desc_len = desc_len * nbuf * ndesc;  	/*  	 * Need additional DMA memory because we can't use @@ -272,7 +304,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  		u32 dma_len;  		while (ndesc_skipped) { -			dma_len = ndesc_skipped * sizeof(struct ath_desc); +			dma_len = ndesc_skipped * desc_len;  			dd->dd_desc_len += dma_len;  			ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); @@ -286,7 +318,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  		error = -ENOMEM;  		goto fail;  	} -	ds = dd->dd_desc; +	ds = (u8 *) dd->dd_desc;  	ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",  		  name, ds, (u32) dd->dd_desc_len,  		  ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); @@ -300,7 +332,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  	}  	dd->dd_bufptr = bf; -	for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { +	for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {  		bf->bf_desc = ds;  		bf->bf_daddr = DS2PHYS(dd, ds); @@ -316,7 +348,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  				       ((caddr_t) dd->dd_desc +  					dd->dd_desc_len)); -				ds += ndesc; +				ds += (desc_len * ndesc);  				bf->bf_desc = ds;  				bf->bf_daddr = DS2PHYS(dd, ds);  			} @@ -514,7 +546,7 @@ static void ath9k_init_misc(struct ath_softc *sc)  	common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;  	common->rx_chainmask = sc->sc_ah->caps.rx_chainmask; -	ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); +	ath9k_hw_set_diversity(sc->sc_ah, true);  	sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);  	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) @@ -568,13 +600,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,  	ath_read_cachesize(common, &csz);  	common->cachelsz = csz << 2; /* convert to bytes */ +	/* Initializes the hardware for all supported chipsets */  	ret = ath9k_hw_init(ah); -	if (ret) { -		ath_print(common, ATH_DBG_FATAL, -			  "Unable to initialize hardware; " -			  "initialization status: %d\n", ret); +	if (ret)  		goto err_hw; -	}  	ret = ath9k_init_debug(ah);  	if (ret) { diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 4a2060e5a77..0e425cb4bbb 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -25,6 +25,8 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,  		  ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,  		  ah->txurn_interrupt_mask); +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_IMR_S0,  		  SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)  		  | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC)); @@ -35,6 +37,9 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,  	ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;  	ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);  	REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah);  }  u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) @@ -57,6 +62,18 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q)  }  EXPORT_SYMBOL(ath9k_hw_txstart); +void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds) +{ +	struct ar5416_desc *ads = AR5416DESC(ds); + +	ads->ds_txstatus0 = ads->ds_txstatus1 = 0; +	ads->ds_txstatus2 = ads->ds_txstatus3 = 0; +	ads->ds_txstatus4 = ads->ds_txstatus5 = 0; +	ads->ds_txstatus6 = ads->ds_txstatus7 = 0; +	ads->ds_txstatus8 = ads->ds_txstatus9 = 0; +} +EXPORT_SYMBOL(ath9k_hw_cleartxdesc); +  u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)  {  	u32 npend; @@ -207,281 +224,6 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)  }  EXPORT_SYMBOL(ath9k_hw_stoptxdma); -void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, -			 u32 segLen, bool firstSeg, -			 bool lastSeg, const struct ath_desc *ds0) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); - -	if (firstSeg) { -		ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); -	} else if (lastSeg) { -		ads->ds_ctl0 = 0; -		ads->ds_ctl1 = segLen; -		ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; -		ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; -	} else { -		ads->ds_ctl0 = 0; -		ads->ds_ctl1 = segLen | AR_TxMore; -		ads->ds_ctl2 = 0; -		ads->ds_ctl3 = 0; -	} -	ads->ds_txstatus0 = ads->ds_txstatus1 = 0; -	ads->ds_txstatus2 = ads->ds_txstatus3 = 0; -	ads->ds_txstatus4 = ads->ds_txstatus5 = 0; -	ads->ds_txstatus6 = ads->ds_txstatus7 = 0; -	ads->ds_txstatus8 = ads->ds_txstatus9 = 0; -} -EXPORT_SYMBOL(ath9k_hw_filltxdesc); - -void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); - -	ads->ds_txstatus0 = ads->ds_txstatus1 = 0; -	ads->ds_txstatus2 = ads->ds_txstatus3 = 0; -	ads->ds_txstatus4 = ads->ds_txstatus5 = 0; -	ads->ds_txstatus6 = ads->ds_txstatus7 = 0; -	ads->ds_txstatus8 = ads->ds_txstatus9 = 0; -} -EXPORT_SYMBOL(ath9k_hw_cleartxdesc); - -int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, -			struct ath_tx_status *ts) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); - -	if ((ads->ds_txstatus9 & AR_TxDone) == 0) -		return -EINPROGRESS; - -	ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); -	ts->ts_tstamp = ads->AR_SendTimestamp; -	ts->ts_status = 0; -	ts->ts_flags = 0; - -	if (ads->ds_txstatus1 & AR_FrmXmitOK) -		ts->ts_status |= ATH9K_TX_ACKED; -	if (ads->ds_txstatus1 & AR_ExcessiveRetries) -		ts->ts_status |= ATH9K_TXERR_XRETRY; -	if (ads->ds_txstatus1 & AR_Filtered) -		ts->ts_status |= ATH9K_TXERR_FILT; -	if (ads->ds_txstatus1 & AR_FIFOUnderrun) { -		ts->ts_status |= ATH9K_TXERR_FIFO; -		ath9k_hw_updatetxtriglevel(ah, true); -	} -	if (ads->ds_txstatus9 & AR_TxOpExceeded) -		ts->ts_status |= ATH9K_TXERR_XTXOP; -	if (ads->ds_txstatus1 & AR_TxTimerExpired) -		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; - -	if (ads->ds_txstatus1 & AR_DescCfgErr) -		ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; -	if (ads->ds_txstatus1 & AR_TxDataUnderrun) { -		ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; -		ath9k_hw_updatetxtriglevel(ah, true); -	} -	if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { -		ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; -		ath9k_hw_updatetxtriglevel(ah, true); -	} -	if (ads->ds_txstatus0 & AR_TxBaStatus) { -		ts->ts_flags |= ATH9K_TX_BA; -		ts->ba_low = ads->AR_BaBitmapLow; -		ts->ba_high = ads->AR_BaBitmapHigh; -	} - -	ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); -	switch (ts->ts_rateindex) { -	case 0: -		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); -		break; -	case 1: -		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); -		break; -	case 2: -		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); -		break; -	case 3: -		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); -		break; -	} - -	ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); -	ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); -	ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); -	ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); -	ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); -	ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); -	ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); -	ts->evm0 = ads->AR_TxEVM0; -	ts->evm1 = ads->AR_TxEVM1; -	ts->evm2 = ads->AR_TxEVM2; -	ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); -	ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); -	ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); -	ts->ts_antenna = 0; - -	return 0; -} -EXPORT_SYMBOL(ath9k_hw_txprocdesc); - -void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, -			    u32 pktLen, enum ath9k_pkt_type type, u32 txPower, -			    u32 keyIx, enum ath9k_key_type keyType, u32 flags) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); - -	txPower += ah->txpower_indexoffset; -	if (txPower > 63) -		txPower = 63; - -	ads->ds_ctl0 = (pktLen & AR_FrameLen) -		| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) -		| SM(txPower, AR_XmitPower) -		| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) -		| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) -		| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) -		| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); - -	ads->ds_ctl1 = -		(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) -		| SM(type, AR_FrameType) -		| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) -		| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) -		| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); - -	ads->ds_ctl6 = SM(keyType, AR_EncrType); - -	if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { -		ads->ds_ctl8 = 0; -		ads->ds_ctl9 = 0; -		ads->ds_ctl10 = 0; -		ads->ds_ctl11 = 0; -	} -} -EXPORT_SYMBOL(ath9k_hw_set11n_txdesc); - -void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, -				  struct ath_desc *lastds, -				  u32 durUpdateEn, u32 rtsctsRate, -				  u32 rtsctsDuration, -				  struct ath9k_11n_rate_series series[], -				  u32 nseries, u32 flags) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); -	struct ar5416_desc *last_ads = AR5416DESC(lastds); -	u32 ds_ctl0; - -	if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { -		ds_ctl0 = ads->ds_ctl0; - -		if (flags & ATH9K_TXDESC_RTSENA) { -			ds_ctl0 &= ~AR_CTSEnable; -			ds_ctl0 |= AR_RTSEnable; -		} else { -			ds_ctl0 &= ~AR_RTSEnable; -			ds_ctl0 |= AR_CTSEnable; -		} - -		ads->ds_ctl0 = ds_ctl0; -	} else { -		ads->ds_ctl0 = -			(ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); -	} - -	ads->ds_ctl2 = set11nTries(series, 0) -		| set11nTries(series, 1) -		| set11nTries(series, 2) -		| set11nTries(series, 3) -		| (durUpdateEn ? AR_DurUpdateEna : 0) -		| SM(0, AR_BurstDur); - -	ads->ds_ctl3 = set11nRate(series, 0) -		| set11nRate(series, 1) -		| set11nRate(series, 2) -		| set11nRate(series, 3); - -	ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) -		| set11nPktDurRTSCTS(series, 1); - -	ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) -		| set11nPktDurRTSCTS(series, 3); - -	ads->ds_ctl7 = set11nRateFlags(series, 0) -		| set11nRateFlags(series, 1) -		| set11nRateFlags(series, 2) -		| set11nRateFlags(series, 3) -		| SM(rtsctsRate, AR_RTSCTSRate); -	last_ads->ds_ctl2 = ads->ds_ctl2; -	last_ads->ds_ctl3 = ads->ds_ctl3; -} -EXPORT_SYMBOL(ath9k_hw_set11n_ratescenario); - -void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, -				u32 aggrLen) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); - -	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); -	ads->ds_ctl6 &= ~AR_AggrLen; -	ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); -} -EXPORT_SYMBOL(ath9k_hw_set11n_aggr_first); - -void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, -				 u32 numDelims) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); -	unsigned int ctl6; - -	ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); - -	ctl6 = ads->ds_ctl6; -	ctl6 &= ~AR_PadDelim; -	ctl6 |= SM(numDelims, AR_PadDelim); -	ads->ds_ctl6 = ctl6; -} -EXPORT_SYMBOL(ath9k_hw_set11n_aggr_middle); - -void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); - -	ads->ds_ctl1 |= AR_IsAggr; -	ads->ds_ctl1 &= ~AR_MoreAggr; -	ads->ds_ctl6 &= ~AR_PadDelim; -} -EXPORT_SYMBOL(ath9k_hw_set11n_aggr_last); - -void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); - -	ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); -} -EXPORT_SYMBOL(ath9k_hw_clr11n_aggr); - -void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, -				   u32 burstDuration) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); - -	ads->ds_ctl2 &= ~AR_BurstDur; -	ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); -} -EXPORT_SYMBOL(ath9k_hw_set11n_burstduration); - -void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, -				     u32 vmf) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); - -	if (vmf) -		ads->ds_ctl0 |= AR_VirtMoreFrag; -	else -		ads->ds_ctl0 &= ~AR_VirtMoreFrag; -} -  void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)  {  	*txqs &= ah->intr_txqs; @@ -733,6 +475,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)  	} else  		cwMin = qi->tqi_cwmin; +	ENABLE_REGWRITE_BUFFER(ah); +  	REG_WRITE(ah, AR_DLCL_IFS(q),  		  SM(cwMin, AR_D_LCL_IFS_CWMIN) |  		  SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) | @@ -747,6 +491,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)  	REG_WRITE(ah, AR_DMISC(q),  		  AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); +	REGWRITE_BUFFER_FLUSH(ah); +  	if (qi->tqi_cbrPeriod) {  		REG_WRITE(ah, AR_QCBRCFG(q),  			  SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | @@ -762,6 +508,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)  			  AR_Q_RDYTIMECFG_EN);  	} +	REGWRITE_BUFFER_FLUSH(ah); +  	REG_WRITE(ah, AR_DCHNTIME(q),  		  SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |  		  (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); @@ -779,6 +527,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)  			  REG_READ(ah, AR_DMISC(q)) |  			  AR_D_MISC_POST_FR_BKOFF_DIS);  	} + +	REGWRITE_BUFFER_FLUSH(ah); +	DISABLE_REGWRITE_BUFFER(ah); +  	if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {  		REG_WRITE(ah, AR_DMISC(q),  			  REG_READ(ah, AR_DMISC(q)) | @@ -786,6 +538,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)  	}  	switch (qi->tqi_type) {  	case ATH9K_TX_QUEUE_BEACON: +		ENABLE_REGWRITE_BUFFER(ah); +  		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))  			  | AR_Q_MISC_FSP_DBA_GATED  			  | AR_Q_MISC_BEACON_USE @@ -796,8 +550,20 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)  			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S)  			  | AR_D_MISC_BEACON_USE  			  | AR_D_MISC_POST_FR_BKOFF_DIS); + +		REGWRITE_BUFFER_FLUSH(ah); +		DISABLE_REGWRITE_BUFFER(ah); + +		/* cwmin and cwmax should be 0 for beacon queue */ +		if (AR_SREV_9300_20_OR_LATER(ah)) { +			REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN) +				  | SM(0, AR_D_LCL_IFS_CWMAX) +				  | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); +		}  		break;  	case ATH9K_TX_QUEUE_CAB: +		ENABLE_REGWRITE_BUFFER(ah); +  		REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))  			  | AR_Q_MISC_FSP_DBA_GATED  			  | AR_Q_MISC_CBR_INCR_DIS1 @@ -811,6 +577,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)  		REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))  			  | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<  			     AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); + +		REGWRITE_BUFFER_FLUSH(ah); +		DISABLE_REGWRITE_BUFFER(ah); +  		break;  	case ATH9K_TX_QUEUE_PSPOLL:  		REG_WRITE(ah, AR_QMISC(q), @@ -832,6 +602,9 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)  			  AR_D_MISC_POST_FR_BKOFF_DIS);  	} +	if (AR_SREV_9300_20_OR_LATER(ah)) +		REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN); +  	if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)  		ah->txok_interrupt_mask |= 1 << q;  	else @@ -940,22 +713,6 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,  }  EXPORT_SYMBOL(ath9k_hw_rxprocdesc); -void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, -			  u32 size, u32 flags) -{ -	struct ar5416_desc *ads = AR5416DESC(ds); -	struct ath9k_hw_capabilities *pCap = &ah->caps; - -	ads->ds_ctl1 = size & AR_BufLen; -	if (flags & ATH9K_RXDESC_INTREQ) -		ads->ds_ctl1 |= AR_RxIntrReq; - -	ads->ds_rxstatus8 &= ~AR_RxDone; -	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) -		memset(&(ads->u), 0, sizeof(ads->u)); -} -EXPORT_SYMBOL(ath9k_hw_setuprxdesc); -  /*   * This can stop or re-enables RX.   * @@ -999,12 +756,6 @@ void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)  }  EXPORT_SYMBOL(ath9k_hw_putrxbuf); -void ath9k_hw_rxena(struct ath_hw *ah) -{ -	REG_WRITE(ah, AR_CR, AR_CR_RXE); -} -EXPORT_SYMBOL(ath9k_hw_rxena); -  void ath9k_hw_startpcureceive(struct ath_hw *ah)  {  	ath9k_enable_mib_counters(ah); @@ -1023,6 +774,14 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah)  }  EXPORT_SYMBOL(ath9k_hw_stoppcurecv); +void ath9k_hw_abortpcurecv(struct ath_hw *ah) +{ +	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); + +	ath9k_hw_disable_mib_counters(ah); +} +EXPORT_SYMBOL(ath9k_hw_abortpcurecv); +  bool ath9k_hw_stopdmarecv(struct ath_hw *ah)  {  #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */ @@ -1068,3 +827,142 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah)  	return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);  }  EXPORT_SYMBOL(ath9k_hw_beaconq_setup); + +bool ath9k_hw_intrpend(struct ath_hw *ah) +{ +	u32 host_isr; + +	if (AR_SREV_9100(ah)) +		return true; + +	host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); +	if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) +		return true; + +	host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); +	if ((host_isr & AR_INTR_SYNC_DEFAULT) +	    && (host_isr != AR_INTR_SPURIOUS)) +		return true; + +	return false; +} +EXPORT_SYMBOL(ath9k_hw_intrpend); + +enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, +					      enum ath9k_int ints) +{ +	enum ath9k_int omask = ah->imask; +	u32 mask, mask2; +	struct ath9k_hw_capabilities *pCap = &ah->caps; +	struct ath_common *common = ath9k_hw_common(ah); + +	ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); + +	if (omask & ATH9K_INT_GLOBAL) { +		ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); +		REG_WRITE(ah, AR_IER, AR_IER_DISABLE); +		(void) REG_READ(ah, AR_IER); +		if (!AR_SREV_9100(ah)) { +			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); +			(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); + +			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); +			(void) REG_READ(ah, AR_INTR_SYNC_ENABLE); +		} +	} + +	/* TODO: global int Ref count */ +	mask = ints & ATH9K_INT_COMMON; +	mask2 = 0; + +	if (ints & ATH9K_INT_TX) { +		if (ah->config.tx_intr_mitigation) +			mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM; +		else { +			if (ah->txok_interrupt_mask) +				mask |= AR_IMR_TXOK; +			if (ah->txdesc_interrupt_mask) +				mask |= AR_IMR_TXDESC; +		} +		if (ah->txerr_interrupt_mask) +			mask |= AR_IMR_TXERR; +		if (ah->txeol_interrupt_mask) +			mask |= AR_IMR_TXEOL; +	} +	if (ints & ATH9K_INT_RX) { +		if (AR_SREV_9300_20_OR_LATER(ah)) { +			mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP; +			if (ah->config.rx_intr_mitigation) { +				mask &= ~AR_IMR_RXOK_LP; +				mask |=  AR_IMR_RXMINTR | AR_IMR_RXINTM; +			} else { +				mask |= AR_IMR_RXOK_LP; +			} +		} else { +			if (ah->config.rx_intr_mitigation) +				mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; +			else +				mask |= AR_IMR_RXOK | AR_IMR_RXDESC; +		} +		if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) +			mask |= AR_IMR_GENTMR; +	} + +	if (ints & (ATH9K_INT_BMISC)) { +		mask |= AR_IMR_BCNMISC; +		if (ints & ATH9K_INT_TIM) +			mask2 |= AR_IMR_S2_TIM; +		if (ints & ATH9K_INT_DTIM) +			mask2 |= AR_IMR_S2_DTIM; +		if (ints & ATH9K_INT_DTIMSYNC) +			mask2 |= AR_IMR_S2_DTIMSYNC; +		if (ints & ATH9K_INT_CABEND) +			mask2 |= AR_IMR_S2_CABEND; +		if (ints & ATH9K_INT_TSFOOR) +			mask2 |= AR_IMR_S2_TSFOOR; +	} + +	if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { +		mask |= AR_IMR_BCNMISC; +		if (ints & ATH9K_INT_GTT) +			mask2 |= AR_IMR_S2_GTT; +		if (ints & ATH9K_INT_CST) +			mask2 |= AR_IMR_S2_CST; +	} + +	ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); +	REG_WRITE(ah, AR_IMR, mask); +	ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | +			   AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | +			   AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); +	ah->imrs2_reg |= mask2; +	REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); + +	if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { +		if (ints & ATH9K_INT_TIM_TIMER) +			REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); +		else +			REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); +	} + +	if (ints & ATH9K_INT_GLOBAL) { +		ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); +		REG_WRITE(ah, AR_IER, AR_IER_ENABLE); +		if (!AR_SREV_9100(ah)) { +			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, +				  AR_INTR_MAC_IRQ); +			REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); + + +			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, +				  AR_INTR_SYNC_DEFAULT); +			REG_WRITE(ah, AR_INTR_SYNC_MASK, +				  AR_INTR_SYNC_DEFAULT); +		} +		ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", +			  REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); +	} + +	return omask; +} +EXPORT_SYMBOL(ath9k_hw_set_interrupts); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 68dbd7a8ddc..00f3e0c7528 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -37,6 +37,8 @@  	  AR_2040_##_index : 0)						\  	 |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ?	\  	   AR_GI##_index : 0)						\ +	 |((_series)[_index].RateFlags & ATH9K_RATESERIES_STBC ?	\ +	   AR_STBC##_index : 0)						\  	 |SM((_series)[_index].ChSel, AR_ChainSel##_index))  #define CCK_SIFS_TIME        10 @@ -86,7 +88,6 @@  #define ATH9K_TX_DESC_CFG_ERR      0x04  #define ATH9K_TX_DATA_UNDERRUN     0x08  #define ATH9K_TX_DELIM_UNDERRUN    0x10 -#define ATH9K_TX_SW_ABORTED        0x40  #define ATH9K_TX_SW_FILTERED       0x80  /* 64 bytes */ @@ -117,7 +118,10 @@ struct ath_tx_status {  	int8_t ts_rssi_ext0;  	int8_t ts_rssi_ext1;  	int8_t ts_rssi_ext2; -	u8 pad[3]; +	u8 qid; +	u16 desc_id; +	u8 tid; +	u8 pad[2];  	u32 ba_low;  	u32 ba_high;  	u32 evm0; @@ -148,11 +152,13 @@ struct ath_rx_status {  	u32 evm0;  	u32 evm1;  	u32 evm2; +	u32 evm3; +	u32 evm4;  };  struct ath_htc_rx_status { -	u64 rs_tstamp; -	u16 rs_datalen; +	__be64 rs_tstamp; +	__be16 rs_datalen;  	u8 rs_status;  	u8 rs_phyerr;  	int8_t rs_rssi; @@ -171,9 +177,9 @@ struct ath_htc_rx_status {  	u8 rs_num_delims;  	u8 rs_flags;  	u8 rs_dummy; -	u32 evm0; -	u32 evm1; -	u32 evm2; +	__be32 evm0; +	__be32 evm1; +	__be32 evm2;  };  #define ATH9K_RXERR_CRC           0x01 @@ -259,7 +265,8 @@ struct ath_desc {  #define ATH9K_TXDESC_EXT_AND_CTL	0x0080  #define ATH9K_TXDESC_VMF		0x0100  #define ATH9K_TXDESC_FRAG_IS_ON 	0x0200 -#define ATH9K_TXDESC_CAB		0x0400 +#define ATH9K_TXDESC_LOWRXCHAIN		0x0400 +#define ATH9K_TXDESC_LDPC		0x00010000  #define ATH9K_RXDESC_INTREQ		0x0020 @@ -353,7 +360,6 @@ struct ar5416_desc {  #define AR_DestIdxValid     0x40000000  #define AR_CTSEnable        0x80000000 -#define AR_BufLen           0x00000fff  #define AR_TxMore           0x00001000  #define AR_DestIdx          0x000fe000  #define AR_DestIdx_S        13 @@ -410,6 +416,7 @@ struct ar5416_desc {  #define AR_EncrType         0x0c000000  #define AR_EncrType_S       26  #define AR_TxCtlRsvd61      0xf0000000 +#define AR_LDPC             0x80000000  #define AR_2040_0           0x00000001  #define AR_GI0              0x00000002 @@ -429,7 +436,10 @@ struct ar5416_desc {  #define AR_ChainSel3_S      17  #define AR_RTSCTSRate       0x0ff00000  #define AR_RTSCTSRate_S     20 -#define AR_TxCtlRsvd70      0xf0000000 +#define AR_STBC0            0x10000000 +#define AR_STBC1            0x20000000 +#define AR_STBC2            0x40000000 +#define AR_STBC3            0x80000000  #define AR_TxRSSIAnt00      0x000000ff  #define AR_TxRSSIAnt00_S    0 @@ -493,7 +503,6 @@ struct ar5416_desc {  #define AR_RxCTLRsvd00  0xffffffff -#define AR_BufLen       0x00000fff  #define AR_RxCtlRsvd00  0x00001000  #define AR_RxIntrReq    0x00002000  #define AR_RxCtlRsvd01  0xffffc000 @@ -643,6 +652,7 @@ enum ath9k_rx_filter {  #define ATH9K_RATESERIES_RTS_CTS  0x0001  #define ATH9K_RATESERIES_2040     0x0002  #define ATH9K_RATESERIES_HALFGI   0x0004 +#define ATH9K_RATESERIES_STBC     0x0008  struct ath9k_11n_rate_series {  	u32 Tries; @@ -686,34 +696,10 @@ struct ath9k_channel;  u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);  void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);  void ath9k_hw_txstart(struct ath_hw *ah, u32 q); +void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);  u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);  bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);  bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); -void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, -			 u32 segLen, bool firstSeg, -			 bool lastSeg, const struct ath_desc *ds0); -void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); -int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, -			struct ath_tx_status *ts); -void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, -			    u32 pktLen, enum ath9k_pkt_type type, u32 txPower, -			    u32 keyIx, enum ath9k_key_type keyType, u32 flags); -void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, -				  struct ath_desc *lastds, -				  u32 durUpdateEn, u32 rtsctsRate, -				  u32 rtsctsDuration, -				  struct ath9k_11n_rate_series series[], -				  u32 nseries, u32 flags); -void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, -				u32 aggrLen); -void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, -				 u32 numDelims); -void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds); -void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds); -void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, -				   u32 burstDuration); -void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, -				     u32 vmf);  void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);  bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,  			    const struct ath9k_tx_queue_info *qinfo); @@ -729,10 +715,17 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,  			  u32 size, u32 flags);  bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);  void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); -void ath9k_hw_rxena(struct ath_hw *ah);  void ath9k_hw_startpcureceive(struct ath_hw *ah);  void ath9k_hw_stoppcurecv(struct ath_hw *ah); +void ath9k_hw_abortpcurecv(struct ath_hw *ah);  bool ath9k_hw_stopdmarecv(struct ath_hw *ah);  int ath9k_hw_beaconq_setup(struct ath_hw *ah); +/* Interrupt Handling */ +bool ath9k_hw_intrpend(struct ath_hw *ah); +enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, +				       enum ath9k_int ints); + +void ar9002_hw_attach_mac_ops(struct ath_hw *ah); +  #endif /* MAC_H */ diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index f7ef11407e2..893b552981a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -401,23 +401,41 @@ void ath9k_tasklet(unsigned long data)  	struct ath_common *common = ath9k_hw_common(ah);  	u32 status = sc->intrstatus; +	u32 rxmask;  	ath9k_ps_wakeup(sc); -	if (status & ATH9K_INT_FATAL) { +	if ((status & ATH9K_INT_FATAL) || +	    !ath9k_hw_check_alive(ah)) {  		ath_reset(sc, false);  		ath9k_ps_restore(sc);  		return;  	} -	if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { +	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) +		rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | +			  ATH9K_INT_RXORN); +	else +		rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN); + +	if (status & rxmask) {  		spin_lock_bh(&sc->rx.rxflushlock); -		ath_rx_tasklet(sc, 0); + +		/* Check for high priority Rx first */ +		if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && +		    (status & ATH9K_INT_RXHP)) +			ath_rx_tasklet(sc, 0, true); + +		ath_rx_tasklet(sc, 0, false);  		spin_unlock_bh(&sc->rx.rxflushlock);  	} -	if (status & ATH9K_INT_TX) -		ath_tx_tasklet(sc); +	if (status & ATH9K_INT_TX) { +		if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) +			ath_tx_edma_tasklet(sc); +		else +			ath_tx_tasklet(sc); +	}  	if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) {  		/* @@ -445,6 +463,8 @@ irqreturn_t ath_isr(int irq, void *dev)  		ATH9K_INT_RXORN |		\  		ATH9K_INT_RXEOL |		\  		ATH9K_INT_RX |			\ +		ATH9K_INT_RXLP |		\ +		ATH9K_INT_RXHP |		\  		ATH9K_INT_TX |			\  		ATH9K_INT_BMISS |		\  		ATH9K_INT_CST |			\ @@ -496,7 +516,8 @@ irqreturn_t ath_isr(int irq, void *dev)  	 * If a FATAL or RXORN interrupt is received, we have to reset the  	 * chip immediately.  	 */ -	if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN)) +	if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) && +	    !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))  		goto chip_reset;  	if (status & ATH9K_INT_SWBA) @@ -505,6 +526,13 @@ irqreturn_t ath_isr(int irq, void *dev)  	if (status & ATH9K_INT_TXURN)  		ath9k_hw_updatetxtriglevel(ah, true); +	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +		if (status & ATH9K_INT_RXEOL) { +			ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN); +			ath9k_hw_set_interrupts(ah, ah->imask); +		} +	} +  	if (status & ATH9K_INT_MIB) {  		/*  		 * Disable interrupts until we service the MIB @@ -724,6 +752,7 @@ static int ath_key_config(struct ath_common *common,  	struct ath_hw *ah = common->ah;  	struct ath9k_keyval hk;  	const u8 *mac = NULL; +	u8 gmac[ETH_ALEN];  	int ret = 0;  	int idx; @@ -747,9 +776,30 @@ static int ath_key_config(struct ath_common *common,  	memcpy(hk.kv_val, key->key, key->keylen);  	if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { -		/* For now, use the default keys for broadcast keys. This may -		 * need to change with virtual interfaces. */ -		idx = key->keyidx; + +		if (key->ap_addr) { +			/* +			 * Group keys on hardware that supports multicast frame +			 * key search use a mac that is the sender's address with +			 * the high bit set instead of the app-specified address. +			 */ +			memcpy(gmac, key->ap_addr, ETH_ALEN); +			gmac[0] |= 0x80; +			mac = gmac; + +			if (key->alg == ALG_TKIP) +				idx = ath_reserve_key_cache_slot_tkip(common); +			else +				idx = ath_reserve_key_cache_slot(common); +			if (idx < 0) +				mac = NULL; /* no free key cache entries */ +		} + +		if (!mac) { +			/* For now, use the default keys for broadcast keys. This may +			 * need to change with virtual interfaces. */ +			idx = key->keyidx; +		}  	} else if (key->keyidx) {  		if (WARN_ON(!sta))  			return -EOPNOTSUPP; @@ -1162,9 +1212,14 @@ static int ath9k_start(struct ieee80211_hw *hw)  	}  	/* Setup our intr mask. */ -	ah->imask = ATH9K_INT_RX | ATH9K_INT_TX -		| ATH9K_INT_RXEOL | ATH9K_INT_RXORN -		| ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; +	ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | +		    ATH9K_INT_RXORN | ATH9K_INT_FATAL | +		    ATH9K_INT_GLOBAL; + +	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) +		ah->imask |= ATH9K_INT_RXHP | ATH9K_INT_RXLP; +	else +		ah->imask |= ATH9K_INT_RX;  	if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT)  		ah->imask |= ATH9K_INT_GTT; @@ -1436,7 +1491,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,  	if ((vif->type == NL80211_IFTYPE_STATION) ||  	    (vif->type == NL80211_IFTYPE_ADHOC) ||  	    (vif->type == NL80211_IFTYPE_MESH_POINT)) { -		ah->imask |= ATH9K_INT_MIB; +		if (ah->config.enable_ani) +			ah->imask |= ATH9K_INT_MIB;  		ah->imask |= ATH9K_INT_TSFOOR;  	} @@ -1988,6 +2044,25 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,  	return ret;  } +static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, +			     struct survey_info *survey) +{ +	struct ath_wiphy *aphy = hw->priv; +	struct ath_softc *sc = aphy->sc; +	struct ath_hw *ah = sc->sc_ah; +	struct ath_common *common = ath9k_hw_common(ah); +	struct ieee80211_conf *conf = &hw->conf; + +	 if (idx != 0) +		return -ENOENT; + +	survey->channel = conf->channel; +	survey->filled = SURVEY_INFO_NOISE_DBM; +	survey->noise = common->ani.noise_floor; + +	return 0; +} +  static void ath9k_sw_scan_start(struct ieee80211_hw *hw)  {  	struct ath_wiphy *aphy = hw->priv; @@ -2059,6 +2134,7 @@ struct ieee80211_ops ath9k_ops = {  	.set_tsf 	    = ath9k_set_tsf,  	.reset_tsf 	    = ath9k_reset_tsf,  	.ampdu_action       = ath9k_ampdu_action, +	.get_survey	    = ath9k_get_survey,  	.sw_scan_start      = ath9k_sw_scan_start,  	.sw_scan_complete   = ath9k_sw_scan_complete,  	.rfkill_poll        = ath9k_rfkill_poll_state, diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 1ec836cf1c0..257b10ba6f5 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -28,6 +28,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {  	{ PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */  	{ PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI   */  	{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ +	{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E  AR9300 */  	{ 0 }  }; diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c deleted file mode 100644 index 2547b3c4a26..00000000000 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ /dev/null @@ -1,978 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/** - * DOC: Programming Atheros 802.11n analog front end radios - * - * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express - * devices have either an external AR2133 analog front end radio for single - * band 2.4 GHz communication or an AR5133 analog front end radio for dual - * band 2.4 GHz / 5 GHz communication. - * - * All devices after the AR5416 and AR5418 family starting with the AR9280 - * have their analog front radios, MAC/BB and host PCIe/USB interface embedded - * into a single-chip and require less programming. - * - * The following single-chips exist with a respective embedded radio: - * - * AR9280 - 11n dual-band 2x2 MIMO for PCIe - * AR9281 - 11n single-band 1x2 MIMO for PCIe - * AR9285 - 11n single-band 1x1 for PCIe - * AR9287 - 11n single-band 2x2 MIMO for PCIe - * - * AR9220 - 11n dual-band 2x2 MIMO for PCI - * AR9223 - 11n single-band 2x2 MIMO for PCI - * - * AR9287 - 11n single-band 1x1 MIMO for USB - */ - -#include <linux/slab.h> - -#include "hw.h" - -/** - * ath9k_hw_write_regs - ?? - * - * @ah: atheros hardware structure - * @freqIndex: - * @regWrites: - * - * Used for both the chipsets with an external AR2133/AR5133 radios and - * single-chip devices. - */ -void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites) -{ -	REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); -} - -/** - * ath9k_hw_ar9280_set_channel - set channel on single-chip device - * @ah: atheros hardware structure - * @chan: - * - * This is the function to change channel on single-chip devices, that is - * all devices after ar9280. - * - * This function takes the channel value in MHz and sets - * hardware channel value. Assumes writes have been enabled to analog bus. - * - * Actual Expression, - * - * For 2GHz channel, - * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) - * (freq_ref = 40MHz) - * - * For 5GHz channel, - * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) - * (freq_ref = 40MHz/(24>>amodeRefSel)) - */ -int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) -{ -	u16 bMode, fracMode, aModeRefSel = 0; -	u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; -	struct chan_centers centers; -	u32 refDivA = 24; - -	ath9k_hw_get_channel_centers(ah, chan, ¢ers); -	freq = centers.synth_center; - -	reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); -	reg32 &= 0xc0000000; - -	if (freq < 4800) { /* 2 GHz, fractional mode */ -		u32 txctl; -		int regWrites = 0; - -		bMode = 1; -		fracMode = 1; -		aModeRefSel = 0; -		channelSel = (freq * 0x10000) / 15; - -		if (AR_SREV_9287_11_OR_LATER(ah)) { -			if (freq == 2484) { -				/* Enable channel spreading for channel 14 */ -				REG_WRITE_ARRAY(&ah->iniCckfirJapan2484, -						1, regWrites); -			} else { -				REG_WRITE_ARRAY(&ah->iniCckfirNormal, -						1, regWrites); -			} -		} else { -			txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); -			if (freq == 2484) { -				/* Enable channel spreading for channel 14 */ -				REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, -					  txctl | AR_PHY_CCK_TX_CTRL_JAPAN); -			} else { -				REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, -					  txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); -			} -		} -	} else { -		bMode = 0; -		fracMode = 0; - -		switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) { -		case 0: -			if ((freq % 20) == 0) { -				aModeRefSel = 3; -			} else if ((freq % 10) == 0) { -				aModeRefSel = 2; -			} -			if (aModeRefSel) -				break; -		case 1: -		default: -			aModeRefSel = 0; -			/* -			 * Enable 2G (fractional) mode for channels -			 * which are 5MHz spaced. -			 */ -			fracMode = 1; -			refDivA = 1; -			channelSel = (freq * 0x8000) / 15; - -			/* RefDivA setting */ -			REG_RMW_FIELD(ah, AR_AN_SYNTH9, -				      AR_AN_SYNTH9_REFDIVA, refDivA); - -		} - -		if (!fracMode) { -			ndiv = (freq * (refDivA >> aModeRefSel)) / 60; -			channelSel = ndiv & 0x1ff; -			channelFrac = (ndiv & 0xfffffe00) * 2; -			channelSel = (channelSel << 17) | channelFrac; -		} -	} - -	reg32 = reg32 | -	    (bMode << 29) | -	    (fracMode << 28) | (aModeRefSel << 26) | (channelSel); - -	REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); - -	ah->curchan = chan; -	ah->curchan_rad_index = -1; - -	return 0; -} - -/** - * ath9k_hw_9280_spur_mitigate - convert baseband spur frequency - * @ah: atheros hardware structure - * @chan: - * - * For single-chip solutions. Converts to baseband spur frequency given the - * input channel frequency and compute register settings below. - */ -void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ -	int bb_spur = AR_NO_SPUR; -	int freq; -	int bin, cur_bin; -	int bb_spur_off, spur_subchannel_sd; -	int spur_freq_sd; -	int spur_delta_phase; -	int denominator; -	int upper, lower, cur_vit_mask; -	int tmp, newVal; -	int i; -	int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, -			  AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 -	}; -	int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, -			 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 -	}; -	int inc[4] = { 0, 100, 0, 0 }; -	struct chan_centers centers; - -	int8_t mask_m[123]; -	int8_t mask_p[123]; -	int8_t mask_amt; -	int tmp_mask; -	int cur_bb_spur; -	bool is2GHz = IS_CHAN_2GHZ(chan); - -	memset(&mask_m, 0, sizeof(int8_t) * 123); -	memset(&mask_p, 0, sizeof(int8_t) * 123); - -	ath9k_hw_get_channel_centers(ah, chan, ¢ers); -	freq = centers.synth_center; - -	ah->config.spurmode = SPUR_ENABLE_EEPROM; -	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { -		cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - -		if (is2GHz) -			cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; -		else -			cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; - -		if (AR_NO_SPUR == cur_bb_spur) -			break; -		cur_bb_spur = cur_bb_spur - freq; - -		if (IS_CHAN_HT40(chan)) { -			if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && -			    (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { -				bb_spur = cur_bb_spur; -				break; -			} -		} else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && -			   (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { -			bb_spur = cur_bb_spur; -			break; -		} -	} - -	if (AR_NO_SPUR == bb_spur) { -		REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, -			    AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); -		return; -	} else { -		REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, -			    AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); -	} - -	bin = bb_spur * 320; - -	tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - -	newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | -			AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | -			AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | -			AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); -	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); - -	newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | -		  AR_PHY_SPUR_REG_ENABLE_MASK_PPM | -		  AR_PHY_SPUR_REG_MASK_RATE_SELECT | -		  AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | -		  SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); -	REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); - -	if (IS_CHAN_HT40(chan)) { -		if (bb_spur < 0) { -			spur_subchannel_sd = 1; -			bb_spur_off = bb_spur + 10; -		} else { -			spur_subchannel_sd = 0; -			bb_spur_off = bb_spur - 10; -		} -	} else { -		spur_subchannel_sd = 0; -		bb_spur_off = bb_spur; -	} - -	if (IS_CHAN_HT40(chan)) -		spur_delta_phase = -			((bb_spur * 262144) / -			 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; -	else -		spur_delta_phase = -			((bb_spur * 524288) / -			 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - -	denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; -	spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; - -	newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | -		  SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | -		  SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); -	REG_WRITE(ah, AR_PHY_TIMING11, newVal); - -	newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; -	REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); - -	cur_bin = -6000; -	upper = bin + 100; -	lower = bin - 100; - -	for (i = 0; i < 4; i++) { -		int pilot_mask = 0; -		int chan_mask = 0; -		int bp = 0; -		for (bp = 0; bp < 30; bp++) { -			if ((cur_bin > lower) && (cur_bin < upper)) { -				pilot_mask = pilot_mask | 0x1 << bp; -				chan_mask = chan_mask | 0x1 << bp; -			} -			cur_bin += 100; -		} -		cur_bin += inc[i]; -		REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); -		REG_WRITE(ah, chan_mask_reg[i], chan_mask); -	} - -	cur_vit_mask = 6100; -	upper = bin + 120; -	lower = bin - 120; - -	for (i = 0; i < 123; i++) { -		if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - -			/* workaround for gcc bug #37014 */ -			volatile int tmp_v = abs(cur_vit_mask - bin); - -			if (tmp_v < 75) -				mask_amt = 1; -			else -				mask_amt = 0; -			if (cur_vit_mask < 0) -				mask_m[abs(cur_vit_mask / 100)] = mask_amt; -			else -				mask_p[cur_vit_mask / 100] = mask_amt; -		} -		cur_vit_mask -= 100; -	} - -	tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) -		| (mask_m[48] << 26) | (mask_m[49] << 24) -		| (mask_m[50] << 22) | (mask_m[51] << 20) -		| (mask_m[52] << 18) | (mask_m[53] << 16) -		| (mask_m[54] << 14) | (mask_m[55] << 12) -		| (mask_m[56] << 10) | (mask_m[57] << 8) -		| (mask_m[58] << 6) | (mask_m[59] << 4) -		| (mask_m[60] << 2) | (mask_m[61] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); -	REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - -	tmp_mask = (mask_m[31] << 28) -		| (mask_m[32] << 26) | (mask_m[33] << 24) -		| (mask_m[34] << 22) | (mask_m[35] << 20) -		| (mask_m[36] << 18) | (mask_m[37] << 16) -		| (mask_m[48] << 14) | (mask_m[39] << 12) -		| (mask_m[40] << 10) | (mask_m[41] << 8) -		| (mask_m[42] << 6) | (mask_m[43] << 4) -		| (mask_m[44] << 2) | (mask_m[45] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - -	tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) -		| (mask_m[18] << 26) | (mask_m[18] << 24) -		| (mask_m[20] << 22) | (mask_m[20] << 20) -		| (mask_m[22] << 18) | (mask_m[22] << 16) -		| (mask_m[24] << 14) | (mask_m[24] << 12) -		| (mask_m[25] << 10) | (mask_m[26] << 8) -		| (mask_m[27] << 6) | (mask_m[28] << 4) -		| (mask_m[29] << 2) | (mask_m[30] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - -	tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) -		| (mask_m[2] << 26) | (mask_m[3] << 24) -		| (mask_m[4] << 22) | (mask_m[5] << 20) -		| (mask_m[6] << 18) | (mask_m[7] << 16) -		| (mask_m[8] << 14) | (mask_m[9] << 12) -		| (mask_m[10] << 10) | (mask_m[11] << 8) -		| (mask_m[12] << 6) | (mask_m[13] << 4) -		| (mask_m[14] << 2) | (mask_m[15] << 0); -	REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - -	tmp_mask = (mask_p[15] << 28) -		| (mask_p[14] << 26) | (mask_p[13] << 24) -		| (mask_p[12] << 22) | (mask_p[11] << 20) -		| (mask_p[10] << 18) | (mask_p[9] << 16) -		| (mask_p[8] << 14) | (mask_p[7] << 12) -		| (mask_p[6] << 10) | (mask_p[5] << 8) -		| (mask_p[4] << 6) | (mask_p[3] << 4) -		| (mask_p[2] << 2) | (mask_p[1] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - -	tmp_mask = (mask_p[30] << 28) -		| (mask_p[29] << 26) | (mask_p[28] << 24) -		| (mask_p[27] << 22) | (mask_p[26] << 20) -		| (mask_p[25] << 18) | (mask_p[24] << 16) -		| (mask_p[23] << 14) | (mask_p[22] << 12) -		| (mask_p[21] << 10) | (mask_p[20] << 8) -		| (mask_p[19] << 6) | (mask_p[18] << 4) -		| (mask_p[17] << 2) | (mask_p[16] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - -	tmp_mask = (mask_p[45] << 28) -		| (mask_p[44] << 26) | (mask_p[43] << 24) -		| (mask_p[42] << 22) | (mask_p[41] << 20) -		| (mask_p[40] << 18) | (mask_p[39] << 16) -		| (mask_p[38] << 14) | (mask_p[37] << 12) -		| (mask_p[36] << 10) | (mask_p[35] << 8) -		| (mask_p[34] << 6) | (mask_p[33] << 4) -		| (mask_p[32] << 2) | (mask_p[31] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - -	tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) -		| (mask_p[59] << 26) | (mask_p[58] << 24) -		| (mask_p[57] << 22) | (mask_p[56] << 20) -		| (mask_p[55] << 18) | (mask_p[54] << 16) -		| (mask_p[53] << 14) | (mask_p[52] << 12) -		| (mask_p[51] << 10) | (mask_p[50] << 8) -		| (mask_p[49] << 6) | (mask_p[48] << 4) -		| (mask_p[47] << 2) | (mask_p[46] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - -/* All code below is for non single-chip solutions */ - -/** - * ath9k_phy_modify_rx_buffer() - perform analog swizzling of parameters - * @rfbuf: - * @reg32: - * @numBits: - * @firstBit: - * @column: - * - * Performs analog "swizzling" of parameters into their location. - * Used on external AR2133/AR5133 radios. - */ -static void ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, -				       u32 numBits, u32 firstBit, -				       u32 column) -{ -	u32 tmp32, mask, arrayEntry, lastBit; -	int32_t bitPosition, bitsLeft; - -	tmp32 = ath9k_hw_reverse_bits(reg32, numBits); -	arrayEntry = (firstBit - 1) / 8; -	bitPosition = (firstBit - 1) % 8; -	bitsLeft = numBits; -	while (bitsLeft > 0) { -		lastBit = (bitPosition + bitsLeft > 8) ? -		    8 : bitPosition + bitsLeft; -		mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << -		    (column * 8); -		rfBuf[arrayEntry] &= ~mask; -		rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << -				      (column * 8)) & mask; -		bitsLeft -= 8 - bitPosition; -		tmp32 = tmp32 >> (8 - bitPosition); -		bitPosition = 0; -		arrayEntry++; -	} -} - -/* - * Fix on 2.4 GHz band for orientation sensitivity issue by increasing - * rf_pwd_icsyndiv. - * - * Theoretical Rules: - *   if 2 GHz band - *      if forceBiasAuto - *         if synth_freq < 2412 - *            bias = 0 - *         else if 2412 <= synth_freq <= 2422 - *            bias = 1 - *         else // synth_freq > 2422 - *            bias = 2 - *      else if forceBias > 0 - *         bias = forceBias & 7 - *      else - *         no change, use value from ini file - *   else - *      no change, invalid band - * - *  1st Mod: - *    2422 also uses value of 2 - *    <approved> - * - *  2nd Mod: - *    Less than 2412 uses value of 0, 2412 and above uses value of 2 - */ -static void ath9k_hw_force_bias(struct ath_hw *ah, u16 synth_freq) -{ -	struct ath_common *common = ath9k_hw_common(ah); -	u32 tmp_reg; -	int reg_writes = 0; -	u32 new_bias = 0; - -	if (!AR_SREV_5416(ah) || synth_freq >= 3000) { -		return; -	} - -	BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); - -	if (synth_freq < 2412) -		new_bias = 0; -	else if (synth_freq < 2422) -		new_bias = 1; -	else -		new_bias = 2; - -	/* pre-reverse this field */ -	tmp_reg = ath9k_hw_reverse_bits(new_bias, 3); - -	ath_print(common, ATH_DBG_CONFIG, -		  "Force rf_pwd_icsyndiv to %1d on %4d\n", -		  new_bias, synth_freq); - -	/* swizzle rf_pwd_icsyndiv */ -	ath9k_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); - -	/* write Bank 6 with new params */ -	REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes); -} - -/** - * ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios - * @ah: atheros hardware stucture - * @chan: - * - * For the external AR2133/AR5133 radios, takes the MHz channel value and set - * the channel value. Assumes writes enabled to analog bus and bank6 register - * cache in ah->analogBank6Data. - */ -int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) -{ -	struct ath_common *common = ath9k_hw_common(ah); -	u32 channelSel = 0; -	u32 bModeSynth = 0; -	u32 aModeRefSel = 0; -	u32 reg32 = 0; -	u16 freq; -	struct chan_centers centers; - -	ath9k_hw_get_channel_centers(ah, chan, ¢ers); -	freq = centers.synth_center; - -	if (freq < 4800) { -		u32 txctl; - -		if (((freq - 2192) % 5) == 0) { -			channelSel = ((freq - 672) * 2 - 3040) / 10; -			bModeSynth = 0; -		} else if (((freq - 2224) % 5) == 0) { -			channelSel = ((freq - 704) * 2 - 3040) / 10; -			bModeSynth = 1; -		} else { -			ath_print(common, ATH_DBG_FATAL, -				  "Invalid channel %u MHz\n", freq); -			return -EINVAL; -		} - -		channelSel = (channelSel << 2) & 0xff; -		channelSel = ath9k_hw_reverse_bits(channelSel, 8); - -		txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); -		if (freq == 2484) { - -			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, -				  txctl | AR_PHY_CCK_TX_CTRL_JAPAN); -		} else { -			REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, -				  txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); -		} - -	} else if ((freq % 20) == 0 && freq >= 5120) { -		channelSel = -		    ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); -		aModeRefSel = ath9k_hw_reverse_bits(1, 2); -	} else if ((freq % 10) == 0) { -		channelSel = -		    ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); -		if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) -			aModeRefSel = ath9k_hw_reverse_bits(2, 2); -		else -			aModeRefSel = ath9k_hw_reverse_bits(1, 2); -	} else if ((freq % 5) == 0) { -		channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); -		aModeRefSel = ath9k_hw_reverse_bits(1, 2); -	} else { -		ath_print(common, ATH_DBG_FATAL, -			  "Invalid channel %u MHz\n", freq); -		return -EINVAL; -	} - -	ath9k_hw_force_bias(ah, freq); - -	reg32 = -	    (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | -	    (1 << 5) | 0x1; - -	REG_WRITE(ah, AR_PHY(0x37), reg32); - -	ah->curchan = chan; -	ah->curchan_rad_index = -1; - -	return 0; -} - -/** - * ath9k_hw_spur_mitigate - convert baseband spur frequency for external radios - * @ah: atheros hardware structure - * @chan: - * - * For non single-chip solutions. Converts to baseband spur frequency given the - * input channel frequency and compute register settings below. - */ -void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ -	int bb_spur = AR_NO_SPUR; -	int bin, cur_bin; -	int spur_freq_sd; -	int spur_delta_phase; -	int denominator; -	int upper, lower, cur_vit_mask; -	int tmp, new; -	int i; -	int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, -			  AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 -	}; -	int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, -			 AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 -	}; -	int inc[4] = { 0, 100, 0, 0 }; - -	int8_t mask_m[123]; -	int8_t mask_p[123]; -	int8_t mask_amt; -	int tmp_mask; -	int cur_bb_spur; -	bool is2GHz = IS_CHAN_2GHZ(chan); - -	memset(&mask_m, 0, sizeof(int8_t) * 123); -	memset(&mask_p, 0, sizeof(int8_t) * 123); - -	for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { -		cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); -		if (AR_NO_SPUR == cur_bb_spur) -			break; -		cur_bb_spur = cur_bb_spur - (chan->channel * 10); -		if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { -			bb_spur = cur_bb_spur; -			break; -		} -	} - -	if (AR_NO_SPUR == bb_spur) -		return; - -	bin = bb_spur * 32; - -	tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); -	new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | -		     AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | -		     AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | -		     AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - -	REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); - -	new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | -	       AR_PHY_SPUR_REG_ENABLE_MASK_PPM | -	       AR_PHY_SPUR_REG_MASK_RATE_SELECT | -	       AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | -	       SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); -	REG_WRITE(ah, AR_PHY_SPUR_REG, new); - -	spur_delta_phase = ((bb_spur * 524288) / 100) & -		AR_PHY_TIMING11_SPUR_DELTA_PHASE; - -	denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; -	spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; - -	new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | -	       SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | -	       SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); -	REG_WRITE(ah, AR_PHY_TIMING11, new); - -	cur_bin = -6000; -	upper = bin + 100; -	lower = bin - 100; - -	for (i = 0; i < 4; i++) { -		int pilot_mask = 0; -		int chan_mask = 0; -		int bp = 0; -		for (bp = 0; bp < 30; bp++) { -			if ((cur_bin > lower) && (cur_bin < upper)) { -				pilot_mask = pilot_mask | 0x1 << bp; -				chan_mask = chan_mask | 0x1 << bp; -			} -			cur_bin += 100; -		} -		cur_bin += inc[i]; -		REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); -		REG_WRITE(ah, chan_mask_reg[i], chan_mask); -	} - -	cur_vit_mask = 6100; -	upper = bin + 120; -	lower = bin - 120; - -	for (i = 0; i < 123; i++) { -		if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - -			/* workaround for gcc bug #37014 */ -			volatile int tmp_v = abs(cur_vit_mask - bin); - -			if (tmp_v < 75) -				mask_amt = 1; -			else -				mask_amt = 0; -			if (cur_vit_mask < 0) -				mask_m[abs(cur_vit_mask / 100)] = mask_amt; -			else -				mask_p[cur_vit_mask / 100] = mask_amt; -		} -		cur_vit_mask -= 100; -	} - -	tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) -		| (mask_m[48] << 26) | (mask_m[49] << 24) -		| (mask_m[50] << 22) | (mask_m[51] << 20) -		| (mask_m[52] << 18) | (mask_m[53] << 16) -		| (mask_m[54] << 14) | (mask_m[55] << 12) -		| (mask_m[56] << 10) | (mask_m[57] << 8) -		| (mask_m[58] << 6) | (mask_m[59] << 4) -		| (mask_m[60] << 2) | (mask_m[61] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); -	REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - -	tmp_mask = (mask_m[31] << 28) -		| (mask_m[32] << 26) | (mask_m[33] << 24) -		| (mask_m[34] << 22) | (mask_m[35] << 20) -		| (mask_m[36] << 18) | (mask_m[37] << 16) -		| (mask_m[48] << 14) | (mask_m[39] << 12) -		| (mask_m[40] << 10) | (mask_m[41] << 8) -		| (mask_m[42] << 6) | (mask_m[43] << 4) -		| (mask_m[44] << 2) | (mask_m[45] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - -	tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) -		| (mask_m[18] << 26) | (mask_m[18] << 24) -		| (mask_m[20] << 22) | (mask_m[20] << 20) -		| (mask_m[22] << 18) | (mask_m[22] << 16) -		| (mask_m[24] << 14) | (mask_m[24] << 12) -		| (mask_m[25] << 10) | (mask_m[26] << 8) -		| (mask_m[27] << 6) | (mask_m[28] << 4) -		| (mask_m[29] << 2) | (mask_m[30] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - -	tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) -		| (mask_m[2] << 26) | (mask_m[3] << 24) -		| (mask_m[4] << 22) | (mask_m[5] << 20) -		| (mask_m[6] << 18) | (mask_m[7] << 16) -		| (mask_m[8] << 14) | (mask_m[9] << 12) -		| (mask_m[10] << 10) | (mask_m[11] << 8) -		| (mask_m[12] << 6) | (mask_m[13] << 4) -		| (mask_m[14] << 2) | (mask_m[15] << 0); -	REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - -	tmp_mask = (mask_p[15] << 28) -		| (mask_p[14] << 26) | (mask_p[13] << 24) -		| (mask_p[12] << 22) | (mask_p[11] << 20) -		| (mask_p[10] << 18) | (mask_p[9] << 16) -		| (mask_p[8] << 14) | (mask_p[7] << 12) -		| (mask_p[6] << 10) | (mask_p[5] << 8) -		| (mask_p[4] << 6) | (mask_p[3] << 4) -		| (mask_p[2] << 2) | (mask_p[1] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - -	tmp_mask = (mask_p[30] << 28) -		| (mask_p[29] << 26) | (mask_p[28] << 24) -		| (mask_p[27] << 22) | (mask_p[26] << 20) -		| (mask_p[25] << 18) | (mask_p[24] << 16) -		| (mask_p[23] << 14) | (mask_p[22] << 12) -		| (mask_p[21] << 10) | (mask_p[20] << 8) -		| (mask_p[19] << 6) | (mask_p[18] << 4) -		| (mask_p[17] << 2) | (mask_p[16] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - -	tmp_mask = (mask_p[45] << 28) -		| (mask_p[44] << 26) | (mask_p[43] << 24) -		| (mask_p[42] << 22) | (mask_p[41] << 20) -		| (mask_p[40] << 18) | (mask_p[39] << 16) -		| (mask_p[38] << 14) | (mask_p[37] << 12) -		| (mask_p[36] << 10) | (mask_p[35] << 8) -		| (mask_p[34] << 6) | (mask_p[33] << 4) -		| (mask_p[32] << 2) | (mask_p[31] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - -	tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) -		| (mask_p[59] << 26) | (mask_p[58] << 24) -		| (mask_p[57] << 22) | (mask_p[56] << 20) -		| (mask_p[55] << 18) | (mask_p[54] << 16) -		| (mask_p[53] << 14) | (mask_p[52] << 12) -		| (mask_p[51] << 10) | (mask_p[50] << 8) -		| (mask_p[49] << 6) | (mask_p[48] << 4) -		| (mask_p[47] << 2) | (mask_p[46] << 0); -	REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); -	REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - -/** - * ath9k_hw_rf_alloc_ext_banks - allocates banks for external radio programming - * @ah: atheros hardware structure - * - * Only required for older devices with external AR2133/AR5133 radios. - */ -int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah) -{ -#define ATH_ALLOC_BANK(bank, size) do { \ -		bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ -		if (!bank) { \ -			ath_print(common, ATH_DBG_FATAL, \ -				  "Cannot allocate RF banks\n"); \ -			return -ENOMEM; \ -		} \ -	} while (0); - -	struct ath_common *common = ath9k_hw_common(ah); - -	BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); - -	ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); -	ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); -	ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows); -	ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows); -	ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows); -	ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows); -	ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows); -	ATH_ALLOC_BANK(ah->addac5416_21, -		       ah->iniAddac.ia_rows * ah->iniAddac.ia_columns); -	ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows); - -	return 0; -#undef ATH_ALLOC_BANK -} - - -/** - * ath9k_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers - * @ah: atheros hardware struture - * For the external AR2133/AR5133 radios banks. - */ -void -ath9k_hw_rf_free_ext_banks(struct ath_hw *ah) -{ -#define ATH_FREE_BANK(bank) do { \ -		kfree(bank); \ -		bank = NULL; \ -	} while (0); - -	BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); - -	ATH_FREE_BANK(ah->analogBank0Data); -	ATH_FREE_BANK(ah->analogBank1Data); -	ATH_FREE_BANK(ah->analogBank2Data); -	ATH_FREE_BANK(ah->analogBank3Data); -	ATH_FREE_BANK(ah->analogBank6Data); -	ATH_FREE_BANK(ah->analogBank6TPCData); -	ATH_FREE_BANK(ah->analogBank7Data); -	ATH_FREE_BANK(ah->addac5416_21); -	ATH_FREE_BANK(ah->bank6Temp); - -#undef ATH_FREE_BANK -} - -/* * - * ath9k_hw_set_rf_regs - programs rf registers based on EEPROM - * @ah: atheros hardware structure - * @chan: - * @modesIndex: - * - * Used for the external AR2133/AR5133 radios. - * - * Reads the EEPROM header info from the device structure and programs - * all rf registers. This routine requires access to the analog - * rf device. This is not required for single-chip devices. - */ -bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, -			  u16 modesIndex) -{ -	u32 eepMinorRev; -	u32 ob5GHz = 0, db5GHz = 0; -	u32 ob2GHz = 0, db2GHz = 0; -	int regWrites = 0; - -	/* -	 * Software does not need to program bank data -	 * for single chip devices, that is AR9280 or anything -	 * after that. -	 */ -	if (AR_SREV_9280_10_OR_LATER(ah)) -		return true; - -	/* Setup rf parameters */ -	eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); - -	/* Setup Bank 0 Write */ -	RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); - -	/* Setup Bank 1 Write */ -	RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); - -	/* Setup Bank 2 Write */ -	RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); - -	/* Setup Bank 6 Write */ -	RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, -		      modesIndex); -	{ -		int i; -		for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) { -			ah->analogBank6Data[i] = -			    INI_RA(&ah->iniBank6TPC, i, modesIndex); -		} -	} - -	/* Only the 5 or 2 GHz OB/DB need to be set for a mode */ -	if (eepMinorRev >= 2) { -		if (IS_CHAN_2GHZ(chan)) { -			ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); -			db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2); -			ath9k_phy_modify_rx_buffer(ah->analogBank6Data, -						   ob2GHz, 3, 197, 0); -			ath9k_phy_modify_rx_buffer(ah->analogBank6Data, -						   db2GHz, 3, 194, 0); -		} else { -			ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5); -			db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5); -			ath9k_phy_modify_rx_buffer(ah->analogBank6Data, -						   ob5GHz, 3, 203, 0); -			ath9k_phy_modify_rx_buffer(ah->analogBank6Data, -						   db5GHz, 3, 200, 0); -		} -	} - -	/* Setup Bank 7 Setup */ -	RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); - -	/* Write Analog registers */ -	REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, -			   regWrites); -	REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, -			   regWrites); -	REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data, -			   regWrites); -	REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data, -			   regWrites); -	REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data, -			   regWrites); -	REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data, -			   regWrites); - -	return true; -} diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 0132e4c9a9f..e724c2c1ae2 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h @@ -17,504 +17,15 @@  #ifndef PHY_H  #define PHY_H -/* Common between single chip and non single-chip solutions */ -void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites); - -/* Single chip radio settings */ -int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan); -void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); - -/* Routines below are for non single-chip solutions */ -int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan); -void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); - -int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah); -void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah); - -bool ath9k_hw_set_rf_regs(struct ath_hw *ah, -			  struct ath9k_channel *chan, -			  u16 modesIndex); +#define CHANSEL_DIV		15 +#define CHANSEL_2G(_freq)	(((_freq) * 0x10000) / CHANSEL_DIV) +#define CHANSEL_5G(_freq)	(((_freq) * 0x8000) / CHANSEL_DIV)  #define AR_PHY_BASE     0x9800  #define AR_PHY(_n)      (AR_PHY_BASE + ((_n)<<2)) -#define AR_PHY_TEST             0x9800 -#define PHY_AGC_CLR             0x10000000 -#define RFSILENT_BB             0x00002000 - -#define AR_PHY_TURBO                0x9804 -#define AR_PHY_FC_TURBO_MODE        0x00000001 -#define AR_PHY_FC_TURBO_SHORT       0x00000002 -#define AR_PHY_FC_DYN2040_EN        0x00000004 -#define AR_PHY_FC_DYN2040_PRI_ONLY  0x00000008 -#define AR_PHY_FC_DYN2040_PRI_CH    0x00000010 -/* For 25 MHz channel spacing -- not used but supported by hw */ -#define AR_PHY_FC_DYN2040_EXT_CH    0x00000020 -#define AR_PHY_FC_HT_EN             0x00000040 -#define AR_PHY_FC_SHORT_GI_40       0x00000080 -#define AR_PHY_FC_WALSH             0x00000100 -#define AR_PHY_FC_SINGLE_HT_LTF1    0x00000200 -#define AR_PHY_FC_ENABLE_DAC_FIFO   0x00000800 - -#define AR_PHY_TEST2 		    0x9808 - -#define AR_PHY_TIMING2           0x9810 -#define AR_PHY_TIMING3           0x9814 -#define AR_PHY_TIMING3_DSC_MAN   0xFFFE0000 -#define AR_PHY_TIMING3_DSC_MAN_S 17 -#define AR_PHY_TIMING3_DSC_EXP   0x0001E000 -#define AR_PHY_TIMING3_DSC_EXP_S 13 - -#define AR_PHY_CHIP_ID            0x9818 -#define AR_PHY_CHIP_ID_REV_0      0x80 -#define AR_PHY_CHIP_ID_REV_1      0x81 -#define AR_PHY_CHIP_ID_9160_REV_0 0xb0 - -#define AR_PHY_ACTIVE       0x981C -#define AR_PHY_ACTIVE_EN    0x00000001 -#define AR_PHY_ACTIVE_DIS   0x00000000 - -#define AR_PHY_RF_CTL2             0x9824 -#define AR_PHY_TX_END_DATA_START   0x000000FF -#define AR_PHY_TX_END_DATA_START_S 0 -#define AR_PHY_TX_END_PA_ON        0x0000FF00 -#define AR_PHY_TX_END_PA_ON_S      8 - -#define AR_PHY_RF_CTL3                  0x9828 -#define AR_PHY_TX_END_TO_A2_RX_ON       0x00FF0000 -#define AR_PHY_TX_END_TO_A2_RX_ON_S     16 - -#define AR_PHY_ADC_CTL                  0x982C -#define AR_PHY_ADC_CTL_OFF_INBUFGAIN    0x00000003 -#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S  0 -#define AR_PHY_ADC_CTL_OFF_PWDDAC       0x00002000 -#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP   0x00004000 -#define AR_PHY_ADC_CTL_OFF_PWDADC       0x00008000 -#define AR_PHY_ADC_CTL_ON_INBUFGAIN     0x00030000 -#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S   16 - -#define AR_PHY_ADC_SERIAL_CTL       0x9830 -#define AR_PHY_SEL_INTERNAL_ADDAC   0x00000000 -#define AR_PHY_SEL_EXTERNAL_RADIO   0x00000001 - -#define AR_PHY_RF_CTL4                    0x9834 -#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF    0xFF000000 -#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S  24 -#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF    0x00FF0000 -#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S  16 -#define AR_PHY_RF_CTL4_FRAME_XPAB_ON      0x0000FF00 -#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S    8 -#define AR_PHY_RF_CTL4_FRAME_XPAA_ON      0x000000FF -#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S    0 - -#define AR_PHY_TSTDAC_CONST               0x983c - -#define AR_PHY_SETTLING          0x9844 -#define AR_PHY_SETTLING_SWITCH   0x00003F80 -#define AR_PHY_SETTLING_SWITCH_S 7 - -#define AR_PHY_RXGAIN                   0x9848 -#define AR_PHY_RXGAIN_TXRX_ATTEN        0x0003F000 -#define AR_PHY_RXGAIN_TXRX_ATTEN_S      12 -#define AR_PHY_RXGAIN_TXRX_RF_MAX       0x007C0000 -#define AR_PHY_RXGAIN_TXRX_RF_MAX_S     18 -#define AR9280_PHY_RXGAIN_TXRX_ATTEN    0x00003F80 -#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S  7 -#define AR9280_PHY_RXGAIN_TXRX_MARGIN   0x001FC000 -#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 - -#define AR_PHY_DESIRED_SZ           0x9850 -#define AR_PHY_DESIRED_SZ_ADC       0x000000FF -#define AR_PHY_DESIRED_SZ_ADC_S     0 -#define AR_PHY_DESIRED_SZ_PGA       0x0000FF00 -#define AR_PHY_DESIRED_SZ_PGA_S     8 -#define AR_PHY_DESIRED_SZ_TOT_DES   0x0FF00000 -#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 - -#define AR_PHY_FIND_SIG           0x9858 -#define AR_PHY_FIND_SIG_FIRSTEP   0x0003F000 -#define AR_PHY_FIND_SIG_FIRSTEP_S 12 -#define AR_PHY_FIND_SIG_FIRPWR    0x03FC0000 -#define AR_PHY_FIND_SIG_FIRPWR_S  18 - -#define AR_PHY_AGC_CTL1                  0x985C -#define AR_PHY_AGC_CTL1_COARSE_LOW       0x00007F80 -#define AR_PHY_AGC_CTL1_COARSE_LOW_S     7 -#define AR_PHY_AGC_CTL1_COARSE_HIGH      0x003F8000 -#define AR_PHY_AGC_CTL1_COARSE_HIGH_S    15 - -#define AR_PHY_AGC_CONTROL               0x9860 -#define AR_PHY_AGC_CONTROL_CAL           0x00000001 -#define AR_PHY_AGC_CONTROL_NF            0x00000002 -#define AR_PHY_AGC_CONTROL_ENABLE_NF     0x00008000 -#define AR_PHY_AGC_CONTROL_FLTR_CAL      0x00010000 -#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF  0x00020000 - -#define AR_PHY_CCA                  0x9864 -#define AR_PHY_MINCCA_PWR           0x0FF80000 -#define AR_PHY_MINCCA_PWR_S         19 -#define AR_PHY_CCA_THRESH62         0x0007F000 -#define AR_PHY_CCA_THRESH62_S       12 -#define AR9280_PHY_MINCCA_PWR       0x1FF00000 -#define AR9280_PHY_MINCCA_PWR_S     20 -#define AR9280_PHY_CCA_THRESH62     0x000FF000 -#define AR9280_PHY_CCA_THRESH62_S   12 - -#define AR_PHY_SFCORR_LOW                    0x986C -#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW  0x00000001 -#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW    0x00003F00 -#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S  8 -#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW      0x001FC000 -#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S    14 -#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW      0x0FE00000 -#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S    21 - -#define AR_PHY_SFCORR                0x9868 -#define AR_PHY_SFCORR_M2COUNT_THR    0x0000001F -#define AR_PHY_SFCORR_M2COUNT_THR_S  0 -#define AR_PHY_SFCORR_M1_THRESH      0x00FE0000 -#define AR_PHY_SFCORR_M1_THRESH_S    17 -#define AR_PHY_SFCORR_M2_THRESH      0x7F000000 -#define AR_PHY_SFCORR_M2_THRESH_S    24 - -#define AR_PHY_SLEEP_CTR_CONTROL    0x9870 -#define AR_PHY_SLEEP_CTR_LIMIT      0x9874 -#define AR_PHY_SYNTH_CONTROL        0x9874 -#define AR_PHY_SLEEP_SCAL           0x9878 - -#define AR_PHY_PLL_CTL          0x987c -#define AR_PHY_PLL_CTL_40       0xaa -#define AR_PHY_PLL_CTL_40_5413  0x04 -#define AR_PHY_PLL_CTL_44       0xab -#define AR_PHY_PLL_CTL_44_2133  0xeb -#define AR_PHY_PLL_CTL_40_2133  0xea - -#define AR_PHY_SPECTRAL_SCAN			0x9910  /* AR9280 spectral scan configuration register */ -#define	AR_PHY_SPECTRAL_SCAN_ENABLE		0x1 -#define AR_PHY_SPECTRAL_SCAN_ENA		0x00000001  /* Enable spectral scan, reg 68, bit 0 */ -#define AR_PHY_SPECTRAL_SCAN_ENA_S		0  /* Enable spectral scan, reg 68, bit 0 */ -#define AR_PHY_SPECTRAL_SCAN_ACTIVE		0x00000002  /* Activate spectral scan reg 68, bit 1*/ -#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S		1  /* Activate spectral scan reg 68, bit 1*/ -#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD		0x000000F0  /* Interval for FFT reports, reg 68, bits 4-7*/ -#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S	4 -#define AR_PHY_SPECTRAL_SCAN_PERIOD		0x0000FF00  /* Interval for FFT reports, reg 68, bits 8-15*/ -#define AR_PHY_SPECTRAL_SCAN_PERIOD_S		8 -#define AR_PHY_SPECTRAL_SCAN_COUNT		0x00FF0000  /* Number of reports, reg 68, bits 16-23*/ -#define AR_PHY_SPECTRAL_SCAN_COUNT_S		16 -#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT	0x01000000  /* Short repeat, reg 68, bit 24*/ -#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S	24  /* Short repeat, reg 68, bit 24*/ - -#define AR_PHY_RX_DELAY           0x9914 -#define AR_PHY_SEARCH_START_DELAY 0x9918 -#define AR_PHY_RX_DELAY_DELAY     0x00003FFF - -#define AR_PHY_TIMING_CTRL4(_i)     (0x9920 + ((_i) << 12)) -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S   0 -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S   5 -#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE   0x800 -#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 -#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S   12 -#define AR_PHY_TIMING_CTRL4_DO_CAL    0x10000 - -#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI	0x80000000 -#define	AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER	0x40000000 -#define	AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK	0x20000000 -#define	AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK	0x10000000 - -#define AR_PHY_TIMING5               0x9924 -#define AR_PHY_TIMING5_CYCPWR_THR1   0x000000FE -#define AR_PHY_TIMING5_CYCPWR_THR1_S 1 - -#define AR_PHY_POWER_TX_RATE1               0x9934 -#define AR_PHY_POWER_TX_RATE2               0x9938 -#define AR_PHY_POWER_TX_RATE_MAX            0x993c -#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 - -#define AR_PHY_FRAME_CTL            0x9944 -#define AR_PHY_FRAME_CTL_TX_CLIP    0x00000038 -#define AR_PHY_FRAME_CTL_TX_CLIP_S  3 - -#define AR_PHY_TXPWRADJ                   0x994C -#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA    0x00000FC0 -#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S  6 -#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX   0x00FC0000 -#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18 - -#define AR_PHY_RADAR_EXT      0x9940 -#define AR_PHY_RADAR_EXT_ENA  0x00004000 - -#define AR_PHY_RADAR_0          0x9954 -#define AR_PHY_RADAR_0_ENA      0x00000001 -#define AR_PHY_RADAR_0_FFT_ENA  0x80000000 -#define AR_PHY_RADAR_0_INBAND   0x0000003e -#define AR_PHY_RADAR_0_INBAND_S 1 -#define AR_PHY_RADAR_0_PRSSI    0x00000FC0 -#define AR_PHY_RADAR_0_PRSSI_S  6 -#define AR_PHY_RADAR_0_HEIGHT   0x0003F000 -#define AR_PHY_RADAR_0_HEIGHT_S 12 -#define AR_PHY_RADAR_0_RRSSI    0x00FC0000 -#define AR_PHY_RADAR_0_RRSSI_S  18 -#define AR_PHY_RADAR_0_FIRPWR   0x7F000000 -#define AR_PHY_RADAR_0_FIRPWR_S 24 - -#define AR_PHY_RADAR_1                  0x9958 -#define AR_PHY_RADAR_1_RELPWR_ENA       0x00800000 -#define AR_PHY_RADAR_1_USE_FIR128       0x00400000 -#define AR_PHY_RADAR_1_RELPWR_THRESH    0x003F0000 -#define AR_PHY_RADAR_1_RELPWR_THRESH_S  16 -#define AR_PHY_RADAR_1_BLOCK_CHECK      0x00008000 -#define AR_PHY_RADAR_1_MAX_RRSSI        0x00004000 -#define AR_PHY_RADAR_1_RELSTEP_CHECK    0x00002000 -#define AR_PHY_RADAR_1_RELSTEP_THRESH   0x00001F00 -#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 -#define AR_PHY_RADAR_1_MAXLEN           0x000000FF -#define AR_PHY_RADAR_1_MAXLEN_S         0 - -#define AR_PHY_SWITCH_CHAIN_0     0x9960 -#define AR_PHY_SWITCH_COM         0x9964 - -#define AR_PHY_SIGMA_DELTA            0x996C -#define AR_PHY_SIGMA_DELTA_ADC_SEL    0x00000003 -#define AR_PHY_SIGMA_DELTA_ADC_SEL_S  0 -#define AR_PHY_SIGMA_DELTA_FILT2      0x000000F8 -#define AR_PHY_SIGMA_DELTA_FILT2_S    3 -#define AR_PHY_SIGMA_DELTA_FILT1      0x00001F00 -#define AR_PHY_SIGMA_DELTA_FILT1_S    8 -#define AR_PHY_SIGMA_DELTA_ADC_CLIP   0x01FFE000 -#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13 - -#define AR_PHY_RESTART          0x9970 -#define AR_PHY_RESTART_DIV_GC   0x001C0000 -#define AR_PHY_RESTART_DIV_GC_S 18 - -#define AR_PHY_RFBUS_REQ        0x997C -#define AR_PHY_RFBUS_REQ_EN     0x00000001 - -#define	AR_PHY_TIMING7		        0x9980 -#define	AR_PHY_TIMING8		        0x9984 -#define	AR_PHY_TIMING8_PILOT_MASK_2	0x000FFFFF -#define	AR_PHY_TIMING8_PILOT_MASK_2_S	0 - -#define	AR_PHY_BIN_MASK2_1	0x9988 -#define	AR_PHY_BIN_MASK2_2	0x998c -#define	AR_PHY_BIN_MASK2_3	0x9990 -#define	AR_PHY_BIN_MASK2_4	0x9994 - -#define	AR_PHY_BIN_MASK_1	0x9900 -#define	AR_PHY_BIN_MASK_2	0x9904 -#define	AR_PHY_BIN_MASK_3	0x9908 - -#define	AR_PHY_MASK_CTL		0x990c - -#define	AR_PHY_BIN_MASK2_4_MASK_4	0x00003FFF -#define	AR_PHY_BIN_MASK2_4_MASK_4_S	0 - -#define	AR_PHY_TIMING9		        0x9998 -#define	AR_PHY_TIMING10		        0x999c -#define	AR_PHY_TIMING10_PILOT_MASK_2	0x000FFFFF -#define	AR_PHY_TIMING10_PILOT_MASK_2_S	0 - -#define	AR_PHY_TIMING11			        0x99a0 -#define	AR_PHY_TIMING11_SPUR_DELTA_PHASE	0x000FFFFF -#define	AR_PHY_TIMING11_SPUR_DELTA_PHASE_S	0 -#define	AR_PHY_TIMING11_SPUR_FREQ_SD		0x3FF00000 -#define	AR_PHY_TIMING11_SPUR_FREQ_SD_S		20 -#define AR_PHY_TIMING11_USE_SPUR_IN_AGC		0x40000000 -#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR	0x80000000 - -#define AR_PHY_RX_CHAINMASK     0x99a4 -#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) -#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 -#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 - -#define AR_PHY_MULTICHAIN_GAIN_CTL          0x99ac -#define AR_PHY_9285_ANT_DIV_CTL_ALL         0x7f000000 -#define AR_PHY_9285_ANT_DIV_CTL             0x01000000 -#define AR_PHY_9285_ANT_DIV_CTL_S           24 -#define AR_PHY_9285_ANT_DIV_ALT_LNACONF     0x06000000 -#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S   25 -#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF    0x18000000 -#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S  27 -#define AR_PHY_9285_ANT_DIV_ALT_GAINTB      0x20000000 -#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S    29 -#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB     0x40000000 -#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S   30 -#define AR_PHY_9285_ANT_DIV_LNA1            2 -#define AR_PHY_9285_ANT_DIV_LNA2            1 -#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2  3 -#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 -#define AR_PHY_9285_ANT_DIV_GAINTB_0        0 -#define AR_PHY_9285_ANT_DIV_GAINTB_1        1 - -#define AR_PHY_EXT_CCA0             0x99b8 -#define AR_PHY_EXT_CCA0_THRESH62    0x000000FF -#define AR_PHY_EXT_CCA0_THRESH62_S  0 - -#define AR_PHY_EXT_CCA                  0x99bc -#define AR_PHY_EXT_CCA_CYCPWR_THR1      0x0000FE00 -#define AR_PHY_EXT_CCA_CYCPWR_THR1_S    9 -#define AR_PHY_EXT_CCA_THRESH62         0x007F0000 -#define AR_PHY_EXT_CCA_THRESH62_S       16 -#define AR_PHY_EXT_MINCCA_PWR           0xFF800000 -#define AR_PHY_EXT_MINCCA_PWR_S         23 -#define AR9280_PHY_EXT_MINCCA_PWR       0x01FF0000 -#define AR9280_PHY_EXT_MINCCA_PWR_S     16 - -#define AR_PHY_SFCORR_EXT                 0x99c0 -#define AR_PHY_SFCORR_EXT_M1_THRESH       0x0000007F -#define AR_PHY_SFCORR_EXT_M1_THRESH_S     0 -#define AR_PHY_SFCORR_EXT_M2_THRESH       0x00003F80 -#define AR_PHY_SFCORR_EXT_M2_THRESH_S     7 -#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW   0x001FC000 -#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 -#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW   0x0FE00000 -#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 -#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S   28 - -#define AR_PHY_HALFGI           0x99D0 -#define AR_PHY_HALFGI_DSC_MAN   0x0007FFF0 -#define AR_PHY_HALFGI_DSC_MAN_S 4 -#define AR_PHY_HALFGI_DSC_EXP   0x0000000F -#define AR_PHY_HALFGI_DSC_EXP_S 0 - -#define AR_PHY_CHAN_INFO_MEMORY               0x99DC -#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK  0x0001 - -#define AR_PHY_HEAVY_CLIP_ENABLE         0x99E0 - -#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS    0x99EC -#define AR_PHY_RIFS_INIT_DELAY         0x03ff0000 - -#define AR_PHY_M_SLEEP      0x99f0 -#define AR_PHY_REFCLKDLY    0x99f4 -#define AR_PHY_REFCLKPD     0x99f8 - -#define AR_PHY_CALMODE      0x99f0 - -#define AR_PHY_CALMODE_IQ           0x00000000 -#define AR_PHY_CALMODE_ADC_GAIN     0x00000001 -#define AR_PHY_CALMODE_ADC_DC_PER   0x00000002 -#define AR_PHY_CALMODE_ADC_DC_INIT  0x00000003 - -#define AR_PHY_CAL_MEAS_0(_i)     (0x9c10 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_1(_i)     (0x9c14 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_2(_i)     (0x9c18 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_3(_i)     (0x9c1c + ((_i) << 12)) - -#define AR_PHY_CURRENT_RSSI 0x9c1c -#define AR9280_PHY_CURRENT_RSSI 0x9c3c - -#define AR_PHY_RFBUS_GRANT       0x9C20 -#define AR_PHY_RFBUS_GRANT_EN    0x00000001 - -#define AR_PHY_CHAN_INFO_GAIN_DIFF             0x9CF4 -#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 - -#define AR_PHY_CHAN_INFO_GAIN          0x9CFC - -#define AR_PHY_MODE         0xA200 -#define AR_PHY_MODE_ASYNCFIFO 0x80 -#define AR_PHY_MODE_AR2133  0x08 -#define AR_PHY_MODE_AR5111  0x00 -#define AR_PHY_MODE_AR5112  0x08 -#define AR_PHY_MODE_DYNAMIC 0x04 -#define AR_PHY_MODE_RF2GHZ  0x02 -#define AR_PHY_MODE_RF5GHZ  0x00 -#define AR_PHY_MODE_CCK     0x01 -#define AR_PHY_MODE_OFDM    0x00 -#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100 - -#define AR_PHY_CCK_TX_CTRL       0xA204 -#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 -#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK         0x0000000C -#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S       2 - -#define AR_PHY_CCK_DETECT                           0xA208 -#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK          0x0000003F -#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S        0 -/* [12:6] settling time for antenna switch */ -#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME           0x00001FC0 -#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S         6 -#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV    0x2000 -#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S  13 - -#define AR_PHY_GAIN_2GHZ                0xA20C -#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN    0x00FC0000 -#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S  18 -#define AR_PHY_GAIN_2GHZ_BSW_MARGIN     0x00003C00 -#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S   10 -#define AR_PHY_GAIN_2GHZ_BSW_ATTEN      0x0000001F -#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S    0 - -#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN     0x003E0000 -#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S   17 -#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN     0x0001F000 -#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S   12 -#define AR_PHY_GAIN_2GHZ_XATTEN2_DB         0x00000FC0 -#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S       6 -#define AR_PHY_GAIN_2GHZ_XATTEN1_DB         0x0000003F -#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S       0 - -#define AR_PHY_CCK_RXCTRL4  0xA21C -#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT   0x01F80000 -#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 - -#define AR_PHY_DAG_CTRLCCK  0xA228 -#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR  0x00000200 -#define AR_PHY_DAG_CTRLCCK_RSSI_THR     0x0001FC00 -#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S   10 - -#define AR_PHY_FORCE_CLKEN_CCK              0xA22C -#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX      0x00000040 - -#define AR_PHY_POWER_TX_RATE3   0xA234 -#define AR_PHY_POWER_TX_RATE4   0xA238 - -#define AR_PHY_SCRM_SEQ_XR       0xA23C -#define AR_PHY_HEADER_DETECT_XR  0xA240 -#define AR_PHY_CHIRP_DETECTED_XR 0xA244 -#define AR_PHY_BLUETOOTH         0xA254 - -#define AR_PHY_TPCRG1   0xA258 -#define AR_PHY_TPCRG1_NUM_PD_GAIN   0x0000c000 -#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 - -#define AR_PHY_TPCRG1_PD_GAIN_1    0x00030000 -#define AR_PHY_TPCRG1_PD_GAIN_1_S  16 -#define AR_PHY_TPCRG1_PD_GAIN_2    0x000C0000 -#define AR_PHY_TPCRG1_PD_GAIN_2_S  18 -#define AR_PHY_TPCRG1_PD_GAIN_3    0x00300000 -#define AR_PHY_TPCRG1_PD_GAIN_3_S  20 - -#define AR_PHY_TPCRG1_PD_CAL_ENABLE   0x00400000 -#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 - -#define AR_PHY_TX_PWRCTRL4       0xa264 -#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID     0x00000001 -#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S   0 -#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT       0x000001FE -#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S     1 - -#define AR_PHY_TX_PWRCTRL6_0     0xa270 -#define AR_PHY_TX_PWRCTRL6_1     0xb270 -#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE     0x03000000 -#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S   24 - -#define AR_PHY_TX_PWRCTRL7       0xa274  #define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX   0x0007E000  #define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13 -#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN     0x01F80000 -#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S   19 - -#define AR_PHY_TX_PWRCTRL9       0xa27C -#define AR_PHY_TX_DESIRED_SCALE_CCK        0x00007C00 -#define AR_PHY_TX_DESIRED_SCALE_CCK_S      10 -#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL  0x80000000 -#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 - -#define AR_PHY_TX_GAIN_TBL1      0xa300  #define AR_PHY_TX_GAIN_CLC       0x0000001E  #define AR_PHY_TX_GAIN_CLC_S     1  #define AR_PHY_TX_GAIN           0x0007F000 @@ -526,91 +37,6 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah,  #define AR_PHY_CLC_Q0        0x0000ffd0  #define AR_PHY_CLC_Q0_S      5 -#define AR_PHY_CH0_TX_PWRCTRL11  0xa398 -#define AR_PHY_CH1_TX_PWRCTRL11  0xb398 -#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP   0x0000FC00 -#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 - -#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 -#define AR_PHY_MASK2_M_31_45     0xa3a4 -#define AR_PHY_MASK2_M_16_30     0xa3a8 -#define AR_PHY_MASK2_M_00_15     0xa3ac -#define AR_PHY_MASK2_P_15_01     0xa3b8 -#define AR_PHY_MASK2_P_30_16     0xa3bc -#define AR_PHY_MASK2_P_45_31     0xa3c0 -#define AR_PHY_MASK2_P_61_45     0xa3c4 -#define AR_PHY_SPUR_REG          0x994c - -#define AR_PHY_SPUR_REG_MASK_RATE_CNTL       (0xFF << 18) -#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S     18 - -#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM      0x20000 -#define AR_PHY_SPUR_REG_MASK_RATE_SELECT     (0xFF << 9) -#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S   9 -#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 -#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH     0x7F -#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S   0 - -#define AR_PHY_PILOT_MASK_01_30   0xa3b0 -#define AR_PHY_PILOT_MASK_31_60   0xa3b4 - -#define AR_PHY_CHANNEL_MASK_01_30 0x99d4 -#define AR_PHY_CHANNEL_MASK_31_60 0x99d8 - -#define AR_PHY_ANALOG_SWAP      0xa268 -#define AR_PHY_SWAP_ALT_CHAIN   0x00000040 - -#define AR_PHY_TPCRG5   0xA26C -#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP       0x0000000F -#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S     0 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1    0x000003F0 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S  4 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2    0x0000FC00 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S  10 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3    0x003F0000 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S  16 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4    0x0FC00000 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S  22 - -/* Carrier leak calibration control, do it after AGC calibration */ -#define AR_PHY_CL_CAL_CTL       0xA358 -#define AR_PHY_CL_CAL_ENABLE    0x00000002 -#define AR_PHY_PARALLEL_CAL_ENABLE    0x00000001 - -#define AR_PHY_POWER_TX_RATE5   0xA38C -#define AR_PHY_POWER_TX_RATE6   0xA390 - -#define AR_PHY_CAL_CHAINMASK    0xA39C - -#define AR_PHY_POWER_TX_SUB     0xA3C8 -#define AR_PHY_POWER_TX_RATE7   0xA3CC -#define AR_PHY_POWER_TX_RATE8   0xA3D0 -#define AR_PHY_POWER_TX_RATE9   0xA3D4 - -#define AR_PHY_XPA_CFG  	0xA3D8 -#define AR_PHY_FORCE_XPA_CFG	0x000000001 -#define AR_PHY_FORCE_XPA_CFG_S	0 - -#define AR_PHY_CH1_CCA          0xa864 -#define AR_PHY_CH1_MINCCA_PWR   0x0FF80000 -#define AR_PHY_CH1_MINCCA_PWR_S 19 -#define AR9280_PHY_CH1_MINCCA_PWR   0x1FF00000 -#define AR9280_PHY_CH1_MINCCA_PWR_S 20 - -#define AR_PHY_CH2_CCA          0xb864 -#define AR_PHY_CH2_MINCCA_PWR   0x0FF80000 -#define AR_PHY_CH2_MINCCA_PWR_S 19 - -#define AR_PHY_CH1_EXT_CCA          0xa9bc -#define AR_PHY_CH1_EXT_MINCCA_PWR   0xFF800000 -#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 -#define AR9280_PHY_CH1_EXT_MINCCA_PWR   0x01FF0000 -#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16 - -#define AR_PHY_CH2_EXT_CCA          0xb9bc -#define AR_PHY_CH2_EXT_MINCCA_PWR   0xFF800000 -#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 -  #define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do {               \  		int r;							\  		for (r = 0; r < ((iniarray)->ia_rows); r++) {		\ @@ -625,6 +51,7 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah,  #define ANTSWAP_AB 0x0001  #define REDUCE_CHAIN_0 0x00000050  #define REDUCE_CHAIN_1 0x00000051 +#define AR_PHY_CHIP_ID 0x9818  #define RF_BANK_SETUP(_bank, _iniarray, _col) do {			\  		int i;							\ @@ -632,4 +59,7 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah,  			(_bank)[i] = INI_RA((_iniarray), i, _col);;	\  	} while (0) +#define	AR_PHY_TIMING11_SPUR_FREQ_SD		0x3FF00000 +#define	AR_PHY_TIMING11_SPUR_FREQ_SD_S		20 +  #endif diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index ee81291f2fb..8519452c95f 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -691,6 +691,19 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,  	rate_table = sc->cur_rate_table;  	rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); +	/* +	 * If we're in HT mode and both us and our peer supports LDPC. +	 * We don't need to check our own device's capabilities as our own +	 * ht capabilities would have already been intersected with our peer's. +	 */ +	if (conf_is_ht(&sc->hw->conf) && +	    (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)) +		tx_info->flags |= IEEE80211_TX_CTL_LDPC; + +	if (conf_is_ht(&sc->hw->conf) && +	    (sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC)) +		tx_info->flags |= (1 << IEEE80211_TX_CTL_STBC_SHIFT); +  	if (is_probe) {  		/* set one try for probe rates. For the  		 * probes don't enable rts */ diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 94560e2fe37..ac60c4ee62d 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -15,6 +15,9 @@   */  #include "ath9k.h" +#include "ar9003_mac.h" + +#define SKB_CB_ATHBUF(__skb)	(*((struct ath_buf **)__skb->cb))  static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,  					     struct ieee80211_hdr *hdr) @@ -115,56 +118,246 @@ static void ath_opmode_init(struct ath_softc *sc)  	ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);  } -int ath_rx_init(struct ath_softc *sc, int nbufs) +static bool ath_rx_edma_buf_link(struct ath_softc *sc, +				 enum ath9k_rx_qtype qtype)  { -	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	struct ath_hw *ah = sc->sc_ah; +	struct ath_rx_edma *rx_edma;  	struct sk_buff *skb;  	struct ath_buf *bf; -	int error = 0; -	spin_lock_init(&sc->rx.rxflushlock); -	sc->sc_flags &= ~SC_OP_RXFLUSH; -	spin_lock_init(&sc->rx.rxbuflock); +	rx_edma = &sc->rx.rx_edma[qtype]; +	if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize) +		return false; -	common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN, -				     min(common->cachelsz, (u16)64)); +	bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); +	list_del_init(&bf->list); + +	skb = bf->bf_mpdu; + +	ATH_RXBUF_RESET(bf); +	memset(skb->data, 0, ah->caps.rx_status_len); +	dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, +				ah->caps.rx_status_len, DMA_TO_DEVICE); + +	SKB_CB_ATHBUF(skb) = bf; +	ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype); +	skb_queue_tail(&rx_edma->rx_fifo, skb); + +	return true; +} + +static void ath_rx_addbuffer_edma(struct ath_softc *sc, +				  enum ath9k_rx_qtype qtype, int size) +{ +	struct ath_rx_edma *rx_edma; +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	u32 nbuf = 0; + +	rx_edma = &sc->rx.rx_edma[qtype]; +	if (list_empty(&sc->rx.rxbuf)) { +		ath_print(common, ATH_DBG_QUEUE, "No free rx buf available\n"); +		return; +	} + +	while (!list_empty(&sc->rx.rxbuf)) { +		nbuf++; + +		if (!ath_rx_edma_buf_link(sc, qtype)) +			break; -	ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", -		  common->cachelsz, common->rx_bufsize); +		if (nbuf >= size) +			break; +	} +} -	/* Initialize rx descriptors */ +static void ath_rx_remove_buffer(struct ath_softc *sc, +				 enum ath9k_rx_qtype qtype) +{ +	struct ath_buf *bf; +	struct ath_rx_edma *rx_edma; +	struct sk_buff *skb; -	error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, -				  "rx", nbufs, 1); -	if (error != 0) { -		ath_print(common, ATH_DBG_FATAL, -			  "failed to allocate rx descriptors: %d\n", error); -		goto err; +	rx_edma = &sc->rx.rx_edma[qtype]; + +	while ((skb = skb_dequeue(&rx_edma->rx_fifo)) != NULL) { +		bf = SKB_CB_ATHBUF(skb); +		BUG_ON(!bf); +		list_add_tail(&bf->list, &sc->rx.rxbuf);  	} +} + +static void ath_rx_edma_cleanup(struct ath_softc *sc) +{ +	struct ath_buf *bf; + +	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); +	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);  	list_for_each_entry(bf, &sc->rx.rxbuf, list) { +		if (bf->bf_mpdu) +			dev_kfree_skb_any(bf->bf_mpdu); +	} + +	INIT_LIST_HEAD(&sc->rx.rxbuf); + +	kfree(sc->rx.rx_bufptr); +	sc->rx.rx_bufptr = NULL; +} + +static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size) +{ +	skb_queue_head_init(&rx_edma->rx_fifo); +	skb_queue_head_init(&rx_edma->rx_buffers); +	rx_edma->rx_fifo_hwsize = size; +} + +static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) +{ +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	struct ath_hw *ah = sc->sc_ah; +	struct sk_buff *skb; +	struct ath_buf *bf; +	int error = 0, i; +	u32 size; + + +	common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN + +				     ah->caps.rx_status_len, +				     min(common->cachelsz, (u16)64)); + +	ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - +				    ah->caps.rx_status_len); + +	ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_LP], +			       ah->caps.rx_lp_qdepth); +	ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP], +			       ah->caps.rx_hp_qdepth); + +	size = sizeof(struct ath_buf) * nbufs; +	bf = kzalloc(size, GFP_KERNEL); +	if (!bf) +		return -ENOMEM; + +	INIT_LIST_HEAD(&sc->rx.rxbuf); +	sc->rx.rx_bufptr = bf; + +	for (i = 0; i < nbufs; i++, bf++) {  		skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL); -		if (skb == NULL) { +		if (!skb) {  			error = -ENOMEM; -			goto err; +			goto rx_init_fail;  		} +		memset(skb->data, 0, common->rx_bufsize);  		bf->bf_mpdu = skb; +  		bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,  						 common->rx_bufsize, -						 DMA_FROM_DEVICE); +						 DMA_BIDIRECTIONAL);  		if (unlikely(dma_mapping_error(sc->dev, -					       bf->bf_buf_addr))) { -			dev_kfree_skb_any(skb); -			bf->bf_mpdu = NULL; +						bf->bf_buf_addr))) { +				dev_kfree_skb_any(skb); +				bf->bf_mpdu = NULL; +				ath_print(common, ATH_DBG_FATAL, +					"dma_mapping_error() on RX init\n"); +				error = -ENOMEM; +				goto rx_init_fail; +		} + +		list_add_tail(&bf->list, &sc->rx.rxbuf); +	} + +	return 0; + +rx_init_fail: +	ath_rx_edma_cleanup(sc); +	return error; +} + +static void ath_edma_start_recv(struct ath_softc *sc) +{ +	spin_lock_bh(&sc->rx.rxbuflock); + +	ath9k_hw_rxena(sc->sc_ah); + +	ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP, +			      sc->rx.rx_edma[ATH9K_RX_QUEUE_HP].rx_fifo_hwsize); + +	ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP, +			      sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize); + +	spin_unlock_bh(&sc->rx.rxbuflock); + +	ath_opmode_init(sc); + +	ath9k_hw_startpcureceive(sc->sc_ah); +} + +static void ath_edma_stop_recv(struct ath_softc *sc) +{ +	spin_lock_bh(&sc->rx.rxbuflock); +	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); +	ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); +	spin_unlock_bh(&sc->rx.rxbuflock); +} + +int ath_rx_init(struct ath_softc *sc, int nbufs) +{ +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	struct sk_buff *skb; +	struct ath_buf *bf; +	int error = 0; + +	spin_lock_init(&sc->rx.rxflushlock); +	sc->sc_flags &= ~SC_OP_RXFLUSH; +	spin_lock_init(&sc->rx.rxbuflock); + +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +		return ath_rx_edma_init(sc, nbufs); +	} else { +		common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN, +				min(common->cachelsz, (u16)64)); + +		ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", +				common->cachelsz, common->rx_bufsize); + +		/* Initialize rx descriptors */ + +		error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, +				"rx", nbufs, 1, 0); +		if (error != 0) {  			ath_print(common, ATH_DBG_FATAL, -				  "dma_mapping_error() on RX init\n"); -			error = -ENOMEM; +				  "failed to allocate rx descriptors: %d\n", +				  error);  			goto err;  		} -		bf->bf_dmacontext = bf->bf_buf_addr; + +		list_for_each_entry(bf, &sc->rx.rxbuf, list) { +			skb = ath_rxbuf_alloc(common, common->rx_bufsize, +					      GFP_KERNEL); +			if (skb == NULL) { +				error = -ENOMEM; +				goto err; +			} + +			bf->bf_mpdu = skb; +			bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, +					common->rx_bufsize, +					DMA_FROM_DEVICE); +			if (unlikely(dma_mapping_error(sc->dev, +							bf->bf_buf_addr))) { +				dev_kfree_skb_any(skb); +				bf->bf_mpdu = NULL; +				ath_print(common, ATH_DBG_FATAL, +					  "dma_mapping_error() on RX init\n"); +				error = -ENOMEM; +				goto err; +			} +			bf->bf_dmacontext = bf->bf_buf_addr; +		} +		sc->rx.rxlink = NULL;  	} -	sc->rx.rxlink = NULL;  err:  	if (error) @@ -180,17 +373,23 @@ void ath_rx_cleanup(struct ath_softc *sc)  	struct sk_buff *skb;  	struct ath_buf *bf; -	list_for_each_entry(bf, &sc->rx.rxbuf, list) { -		skb = bf->bf_mpdu; -		if (skb) { -			dma_unmap_single(sc->dev, bf->bf_buf_addr, -					 common->rx_bufsize, DMA_FROM_DEVICE); -			dev_kfree_skb(skb); +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +		ath_rx_edma_cleanup(sc); +		return; +	} else { +		list_for_each_entry(bf, &sc->rx.rxbuf, list) { +			skb = bf->bf_mpdu; +			if (skb) { +				dma_unmap_single(sc->dev, bf->bf_buf_addr, +						common->rx_bufsize, +						DMA_FROM_DEVICE); +				dev_kfree_skb(skb); +			}  		} -	} -	if (sc->rx.rxdma.dd_desc_len != 0) -		ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf); +		if (sc->rx.rxdma.dd_desc_len != 0) +			ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf); +	}  }  /* @@ -273,6 +472,11 @@ int ath_startrecv(struct ath_softc *sc)  	struct ath_hw *ah = sc->sc_ah;  	struct ath_buf *bf, *tbf; +	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +		ath_edma_start_recv(sc); +		return 0; +	} +  	spin_lock_bh(&sc->rx.rxbuflock);  	if (list_empty(&sc->rx.rxbuf))  		goto start_recv; @@ -306,7 +510,11 @@ bool ath_stoprecv(struct ath_softc *sc)  	ath9k_hw_stoppcurecv(ah);  	ath9k_hw_setrxfilter(ah, 0);  	stopped = ath9k_hw_stopdmarecv(ah); -	sc->rx.rxlink = NULL; + +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) +		ath_edma_stop_recv(sc); +	else +		sc->rx.rxlink = NULL;  	return stopped;  } @@ -315,7 +523,9 @@ void ath_flushrecv(struct ath_softc *sc)  {  	spin_lock_bh(&sc->rx.rxflushlock);  	sc->sc_flags |= SC_OP_RXFLUSH; -	ath_rx_tasklet(sc, 1); +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) +		ath_rx_tasklet(sc, 1, true); +	ath_rx_tasklet(sc, 1, false);  	sc->sc_flags &= ~SC_OP_RXFLUSH;  	spin_unlock_bh(&sc->rx.rxflushlock);  } @@ -469,14 +679,147 @@ static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw,  		ieee80211_rx(hw, skb);  } -int ath_rx_tasklet(struct ath_softc *sc, int flush) +static bool ath_edma_get_buffers(struct ath_softc *sc, +				 enum ath9k_rx_qtype qtype)  { -#define PA2DESC(_sc, _pa)                                               \ -	((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc +		\ -			     ((_pa) - (_sc)->rx.rxdma.dd_desc_paddr))) +	struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; +	struct ath_hw *ah = sc->sc_ah; +	struct ath_common *common = ath9k_hw_common(ah); +	struct sk_buff *skb; +	struct ath_buf *bf; +	int ret; + +	skb = skb_peek(&rx_edma->rx_fifo); +	if (!skb) +		return false; + +	bf = SKB_CB_ATHBUF(skb); +	BUG_ON(!bf); + +	dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, +				common->rx_bufsize, DMA_FROM_DEVICE); + +	ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data); +	if (ret == -EINPROGRESS) +		return false; + +	__skb_unlink(skb, &rx_edma->rx_fifo); +	if (ret == -EINVAL) { +		/* corrupt descriptor, skip this one and the following one */ +		list_add_tail(&bf->list, &sc->rx.rxbuf); +		ath_rx_edma_buf_link(sc, qtype); +		skb = skb_peek(&rx_edma->rx_fifo); +		if (!skb) +			return true; + +		bf = SKB_CB_ATHBUF(skb); +		BUG_ON(!bf); + +		__skb_unlink(skb, &rx_edma->rx_fifo); +		list_add_tail(&bf->list, &sc->rx.rxbuf); +		ath_rx_edma_buf_link(sc, qtype); +	} +	skb_queue_tail(&rx_edma->rx_buffers, skb); + +	return true; +} +static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc, +						struct ath_rx_status *rs, +						enum ath9k_rx_qtype qtype) +{ +	struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; +	struct sk_buff *skb;  	struct ath_buf *bf; + +	while (ath_edma_get_buffers(sc, qtype)); +	skb = __skb_dequeue(&rx_edma->rx_buffers); +	if (!skb) +		return NULL; + +	bf = SKB_CB_ATHBUF(skb); +	ath9k_hw_process_rxdesc_edma(sc->sc_ah, rs, skb->data); +	return bf; +} + +static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, +					   struct ath_rx_status *rs) +{ +	struct ath_hw *ah = sc->sc_ah; +	struct ath_common *common = ath9k_hw_common(ah);  	struct ath_desc *ds; +	struct ath_buf *bf; +	int ret; + +	if (list_empty(&sc->rx.rxbuf)) { +		sc->rx.rxlink = NULL; +		return NULL; +	} + +	bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); +	ds = bf->bf_desc; + +	/* +	 * Must provide the virtual address of the current +	 * descriptor, the physical address, and the virtual +	 * address of the next descriptor in the h/w chain. +	 * This allows the HAL to look ahead to see if the +	 * hardware is done with a descriptor by checking the +	 * done bit in the following descriptor and the address +	 * of the current descriptor the DMA engine is working +	 * on.  All this is necessary because of our use of +	 * a self-linked list to avoid rx overruns. +	 */ +	ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0); +	if (ret == -EINPROGRESS) { +		struct ath_rx_status trs; +		struct ath_buf *tbf; +		struct ath_desc *tds; + +		memset(&trs, 0, sizeof(trs)); +		if (list_is_last(&bf->list, &sc->rx.rxbuf)) { +			sc->rx.rxlink = NULL; +			return NULL; +		} + +		tbf = list_entry(bf->list.next, struct ath_buf, list); + +		/* +		 * On some hardware the descriptor status words could +		 * get corrupted, including the done bit. Because of +		 * this, check if the next descriptor's done bit is +		 * set or not. +		 * +		 * If the next descriptor's done bit is set, the current +		 * descriptor has been corrupted. Force s/w to discard +		 * this descriptor and continue... +		 */ + +		tds = tbf->bf_desc; +		ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0); +		if (ret == -EINPROGRESS) +			return NULL; +	} + +	if (!bf->bf_mpdu) +		return bf; + +	/* +	 * Synchronize the DMA transfer with CPU before +	 * 1. accessing the frame +	 * 2. requeueing the same buffer to h/w +	 */ +	dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, +			common->rx_bufsize, +			DMA_FROM_DEVICE); + +	return bf; +} + + +int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) +{ +	struct ath_buf *bf;  	struct sk_buff *skb = NULL, *requeue_skb;  	struct ieee80211_rx_status *rxs;  	struct ath_hw *ah = sc->sc_ah; @@ -491,7 +834,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)  	int retval;  	bool decrypt_error = false;  	struct ath_rx_status rs; +	enum ath9k_rx_qtype qtype; +	bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); +	int dma_type; +	if (edma) +		dma_type = DMA_FROM_DEVICE; +	else +		dma_type = DMA_BIDIRECTIONAL; + +	qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;  	spin_lock_bh(&sc->rx.rxbuflock);  	do { @@ -499,71 +851,19 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)  		if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))  			break; -		if (list_empty(&sc->rx.rxbuf)) { -			sc->rx.rxlink = NULL; -			break; -		} - -		bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); -		ds = bf->bf_desc; - -		/* -		 * Must provide the virtual address of the current -		 * descriptor, the physical address, and the virtual -		 * address of the next descriptor in the h/w chain. -		 * This allows the HAL to look ahead to see if the -		 * hardware is done with a descriptor by checking the -		 * done bit in the following descriptor and the address -		 * of the current descriptor the DMA engine is working -		 * on.  All this is necessary because of our use of -		 * a self-linked list to avoid rx overruns. -		 */  		memset(&rs, 0, sizeof(rs)); -		retval = ath9k_hw_rxprocdesc(ah, ds, &rs, 0); -		if (retval == -EINPROGRESS) { -			struct ath_rx_status trs; -			struct ath_buf *tbf; -			struct ath_desc *tds; - -			memset(&trs, 0, sizeof(trs)); -			if (list_is_last(&bf->list, &sc->rx.rxbuf)) { -				sc->rx.rxlink = NULL; -				break; -			} +		if (edma) +			bf = ath_edma_get_next_rx_buf(sc, &rs, qtype); +		else +			bf = ath_get_next_rx_buf(sc, &rs); -			tbf = list_entry(bf->list.next, struct ath_buf, list); - -			/* -			 * On some hardware the descriptor status words could -			 * get corrupted, including the done bit. Because of -			 * this, check if the next descriptor's done bit is -			 * set or not. -			 * -			 * If the next descriptor's done bit is set, the current -			 * descriptor has been corrupted. Force s/w to discard -			 * this descriptor and continue... -			 */ - -			tds = tbf->bf_desc; -			retval = ath9k_hw_rxprocdesc(ah, tds, &trs, 0); -			if (retval == -EINPROGRESS) { -				break; -			} -		} +		if (!bf) +			break;  		skb = bf->bf_mpdu;  		if (!skb)  			continue; -		/* -		 * Synchronize the DMA transfer with CPU before -		 * 1. accessing the frame -		 * 2. requeueing the same buffer to h/w -		 */ -		dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, -				common->rx_bufsize, -				DMA_FROM_DEVICE); -  		hdr = (struct ieee80211_hdr *) skb->data;  		rxs =  IEEE80211_SKB_RXCB(skb); @@ -597,9 +897,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)  		/* Unmap the frame */  		dma_unmap_single(sc->dev, bf->bf_buf_addr,  				 common->rx_bufsize, -				 DMA_FROM_DEVICE); +				 dma_type); -		skb_put(skb, rs.rs_datalen); +		skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len); +		if (ah->caps.rx_status_len) +			skb_pull(skb, ah->caps.rx_status_len);  		ath9k_cmn_rx_skb_postprocess(common, skb, &rs,  					     rxs, decrypt_error); @@ -608,7 +910,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)  		bf->bf_mpdu = requeue_skb;  		bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,  						 common->rx_bufsize, -						 DMA_FROM_DEVICE); +						 dma_type);  		if (unlikely(dma_mapping_error(sc->dev,  			  bf->bf_buf_addr))) {  			dev_kfree_skb_any(requeue_skb); @@ -639,12 +941,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)  		ath_rx_send_to_mac80211(hw, sc, skb, rxs);  requeue: -		list_move_tail(&bf->list, &sc->rx.rxbuf); -		ath_rx_buf_link(sc, bf); +		if (edma) { +			list_add_tail(&bf->list, &sc->rx.rxbuf); +			ath_rx_edma_buf_link(sc, qtype); +		} else { +			list_move_tail(&bf->list, &sc->rx.rxbuf); +			ath_rx_buf_link(sc, bf); +		}  	} while (1);  	spin_unlock_bh(&sc->rx.rxbuflock);  	return 0; -#undef PA2DESC  } diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 7e36ad7421b..d4371a43bda 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -20,7 +20,7 @@  #include "../reg.h"  #define AR_CR                0x0008 -#define AR_CR_RXE            0x00000004 +#define AR_CR_RXE            (AR_SREV_9300_20_OR_LATER(ah) ? 0x0000000c : 0x00000004)  #define AR_CR_RXD            0x00000020  #define AR_CR_SWI            0x00000040 @@ -39,6 +39,12 @@  #define AR_CFG_PCI_MASTER_REQ_Q_THRESH         0x00060000  #define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S       17 +#define AR_RXBP_THRESH       0x0018 +#define AR_RXBP_THRESH_HP    0x0000000f +#define AR_RXBP_THRESH_HP_S  0 +#define AR_RXBP_THRESH_LP    0x00003f00 +#define AR_RXBP_THRESH_LP_S  8 +  #define AR_MIRT              0x0020  #define AR_MIRT_VAL          0x0000ffff  #define AR_MIRT_VAL_S        16 @@ -144,6 +150,9 @@  #define AR_MACMISC_MISC_OBS_BUS_MSB_S   15  #define AR_MACMISC_MISC_OBS_BUS_1       1 +#define AR_DATABUF_SIZE		0x0060 +#define AR_DATABUF_SIZE_MASK	0x00000FFF +  #define AR_GTXTO    0x0064  #define AR_GTXTO_TIMEOUT_COUNTER    0x0000FFFF  #define AR_GTXTO_TIMEOUT_LIMIT      0xFFFF0000 @@ -160,9 +169,14 @@  #define AR_CST_TIMEOUT_LIMIT      0xFFFF0000  #define AR_CST_TIMEOUT_LIMIT_S    16 +#define AR_HP_RXDP 0x0074 +#define AR_LP_RXDP 0x0078 +  #define AR_ISR               0x0080  #define AR_ISR_RXOK          0x00000001  #define AR_ISR_RXDESC        0x00000002 +#define AR_ISR_HP_RXOK	     0x00000001 +#define AR_ISR_LP_RXOK	     0x00000002  #define AR_ISR_RXERR         0x00000004  #define AR_ISR_RXNOPKT       0x00000008  #define AR_ISR_RXEOL         0x00000010 @@ -232,7 +246,6 @@  #define AR_ISR_S5_TIMER_THRESH      0x0007FE00  #define AR_ISR_S5_TIM_TIMER         0x00000010  #define AR_ISR_S5_DTIM_TIMER        0x00000020 -#define AR_ISR_S5_S                 0x00d8  #define AR_IMR_S5                   0x00b8  #define AR_IMR_S5_TIM_TIMER         0x00000010  #define AR_IMR_S5_DTIM_TIMER        0x00000020 @@ -240,7 +253,6 @@  #define AR_ISR_S5_GENTIMER_TRIG_S   0  #define AR_ISR_S5_GENTIMER_THRESH   0xFF800000  #define AR_ISR_S5_GENTIMER_THRESH_S 16 -#define AR_ISR_S5_S                 0x00d8  #define AR_IMR_S5_GENTIMER_TRIG     0x0000FF80  #define AR_IMR_S5_GENTIMER_TRIG_S   0  #define AR_IMR_S5_GENTIMER_THRESH   0xFF800000 @@ -249,6 +261,8 @@  #define AR_IMR               0x00a0  #define AR_IMR_RXOK          0x00000001  #define AR_IMR_RXDESC        0x00000002 +#define AR_IMR_RXOK_HP	     0x00000001 +#define AR_IMR_RXOK_LP	     0x00000002  #define AR_IMR_RXERR         0x00000004  #define AR_IMR_RXNOPKT       0x00000008  #define AR_IMR_RXEOL         0x00000010 @@ -332,10 +346,10 @@  #define AR_ISR_S1_QCU_TXEOL    0x03FF0000  #define AR_ISR_S1_QCU_TXEOL_S  16 -#define AR_ISR_S2_S           0x00cc -#define AR_ISR_S3_S           0x00d0 -#define AR_ISR_S4_S           0x00d4 -#define AR_ISR_S5_S           0x00d8 +#define AR_ISR_S2_S           (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d0 : 0x00cc) +#define AR_ISR_S3_S           (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d4 : 0x00d0) +#define AR_ISR_S4_S           (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d8 : 0x00d4) +#define AR_ISR_S5_S           (AR_SREV_9300_20_OR_LATER(ah) ? 0x00dc : 0x00d8)  #define AR_DMADBG_0           0x00e0  #define AR_DMADBG_1           0x00e4  #define AR_DMADBG_2           0x00e8 @@ -369,6 +383,9 @@  #define AR_Q9_TXDP           0x0824  #define AR_QTXDP(_i)    (AR_Q0_TXDP + ((_i)<<2)) +#define AR_Q_STATUS_RING_START	0x830 +#define AR_Q_STATUS_RING_END	0x834 +  #define AR_Q_TXE             0x0840  #define AR_Q_TXE_M           0x000003FF @@ -461,6 +478,10 @@  #define AR_Q_RDYTIMESHDN    0x0a40  #define AR_Q_RDYTIMESHDN_M  0x000003FF +/* MAC Descriptor CRC check */ +#define AR_Q_DESC_CRCCHK    0xa44 +/* Enable CRC check on the descriptor fetched from host */ +#define AR_Q_DESC_CRCCHK_EN 1  #define AR_NUM_DCU      10  #define AR_DCU_0        0x0001 @@ -759,6 +780,8 @@  #define AR_SREV_VERSION_9271			0x140  #define AR_SREV_REVISION_9271_10		0  #define AR_SREV_REVISION_9271_11		1 +#define AR_SREV_VERSION_9300                  0x1c0 +#define AR_SREV_REVISION_9300_20              2 /* 2.0 and 2.1 */  #define AR_SREV_5416(_ah) \  	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -844,6 +867,15 @@  #define AR_SREV_9271_11(_ah) \      (AR_SREV_9271(_ah) && \       ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) +#define AR_SREV_9300(_ah) \ +	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) +#define AR_SREV_9300_20(_ah) \ +	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ +	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_20)) +#define AR_SREV_9300_20_OR_LATER(_ah) \ +	(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \ +	 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ +	  ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20)))  #define AR_SREV_9285E_20(_ah) \      (AR_SREV_9285_12_OR_LATER(_ah) && \ @@ -945,6 +977,7 @@ enum {  #define AR9285_NUM_GPIO                          12  #define AR9287_NUM_GPIO                          11  #define AR9271_NUM_GPIO                          16 +#define AR9300_NUM_GPIO                          17  #define AR_GPIO_IN_OUT                           0x4048  #define AR_GPIO_IN_VAL                           0x0FFFC000 @@ -957,19 +990,21 @@ enum {  #define AR9287_GPIO_IN_VAL_S                     11  #define AR9271_GPIO_IN_VAL                       0xFFFF0000  #define AR9271_GPIO_IN_VAL_S                     16 +#define AR9300_GPIO_IN_VAL                       0x0001FFFF +#define AR9300_GPIO_IN_VAL_S                     0 -#define AR_GPIO_OE_OUT                           0x404c +#define AR_GPIO_OE_OUT                           (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)  #define AR_GPIO_OE_OUT_DRV                       0x3  #define AR_GPIO_OE_OUT_DRV_NO                    0x0  #define AR_GPIO_OE_OUT_DRV_LOW                   0x1  #define AR_GPIO_OE_OUT_DRV_HI                    0x2  #define AR_GPIO_OE_OUT_DRV_ALL                   0x3 -#define AR_GPIO_INTR_POL                         0x4050 -#define AR_GPIO_INTR_POL_VAL                     0x00001FFF +#define AR_GPIO_INTR_POL                         (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050) +#define AR_GPIO_INTR_POL_VAL                     0x0001FFFF  #define AR_GPIO_INTR_POL_VAL_S                   0 -#define AR_GPIO_INPUT_EN_VAL                     0x4054 +#define AR_GPIO_INPUT_EN_VAL                     (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054)  #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF     0x00000004  #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S       2  #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF    0x00000008 @@ -987,13 +1022,13 @@ enum {  #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE        0x00010000  #define AR_GPIO_JTAG_DISABLE                     0x00020000 -#define AR_GPIO_INPUT_MUX1                       0x4058 +#define AR_GPIO_INPUT_MUX1                       (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058)  #define AR_GPIO_INPUT_MUX1_BT_ACTIVE             0x000f0000  #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S           16  #define AR_GPIO_INPUT_MUX1_BT_PRIORITY           0x00000f00  #define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S         8 -#define AR_GPIO_INPUT_MUX2                       0x405c +#define AR_GPIO_INPUT_MUX2                       (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c)  #define AR_GPIO_INPUT_MUX2_CLK25                 0x0000000f  #define AR_GPIO_INPUT_MUX2_CLK25_S               0  #define AR_GPIO_INPUT_MUX2_RFSILENT              0x000000f0 @@ -1001,13 +1036,13 @@ enum {  #define AR_GPIO_INPUT_MUX2_RTC_RESET             0x00000f00  #define AR_GPIO_INPUT_MUX2_RTC_RESET_S           8 -#define AR_GPIO_OUTPUT_MUX1                      0x4060 -#define AR_GPIO_OUTPUT_MUX2                      0x4064 -#define AR_GPIO_OUTPUT_MUX3                      0x4068 +#define AR_GPIO_OUTPUT_MUX1                      (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060) +#define AR_GPIO_OUTPUT_MUX2                      (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064) +#define AR_GPIO_OUTPUT_MUX3                      (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068) -#define AR_INPUT_STATE                           0x406c +#define AR_INPUT_STATE                           (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c) -#define AR_EEPROM_STATUS_DATA                    0x407c +#define AR_EEPROM_STATUS_DATA                    (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c)  #define AR_EEPROM_STATUS_DATA_VAL                0x0000ffff  #define AR_EEPROM_STATUS_DATA_VAL_S              0  #define AR_EEPROM_STATUS_DATA_BUSY               0x00010000 @@ -1015,13 +1050,24 @@ enum {  #define AR_EEPROM_STATUS_DATA_PROT_ACCESS        0x00040000  #define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS      0x00080000 -#define AR_OBS                  0x4080 +#define AR_OBS                  (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080) -#define AR_GPIO_PDPU                             0x4088 +#define AR_GPIO_PDPU                             (AR_SREV_9300_20_OR_LATER(ah) ? 0x4090 : 0x4088) -#define AR_PCIE_MSI                              0x4094 +#define AR_PCIE_MSI                              (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094)  #define AR_PCIE_MSI_ENABLE                       0x00000001 +#define AR_INTR_PRIO_SYNC_ENABLE  0x40c4 +#define AR_INTR_PRIO_ASYNC_MASK   0x40c8 +#define AR_INTR_PRIO_SYNC_MASK    0x40cc +#define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4 + +#define AR_RTC_9300_PLL_DIV          0x000003ff +#define AR_RTC_9300_PLL_DIV_S        0 +#define AR_RTC_9300_PLL_REFDIV       0x00003C00 +#define AR_RTC_9300_PLL_REFDIV_S     10 +#define AR_RTC_9300_PLL_CLKSEL       0x0000C000 +#define AR_RTC_9300_PLL_CLKSEL_S     14  #define AR_RTC_9160_PLL_DIV	0x000003ff  #define AR_RTC_9160_PLL_DIV_S   0 @@ -1039,6 +1085,16 @@ enum {  #define AR_RTC_RC_COLD_RESET    0x00000004  #define AR_RTC_RC_WARM_RESET    0x00000008 +/* Crystal Control */ +#define AR_RTC_XTAL_CONTROL     0x7004 + +/* Reg Control 0 */ +#define AR_RTC_REG_CONTROL0     0x7008 + +/* Reg Control 1 */ +#define AR_RTC_REG_CONTROL1     0x700c +#define AR_RTC_REG_CONTROL1_SWREG_PROGRAM       0x00000001 +  #define AR_RTC_PLL_CONTROL \  	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014) @@ -1069,6 +1125,7 @@ enum {  #define AR_RTC_SLEEP_CLK \  	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048)  #define AR_RTC_FORCE_DERIVED_CLK    0x2 +#define AR_RTC_FORCE_SWREG_PRD      0x00000004  #define AR_RTC_FORCE_WAKE \  	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c) @@ -1533,7 +1590,7 @@ enum {  #define AR_TSFOOR_THRESHOLD       0x813c  #define AR_TSFOOR_THRESHOLD_VAL   0x0000FFFF -#define AR_PHY_ERR_EIFS_MASK   8144 +#define AR_PHY_ERR_EIFS_MASK   0x8144  #define AR_PHY_ERR_3           0x8168  #define AR_PHY_ERR_3_COUNT     0x00FFFFFF @@ -1599,24 +1656,26 @@ enum {  #define AR_FIRST_NDP_TIMER                  7  #define AR_NDP2_PERIOD                      0x81a0  #define AR_NDP2_TIMER_MODE                  0x81c0 -#define AR_NEXT_TBTT_TIMER                  0x8200 -#define AR_NEXT_DMA_BEACON_ALERT            0x8204 -#define AR_NEXT_SWBA                        0x8208 -#define AR_NEXT_CFP                         0x8208 -#define AR_NEXT_HCF                         0x820C -#define AR_NEXT_TIM                         0x8210 -#define AR_NEXT_DTIM                        0x8214 -#define AR_NEXT_QUIET_TIMER                 0x8218 -#define AR_NEXT_NDP_TIMER                   0x821C -#define AR_BEACON_PERIOD                    0x8220 -#define AR_DMA_BEACON_PERIOD                0x8224 -#define AR_SWBA_PERIOD                      0x8228 -#define AR_HCF_PERIOD                       0x822C -#define AR_TIM_PERIOD                       0x8230 -#define AR_DTIM_PERIOD                      0x8234 -#define AR_QUIET_PERIOD                     0x8238 -#define AR_NDP_PERIOD                       0x823C +#define AR_GEN_TIMERS(_i)                   (0x8200 + ((_i) << 2)) +#define AR_NEXT_TBTT_TIMER                  AR_GEN_TIMERS(0) +#define AR_NEXT_DMA_BEACON_ALERT            AR_GEN_TIMERS(1) +#define AR_NEXT_SWBA                        AR_GEN_TIMERS(2) +#define AR_NEXT_CFP                         AR_GEN_TIMERS(2) +#define AR_NEXT_HCF                         AR_GEN_TIMERS(3) +#define AR_NEXT_TIM                         AR_GEN_TIMERS(4) +#define AR_NEXT_DTIM                        AR_GEN_TIMERS(5) +#define AR_NEXT_QUIET_TIMER                 AR_GEN_TIMERS(6) +#define AR_NEXT_NDP_TIMER                   AR_GEN_TIMERS(7) + +#define AR_BEACON_PERIOD                    AR_GEN_TIMERS(8) +#define AR_DMA_BEACON_PERIOD                AR_GEN_TIMERS(9) +#define AR_SWBA_PERIOD                      AR_GEN_TIMERS(10) +#define AR_HCF_PERIOD                       AR_GEN_TIMERS(11) +#define AR_TIM_PERIOD                       AR_GEN_TIMERS(12) +#define AR_DTIM_PERIOD                      AR_GEN_TIMERS(13) +#define AR_QUIET_PERIOD                     AR_GEN_TIMERS(14) +#define AR_NDP_PERIOD                       AR_GEN_TIMERS(15)  #define AR_TIMER_MODE                       0x8240  #define AR_TBTT_TIMER_EN                    0x00000001 @@ -1730,4 +1789,32 @@ enum {  #define AR9271_CORE_CLOCK	117   /* clock to 117Mhz */  #define AR9271_TARGET_BAUD_RATE	19200 /* 115200 */ +#define AR_AGG_WEP_ENABLE_FIX		0x00000008  /* This allows the use of AR_AGG_WEP_ENABLE */ +#define AR_ADHOC_MCAST_KEYID_ENABLE     0x00000040  /* This bit enables the Multicast search +						     * based on both MAC Address and Key ID. +						     * If bit is 0, then Multicast search is +						     * based on MAC address only. +						     * For Merlin and above only. +						     */ +#define AR_AGG_WEP_ENABLE               0x00020000  /* This field enables AGG_WEP feature, +						     * when it is enable, AGG_WEP would takes +						     * charge of the encryption interface of +						     * pcu_txsm. +						     */ + +#define AR9300_SM_BASE				0xa200 +#define AR9002_PHY_AGC_CONTROL			0x9860 +#define AR9003_PHY_AGC_CONTROL			AR9300_SM_BASE + 0xc4 +#define AR_PHY_AGC_CONTROL			(AR_SREV_9300_20_OR_LATER(ah) ? AR9003_PHY_AGC_CONTROL : AR9002_PHY_AGC_CONTROL) +#define AR_PHY_AGC_CONTROL_CAL			0x00000001  /* do internal calibration */ +#define AR_PHY_AGC_CONTROL_NF			0x00000002  /* do noise-floor calibration */ +#define AR_PHY_AGC_CONTROL_OFFSET_CAL		0x00000800  /* allow offset calibration */ +#define AR_PHY_AGC_CONTROL_ENABLE_NF		0x00008000  /* enable noise floor calibration to happen */ +#define AR_PHY_AGC_CONTROL_FLTR_CAL		0x00010000  /* allow tx filter calibration */ +#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF		0x00020000  /* don't update noise floor automatically */ +#define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS	0x00040000  /* extend noise floor power measurement */ +#define AR_PHY_AGC_CONTROL_CLC_SUCCESS		0x00080000  /* carrier leak calibration done */ +#define AR_PHY_AGC_CONTROL_YCOK_MAX		0x000003c0 +#define AR_PHY_AGC_CONTROL_YCOK_MAX_S		6 +  #endif diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index f2ff18cf3e6..e23172c9caa 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -101,6 +101,7 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv)  	wmi->drv_priv = priv;  	wmi->stopped = false;  	mutex_init(&wmi->op_mutex); +	mutex_init(&wmi->multi_write_mutex);  	init_completion(&wmi->cmd_wait);  	return wmi; @@ -128,7 +129,7 @@ void ath9k_wmi_tasklet(unsigned long data)  	void *wmi_event;  	unsigned long flags;  #ifdef CONFIG_ATH9K_HTC_DEBUGFS -	u32 txrate; +	__be32 txrate;  #endif  	spin_lock_irqsave(&priv->wmi->wmi_lock, flags); @@ -203,6 +204,14 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,  		return;  	} +	/* Check if there has been a timeout. */ +	spin_lock(&wmi->wmi_lock); +	if (cmd_id != wmi->last_cmd_id) { +		spin_unlock(&wmi->wmi_lock); +		goto free_skb; +	} +	spin_unlock(&wmi->wmi_lock); +  	/* WMI command response */  	ath9k_wmi_rsp_callback(wmi, skb); @@ -265,6 +274,10 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,  	struct sk_buff *skb;  	u8 *data;  	int time_left, ret = 0; +	unsigned long flags; + +	if (wmi->drv_priv->op_flags & OP_UNPLUGGED) +		return 0;  	if (!wmi)  		return -EINVAL; @@ -292,6 +305,10 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,  	wmi->cmd_rsp_buf = rsp_buf;  	wmi->cmd_rsp_len = rsp_len; +	spin_lock_irqsave(&wmi->wmi_lock, flags); +	wmi->last_cmd_id = cmd_id; +	spin_unlock_irqrestore(&wmi->wmi_lock, flags); +  	ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len);  	if (ret)  		goto out; diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 39ef926f27c..765db5faa2d 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h @@ -19,7 +19,7 @@  struct wmi_event_txrate { -	u32 txrate; +	__be32 txrate;  	struct {  		u8 rssi_thresh;  		u8 per; @@ -27,8 +27,8 @@ struct wmi_event_txrate {  } __packed;  struct wmi_cmd_hdr { -	u16 command_id; -	u16 seq_no; +	__be16 command_id; +	__be16 seq_no;  } __packed;  struct wmi_swba { @@ -84,12 +84,20 @@ enum wmi_event_id {  	WMI_TXRATE_EVENTID,  }; +#define MAX_CMD_NUMBER 62 + +struct register_write { +	__be32 reg; +	__be32 val; +}; +  struct wmi {  	struct ath9k_htc_priv *drv_priv;  	struct htc_target *htc;  	enum htc_endpoint_id ctrl_epid;  	struct mutex op_mutex;  	struct completion cmd_wait; +	enum wmi_cmd_id last_cmd_id;  	u16 tx_seq_id;  	u8 *cmd_rsp_buf;  	u32 cmd_rsp_len; @@ -97,6 +105,11 @@ struct wmi {  	struct sk_buff *wmi_skb;  	spinlock_t wmi_lock; + +	atomic_t mwrite_cnt; +	struct register_write multi_write[MAX_CMD_NUMBER]; +	u32 multi_write_idx; +	struct mutex multi_write_mutex;  };  struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv); @@ -113,14 +126,14 @@ void ath9k_wmi_tasklet(unsigned long data);  	do {								\  		ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, NULL, 0,	\  				    (u8 *) &cmd_rsp,			\ -				    sizeof(cmd_rsp), HZ);		\ +				    sizeof(cmd_rsp), HZ*2);		\  	} while (0)  #define WMI_CMD_BUF(_wmi_cmd, _buf)					\  	do {								\  		ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd,		\  				    (u8 *) _buf, sizeof(*_buf),		\ -				    &cmd_rsp, sizeof(cmd_rsp), HZ);	\ +				    &cmd_rsp, sizeof(cmd_rsp), HZ*2);	\  	} while (0)  #endif /* WMI_H */ diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 02df4cbf179..3db19172b43 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -15,10 +15,11 @@   */  #include "ath9k.h" +#include "ar9003_mac.h"  #define BITS_PER_BYTE           8  #define OFDM_PLCP_BITS          22 -#define HT_RC_2_MCS(_rc)        ((_rc) & 0x0f) +#define HT_RC_2_MCS(_rc)        ((_rc) & 0x1f)  #define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)  #define L_STF                   8  #define L_LTF                   8 @@ -33,7 +34,7 @@  #define OFDM_SIFS_TIME    	    16 -static u32 bits_per_symbol[][2] = { +static u16 bits_per_symbol[][2] = {  	/* 20MHz 40MHz */  	{    26,   54 },     /*  0: BPSK */  	{    52,  108 },     /*  1: QPSK 1/2 */ @@ -43,14 +44,6 @@ static u32 bits_per_symbol[][2] = {  	{   208,  432 },     /*  5: 64-QAM 2/3 */  	{   234,  486 },     /*  6: 64-QAM 3/4 */  	{   260,  540 },     /*  7: 64-QAM 5/6 */ -	{    52,  108 },     /*  8: BPSK */ -	{   104,  216 },     /*  9: QPSK 1/2 */ -	{   156,  324 },     /* 10: QPSK 3/4 */ -	{   208,  432 },     /* 11: 16-QAM 1/2 */ -	{   312,  648 },     /* 12: 16-QAM 3/4 */ -	{   416,  864 },     /* 13: 64-QAM 2/3 */ -	{   468,  972 },     /* 14: 64-QAM 3/4 */ -	{   520, 1080 },     /* 15: 64-QAM 5/6 */  };  #define IS_HT_RATE(_rate)     ((_rate) & 0x80) @@ -70,28 +63,39 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,  			     int nbad, int txok, bool update_rc);  enum { -	MCS_DEFAULT, +	MCS_HT20, +	MCS_HT20_SGI,  	MCS_HT40,  	MCS_HT40_SGI,  }; -static int ath_max_4ms_framelen[3][16] = { -	[MCS_DEFAULT] = { -		3216,  6434,  9650,  12868, 19304, 25740,  28956,  32180, -		6430,  12860, 19300, 25736, 38600, 51472,  57890,  64320, +static int ath_max_4ms_framelen[4][32] = { +	[MCS_HT20] = { +		3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172, +		6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280, +		9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532, +		12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532, +	}, +	[MCS_HT20_SGI] = { +		3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744, +		7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532, +		10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532, +		14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,  	},  	[MCS_HT40] = { -		6684,  13368, 20052, 26738, 40104, 53476,  60156,  66840, -		13360, 26720, 40080, 53440, 80160, 106880, 120240, 133600, +		6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532, +		13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532, +		20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532, +		26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,  	},  	[MCS_HT40_SGI] = { -		/* TODO: Only MCS 7 and 15 updated, recalculate the rest */ -		6684,  13368, 20052, 26738, 40104, 53476,  60156,  74200, -		13360, 26720, 40080, 53440, 80160, 106880, 120240, 148400, +		7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532, +		14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532, +		22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532, +		29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,  	}  }; -  /*********************/  /* Aggregation logic */  /*********************/ @@ -261,25 +265,46 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,  	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);  } -static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) +static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)  { -	struct ath_buf *tbf; +	struct ath_buf *bf = NULL;  	spin_lock_bh(&sc->tx.txbuflock); -	if (WARN_ON(list_empty(&sc->tx.txbuf))) { + +	if (unlikely(list_empty(&sc->tx.txbuf))) {  		spin_unlock_bh(&sc->tx.txbuflock);  		return NULL;  	} -	tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); -	list_del(&tbf->list); + +	bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); +	list_del(&bf->list); +  	spin_unlock_bh(&sc->tx.txbuflock); +	return bf; +} + +static void ath_tx_return_buffer(struct ath_softc *sc, struct ath_buf *bf) +{ +	spin_lock_bh(&sc->tx.txbuflock); +	list_add_tail(&bf->list, &sc->tx.txbuf); +	spin_unlock_bh(&sc->tx.txbuflock); +} + +static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) +{ +	struct ath_buf *tbf; + +	tbf = ath_tx_get_buffer(sc); +	if (WARN_ON(!tbf)) +		return NULL; +  	ATH_TXBUF_RESET(tbf);  	tbf->aphy = bf->aphy;  	tbf->bf_mpdu = bf->bf_mpdu;  	tbf->bf_buf_addr = bf->bf_buf_addr; -	*(tbf->bf_desc) = *(bf->bf_desc); +	memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);  	tbf->bf_state = bf->bf_state;  	tbf->bf_dmacontext = bf->bf_dmacontext; @@ -359,7 +384,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  			acked_cnt++;  		} else {  			if (!(tid->state & AGGR_CLEANUP) && -			    ts->ts_flags != ATH9K_TX_SW_ABORTED) { +			    !bf_last->bf_tx_aborted) {  				if (bf->bf_retries < ATH_MAX_SW_RETRIES) {  					ath_tx_set_retry(sc, txq, bf);  					txpending = 1; @@ -378,7 +403,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  			}  		} -		if (bf_next == NULL) { +		if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && +		    bf_next == NULL) {  			/*  			 * Make sure the last desc is reclaimed if it  			 * not a holding desc. @@ -412,36 +438,43 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  				!txfail, sendbar);  		} else {  			/* retry the un-acked ones */ -			if (bf->bf_next == NULL && bf_last->bf_stale) { -				struct ath_buf *tbf; +			if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { +				if (bf->bf_next == NULL && bf_last->bf_stale) { +					struct ath_buf *tbf; -				tbf = ath_clone_txbuf(sc, bf_last); -				/* -				 * Update tx baw and complete the frame with -				 * failed status if we run out of tx buf -				 */ -				if (!tbf) { -					spin_lock_bh(&txq->axq_lock); -					ath_tx_update_baw(sc, tid, -							  bf->bf_seqno); -					spin_unlock_bh(&txq->axq_lock); +					tbf = ath_clone_txbuf(sc, bf_last); +					/* +					 * Update tx baw and complete the +					 * frame with failed status if we +					 * run out of tx buf. +					 */ +					if (!tbf) { +						spin_lock_bh(&txq->axq_lock); +						ath_tx_update_baw(sc, tid, +								bf->bf_seqno); +						spin_unlock_bh(&txq->axq_lock); -					bf->bf_state.bf_type |= BUF_XRETRY; -					ath_tx_rc_status(bf, ts, nbad, -							 0, false); -					ath_tx_complete_buf(sc, bf, txq, -							    &bf_head, ts, 0, 0); -					break; -				} +						bf->bf_state.bf_type |= +							BUF_XRETRY; +						ath_tx_rc_status(bf, ts, nbad, +								0, false); +						ath_tx_complete_buf(sc, bf, txq, +								    &bf_head, +								    ts, 0, 0); +						break; +					} -				ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); -				list_add_tail(&tbf->list, &bf_head); -			} else { -				/* -				 * Clear descriptor status words for -				 * software retry -				 */ -				ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc); +					ath9k_hw_cleartxdesc(sc->sc_ah, +							     tbf->bf_desc); +					list_add_tail(&tbf->list, &bf_head); +				} else { +					/* +					 * Clear descriptor status words for +					 * software retry +					 */ +					ath9k_hw_cleartxdesc(sc->sc_ah, +							     bf->bf_desc); +				}  			}  			/* @@ -509,12 +542,13 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,  				break;  			} -			if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) -				modeidx = MCS_HT40_SGI; -			else if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) +			if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)  				modeidx = MCS_HT40;  			else -				modeidx = MCS_DEFAULT; +				modeidx = MCS_HT20; + +			if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) +				modeidx++;  			frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];  			max_4ms_framelen = min(max_4ms_framelen, frmlen); @@ -559,7 +593,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,  	u32 nsymbits, nsymbols;  	u16 minlen;  	u8 flags, rix; -	int width, half_gi, ndelim, mindelim; +	int width, streams, half_gi, ndelim, mindelim;  	/* Select standard number of delimiters based on frame length alone */  	ndelim = ATH_AGGR_GET_NDELIM(frmlen); @@ -599,7 +633,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,  	if (nsymbols == 0)  		nsymbols = 1; -	nsymbits = bits_per_symbol[rix][width]; +	streams = HT_RC_2_STREAMS(rix); +	nsymbits = bits_per_symbol[rix % 8][width] * streams;  	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;  	if (frmlen < minlen) { @@ -665,7 +700,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,  		bpad = PADBYTES(al_delta) + (ndelim << 2);  		bf->bf_next = NULL; -		bf->bf_desc->ds_link = 0; +		ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);  		/* link buffers of this frame to the aggregate */  		ath_tx_addto_baw(sc, tid, bf); @@ -673,7 +708,8 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,  		list_move_tail(&bf->list, bf_q);  		if (bf_prev) {  			bf_prev->bf_next = bf; -			bf_prev->bf_desc->ds_link = bf->bf_daddr; +			ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc, +					       bf->bf_daddr);  		}  		bf_prev = bf; @@ -853,7 +889,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)  	struct ath_hw *ah = sc->sc_ah;  	struct ath_common *common = ath9k_hw_common(ah);  	struct ath9k_tx_queue_info qi; -	int qnum; +	int qnum, i;  	memset(&qi, 0, sizeof(qi));  	qi.tqi_subtype = subtype; @@ -877,11 +913,16 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)  	 * The UAPSD queue is an exception, since we take a desc-  	 * based intr on the EOSP frames.  	 */ -	if (qtype == ATH9K_TX_QUEUE_UAPSD) -		qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; -	else -		qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | -			TXQ_FLAG_TXDESCINT_ENABLE; +	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +		qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE | +				TXQ_FLAG_TXERRINT_ENABLE; +	} else { +		if (qtype == ATH9K_TX_QUEUE_UAPSD) +			qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; +		else +			qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | +					TXQ_FLAG_TXDESCINT_ENABLE; +	}  	qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);  	if (qnum == -1) {  		/* @@ -908,6 +949,11 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)  		txq->axq_depth = 0;  		txq->axq_tx_inprogress = false;  		sc->tx.txqsetup |= 1<<qnum; + +		txq->txq_headidx = txq->txq_tailidx = 0; +		for (i = 0; i < ATH_TXFIFO_DEPTH; i++) +			INIT_LIST_HEAD(&txq->txq_fifo[i]); +		INIT_LIST_HEAD(&txq->txq_fifo_pending);  	}  	return &sc->tx.txq[qnum];  } @@ -1035,36 +1081,52 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)  	struct ath_tx_status ts;  	memset(&ts, 0, sizeof(ts)); -	if (!retry_tx) -		ts.ts_flags = ATH9K_TX_SW_ABORTED; -  	INIT_LIST_HEAD(&bf_head);  	for (;;) {  		spin_lock_bh(&txq->axq_lock); -		if (list_empty(&txq->axq_q)) { -			txq->axq_link = NULL; -			spin_unlock_bh(&txq->axq_lock); -			break; -		} - -		bf = list_first_entry(&txq->axq_q, struct ath_buf, list); +		if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +			if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { +				txq->txq_headidx = txq->txq_tailidx = 0; +				spin_unlock_bh(&txq->axq_lock); +				break; +			} else { +				bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx], +						      struct ath_buf, list); +			} +		} else { +			if (list_empty(&txq->axq_q)) { +				txq->axq_link = NULL; +				spin_unlock_bh(&txq->axq_lock); +				break; +			} +			bf = list_first_entry(&txq->axq_q, struct ath_buf, +					      list); -		if (bf->bf_stale) { -			list_del(&bf->list); -			spin_unlock_bh(&txq->axq_lock); +			if (bf->bf_stale) { +				list_del(&bf->list); +				spin_unlock_bh(&txq->axq_lock); -			spin_lock_bh(&sc->tx.txbuflock); -			list_add_tail(&bf->list, &sc->tx.txbuf); -			spin_unlock_bh(&sc->tx.txbuflock); -			continue; +				ath_tx_return_buffer(sc, bf); +				continue; +			}  		}  		lastbf = bf->bf_lastbf; +		if (!retry_tx) +			lastbf->bf_tx_aborted = true; + +		if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +			list_cut_position(&bf_head, +					  &txq->txq_fifo[txq->txq_tailidx], +					  &lastbf->list); +			INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); +		} else { +			/* remove ath_buf's of the same mpdu from txq */ +			list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); +		} -		/* remove ath_buf's of the same mpdu from txq */ -		list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);  		txq->axq_depth--;  		spin_unlock_bh(&txq->axq_lock); @@ -1087,6 +1149,27 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)  			spin_unlock_bh(&txq->axq_lock);  		}  	} + +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +		spin_lock_bh(&txq->axq_lock); +		while (!list_empty(&txq->txq_fifo_pending)) { +			bf = list_first_entry(&txq->txq_fifo_pending, +					      struct ath_buf, list); +			list_cut_position(&bf_head, +					  &txq->txq_fifo_pending, +					  &bf->bf_lastbf->list); +			spin_unlock_bh(&txq->axq_lock); + +			if (bf_isampdu(bf)) +				ath_tx_complete_aggr(sc, txq, bf, &bf_head, +						     &ts, 0); +			else +				ath_tx_complete_buf(sc, bf, txq, &bf_head, +						    &ts, 0, 0); +			spin_lock_bh(&txq->axq_lock); +		} +		spin_unlock_bh(&txq->axq_lock); +	}  }  void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) @@ -1224,44 +1307,47 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,  	bf = list_first_entry(head, struct ath_buf, list); -	list_splice_tail_init(head, &txq->axq_q); -	txq->axq_depth++; -  	ath_print(common, ATH_DBG_QUEUE,  		  "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); -	if (txq->axq_link == NULL) { +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +		if (txq->axq_depth >= ATH_TXFIFO_DEPTH) { +			list_splice_tail_init(head, &txq->txq_fifo_pending); +			return; +		} +		if (!list_empty(&txq->txq_fifo[txq->txq_headidx])) +			ath_print(common, ATH_DBG_XMIT, +				  "Initializing tx fifo %d which " +				  "is non-empty\n", +				  txq->txq_headidx); +		INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]); +		list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]); +		INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);  		ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);  		ath_print(common, ATH_DBG_XMIT,  			  "TXDP[%u] = %llx (%p)\n",  			  txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);  	} else { -		*txq->axq_link = bf->bf_daddr; -		ath_print(common, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n", -			  txq->axq_qnum, txq->axq_link, -			  ito64(bf->bf_daddr), bf->bf_desc); -	} -	txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); -	ath9k_hw_txstart(ah, txq->axq_qnum); -} +		list_splice_tail_init(head, &txq->axq_q); -static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) -{ -	struct ath_buf *bf = NULL; - -	spin_lock_bh(&sc->tx.txbuflock); - -	if (unlikely(list_empty(&sc->tx.txbuf))) { -		spin_unlock_bh(&sc->tx.txbuflock); -		return NULL; +		if (txq->axq_link == NULL) { +			ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); +			ath_print(common, ATH_DBG_XMIT, +					"TXDP[%u] = %llx (%p)\n", +					txq->axq_qnum, ito64(bf->bf_daddr), +					bf->bf_desc); +		} else { +			*txq->axq_link = bf->bf_daddr; +			ath_print(common, ATH_DBG_XMIT, +					"link[%u] (%p)=%llx (%p)\n", +					txq->axq_qnum, txq->axq_link, +					ito64(bf->bf_daddr), bf->bf_desc); +		} +		ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc, +				       &txq->axq_link); +		ath9k_hw_txstart(ah, txq->axq_qnum);  	} - -	bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); -	list_del(&bf->list); - -	spin_unlock_bh(&sc->tx.txbuflock); - -	return bf; +	txq->axq_depth++;  }  static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, @@ -1408,8 +1494,7 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb,  	INCR(tid->seq_next, IEEE80211_SEQ_MAX);  } -static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, -			  struct ath_txq *txq) +static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc)  {  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	int flags = 0; @@ -1420,6 +1505,9 @@ static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,  	if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)  		flags |= ATH9K_TXDESC_NOACK; +	if (use_ldpc) +		flags |= ATH9K_TXDESC_LDPC; +  	return flags;  } @@ -1438,8 +1526,9 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,  	pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;  	/* find number of symbols: PLCP + data */ +	streams = HT_RC_2_STREAMS(rix);  	nbits = (pktlen << 3) + OFDM_PLCP_BITS; -	nsymbits = bits_per_symbol[rix][width]; +	nsymbits = bits_per_symbol[rix % 8][width] * streams;  	nsymbols = (nbits + nsymbits - 1) / nsymbits;  	if (!half_gi) @@ -1448,7 +1537,6 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,  		duration = SYMBOL_TIME_HALFGI(nsymbols);  	/* addup duration for legacy/ht training and signal fields */ -	streams = HT_RC_2_STREAMS(rix);  	duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);  	return duration; @@ -1519,6 +1607,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)  			series[i].Rate = rix | 0x80;  			series[i].PktDuration = ath_pkt_duration(sc, rix, bf,  				 is_40, is_sgi, is_sp); +			if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) +				series[i].RateFlags |= ATH9K_RATESERIES_STBC;  			continue;  		} @@ -1571,6 +1661,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,  	int hdrlen;  	__le16 fc;  	int padpos, padsize; +	bool use_ldpc = false;  	tx_info->pad[0] = 0;  	switch (txctl->frame_type) { @@ -1597,10 +1688,13 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,  		bf->bf_frmlen -= padsize;  	} -	if (conf_is_ht(&hw->conf)) +	if (conf_is_ht(&hw->conf)) {  		bf->bf_state.bf_type |= BUF_HT; +		if (tx_info->flags & IEEE80211_TX_CTL_LDPC) +			use_ldpc = true; +	} -	bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); +	bf->bf_flags = setup_tx_flags(skb, use_ldpc);  	bf->bf_keytype = get_hw_crypto_keytype(skb);  	if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { @@ -1659,8 +1753,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,  	list_add_tail(&bf->list, &bf_head);  	ds = bf->bf_desc; -	ds->ds_link = 0; -	ds->ds_data = bf->bf_buf_addr; +	ath9k_hw_set_desc_link(ah, ds, 0);  	ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER,  			       bf->bf_keyix, bf->bf_keytype, bf->bf_flags); @@ -1669,7 +1762,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,  			    skb->len,	/* segment length */  			    true,	/* first segment */  			    true,	/* last segment */ -			    ds);	/* first descriptor */ +			    ds,		/* first descriptor */ +			    bf->bf_buf_addr, +			    txctl->txq->axq_qnum);  	spin_lock_bh(&txctl->txq->axq_lock); @@ -1738,9 +1833,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,  		}  		spin_unlock_bh(&txq->axq_lock); -		spin_lock_bh(&sc->tx.txbuflock); -		list_add_tail(&bf->list, &sc->tx.txbuf); -		spin_unlock_bh(&sc->tx.txbuflock); +		ath_tx_return_buffer(sc, bf);  		return r;  	} @@ -1896,7 +1989,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,  	int nbad = 0;  	int isaggr = 0; -	if (ts->ts_flags == ATH9K_TX_SW_ABORTED) +	if (bf->bf_tx_aborted)  		return 0;  	isaggr = bf_isaggr(bf); @@ -2054,13 +2147,12 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)  		txq->axq_depth--;  		txok = !(ts.ts_status & ATH9K_TXERR_MASK);  		txq->axq_tx_inprogress = false; +		if (bf_held) +			list_del(&bf_held->list);  		spin_unlock_bh(&txq->axq_lock); -		if (bf_held) { -			spin_lock_bh(&sc->tx.txbuflock); -			list_move_tail(&bf_held->list, &sc->tx.txbuf); -			spin_unlock_bh(&sc->tx.txbuflock); -		} +		if (bf_held) +			ath_tx_return_buffer(sc, bf_held);  		if (!bf_isampdu(bf)) {  			/* @@ -2138,10 +2230,121 @@ void ath_tx_tasklet(struct ath_softc *sc)  	}  } +void ath_tx_edma_tasklet(struct ath_softc *sc) +{ +	struct ath_tx_status txs; +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	struct ath_hw *ah = sc->sc_ah; +	struct ath_txq *txq; +	struct ath_buf *bf, *lastbf; +	struct list_head bf_head; +	int status; +	int txok; + +	for (;;) { +		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs); +		if (status == -EINPROGRESS) +			break; +		if (status == -EIO) { +			ath_print(common, ATH_DBG_XMIT, +				  "Error processing tx status\n"); +			break; +		} + +		/* Skip beacon completions */ +		if (txs.qid == sc->beacon.beaconq) +			continue; + +		txq = &sc->tx.txq[txs.qid]; + +		spin_lock_bh(&txq->axq_lock); +		if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { +			spin_unlock_bh(&txq->axq_lock); +			return; +		} + +		bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx], +				      struct ath_buf, list); +		lastbf = bf->bf_lastbf; + +		INIT_LIST_HEAD(&bf_head); +		list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx], +				  &lastbf->list); +		INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); +		txq->axq_depth--; +		txq->axq_tx_inprogress = false; +		spin_unlock_bh(&txq->axq_lock); + +		txok = !(txs.ts_status & ATH9K_TXERR_MASK); + +		if (!bf_isampdu(bf)) { +			bf->bf_retries = txs.ts_longretry; +			if (txs.ts_status & ATH9K_TXERR_XRETRY) +				bf->bf_state.bf_type |= BUF_XRETRY; +			ath_tx_rc_status(bf, &txs, 0, txok, true); +		} + +		if (bf_isampdu(bf)) +			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok); +		else +			ath_tx_complete_buf(sc, bf, txq, &bf_head, +					    &txs, txok, 0); + +		ath_wake_mac80211_queue(sc, txq); + +		spin_lock_bh(&txq->axq_lock); +		if (!list_empty(&txq->txq_fifo_pending)) { +			INIT_LIST_HEAD(&bf_head); +			bf = list_first_entry(&txq->txq_fifo_pending, +				struct ath_buf, list); +			list_cut_position(&bf_head, &txq->txq_fifo_pending, +				&bf->bf_lastbf->list); +			ath_tx_txqaddbuf(sc, txq, &bf_head); +		} else if (sc->sc_flags & SC_OP_TXAGGR) +			ath_txq_schedule(sc, txq); +		spin_unlock_bh(&txq->axq_lock); +	} +} +  /*****************/  /* Init, Cleanup */  /*****************/ +static int ath_txstatus_setup(struct ath_softc *sc, int size) +{ +	struct ath_descdma *dd = &sc->txsdma; +	u8 txs_len = sc->sc_ah->caps.txs_len; + +	dd->dd_desc_len = size * txs_len; +	dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, +					 &dd->dd_desc_paddr, GFP_KERNEL); +	if (!dd->dd_desc) +		return -ENOMEM; + +	return 0; +} + +static int ath_tx_edma_init(struct ath_softc *sc) +{ +	int err; + +	err = ath_txstatus_setup(sc, ATH_TXSTATUS_RING_SIZE); +	if (!err) +		ath9k_hw_setup_statusring(sc->sc_ah, sc->txsdma.dd_desc, +					  sc->txsdma.dd_desc_paddr, +					  ATH_TXSTATUS_RING_SIZE); + +	return err; +} + +static void ath_tx_edma_cleanup(struct ath_softc *sc) +{ +	struct ath_descdma *dd = &sc->txsdma; + +	dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, +			  dd->dd_desc_paddr); +} +  int ath_tx_init(struct ath_softc *sc, int nbufs)  {  	struct ath_common *common = ath9k_hw_common(sc->sc_ah); @@ -2150,7 +2353,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)  	spin_lock_init(&sc->tx.txbuflock);  	error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, -				  "tx", nbufs, 1); +				  "tx", nbufs, 1, 1);  	if (error != 0) {  		ath_print(common, ATH_DBG_FATAL,  			  "Failed to allocate tx descriptors: %d\n", error); @@ -2158,7 +2361,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)  	}  	error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, -				  "beacon", ATH_BCBUF, 1); +				  "beacon", ATH_BCBUF, 1, 1);  	if (error != 0) {  		ath_print(common, ATH_DBG_FATAL,  			  "Failed to allocate beacon descriptors: %d\n", error); @@ -2167,6 +2370,12 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)  	INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +		error = ath_tx_edma_init(sc); +		if (error) +			goto err; +	} +  err:  	if (error != 0)  		ath_tx_cleanup(sc); @@ -2181,6 +2390,9 @@ void ath_tx_cleanup(struct ath_softc *sc)  	if (sc->tx.txdma.dd_desc_len != 0)  		ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); + +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) +		ath_tx_edma_cleanup(sc);  }  void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 997303bcf4a..7965b70efba 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4571,6 +4571,23 @@ static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw)  	mutex_unlock(&wl->mutex);  } +static int b43_op_get_survey(struct ieee80211_hw *hw, int idx, +			     struct survey_info *survey) +{ +	struct b43_wl *wl = hw_to_b43_wl(hw); +	struct b43_wldev *dev = wl->current_dev; +	struct ieee80211_conf *conf = &hw->conf; + +	if (idx != 0) +		return -ENOENT; + +	survey->channel = conf->channel; +	survey->filled = SURVEY_INFO_NOISE_DBM; +	survey->noise = dev->stats.link_noise; + +	return 0; +} +  static const struct ieee80211_ops b43_hw_ops = {  	.tx			= b43_op_tx,  	.conf_tx		= b43_op_conf_tx, @@ -4590,6 +4607,7 @@ static const struct ieee80211_ops b43_hw_ops = {  	.sta_notify		= b43_op_sta_notify,  	.sw_scan_start		= b43_op_sw_scan_start_notifier,  	.sw_scan_complete	= b43_op_sw_scan_complete_notifier, +	.get_survey		= b43_op_get_survey,  	.rfkill_poll		= b43_rfkill_poll,  }; @@ -4905,8 +4923,7 @@ static int b43_wireless_init(struct ssb_device *dev)  	/* fill hw info */  	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | -		    IEEE80211_HW_SIGNAL_DBM | -		    IEEE80211_HW_NOISE_DBM; +		    IEEE80211_HW_SIGNAL_DBM;  	hw->wiphy->interface_modes =  		BIT(NL80211_IFTYPE_AP) | diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index eda06529ef5..e6b0528f3b5 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -610,7 +610,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)  	}  	/* Link quality statistics */ -	status.noise = dev->stats.link_noise;  	if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {  //		s8 rssi = max(rxhdr->power0, rxhdr->power1);  		//TODO: Find out what the rssi value is (dBm or percentage?) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index bb2dd9329aa..1713f5f7a58 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3482,6 +3482,23 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,  	return 0;  } +static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx, +				   struct survey_info *survey) +{ +	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); +	struct b43legacy_wldev *dev = wl->current_dev; +	struct ieee80211_conf *conf = &hw->conf; + +	if (idx != 0) +		return -ENOENT; + +	survey->channel = conf->channel; +	survey->filled = SURVEY_INFO_NOISE_DBM; +	survey->noise = dev->stats.link_noise; + +	return 0; +} +  static const struct ieee80211_ops b43legacy_hw_ops = {  	.tx			= b43legacy_op_tx,  	.conf_tx		= b43legacy_op_conf_tx, @@ -3494,6 +3511,7 @@ static const struct ieee80211_ops b43legacy_hw_ops = {  	.start			= b43legacy_op_start,  	.stop			= b43legacy_op_stop,  	.set_tim		= b43legacy_op_beacon_set_tim, +	.get_survey		= b43legacy_op_get_survey,  	.rfkill_poll		= b43legacy_rfkill_poll,  }; @@ -3769,8 +3787,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)  	/* fill hw info */  	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | -		    IEEE80211_HW_SIGNAL_DBM | -		    IEEE80211_HW_NOISE_DBM; +		    IEEE80211_HW_SIGNAL_DBM;  	hw->wiphy->interface_modes =  		BIT(NL80211_IFTYPE_AP) |  		BIT(NL80211_IFTYPE_STATION) | diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 9c8882d9275..7d177d97f1f 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -548,7 +548,6 @@ void b43legacy_rx(struct b43legacy_wldev *dev,  				      (phystat0 & B43legacy_RX_PHYST0_OFDM),  				      (phystat0 & B43legacy_RX_PHYST0_GAINCTL),  				      (phystat3 & B43legacy_RX_PHYST3_TRSTATE)); -	status.noise = dev->stats.link_noise;  	/* change to support A PHY */  	if (phystat0 & B43legacy_RX_PHYST0_OFDM)  		status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false); diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index a684a72eb6e..7c723538551 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_IWLAGN)	+= iwlagn.o  iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o  iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o  iwlagn-objs		+= iwl-agn-lib.o +iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o  iwlagn-$(CONFIG_IWL4965) += iwl-4965.o  iwlagn-$(CONFIG_IWL5000) += iwl-5000.o @@ -21,5 +22,6 @@ iwlagn-$(CONFIG_IWL5000) += iwl-1000.o  # 3945  obj-$(CONFIG_IWL3945)	+= iwl3945.o  iwl3945-objs		:= iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o +iwl3945-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-3945-debugfs.o  ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 9a0191a5ea3..fb59af2d41c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -46,6 +46,7 @@  #include "iwl-helpers.h"  #include "iwl-agn-hw.h"  #include "iwl-agn-led.h" +#include "iwl-agn-debugfs.h"  /* Highest firmware API version supported */  #define IWL1000_UCODE_API_MAX 3 @@ -212,6 +213,11 @@ static struct iwl_lib_ops iwl1000_lib = {  		.set_ct_kill = iwl1000_set_ct_threshold,  	 },  	.add_bcast_station = iwl_add_bcast_station, +	.debugfs_ops = { +		.rx_stats_read = iwl_ucode_rx_stats_read, +		.tx_stats_read = iwl_ucode_tx_stats_read, +		.general_stats_read = iwl_ucode_general_stats_read, +	},  	.recover_from_tx_stall = iwl_bg_monitor_recover,  	.check_plcp_health = iwl_good_plcp_health,  	.check_ack_health = iwl_good_ack_health, @@ -276,7 +282,6 @@ struct iwl_cfg iwl1000_bg_cfg = {  	.use_bsm = false,  	.max_ll_items = OTP_MAX_LL_ITEMS_1000,  	.shadow_ram_support = false, -	.ht_greenfield_support = true,  	.led_compensation = 51,  	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,  	.support_ct_kill_exit = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c new file mode 100644 index 00000000000..6a9c64a50e3 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c @@ -0,0 +1,500 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + *  Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include "iwl-3945-debugfs.h" + +ssize_t iwl3945_ucode_rx_stats_read(struct file *file, +				    char __user *user_buf, +				    size_t count, loff_t *ppos) +{ +	struct iwl_priv *priv = file->private_data; +	int pos = 0; +	char *buf; +	int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 + +		    sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400; +	ssize_t ret; +	struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; +	struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; +	struct iwl39_statistics_rx_non_phy *general, *accum_general; +	struct iwl39_statistics_rx_non_phy *delta_general, *max_general; + +	if (!iwl_is_alive(priv)) +		return -EAGAIN; + +	buf = kzalloc(bufsz, GFP_KERNEL); +	if (!buf) { +		IWL_ERR(priv, "Can not allocate Buffer\n"); +		return -ENOMEM; +	} + +	/* +	 * The statistic information display here is based on +	 * the last statistics notification from uCode +	 * might not reflect the current uCode activity +	 */ +	ofdm = &priv->_3945.statistics.rx.ofdm; +	cck = &priv->_3945.statistics.rx.cck; +	general = &priv->_3945.statistics.rx.general; +	accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm; +	accum_cck = &priv->_3945.accum_statistics.rx.cck; +	accum_general = &priv->_3945.accum_statistics.rx.general; +	delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm; +	delta_cck = &priv->_3945.delta_statistics.rx.cck; +	delta_general = &priv->_3945.delta_statistics.rx.general; +	max_ofdm = &priv->_3945.max_delta.rx.ofdm; +	max_cck = &priv->_3945.max_delta.rx.cck; +	max_general = &priv->_3945.max_delta.rx.general; + +	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); +	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_Rx - OFDM:"); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), +			 accum_ofdm->ina_cnt, +			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "fina_cnt:", +			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, +			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "plcp_err:", +			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, +			 delta_ofdm->plcp_err, max_ofdm->plcp_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n",  "crc32_err:", +			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, +			 delta_ofdm->crc32_err, max_ofdm->crc32_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:", +			 le32_to_cpu(ofdm->overrun_err), +			 accum_ofdm->overrun_err, delta_ofdm->overrun_err, +			 max_ofdm->overrun_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "early_overrun_err:", +			 le32_to_cpu(ofdm->early_overrun_err), +			 accum_ofdm->early_overrun_err, +			 delta_ofdm->early_overrun_err, +			 max_ofdm->early_overrun_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "crc32_good:", le32_to_cpu(ofdm->crc32_good), +			 accum_ofdm->crc32_good, delta_ofdm->crc32_good, +			 max_ofdm->crc32_good); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:", +			 le32_to_cpu(ofdm->false_alarm_cnt), +			 accum_ofdm->false_alarm_cnt, +			 delta_ofdm->false_alarm_cnt, +			 max_ofdm->false_alarm_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "fina_sync_err_cnt:", +			 le32_to_cpu(ofdm->fina_sync_err_cnt), +			 accum_ofdm->fina_sync_err_cnt, +			 delta_ofdm->fina_sync_err_cnt, +			 max_ofdm->fina_sync_err_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "sfd_timeout:", +			 le32_to_cpu(ofdm->sfd_timeout), +			 accum_ofdm->sfd_timeout, +			 delta_ofdm->sfd_timeout, +			 max_ofdm->sfd_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "fina_timeout:", +			 le32_to_cpu(ofdm->fina_timeout), +			 accum_ofdm->fina_timeout, +			 delta_ofdm->fina_timeout, +			 max_ofdm->fina_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "unresponded_rts:", +			 le32_to_cpu(ofdm->unresponded_rts), +			 accum_ofdm->unresponded_rts, +			 delta_ofdm->unresponded_rts, +			 max_ofdm->unresponded_rts); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "rxe_frame_lmt_ovrun:", +			 le32_to_cpu(ofdm->rxe_frame_limit_overrun), +			 accum_ofdm->rxe_frame_limit_overrun, +			 delta_ofdm->rxe_frame_limit_overrun, +			 max_ofdm->rxe_frame_limit_overrun); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "sent_ack_cnt:", +			 le32_to_cpu(ofdm->sent_ack_cnt), +			 accum_ofdm->sent_ack_cnt, +			 delta_ofdm->sent_ack_cnt, +			 max_ofdm->sent_ack_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "sent_cts_cnt:", +			 le32_to_cpu(ofdm->sent_cts_cnt), +			 accum_ofdm->sent_cts_cnt, +			 delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt); + +	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_Rx - CCK:"); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "ina_cnt:", +			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, +			 delta_cck->ina_cnt, max_cck->ina_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "fina_cnt:", +			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, +			 delta_cck->fina_cnt, max_cck->fina_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "plcp_err:", +			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, +			 delta_cck->plcp_err, max_cck->plcp_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "crc32_err:", +			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, +			 delta_cck->crc32_err, max_cck->crc32_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "overrun_err:", +			 le32_to_cpu(cck->overrun_err), +			 accum_cck->overrun_err, +			 delta_cck->overrun_err, max_cck->overrun_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "early_overrun_err:", +			 le32_to_cpu(cck->early_overrun_err), +			 accum_cck->early_overrun_err, +			 delta_cck->early_overrun_err, +			 max_cck->early_overrun_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "crc32_good:", +			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, +			 delta_cck->crc32_good, +			 max_cck->crc32_good); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "false_alarm_cnt:", +			 le32_to_cpu(cck->false_alarm_cnt), +			 accum_cck->false_alarm_cnt, +			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "fina_sync_err_cnt:", +			 le32_to_cpu(cck->fina_sync_err_cnt), +			 accum_cck->fina_sync_err_cnt, +			 delta_cck->fina_sync_err_cnt, +			 max_cck->fina_sync_err_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "sfd_timeout:", +			 le32_to_cpu(cck->sfd_timeout), +			 accum_cck->sfd_timeout, +			 delta_cck->sfd_timeout, max_cck->sfd_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "fina_timeout:", +			 le32_to_cpu(cck->fina_timeout), +			 accum_cck->fina_timeout, +			 delta_cck->fina_timeout, max_cck->fina_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "unresponded_rts:", +			 le32_to_cpu(cck->unresponded_rts), +			 accum_cck->unresponded_rts, +			 delta_cck->unresponded_rts, +			 max_cck->unresponded_rts); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "rxe_frame_lmt_ovrun:", +			 le32_to_cpu(cck->rxe_frame_limit_overrun), +			 accum_cck->rxe_frame_limit_overrun, +			 delta_cck->rxe_frame_limit_overrun, +			 max_cck->rxe_frame_limit_overrun); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "sent_ack_cnt:", +			 le32_to_cpu(cck->sent_ack_cnt), +			 accum_cck->sent_ack_cnt, +			 delta_cck->sent_ack_cnt, +			 max_cck->sent_ack_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "sent_cts_cnt:", +			 le32_to_cpu(cck->sent_cts_cnt), +			 accum_cck->sent_cts_cnt, +			 delta_cck->sent_cts_cnt, +			 max_cck->sent_cts_cnt); + +	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_Rx - GENERAL:"); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "bogus_cts:", +			 le32_to_cpu(general->bogus_cts), +			 accum_general->bogus_cts, +			 delta_general->bogus_cts, max_general->bogus_cts); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "bogus_ack:", +			 le32_to_cpu(general->bogus_ack), +			 accum_general->bogus_ack, +			 delta_general->bogus_ack, max_general->bogus_ack); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "non_bssid_frames:", +			 le32_to_cpu(general->non_bssid_frames), +			 accum_general->non_bssid_frames, +			 delta_general->non_bssid_frames, +			 max_general->non_bssid_frames); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "filtered_frames:", +			 le32_to_cpu(general->filtered_frames), +			 accum_general->filtered_frames, +			 delta_general->filtered_frames, +			 max_general->filtered_frames); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "non_channel_beacons:", +			 le32_to_cpu(general->non_channel_beacons), +			 accum_general->non_channel_beacons, +			 delta_general->non_channel_beacons, +			 max_general->non_channel_beacons); + +	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); +	kfree(buf); +	return ret; +} + +ssize_t iwl3945_ucode_tx_stats_read(struct file *file, +				    char __user *user_buf, +				    size_t count, loff_t *ppos) +{ +	struct iwl_priv *priv = file->private_data; +	int pos = 0; +	char *buf; +	int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250; +	ssize_t ret; +	struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; + +	if (!iwl_is_alive(priv)) +		return -EAGAIN; + +	buf = kzalloc(bufsz, GFP_KERNEL); +	if (!buf) { +		IWL_ERR(priv, "Can not allocate Buffer\n"); +		return -ENOMEM; +	} + +	/* +	 * The statistic information display here is based on +	 * the last statistics notification from uCode +	 * might not reflect the current uCode activity +	 */ +	tx = &priv->_3945.statistics.tx; +	accum_tx = &priv->_3945.accum_statistics.tx; +	delta_tx = &priv->_3945.delta_statistics.tx; +	max_tx = &priv->_3945.max_delta.tx; +	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); +	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_Tx:"); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "preamble:", +			 le32_to_cpu(tx->preamble_cnt), +			 accum_tx->preamble_cnt, +			 delta_tx->preamble_cnt, max_tx->preamble_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "rx_detected_cnt:", +			 le32_to_cpu(tx->rx_detected_cnt), +			 accum_tx->rx_detected_cnt, +			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "bt_prio_defer_cnt:", +			 le32_to_cpu(tx->bt_prio_defer_cnt), +			 accum_tx->bt_prio_defer_cnt, +			 delta_tx->bt_prio_defer_cnt, +			 max_tx->bt_prio_defer_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "bt_prio_kill_cnt:", +			 le32_to_cpu(tx->bt_prio_kill_cnt), +			 accum_tx->bt_prio_kill_cnt, +			 delta_tx->bt_prio_kill_cnt, +			 max_tx->bt_prio_kill_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "few_bytes_cnt:", +			 le32_to_cpu(tx->few_bytes_cnt), +			 accum_tx->few_bytes_cnt, +			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "cts_timeout:", +			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, +			 delta_tx->cts_timeout, max_tx->cts_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "ack_timeout:", +			 le32_to_cpu(tx->ack_timeout), +			 accum_tx->ack_timeout, +			 delta_tx->ack_timeout, max_tx->ack_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "expected_ack_cnt:", +			 le32_to_cpu(tx->expected_ack_cnt), +			 accum_tx->expected_ack_cnt, +			 delta_tx->expected_ack_cnt, +			 max_tx->expected_ack_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "actual_ack_cnt:", +			 le32_to_cpu(tx->actual_ack_cnt), +			 accum_tx->actual_ack_cnt, +			 delta_tx->actual_ack_cnt, +			 max_tx->actual_ack_cnt); + +	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); +	kfree(buf); +	return ret; +} + +ssize_t iwl3945_ucode_general_stats_read(struct file *file, +					 char __user *user_buf, +					 size_t count, loff_t *ppos) +{ +	struct iwl_priv *priv = file->private_data; +	int pos = 0; +	char *buf; +	int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300; +	ssize_t ret; +	struct iwl39_statistics_general *general, *accum_general; +	struct iwl39_statistics_general *delta_general, *max_general; +	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; +	struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div; + +	if (!iwl_is_alive(priv)) +		return -EAGAIN; + +	buf = kzalloc(bufsz, GFP_KERNEL); +	if (!buf) { +		IWL_ERR(priv, "Can not allocate Buffer\n"); +		return -ENOMEM; +	} + +	/* +	 * The statistic information display here is based on +	 * the last statistics notification from uCode +	 * might not reflect the current uCode activity +	 */ +	general = &priv->_3945.statistics.general; +	dbg = &priv->_3945.statistics.general.dbg; +	div = &priv->_3945.statistics.general.div; +	accum_general = &priv->_3945.accum_statistics.general; +	delta_general = &priv->_3945.delta_statistics.general; +	max_general = &priv->_3945.max_delta.general; +	accum_dbg = &priv->_3945.accum_statistics.general.dbg; +	delta_dbg = &priv->_3945.delta_statistics.general.dbg; +	max_dbg = &priv->_3945.max_delta.general.dbg; +	accum_div = &priv->_3945.accum_statistics.general.div; +	delta_div = &priv->_3945.delta_statistics.general.div; +	max_div = &priv->_3945.max_delta.general.div; +	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); +	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_General:"); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "burst_check:", +			 le32_to_cpu(dbg->burst_check), +			 accum_dbg->burst_check, +			 delta_dbg->burst_check, max_dbg->burst_check); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "burst_count:", +			 le32_to_cpu(dbg->burst_count), +			 accum_dbg->burst_count, +			 delta_dbg->burst_count, max_dbg->burst_count); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "sleep_time:", +			 le32_to_cpu(general->sleep_time), +			 accum_general->sleep_time, +			 delta_general->sleep_time, max_general->sleep_time); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "slots_out:", +			 le32_to_cpu(general->slots_out), +			 accum_general->slots_out, +			 delta_general->slots_out, max_general->slots_out); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "slots_idle:", +			 le32_to_cpu(general->slots_idle), +			 accum_general->slots_idle, +			 delta_general->slots_idle, max_general->slots_idle); +	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", +			 le32_to_cpu(general->ttl_timestamp)); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "tx_on_a:", +			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, +			 delta_div->tx_on_a, max_div->tx_on_a); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "tx_on_b:", +			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, +			 delta_div->tx_on_b, max_div->tx_on_b); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "exec_time:", +			 le32_to_cpu(div->exec_time), accum_div->exec_time, +			 delta_div->exec_time, max_div->exec_time); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "probe_time:", +			 le32_to_cpu(div->probe_time), accum_div->probe_time, +			 delta_div->probe_time, max_div->probe_time); +	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); +	kfree(buf); +	return ret; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h new file mode 100644 index 00000000000..70809c53c21 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + *  Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-debug.h" + +#ifdef CONFIG_IWLWIFI_DEBUGFS +ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf, +				    size_t count, loff_t *ppos); +ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf, +				    size_t count, loff_t *ppos); +ssize_t iwl3945_ucode_general_stats_read(struct file *file, +					 char __user *user_buf, size_t count, +					 loff_t *ppos); +#else +static ssize_t iwl3945_ucode_rx_stats_read(struct file *file, +					   char __user *user_buf, size_t count, +					   loff_t *ppos) +{ +	return 0; +} +static ssize_t iwl3945_ucode_tx_stats_read(struct file *file, +					   char __user *user_buf, size_t count, +					   loff_t *ppos) +{ +	return 0; +} +static ssize_t iwl3945_ucode_general_stats_read(struct file *file, +						char __user *user_buf, +						size_t count, loff_t *ppos) +{ +	return 0; +} +#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index bde3b4cbab9..17197a78d89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -50,6 +50,7 @@  #include "iwl-helpers.h"  #include "iwl-led.h"  #include "iwl-3945-led.h" +#include "iwl-3945-debugfs.h"  #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \  	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,   \ @@ -293,7 +294,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,   * iwl3945_rx_reply_tx - Handle Tx response   */  static void iwl3945_rx_reply_tx(struct iwl_priv *priv, -			    struct iwl_rx_mem_buffer *rxb) +				struct iwl_rx_mem_buffer *rxb)  {  	struct iwl_rx_packet *pkt = rxb_addr(rxb);  	u16 sequence = le16_to_cpu(pkt->hdr.sequence); @@ -351,18 +352,81 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,   *  RX handler implementations   *   *****************************************************************************/ +#ifdef CONFIG_IWLWIFI_DEBUG +/* + *  based on the assumption of all statistics counter are in DWORD + *  FIXME: This function is for debugging, do not deal with + *  the case of counters roll-over. + */ +static void iwl3945_accumulative_statistics(struct iwl_priv *priv, +					    __le32 *stats) +{ +	int i; +	__le32 *prev_stats; +	u32 *accum_stats; +	u32 *delta, *max_delta; + +	prev_stats = (__le32 *)&priv->_3945.statistics; +	accum_stats = (u32 *)&priv->_3945.accum_statistics; +	delta = (u32 *)&priv->_3945.delta_statistics; +	max_delta = (u32 *)&priv->_3945.max_delta; + +	for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics); +	     i += sizeof(__le32), stats++, prev_stats++, delta++, +	     max_delta++, accum_stats++) { +		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { +			*delta = (le32_to_cpu(*stats) - +				le32_to_cpu(*prev_stats)); +			*accum_stats += *delta; +			if (*delta > *max_delta) +				*max_delta = *delta; +		} +	} + +	/* reset accumulative statistics for "no-counter" type statistics */ +	priv->_3945.accum_statistics.general.temperature = +		priv->_3945.statistics.general.temperature; +	priv->_3945.accum_statistics.general.ttl_timestamp = +		priv->_3945.statistics.general.ttl_timestamp; +} +#endif  void iwl3945_hw_rx_statistics(struct iwl_priv *priv,  		struct iwl_rx_mem_buffer *rxb)  {  	struct iwl_rx_packet *pkt = rxb_addr(rxb); +  	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",  		     (int)sizeof(struct iwl3945_notif_statistics),  		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); +#ifdef CONFIG_IWLWIFI_DEBUG +	iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw); +#endif  	memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));  } +void iwl3945_reply_statistics(struct iwl_priv *priv, +			      struct iwl_rx_mem_buffer *rxb) +{ +	struct iwl_rx_packet *pkt = rxb_addr(rxb); +	__le32 *flag = (__le32 *)&pkt->u.raw; + +	if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) { +#ifdef CONFIG_IWLWIFI_DEBUG +		memset(&priv->_3945.accum_statistics, 0, +			sizeof(struct iwl3945_notif_statistics)); +		memset(&priv->_3945.delta_statistics, 0, +			sizeof(struct iwl3945_notif_statistics)); +		memset(&priv->_3945.max_delta, 0, +			sizeof(struct iwl3945_notif_statistics)); +#endif +		IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); +	} +	iwl3945_hw_rx_statistics(priv, rxb); +} + +  /******************************************************************************   *   * Misc. internal state and helper functions @@ -2688,6 +2752,7 @@ IWL3945_UCODE_GET(boot_size);  static struct iwl_hcmd_ops iwl3945_hcmd = {  	.rxon_assoc = iwl3945_send_rxon_assoc,  	.commit_rxon = iwl3945_commit_rxon, +	.send_bt_config = iwl_send_bt_config,  };  static struct iwl_ucode_ops iwl3945_ucode = { @@ -2735,12 +2800,19 @@ static struct iwl_lib_ops iwl3945_lib = {  	.isr = iwl_isr_legacy,  	.config_ap = iwl3945_config_ap,  	.add_bcast_station = iwl3945_add_bcast_station, + +	.debugfs_ops = { +		.rx_stats_read = iwl3945_ucode_rx_stats_read, +		.tx_stats_read = iwl3945_ucode_tx_stats_read, +		.general_stats_read = iwl3945_ucode_general_stats_read, +	},  };  static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {  	.get_hcmd_size = iwl3945_get_hcmd_size,  	.build_addsta_hcmd = iwl3945_build_addsta_hcmd,  	.rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag, +	.request_scan = iwl3945_request_scan,  };  static const struct iwl_ops iwl3945_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index b89219573b9..643adb644bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -264,6 +264,8 @@ extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);  extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);  extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,  				 struct iwl_rx_mem_buffer *rxb); +void iwl3945_reply_statistics(struct iwl_priv *priv, +			      struct iwl_rx_mem_buffer *rxb);  extern void iwl3945_disable_events(struct iwl_priv *priv);  extern int iwl4965_get_temperature(const struct iwl_priv *priv);  extern void iwl3945_post_associate(struct iwl_priv *priv); @@ -294,6 +296,9 @@ extern const struct iwl_channel_info *iwl3945_get_channel_info(  extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); +/* scanning */ +void iwl3945_request_scan(struct iwl_priv *priv); +  /* Requires full declaration of iwl_priv before including */  #include "iwl-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 2e3cda75f3a..136c2906748 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -47,6 +47,7 @@  #include "iwl-sta.h"  #include "iwl-agn-led.h"  #include "iwl-agn.h" +#include "iwl-agn-debugfs.h"  static int iwl4965_send_tx_power(struct iwl_priv *priv);  static int iwl4965_hw_get_temperature(struct iwl_priv *priv); @@ -2143,6 +2144,7 @@ static struct iwl_hcmd_ops iwl4965_hcmd = {  	.rxon_assoc = iwl4965_send_rxon_assoc,  	.commit_rxon = iwl_commit_rxon,  	.set_rxon_chain = iwl_set_rxon_chain, +	.send_bt_config = iwl_send_bt_config,  };  static struct iwl_ucode_ops iwl4965_ucode = { @@ -2162,6 +2164,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {  	.gain_computation = iwl4965_gain_computation,  	.rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,  	.calc_rssi = iwl4965_calc_rssi, +	.request_scan = iwlagn_request_scan,  };  static struct iwl_lib_ops iwl4965_lib = { @@ -2216,6 +2219,11 @@ static struct iwl_lib_ops iwl4965_lib = {  		.set_ct_kill = iwl4965_set_ct_threshold,  	},  	.add_bcast_station = iwl_add_bcast_station, +	.debugfs_ops = { +		.rx_stats_read = iwl_ucode_rx_stats_read, +		.tx_stats_read = iwl_ucode_tx_stats_read, +		.general_stats_read = iwl_ucode_general_stats_read, +	},  	.check_plcp_health = iwl_good_plcp_health,  }; @@ -2253,8 +2261,13 @@ struct iwl_cfg iwl4965_agn_cfg = {  	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,  	.monitor_recover_period = IWL_MONITORING_PERIOD,  	.temperature_kelvin = true, -	.off_channel_workaround = true,  	.max_event_log_size = 512, + +	/* +	 * Force use of chains B and C for scan RX on 5 GHz band +	 * because the device has off-channel reception on chain A. +	 */ +	.scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,  };  /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e967cfcac22..115d3ea1142 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -48,6 +48,7 @@  #include "iwl-agn-led.h"  #include "iwl-agn-hw.h"  #include "iwl-5000-hw.h" +#include "iwl-agn-debugfs.h"  /* Highest firmware API version supported */  #define IWL5000_UCODE_API_MAX 2 @@ -199,26 +200,57 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)  	/* Set initial sensitivity parameters */  	/* Set initial calibration set */ -	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { -	case CSR_HW_REV_TYPE_5150: -		priv->hw_params.sens = &iwl5150_sensitivity; -		priv->hw_params.calib_init_cfg = -			BIT(IWL_CALIB_DC)		| -			BIT(IWL_CALIB_LO)		| -			BIT(IWL_CALIB_TX_IQ) 		| -			BIT(IWL_CALIB_BASE_BAND); +	priv->hw_params.sens = &iwl5000_sensitivity; +	priv->hw_params.calib_init_cfg = +		BIT(IWL_CALIB_XTAL)		| +		BIT(IWL_CALIB_LO)		| +		BIT(IWL_CALIB_TX_IQ)		| +		BIT(IWL_CALIB_TX_IQ_PERD)	| +		BIT(IWL_CALIB_BASE_BAND); -		break; -	default: -		priv->hw_params.sens = &iwl5000_sensitivity; -		priv->hw_params.calib_init_cfg = -			BIT(IWL_CALIB_XTAL)		| -			BIT(IWL_CALIB_LO)		| -			BIT(IWL_CALIB_TX_IQ) 		| -			BIT(IWL_CALIB_TX_IQ_PERD)	| -			BIT(IWL_CALIB_BASE_BAND); -		break; -	} +	return 0; +} + +static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) +{ +	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && +	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) +		priv->cfg->num_of_queues = +			priv->cfg->mod_params->num_of_queues; + +	priv->hw_params.max_txq_num = priv->cfg->num_of_queues; +	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; +	priv->hw_params.scd_bc_tbls_size = +			priv->cfg->num_of_queues * +			sizeof(struct iwlagn_scd_bc_tbl); +	priv->hw_params.tfd_size = sizeof(struct iwl_tfd); +	priv->hw_params.max_stations = IWL5000_STATION_COUNT; +	priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; + +	priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; +	priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; + +	priv->hw_params.max_bsm_size = 0; +	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) | +					BIT(IEEE80211_BAND_5GHZ); +	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; + +	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); +	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); +	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; +	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; + +	if (priv->cfg->ops->lib->temp_ops.set_ct_kill) +		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); + +	/* Set initial sensitivity parameters */ +	/* Set initial calibration set */ +	priv->hw_params.sens = &iwl5150_sensitivity; +	priv->hw_params.calib_init_cfg = +		BIT(IWL_CALIB_DC)		| +		BIT(IWL_CALIB_LO)		| +		BIT(IWL_CALIB_TX_IQ)		| +		BIT(IWL_CALIB_BASE_BAND);  	return 0;  } @@ -320,13 +352,18 @@ static struct iwl_lib_ops iwl5000_lib = {  		.set_ct_kill = iwl5000_set_ct_threshold,  	 },  	.add_bcast_station = iwl_add_bcast_station, +	.debugfs_ops = { +		.rx_stats_read = iwl_ucode_rx_stats_read, +		.tx_stats_read = iwl_ucode_tx_stats_read, +		.general_stats_read = iwl_ucode_general_stats_read, +	},  	.recover_from_tx_stall = iwl_bg_monitor_recover,  	.check_plcp_health = iwl_good_plcp_health,  	.check_ack_health = iwl_good_ack_health,  };  static struct iwl_lib_ops iwl5150_lib = { -	.set_hw_params = iwl5000_hw_set_hw_params, +	.set_hw_params = iwl5150_hw_set_hw_params,  	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,  	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,  	.txq_set_sched = iwlagn_txq_set_sched, @@ -377,6 +414,11 @@ static struct iwl_lib_ops iwl5150_lib = {  		.set_ct_kill = iwl5150_set_ct_threshold,  	 },  	.add_bcast_station = iwl_add_bcast_station, +	.debugfs_ops = { +		.rx_stats_read = iwl_ucode_rx_stats_read, +		.tx_stats_read = iwl_ucode_tx_stats_read, +		.general_stats_read = iwl_ucode_general_stats_read, +	},  	.recover_from_tx_stall = iwl_bg_monitor_recover,  	.check_plcp_health = iwl_good_plcp_health,  	.check_ack_health = iwl_good_ack_health, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index dd03384432f..7acef703253 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -47,17 +47,19 @@  #include "iwl-agn-hw.h"  #include "iwl-6000-hw.h"  #include "iwl-agn-led.h" +#include "iwl-agn-debugfs.h"  /* Highest firmware API version supported */  #define IWL6000_UCODE_API_MAX 4  #define IWL6050_UCODE_API_MAX 4 +#define IWL6000G2_UCODE_API_MAX 4  /* Lowest firmware API version supported */  #define IWL6000_UCODE_API_MIN 4  #define IWL6050_UCODE_API_MIN 4 +#define IWL6000G2_UCODE_API_MIN 4  #define IWL6000_FW_PRE "iwlwifi-6000-" -#define IWL6000_G2_FW_PRE "iwlwifi-6005-"  #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"  #define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) @@ -65,6 +67,10 @@  #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"  #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) +#define IWL6000G2_FW_PRE "iwlwifi-6005-" +#define _IWL6000G2_MODULE_FIRMWARE(api) IWL6000G2_FW_PRE #api ".ucode" +#define IWL6000G2_MODULE_FIRMWARE(api) _IWL6000G2_MODULE_FIRMWARE(api) +  static void iwl6000_set_ct_threshold(struct iwl_priv *priv)  {  	/* want Celsius */ @@ -170,24 +176,56 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)  	/* Set initial sensitivity parameters */  	/* Set initial calibration set */  	priv->hw_params.sens = &iwl6000_sensitivity; -	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { -	case CSR_HW_REV_TYPE_6x50: -		priv->hw_params.calib_init_cfg = -			BIT(IWL_CALIB_XTAL)		| -			BIT(IWL_CALIB_DC)		| -			BIT(IWL_CALIB_LO)		| -			BIT(IWL_CALIB_TX_IQ) 		| -			BIT(IWL_CALIB_BASE_BAND); +	priv->hw_params.calib_init_cfg = +		BIT(IWL_CALIB_XTAL)		| +		BIT(IWL_CALIB_LO)		| +		BIT(IWL_CALIB_TX_IQ)		| +		BIT(IWL_CALIB_BASE_BAND); -		break; -	default: -		priv->hw_params.calib_init_cfg = -			BIT(IWL_CALIB_XTAL)		| -			BIT(IWL_CALIB_LO)		| -			BIT(IWL_CALIB_TX_IQ) 		| -			BIT(IWL_CALIB_BASE_BAND); -		break; -	} +	return 0; +} + +static int iwl6050_hw_set_hw_params(struct iwl_priv *priv) +{ +	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && +	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) +		priv->cfg->num_of_queues = +			priv->cfg->mod_params->num_of_queues; + +	priv->hw_params.max_txq_num = priv->cfg->num_of_queues; +	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; +	priv->hw_params.scd_bc_tbls_size = +			priv->cfg->num_of_queues * +			sizeof(struct iwlagn_scd_bc_tbl); +	priv->hw_params.tfd_size = sizeof(struct iwl_tfd); +	priv->hw_params.max_stations = IWL5000_STATION_COUNT; +	priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; + +	priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; +	priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; + +	priv->hw_params.max_bsm_size = 0; +	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) | +					BIT(IEEE80211_BAND_5GHZ); +	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; + +	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); +	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); +	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; +	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; + +	if (priv->cfg->ops->lib->temp_ops.set_ct_kill) +		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); + +	/* Set initial sensitivity parameters */ +	/* Set initial calibration set */ +	priv->hw_params.sens = &iwl6000_sensitivity; +	priv->hw_params.calib_init_cfg = +		BIT(IWL_CALIB_XTAL)		| +		BIT(IWL_CALIB_DC)		| +		BIT(IWL_CALIB_LO)		| +		BIT(IWL_CALIB_TX_IQ)		| +		BIT(IWL_CALIB_BASE_BAND);  	return 0;  } @@ -261,7 +299,7 @@ static struct iwl_lib_ops iwl6000_lib = {  			EEPROM_REG_BAND_3_CHANNELS,  			EEPROM_REG_BAND_4_CHANNELS,  			EEPROM_REG_BAND_5_CHANNELS, -			EEPROM_REG_BAND_24_HT40_CHANNELS, +			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,  			EEPROM_REG_BAND_52_HT40_CHANNELS  		},  		.verify_signature  = iwlcore_eeprom_verify_signature, @@ -279,6 +317,11 @@ static struct iwl_lib_ops iwl6000_lib = {  		.set_ct_kill = iwl6000_set_ct_threshold,  	 },  	.add_bcast_station = iwl_add_bcast_station, +	.debugfs_ops = { +		.rx_stats_read = iwl_ucode_rx_stats_read, +		.tx_stats_read = iwl_ucode_tx_stats_read, +		.general_stats_read = iwl_ucode_general_stats_read, +	},  	.recover_from_tx_stall = iwl_bg_monitor_recover,  	.check_plcp_health = iwl_good_plcp_health,  	.check_ack_health = iwl_good_ack_health, @@ -293,7 +336,7 @@ static const struct iwl_ops iwl6000_ops = {  };  static struct iwl_lib_ops iwl6050_lib = { -	.set_hw_params = iwl6000_hw_set_hw_params, +	.set_hw_params = iwl6050_hw_set_hw_params,  	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,  	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,  	.txq_set_sched = iwlagn_txq_set_sched, @@ -328,7 +371,7 @@ static struct iwl_lib_ops iwl6050_lib = {  			EEPROM_REG_BAND_3_CHANNELS,  			EEPROM_REG_BAND_4_CHANNELS,  			EEPROM_REG_BAND_5_CHANNELS, -			EEPROM_REG_BAND_24_HT40_CHANNELS, +			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,  			EEPROM_REG_BAND_52_HT40_CHANNELS  		},  		.verify_signature  = iwlcore_eeprom_verify_signature, @@ -347,6 +390,11 @@ static struct iwl_lib_ops iwl6050_lib = {  		.set_calib_version = iwl6050_set_calib_version,  	 },  	.add_bcast_station = iwl_add_bcast_station, +	.debugfs_ops = { +		.rx_stats_read = iwl_ucode_rx_stats_read, +		.tx_stats_read = iwl_ucode_tx_stats_read, +		.general_stats_read = iwl_ucode_general_stats_read, +	},  	.recover_from_tx_stall = iwl_bg_monitor_recover,  	.check_plcp_health = iwl_good_plcp_health,  	.check_ack_health = iwl_good_ack_health, @@ -363,16 +411,16 @@ static const struct iwl_ops iwl6050_ops = {  /*   * "i": Internal configuration, use internal Power Amplifier   */ -struct iwl_cfg iwl6000i_g2_2agn_cfg = { +struct iwl_cfg iwl6000g2_2agn_cfg = {  	.name = "6000 Series 2x2 AGN Gen2", -	.fw_name_pre = IWL6000_G2_FW_PRE, -	.ucode_api_max = IWL6000_UCODE_API_MAX, -	.ucode_api_min = IWL6000_UCODE_API_MIN, +	.fw_name_pre = IWL6000G2_FW_PRE, +	.ucode_api_max = IWL6000G2_UCODE_API_MAX, +	.ucode_api_min = IWL6000G2_UCODE_API_MIN,  	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,  	.ops = &iwl6000_ops,  	.eeprom_size = OTP_LOW_IMAGE_SIZE, -	.eeprom_ver = EEPROM_6000_EEPROM_VERSION, -	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, +	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, +	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,  	.num_of_queues = IWLAGN_NUM_QUEUES,  	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,  	.mod_params = &iwlagn_mod_params, @@ -381,7 +429,7 @@ struct iwl_cfg iwl6000i_g2_2agn_cfg = {  	.pll_cfg_val = 0,  	.set_l0s = true,  	.use_bsm = false, -	.pa_type = IWL_PA_INTERNAL, +	.pa_type = IWL_PA_SYSTEM,  	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,  	.shadow_ram_support = true,  	.ht_greenfield_support = true, @@ -452,7 +500,6 @@ struct iwl_cfg iwl6000i_2abg_cfg = {  	.pa_type = IWL_PA_INTERNAL,  	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,  	.shadow_ram_support = true, -	.ht_greenfield_support = true,  	.led_compensation = 51,  	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,  	.supports_idle = true, @@ -485,7 +532,6 @@ struct iwl_cfg iwl6000i_2bg_cfg = {  	.pa_type = IWL_PA_INTERNAL,  	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,  	.shadow_ram_support = true, -	.ht_greenfield_support = true,  	.led_compensation = 51,  	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,  	.supports_idle = true, @@ -552,7 +598,6 @@ struct iwl_cfg iwl6050_2abg_cfg = {  	.pa_type = IWL_PA_SYSTEM,  	.max_ll_items = OTP_MAX_LL_ITEMS_6x50,  	.shadow_ram_support = true, -	.ht_greenfield_support = true,  	.led_compensation = 51,  	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,  	.supports_idle = true, @@ -600,3 +645,4 @@ struct iwl_cfg iwl6000_3agn_cfg = {  MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));  MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL6000G2_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c new file mode 100644 index 00000000000..f249b706bf1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -0,0 +1,834 @@ +/****************************************************************************** +* +* GPL LICENSE SUMMARY +* +* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of version 2 of the GNU General Public License as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, +* USA +* +* The full GNU General Public License is included in this distribution +* in the file called LICENSE.GPL. +* +* Contact Information: +*  Intel Linux Wireless <ilw@linux.intel.com> +* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +*****************************************************************************/ + +#include "iwl-agn-debugfs.h" + +ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, +				size_t count, loff_t *ppos) +  { +	struct iwl_priv *priv = file->private_data; +	int pos = 0; +	char *buf; +	int bufsz = sizeof(struct statistics_rx_phy) * 40 + +		    sizeof(struct statistics_rx_non_phy) * 40 + +		    sizeof(struct statistics_rx_ht_phy) * 40 + 400; +	ssize_t ret; +	struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; +	struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; +	struct statistics_rx_non_phy *general, *accum_general; +	struct statistics_rx_non_phy *delta_general, *max_general; +	struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; + +	if (!iwl_is_alive(priv)) +		return -EAGAIN; + +	buf = kzalloc(bufsz, GFP_KERNEL); +	if (!buf) { +		IWL_ERR(priv, "Can not allocate Buffer\n"); +		return -ENOMEM; +	} + +	/* +	 * the statistic information display here is based on +	 * the last statistics notification from uCode +	 * might not reflect the current uCode activity +	 */ +	ofdm = &priv->statistics.rx.ofdm; +	cck = &priv->statistics.rx.cck; +	general = &priv->statistics.rx.general; +	ht = &priv->statistics.rx.ofdm_ht; +	accum_ofdm = &priv->accum_statistics.rx.ofdm; +	accum_cck = &priv->accum_statistics.rx.cck; +	accum_general = &priv->accum_statistics.rx.general; +	accum_ht = &priv->accum_statistics.rx.ofdm_ht; +	delta_ofdm = &priv->delta_statistics.rx.ofdm; +	delta_cck = &priv->delta_statistics.rx.cck; +	delta_general = &priv->delta_statistics.rx.general; +	delta_ht = &priv->delta_statistics.rx.ofdm_ht; +	max_ofdm = &priv->max_delta.rx.ofdm; +	max_cck = &priv->max_delta.rx.cck; +	max_general = &priv->max_delta.rx.general; +	max_ht = &priv->max_delta.rx.ofdm_ht; + +	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); +	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_Rx - OFDM:"); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), +			 accum_ofdm->ina_cnt, +			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "fina_cnt:", +			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, +			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "plcp_err:", +			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, +			 delta_ofdm->plcp_err, max_ofdm->plcp_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "crc32_err:", +			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, +			 delta_ofdm->crc32_err, max_ofdm->crc32_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:", +			 le32_to_cpu(ofdm->overrun_err), +			 accum_ofdm->overrun_err, delta_ofdm->overrun_err, +			 max_ofdm->overrun_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "early_overrun_err:", +			 le32_to_cpu(ofdm->early_overrun_err), +			 accum_ofdm->early_overrun_err, +			 delta_ofdm->early_overrun_err, +			 max_ofdm->early_overrun_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "crc32_good:", le32_to_cpu(ofdm->crc32_good), +			 accum_ofdm->crc32_good, delta_ofdm->crc32_good, +			 max_ofdm->crc32_good); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:", +			 le32_to_cpu(ofdm->false_alarm_cnt), +			 accum_ofdm->false_alarm_cnt, +			 delta_ofdm->false_alarm_cnt, +			 max_ofdm->false_alarm_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "fina_sync_err_cnt:", +			 le32_to_cpu(ofdm->fina_sync_err_cnt), +			 accum_ofdm->fina_sync_err_cnt, +			 delta_ofdm->fina_sync_err_cnt, +			 max_ofdm->fina_sync_err_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "sfd_timeout:", +			 le32_to_cpu(ofdm->sfd_timeout), +			 accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout, +			 max_ofdm->sfd_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "fina_timeout:", +			 le32_to_cpu(ofdm->fina_timeout), +			 accum_ofdm->fina_timeout, delta_ofdm->fina_timeout, +			 max_ofdm->fina_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "unresponded_rts:", +			 le32_to_cpu(ofdm->unresponded_rts), +			 accum_ofdm->unresponded_rts, +			 delta_ofdm->unresponded_rts, +			 max_ofdm->unresponded_rts); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "rxe_frame_lmt_ovrun:", +			 le32_to_cpu(ofdm->rxe_frame_limit_overrun), +			 accum_ofdm->rxe_frame_limit_overrun, +			 delta_ofdm->rxe_frame_limit_overrun, +			 max_ofdm->rxe_frame_limit_overrun); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "sent_ack_cnt:", +			 le32_to_cpu(ofdm->sent_ack_cnt), +			 accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt, +			 max_ofdm->sent_ack_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "sent_cts_cnt:", +			 le32_to_cpu(ofdm->sent_cts_cnt), +			 accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt, +			 max_ofdm->sent_cts_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "sent_ba_rsp_cnt:", +			 le32_to_cpu(ofdm->sent_ba_rsp_cnt), +			 accum_ofdm->sent_ba_rsp_cnt, +			 delta_ofdm->sent_ba_rsp_cnt, +			 max_ofdm->sent_ba_rsp_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "dsp_self_kill:", +			 le32_to_cpu(ofdm->dsp_self_kill), +			 accum_ofdm->dsp_self_kill, +			 delta_ofdm->dsp_self_kill, +			 max_ofdm->dsp_self_kill); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "mh_format_err:", +			 le32_to_cpu(ofdm->mh_format_err), +			 accum_ofdm->mh_format_err, +			 delta_ofdm->mh_format_err, +			 max_ofdm->mh_format_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "re_acq_main_rssi_sum:", +			 le32_to_cpu(ofdm->re_acq_main_rssi_sum), +			 accum_ofdm->re_acq_main_rssi_sum, +			 delta_ofdm->re_acq_main_rssi_sum, +			 max_ofdm->re_acq_main_rssi_sum); + +	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_Rx - CCK:"); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "ina_cnt:", +			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, +			 delta_cck->ina_cnt, max_cck->ina_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "fina_cnt:", +			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, +			 delta_cck->fina_cnt, max_cck->fina_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "plcp_err:", +			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, +			 delta_cck->plcp_err, max_cck->plcp_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "crc32_err:", +			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, +			 delta_cck->crc32_err, max_cck->crc32_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "overrun_err:", +			 le32_to_cpu(cck->overrun_err), +			 accum_cck->overrun_err, delta_cck->overrun_err, +			 max_cck->overrun_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "early_overrun_err:", +			 le32_to_cpu(cck->early_overrun_err), +			 accum_cck->early_overrun_err, +			 delta_cck->early_overrun_err, +			 max_cck->early_overrun_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "crc32_good:", +			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, +			 delta_cck->crc32_good, max_cck->crc32_good); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "false_alarm_cnt:", +			 le32_to_cpu(cck->false_alarm_cnt), +			 accum_cck->false_alarm_cnt, +			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "fina_sync_err_cnt:", +			 le32_to_cpu(cck->fina_sync_err_cnt), +			 accum_cck->fina_sync_err_cnt, +			 delta_cck->fina_sync_err_cnt, +			 max_cck->fina_sync_err_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "sfd_timeout:", +			 le32_to_cpu(cck->sfd_timeout), +			 accum_cck->sfd_timeout, delta_cck->sfd_timeout, +			 max_cck->sfd_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "fina_timeout:", +			 le32_to_cpu(cck->fina_timeout), +			 accum_cck->fina_timeout, delta_cck->fina_timeout, +			 max_cck->fina_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "unresponded_rts:", +			 le32_to_cpu(cck->unresponded_rts), +			 accum_cck->unresponded_rts, delta_cck->unresponded_rts, +			 max_cck->unresponded_rts); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "rxe_frame_lmt_ovrun:", +			 le32_to_cpu(cck->rxe_frame_limit_overrun), +			 accum_cck->rxe_frame_limit_overrun, +			 delta_cck->rxe_frame_limit_overrun, +			 max_cck->rxe_frame_limit_overrun); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "sent_ack_cnt:", +			 le32_to_cpu(cck->sent_ack_cnt), +			 accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt, +			 max_cck->sent_ack_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "sent_cts_cnt:", +			 le32_to_cpu(cck->sent_cts_cnt), +			 accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt, +			 max_cck->sent_cts_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "sent_ba_rsp_cnt:", +			 le32_to_cpu(cck->sent_ba_rsp_cnt), +			 accum_cck->sent_ba_rsp_cnt, +			 delta_cck->sent_ba_rsp_cnt, +			 max_cck->sent_ba_rsp_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "dsp_self_kill:", +			 le32_to_cpu(cck->dsp_self_kill), +			 accum_cck->dsp_self_kill, delta_cck->dsp_self_kill, +			 max_cck->dsp_self_kill); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "mh_format_err:", +			 le32_to_cpu(cck->mh_format_err), +			 accum_cck->mh_format_err, delta_cck->mh_format_err, +			 max_cck->mh_format_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "re_acq_main_rssi_sum:", +			 le32_to_cpu(cck->re_acq_main_rssi_sum), +			 accum_cck->re_acq_main_rssi_sum, +			 delta_cck->re_acq_main_rssi_sum, +			 max_cck->re_acq_main_rssi_sum); + +	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_Rx - GENERAL:"); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "bogus_cts:", +			 le32_to_cpu(general->bogus_cts), +			 accum_general->bogus_cts, delta_general->bogus_cts, +			 max_general->bogus_cts); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", "bogus_ack:", +			 le32_to_cpu(general->bogus_ack), +			 accum_general->bogus_ack, delta_general->bogus_ack, +			 max_general->bogus_ack); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "non_bssid_frames:", +			 le32_to_cpu(general->non_bssid_frames), +			 accum_general->non_bssid_frames, +			 delta_general->non_bssid_frames, +			 max_general->non_bssid_frames); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "filtered_frames:", +			 le32_to_cpu(general->filtered_frames), +			 accum_general->filtered_frames, +			 delta_general->filtered_frames, +			 max_general->filtered_frames); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "non_channel_beacons:", +			 le32_to_cpu(general->non_channel_beacons), +			 accum_general->non_channel_beacons, +			 delta_general->non_channel_beacons, +			 max_general->non_channel_beacons); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "channel_beacons:", +			 le32_to_cpu(general->channel_beacons), +			 accum_general->channel_beacons, +			 delta_general->channel_beacons, +			 max_general->channel_beacons); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "num_missed_bcon:", +			 le32_to_cpu(general->num_missed_bcon), +			 accum_general->num_missed_bcon, +			 delta_general->num_missed_bcon, +			 max_general->num_missed_bcon); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "adc_rx_saturation_time:", +			 le32_to_cpu(general->adc_rx_saturation_time), +			 accum_general->adc_rx_saturation_time, +			 delta_general->adc_rx_saturation_time, +			 max_general->adc_rx_saturation_time); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "ina_detect_search_tm:", +			 le32_to_cpu(general->ina_detection_search_time), +			 accum_general->ina_detection_search_time, +			 delta_general->ina_detection_search_time, +			 max_general->ina_detection_search_time); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "beacon_silence_rssi_a:", +			 le32_to_cpu(general->beacon_silence_rssi_a), +			 accum_general->beacon_silence_rssi_a, +			 delta_general->beacon_silence_rssi_a, +			 max_general->beacon_silence_rssi_a); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "beacon_silence_rssi_b:", +			 le32_to_cpu(general->beacon_silence_rssi_b), +			 accum_general->beacon_silence_rssi_b, +			 delta_general->beacon_silence_rssi_b, +			 max_general->beacon_silence_rssi_b); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "beacon_silence_rssi_c:", +			 le32_to_cpu(general->beacon_silence_rssi_c), +			 accum_general->beacon_silence_rssi_c, +			 delta_general->beacon_silence_rssi_c, +			 max_general->beacon_silence_rssi_c); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "interference_data_flag:", +			 le32_to_cpu(general->interference_data_flag), +			 accum_general->interference_data_flag, +			 delta_general->interference_data_flag, +			 max_general->interference_data_flag); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "channel_load:", +			 le32_to_cpu(general->channel_load), +			 accum_general->channel_load, +			 delta_general->channel_load, +			 max_general->channel_load); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "dsp_false_alarms:", +			 le32_to_cpu(general->dsp_false_alarms), +			 accum_general->dsp_false_alarms, +			 delta_general->dsp_false_alarms, +			 max_general->dsp_false_alarms); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "beacon_rssi_a:", +			 le32_to_cpu(general->beacon_rssi_a), +			 accum_general->beacon_rssi_a, +			 delta_general->beacon_rssi_a, +			 max_general->beacon_rssi_a); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "beacon_rssi_b:", +			 le32_to_cpu(general->beacon_rssi_b), +			 accum_general->beacon_rssi_b, +			 delta_general->beacon_rssi_b, +			 max_general->beacon_rssi_b); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "beacon_rssi_c:", +			 le32_to_cpu(general->beacon_rssi_c), +			 accum_general->beacon_rssi_c, +			 delta_general->beacon_rssi_c, +			 max_general->beacon_rssi_c); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "beacon_energy_a:", +			 le32_to_cpu(general->beacon_energy_a), +			 accum_general->beacon_energy_a, +			 delta_general->beacon_energy_a, +			 max_general->beacon_energy_a); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "beacon_energy_b:", +			 le32_to_cpu(general->beacon_energy_b), +			 accum_general->beacon_energy_b, +			 delta_general->beacon_energy_b, +			 max_general->beacon_energy_b); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "beacon_energy_c:", +			 le32_to_cpu(general->beacon_energy_c), +			 accum_general->beacon_energy_c, +			 delta_general->beacon_energy_c, +			 max_general->beacon_energy_c); + +	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); +	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_Rx - OFDM_HT:"); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "plcp_err:", +			 le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, +			 delta_ht->plcp_err, max_ht->plcp_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "overrun_err:", +			 le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, +			 delta_ht->overrun_err, max_ht->overrun_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "early_overrun_err:", +			 le32_to_cpu(ht->early_overrun_err), +			 accum_ht->early_overrun_err, +			 delta_ht->early_overrun_err, +			 max_ht->early_overrun_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "crc32_good:", +			 le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, +			 delta_ht->crc32_good, max_ht->crc32_good); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "crc32_err:", +			 le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, +			 delta_ht->crc32_err, max_ht->crc32_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "mh_format_err:", +			 le32_to_cpu(ht->mh_format_err), +			 accum_ht->mh_format_err, +			 delta_ht->mh_format_err, max_ht->mh_format_err); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg_crc32_good:", +			 le32_to_cpu(ht->agg_crc32_good), +			 accum_ht->agg_crc32_good, +			 delta_ht->agg_crc32_good, max_ht->agg_crc32_good); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg_mpdu_cnt:", +			 le32_to_cpu(ht->agg_mpdu_cnt), +			 accum_ht->agg_mpdu_cnt, +			 delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg_cnt:", +			 le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, +			 delta_ht->agg_cnt, max_ht->agg_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "unsupport_mcs:", +			 le32_to_cpu(ht->unsupport_mcs), +			 accum_ht->unsupport_mcs, +			 delta_ht->unsupport_mcs, max_ht->unsupport_mcs); + +	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); +	kfree(buf); +	return ret; +} + +ssize_t iwl_ucode_tx_stats_read(struct file *file, +				char __user *user_buf, +				size_t count, loff_t *ppos) +{ +	struct iwl_priv *priv = file->private_data; +	int pos = 0; +	char *buf; +	int bufsz = (sizeof(struct statistics_tx) * 48) + 250; +	ssize_t ret; +	struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; + +	if (!iwl_is_alive(priv)) +		return -EAGAIN; + +	buf = kzalloc(bufsz, GFP_KERNEL); +	if (!buf) { +		IWL_ERR(priv, "Can not allocate Buffer\n"); +		return -ENOMEM; +	} + +	/* the statistic information display here is based on +	  * the last statistics notification from uCode +	  * might not reflect the current uCode activity +	  */ +	tx = &priv->statistics.tx; +	accum_tx = &priv->accum_statistics.tx; +	delta_tx = &priv->delta_statistics.tx; +	max_tx = &priv->max_delta.tx; +	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); +	pos += scnprintf(buf + pos, bufsz - pos,  "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_Tx:"); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "preamble:", +			 le32_to_cpu(tx->preamble_cnt), +			 accum_tx->preamble_cnt, +			 delta_tx->preamble_cnt, max_tx->preamble_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "rx_detected_cnt:", +			 le32_to_cpu(tx->rx_detected_cnt), +			 accum_tx->rx_detected_cnt, +			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "bt_prio_defer_cnt:", +			 le32_to_cpu(tx->bt_prio_defer_cnt), +			 accum_tx->bt_prio_defer_cnt, +			 delta_tx->bt_prio_defer_cnt, +			 max_tx->bt_prio_defer_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "bt_prio_kill_cnt:", +			 le32_to_cpu(tx->bt_prio_kill_cnt), +			 accum_tx->bt_prio_kill_cnt, +			 delta_tx->bt_prio_kill_cnt, +			 max_tx->bt_prio_kill_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "few_bytes_cnt:", +			 le32_to_cpu(tx->few_bytes_cnt), +			 accum_tx->few_bytes_cnt, +			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "cts_timeout:", +			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, +			 delta_tx->cts_timeout, max_tx->cts_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "ack_timeout:", +			 le32_to_cpu(tx->ack_timeout), +			 accum_tx->ack_timeout, +			 delta_tx->ack_timeout, max_tx->ack_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "expected_ack_cnt:", +			 le32_to_cpu(tx->expected_ack_cnt), +			 accum_tx->expected_ack_cnt, +			 delta_tx->expected_ack_cnt, +			 max_tx->expected_ack_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "actual_ack_cnt:", +			 le32_to_cpu(tx->actual_ack_cnt), +			 accum_tx->actual_ack_cnt, +			 delta_tx->actual_ack_cnt, +			 max_tx->actual_ack_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "dump_msdu_cnt:", +			 le32_to_cpu(tx->dump_msdu_cnt), +			 accum_tx->dump_msdu_cnt, +			 delta_tx->dump_msdu_cnt, +			 max_tx->dump_msdu_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "abort_nxt_frame_mismatch:", +			 le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), +			 accum_tx->burst_abort_next_frame_mismatch_cnt, +			 delta_tx->burst_abort_next_frame_mismatch_cnt, +			 max_tx->burst_abort_next_frame_mismatch_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "abort_missing_nxt_frame:", +			 le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), +			 accum_tx->burst_abort_missing_next_frame_cnt, +			 delta_tx->burst_abort_missing_next_frame_cnt, +			 max_tx->burst_abort_missing_next_frame_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "cts_timeout_collision:", +			 le32_to_cpu(tx->cts_timeout_collision), +			 accum_tx->cts_timeout_collision, +			 delta_tx->cts_timeout_collision, +			 max_tx->cts_timeout_collision); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "ack_ba_timeout_collision:", +			 le32_to_cpu(tx->ack_or_ba_timeout_collision), +			 accum_tx->ack_or_ba_timeout_collision, +			 delta_tx->ack_or_ba_timeout_collision, +			 max_tx->ack_or_ba_timeout_collision); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg ba_timeout:", +			 le32_to_cpu(tx->agg.ba_timeout), +			 accum_tx->agg.ba_timeout, +			 delta_tx->agg.ba_timeout, +			 max_tx->agg.ba_timeout); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg ba_resched_frames:", +			 le32_to_cpu(tx->agg.ba_reschedule_frames), +			 accum_tx->agg.ba_reschedule_frames, +			 delta_tx->agg.ba_reschedule_frames, +			 max_tx->agg.ba_reschedule_frames); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg scd_query_agg_frame:", +			 le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), +			 accum_tx->agg.scd_query_agg_frame_cnt, +			 delta_tx->agg.scd_query_agg_frame_cnt, +			 max_tx->agg.scd_query_agg_frame_cnt); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg scd_query_no_agg:", +			 le32_to_cpu(tx->agg.scd_query_no_agg), +			 accum_tx->agg.scd_query_no_agg, +			 delta_tx->agg.scd_query_no_agg, +			 max_tx->agg.scd_query_no_agg); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg scd_query_agg:", +			 le32_to_cpu(tx->agg.scd_query_agg), +			 accum_tx->agg.scd_query_agg, +			 delta_tx->agg.scd_query_agg, +			 max_tx->agg.scd_query_agg); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg scd_query_mismatch:", +			 le32_to_cpu(tx->agg.scd_query_mismatch), +			 accum_tx->agg.scd_query_mismatch, +			 delta_tx->agg.scd_query_mismatch, +			 max_tx->agg.scd_query_mismatch); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg frame_not_ready:", +			 le32_to_cpu(tx->agg.frame_not_ready), +			 accum_tx->agg.frame_not_ready, +			 delta_tx->agg.frame_not_ready, +			 max_tx->agg.frame_not_ready); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg underrun:", +			 le32_to_cpu(tx->agg.underrun), +			 accum_tx->agg.underrun, +			 delta_tx->agg.underrun, max_tx->agg.underrun); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg bt_prio_kill:", +			 le32_to_cpu(tx->agg.bt_prio_kill), +			 accum_tx->agg.bt_prio_kill, +			 delta_tx->agg.bt_prio_kill, +			 max_tx->agg.bt_prio_kill); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "agg rx_ba_rsp_cnt:", +			 le32_to_cpu(tx->agg.rx_ba_rsp_cnt), +			 accum_tx->agg.rx_ba_rsp_cnt, +			 delta_tx->agg.rx_ba_rsp_cnt, +			 max_tx->agg.rx_ba_rsp_cnt); + +	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); +	kfree(buf); +	return ret; +} + +ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, +				     size_t count, loff_t *ppos) +{ +	struct iwl_priv *priv = file->private_data; +	int pos = 0; +	char *buf; +	int bufsz = sizeof(struct statistics_general) * 10 + 300; +	ssize_t ret; +	struct statistics_general *general, *accum_general; +	struct statistics_general *delta_general, *max_general; +	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; +	struct statistics_div *div, *accum_div, *delta_div, *max_div; + +	if (!iwl_is_alive(priv)) +		return -EAGAIN; + +	buf = kzalloc(bufsz, GFP_KERNEL); +	if (!buf) { +		IWL_ERR(priv, "Can not allocate Buffer\n"); +		return -ENOMEM; +	} + +	/* the statistic information display here is based on +	  * the last statistics notification from uCode +	  * might not reflect the current uCode activity +	  */ +	general = &priv->statistics.general; +	dbg = &priv->statistics.general.dbg; +	div = &priv->statistics.general.div; +	accum_general = &priv->accum_statistics.general; +	delta_general = &priv->delta_statistics.general; +	max_general = &priv->max_delta.general; +	accum_dbg = &priv->accum_statistics.general.dbg; +	delta_dbg = &priv->delta_statistics.general.dbg; +	max_dbg = &priv->max_delta.general.dbg; +	accum_div = &priv->accum_statistics.general.div; +	delta_div = &priv->delta_statistics.general.div; +	max_div = &priv->max_delta.general.div; +	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); +	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current" +			 "acumulative       delta         max\n", +			 "Statistics_General:"); +	pos += scnprintf(buf + pos, bufsz - pos, "  %-30s %10u\n", +			 "temperature:", +			 le32_to_cpu(general->temperature)); +	pos += scnprintf(buf + pos, bufsz - pos, "  %-30s %10u\n", +			 "temperature_m:", +			 le32_to_cpu(general->temperature_m)); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "burst_check:", +			 le32_to_cpu(dbg->burst_check), +			 accum_dbg->burst_check, +			 delta_dbg->burst_check, max_dbg->burst_check); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "burst_count:", +			 le32_to_cpu(dbg->burst_count), +			 accum_dbg->burst_count, +			 delta_dbg->burst_count, max_dbg->burst_count); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "sleep_time:", +			 le32_to_cpu(general->sleep_time), +			 accum_general->sleep_time, +			 delta_general->sleep_time, max_general->sleep_time); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "slots_out:", +			 le32_to_cpu(general->slots_out), +			 accum_general->slots_out, +			 delta_general->slots_out, max_general->slots_out); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "slots_idle:", +			 le32_to_cpu(general->slots_idle), +			 accum_general->slots_idle, +			 delta_general->slots_idle, max_general->slots_idle); +	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", +			 le32_to_cpu(general->ttl_timestamp)); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "tx_on_a:", +			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, +			 delta_div->tx_on_a, max_div->tx_on_a); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "tx_on_b:", +			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, +			 delta_div->tx_on_b, max_div->tx_on_b); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "exec_time:", +			 le32_to_cpu(div->exec_time), accum_div->exec_time, +			 delta_div->exec_time, max_div->exec_time); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "probe_time:", +			 le32_to_cpu(div->probe_time), accum_div->probe_time, +			 delta_div->probe_time, max_div->probe_time); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "rx_enable_counter:", +			 le32_to_cpu(general->rx_enable_counter), +			 accum_general->rx_enable_counter, +			 delta_general->rx_enable_counter, +			 max_general->rx_enable_counter); +	pos += scnprintf(buf + pos, bufsz - pos, +			 "  %-30s %10u  %10u  %10u  %10u\n", +			 "num_of_sos_states:", +			 le32_to_cpu(general->num_of_sos_states), +			 accum_general->num_of_sos_states, +			 delta_general->num_of_sos_states, +			 max_general->num_of_sos_states); +	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); +	kfree(buf); +	return ret; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h new file mode 100644 index 00000000000..59b1f25f0d8 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + *  Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-debug.h" + +#ifdef CONFIG_IWLWIFI_DEBUGFS +ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, +				size_t count, loff_t *ppos); +ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, +				size_t count, loff_t *ppos); +ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, +				     size_t count, loff_t *ppos); +#else +static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, +				       size_t count, loff_t *ppos) +{ +	return 0; +} +static ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, +				       size_t count, loff_t *ppos) +{ +	return 0; +} +static ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, +					    size_t count, loff_t *ppos) +{ +	return 0; +} +#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 28bc8f8ba98..44ef5d93bef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -262,6 +262,7 @@ struct iwl_hcmd_ops iwlagn_hcmd = {  	.commit_rxon = iwl_commit_rxon,  	.set_rxon_chain = iwl_set_rxon_chain,  	.set_tx_ant = iwlagn_send_tx_ant_config, +	.send_bt_config = iwl_send_bt_config,  };  struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { @@ -271,4 +272,5 @@ struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {  	.chain_noise_reset = iwlagn_chain_noise_reset,  	.rts_tx_cmd_flag = iwlagn_rts_tx_cmd_flag,  	.calc_rssi = iwlagn_calc_rssi, +	.request_scan = iwlagn_request_scan,  }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index c465c859083..a2734742596 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -331,7 +331,7 @@ u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)  	} *hdr;  	hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, -							EEPROM_5000_CALIB_ALL); +							EEPROM_CALIB_ALL);  	return hdr->version;  } @@ -348,22 +348,22 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)  	switch (address & INDIRECT_TYPE_MSK) {  	case INDIRECT_HOST: -		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); +		offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST);  		break;  	case INDIRECT_GENERAL: -		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); +		offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL);  		break;  	case INDIRECT_REGULATORY: -		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); +		offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY);  		break;  	case INDIRECT_CALIBRATION: -		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); +		offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION);  		break;  	case INDIRECT_PROCESS_ADJST: -		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); +		offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST);  		break;  	case INDIRECT_OTHERS: -		offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); +		offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS);  		break;  	default:  		IWL_ERR(priv, "illegal indirect type: 0x%X\n", @@ -1111,3 +1111,405 @@ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,  	memcpy(&priv->_agn.last_phy_res, pkt->u.raw,  	       sizeof(struct iwl_rx_phy_res));  } + +static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, +				     enum ieee80211_band band, +				     struct iwl_scan_channel *scan_ch) +{ +	const struct ieee80211_supported_band *sband; +	const struct iwl_channel_info *ch_info; +	u16 passive_dwell = 0; +	u16 active_dwell = 0; +	int i, added = 0; +	u16 channel = 0; + +	sband = iwl_get_hw_mode(priv, band); +	if (!sband) { +		IWL_ERR(priv, "invalid band\n"); +		return added; +	} + +	active_dwell = iwl_get_active_dwell_time(priv, band, 0); +	passive_dwell = iwl_get_passive_dwell_time(priv, band); + +	if (passive_dwell <= active_dwell) +		passive_dwell = active_dwell + 1; + +	/* only scan single channel, good enough to reset the RF */ +	/* pick the first valid not in-use channel */ +	if (band == IEEE80211_BAND_5GHZ) { +		for (i = 14; i < priv->channel_count; i++) { +			if (priv->channel_info[i].channel != +			    le16_to_cpu(priv->staging_rxon.channel)) { +				channel = priv->channel_info[i].channel; +				ch_info = iwl_get_channel_info(priv, +					band, channel); +				if (is_channel_valid(ch_info)) +					break; +			} +		} +	} else { +		for (i = 0; i < 14; i++) { +			if (priv->channel_info[i].channel != +			    le16_to_cpu(priv->staging_rxon.channel)) { +					channel = +						priv->channel_info[i].channel; +					ch_info = iwl_get_channel_info(priv, +						band, channel); +					if (is_channel_valid(ch_info)) +						break; +			} +		} +	} +	if (channel) { +		scan_ch->channel = cpu_to_le16(channel); +		scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; +		scan_ch->active_dwell = cpu_to_le16(active_dwell); +		scan_ch->passive_dwell = cpu_to_le16(passive_dwell); +		/* Set txpower levels to defaults */ +		scan_ch->dsp_atten = 110; +		if (band == IEEE80211_BAND_5GHZ) +			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; +		else +			scan_ch->tx_gain = ((1 << 5) | (5 << 3)); +		added++; +	} else +		IWL_ERR(priv, "no valid channel found\n"); +	return added; +} + +static int iwl_get_channels_for_scan(struct iwl_priv *priv, +				     enum ieee80211_band band, +				     u8 is_active, u8 n_probes, +				     struct iwl_scan_channel *scan_ch) +{ +	struct ieee80211_channel *chan; +	const struct ieee80211_supported_band *sband; +	const struct iwl_channel_info *ch_info; +	u16 passive_dwell = 0; +	u16 active_dwell = 0; +	int added, i; +	u16 channel; + +	sband = iwl_get_hw_mode(priv, band); +	if (!sband) +		return 0; + +	active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); +	passive_dwell = iwl_get_passive_dwell_time(priv, band); + +	if (passive_dwell <= active_dwell) +		passive_dwell = active_dwell + 1; + +	for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { +		chan = priv->scan_request->channels[i]; + +		if (chan->band != band) +			continue; + +		channel = ieee80211_frequency_to_channel(chan->center_freq); +		scan_ch->channel = cpu_to_le16(channel); + +		ch_info = iwl_get_channel_info(priv, band, channel); +		if (!is_channel_valid(ch_info)) { +			IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", +					channel); +			continue; +		} + +		if (!is_active || is_channel_passive(ch_info) || +		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) +			scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; +		else +			scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; + +		if (n_probes) +			scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); + +		scan_ch->active_dwell = cpu_to_le16(active_dwell); +		scan_ch->passive_dwell = cpu_to_le16(passive_dwell); + +		/* Set txpower levels to defaults */ +		scan_ch->dsp_atten = 110; + +		/* NOTE: if we were doing 6Mb OFDM for scans we'd use +		 * power level: +		 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; +		 */ +		if (band == IEEE80211_BAND_5GHZ) +			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; +		else +			scan_ch->tx_gain = ((1 << 5) | (5 << 3)); + +		IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", +			       channel, le32_to_cpu(scan_ch->type), +			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? +				"ACTIVE" : "PASSIVE", +			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? +			       active_dwell : passive_dwell); + +		scan_ch++; +		added++; +	} + +	IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); +	return added; +} + +void iwlagn_request_scan(struct iwl_priv *priv) +{ +	struct iwl_host_cmd cmd = { +		.id = REPLY_SCAN_CMD, +		.len = sizeof(struct iwl_scan_cmd), +		.flags = CMD_SIZE_HUGE, +	}; +	struct iwl_scan_cmd *scan; +	struct ieee80211_conf *conf = NULL; +	u32 rate_flags = 0; +	u16 cmd_len; +	u16 rx_chain = 0; +	enum ieee80211_band band; +	u8 n_probes = 0; +	u8 rx_ant = priv->hw_params.valid_rx_ant; +	u8 rate; +	bool is_active = false; +	int  chan_mod; +	u8 active_chains; + +	conf = ieee80211_get_hw_conf(priv->hw); + +	cancel_delayed_work(&priv->scan_check); + +	if (!iwl_is_ready(priv)) { +		IWL_WARN(priv, "request scan called when driver not ready.\n"); +		goto done; +	} + +	/* Make sure the scan wasn't canceled before this queued work +	 * was given the chance to run... */ +	if (!test_bit(STATUS_SCANNING, &priv->status)) +		goto done; + +	/* This should never be called or scheduled if there is currently +	 * a scan active in the hardware. */ +	if (test_bit(STATUS_SCAN_HW, &priv->status)) { +		IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " +			       "Ignoring second request.\n"); +		goto done; +	} + +	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { +		IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); +		goto done; +	} + +	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { +		IWL_DEBUG_HC(priv, "Scan request while abort pending.  Queuing.\n"); +		goto done; +	} + +	if (iwl_is_rfkill(priv)) { +		IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); +		goto done; +	} + +	if (!test_bit(STATUS_READY, &priv->status)) { +		IWL_DEBUG_HC(priv, "Scan request while uninitialized.  Queuing.\n"); +		goto done; +	} + +	if (!priv->scan_cmd) { +		priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + +					 IWL_MAX_SCAN_SIZE, GFP_KERNEL); +		if (!priv->scan_cmd) { +			IWL_DEBUG_SCAN(priv, +				       "fail to allocate memory for scan\n"); +			goto done; +		} +	} +	scan = priv->scan_cmd; +	memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); + +	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; +	scan->quiet_time = IWL_ACTIVE_QUIET_TIME; + +	if (iwl_is_associated(priv)) { +		u16 interval = 0; +		u32 extra; +		u32 suspend_time = 100; +		u32 scan_suspend_time = 100; +		unsigned long flags; + +		IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); +		spin_lock_irqsave(&priv->lock, flags); +		interval = priv->beacon_int; +		spin_unlock_irqrestore(&priv->lock, flags); + +		scan->suspend_time = 0; +		scan->max_out_time = cpu_to_le32(200 * 1024); +		if (!interval) +			interval = suspend_time; + +		extra = (suspend_time / interval) << 22; +		scan_suspend_time = (extra | +		    ((suspend_time % interval) * 1024)); +		scan->suspend_time = cpu_to_le32(scan_suspend_time); +		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", +			       scan_suspend_time, interval); +	} + +	if (priv->is_internal_short_scan) { +		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); +	} else if (priv->scan_request->n_ssids) { +		int i, p = 0; +		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); +		for (i = 0; i < priv->scan_request->n_ssids; i++) { +			/* always does wildcard anyway */ +			if (!priv->scan_request->ssids[i].ssid_len) +				continue; +			scan->direct_scan[p].id = WLAN_EID_SSID; +			scan->direct_scan[p].len = +				priv->scan_request->ssids[i].ssid_len; +			memcpy(scan->direct_scan[p].ssid, +			       priv->scan_request->ssids[i].ssid, +			       priv->scan_request->ssids[i].ssid_len); +			n_probes++; +			p++; +		} +		is_active = true; +	} else +		IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); + +	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; +	scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; +	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; + +	switch (priv->scan_band) { +	case IEEE80211_BAND_2GHZ: +		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; +		chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) +				       >> RXON_FLG_CHANNEL_MODE_POS; +		if (chan_mod == CHANNEL_MODE_PURE_40) { +			rate = IWL_RATE_6M_PLCP; +		} else { +			rate = IWL_RATE_1M_PLCP; +			rate_flags = RATE_MCS_CCK_MSK; +		} +		scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; +		break; +	case IEEE80211_BAND_5GHZ: +		rate = IWL_RATE_6M_PLCP; +		/* +		 * If active scanning is requested but a certain channel is +		 * marked passive, we can do active scanning if we detect +		 * transmissions. +		 * +		 * There is an issue with some firmware versions that triggers +		 * a sysassert on a "good CRC threshold" of zero (== disabled), +		 * on a radar channel even though this means that we should NOT +		 * send probes. +		 * +		 * The "good CRC threshold" is the number of frames that we +		 * need to receive during our dwell time on a channel before +		 * sending out probes -- setting this to a huge value will +		 * mean we never reach it, but at the same time work around +		 * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER +		 * here instead of IWL_GOOD_CRC_TH_DISABLED. +		 */ +		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : +						IWL_GOOD_CRC_TH_NEVER; +		break; +	default: +		IWL_WARN(priv, "Invalid scan band count\n"); +		goto done; +	} + +	band = priv->scan_band; + +	if (priv->cfg->scan_antennas[band]) +		rx_ant = priv->cfg->scan_antennas[band]; + +	priv->scan_tx_ant[band] = +			iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); +	rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); +	scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); + +	/* In power save mode use one chain, otherwise use all chains */ +	if (test_bit(STATUS_POWER_PMI, &priv->status)) { +		/* rx_ant has been set to all valid chains previously */ +		active_chains = rx_ant & +				((u8)(priv->chain_noise_data.active_chains)); +		if (!active_chains) +			active_chains = rx_ant; + +		IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", +				priv->chain_noise_data.active_chains); + +		rx_ant = first_antenna(active_chains); +	} +	/* MIMO is not used here, but value is required */ +	rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; +	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; +	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; +	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; +	scan->rx_chain = cpu_to_le16(rx_chain); +	if (!priv->is_internal_short_scan) { +		cmd_len = iwl_fill_probe_req(priv, +					(struct ieee80211_mgmt *)scan->data, +					priv->scan_request->ie, +					priv->scan_request->ie_len, +					IWL_MAX_SCAN_SIZE - sizeof(*scan)); +	} else { +		cmd_len = iwl_fill_probe_req(priv, +					(struct ieee80211_mgmt *)scan->data, +					NULL, 0, +					IWL_MAX_SCAN_SIZE - sizeof(*scan)); + +	} +	scan->tx_cmd.len = cpu_to_le16(cmd_len); + +	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | +			       RXON_FILTER_BCON_AWARE_MSK); + +	if (priv->is_internal_short_scan) { +		scan->channel_count = +			iwl_get_single_channel_for_scan(priv, band, +				(void *)&scan->data[le16_to_cpu( +				scan->tx_cmd.len)]); +	} else { +		scan->channel_count = +			iwl_get_channels_for_scan(priv, band, +				is_active, n_probes, +				(void *)&scan->data[le16_to_cpu( +				scan->tx_cmd.len)]); +	} +	if (scan->channel_count == 0) { +		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); +		goto done; +	} + +	cmd.len += le16_to_cpu(scan->tx_cmd.len) + +	    scan->channel_count * sizeof(struct iwl_scan_channel); +	cmd.data = scan; +	scan->len = cpu_to_le16(cmd.len); + +	set_bit(STATUS_SCAN_HW, &priv->status); +	if (iwl_send_cmd_sync(priv, &cmd)) +		goto done; + +	queue_delayed_work(priv->workqueue, &priv->scan_check, +			   IWL_SCAN_CHECK_WATCHDOG); + +	return; + + done: +	/* Cannot perform scan. Make sure we clear scanning +	* bits from status so next scan request can be performed. +	* If we don't clear scanning status bit here all next scan +	* will fail +	*/ +	clear_bit(STATUS_SCAN_HW, &priv->status); +	clear_bit(STATUS_SCANNING, &priv->status); +	/* inform mac80211 scan aborted */ +	queue_work(priv->workqueue, &priv->scan_completed); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index f7d85a2173c..bfcac5608d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -295,11 +295,11 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)  	return tl->total;  } -static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, +static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,  				      struct iwl_lq_sta *lq_data, u8 tid,  				      struct ieee80211_sta *sta)  { -	int ret; +	int ret = -EAGAIN;  	if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {  		IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", @@ -313,29 +313,29 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,  			 */  			IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",  				tid); -			ret = ieee80211_stop_tx_ba_session(sta, tid, +			ieee80211_stop_tx_ba_session(sta, tid,  						WLAN_BACK_INITIATOR);  		} -	} +	} else +		IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); +	return ret;  }  static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,  			      struct iwl_lq_sta *lq_data,  			      struct ieee80211_sta *sta)  { -	if ((tid < TID_MAX_LOAD_COUNT)) -		rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); -	else if (tid == IWL_AGG_ALL_TID) -		for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) -			rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); -	if (priv->cfg->use_rts_for_ht) { -		/* -		 * switch to RTS/CTS if it is the prefer protection method -		 * for HT traffic -		 */ -		IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); -		priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; -		iwlcore_commit_rxon(priv); +	if ((tid < TID_MAX_LOAD_COUNT) && +	    !rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) { +		if (priv->cfg->use_rts_for_ht) { +			/* +			 * switch to RTS/CTS if it is the prefer protection +			 * method for HT traffic +			 */ +			IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); +			priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; +			iwlcore_commit_rxon(priv); +		}  	}  } @@ -868,14 +868,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,  		rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,  				&rs_index);  		rs_collect_tx_data(curr_tbl, rs_index, -				   info->status.ampdu_ack_len, -				   info->status.ampdu_ack_map); +				   info->status.ampdu_len, +				   info->status.ampdu_ack_len);  		/* Update success/fail counts if not searching for new mode */  		if (lq_sta->stay_in_tbl) { -			lq_sta->total_success += info->status.ampdu_ack_map; -			lq_sta->total_failed += (info->status.ampdu_ack_len - -					info->status.ampdu_ack_map); +			lq_sta->total_success += info->status.ampdu_ack_len; +			lq_sta->total_failed += (info->status.ampdu_len - +					info->status.ampdu_ack_len);  		}  	} else {  	/* @@ -2078,10 +2078,12 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,  	}  	/* Else we have enough samples; calculate estimate of  	 * actual average throughput */ - -	/* Sanity-check TPT calculations */ -	BUG_ON(window->average_tpt != ((window->success_ratio * -			tbl->expected_tpt[index] + 64) / 128)); +	if (window->average_tpt != ((window->success_ratio * +			tbl->expected_tpt[index] + 64) / 128)) { +		IWL_ERR(priv, "expected_tpt should have been calculated by now\n"); +		window->average_tpt = ((window->success_ratio * +					tbl->expected_tpt[index] + 64) / 128); +	}  	/* If we are searching for better modulation mode, check success. */  	if (lq_sta->search_better_tbl && @@ -2558,8 +2560,17 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i  		     lq_sta->active_mimo3_rate);  	/* These values will be overridden later */ -	lq_sta->lq.general_params.single_stream_ant_msk = ANT_A; -	lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; +	lq_sta->lq.general_params.single_stream_ant_msk = +		first_antenna(priv->hw_params.valid_tx_ant); +	lq_sta->lq.general_params.dual_stream_ant_msk = +		priv->hw_params.valid_tx_ant & +		~first_antenna(priv->hw_params.valid_tx_ant); +	if (!lq_sta->lq.general_params.dual_stream_ant_msk) { +		lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; +	} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { +		lq_sta->lq.general_params.dual_stream_ant_msk = +			priv->hw_params.valid_tx_ant; +	}  	/* as default allow aggregation for all tids */  	lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 3077eac5888..c2a5c85542b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -83,6 +83,15 @@ static inline int get_fifo_from_ac(u8 ac)  	return ac_to_fifo[ac];  } +static inline int get_ac_from_tid(u16 tid) +{ +	if (likely(tid < ARRAY_SIZE(tid_to_ac))) +		return tid_to_ac[tid]; + +	/* no support for TIDs 8-15 yet */ +	return -EINVAL; +} +  static inline int get_fifo_from_tid(u16 tid)  {  	if (likely(tid < ARRAY_SIZE(tid_to_ac))) @@ -167,7 +176,7 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,  	scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;  	tbl_dw_addr = priv->scd_base_addr + -			IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); +			IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);  	tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); @@ -186,9 +195,9 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)  	/* Simply stop the queue, but don't change any configuration;  	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */  	iwl_write_prph(priv, -		IWL50_SCD_QUEUE_STATUS_BITS(txq_id), -		(0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| -		(1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); +		IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id), +		(0 << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE)| +		(1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));  }  void iwlagn_set_wr_ptrs(struct iwl_priv *priv, @@ -196,7 +205,7 @@ void iwlagn_set_wr_ptrs(struct iwl_priv *priv,  {  	iwl_write_direct32(priv, HBUS_TARG_WRPTR,  			(index & 0xff) | (txq_id << 8)); -	iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index); +	iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(txq_id), index);  }  void iwlagn_tx_queue_set_status(struct iwl_priv *priv, @@ -206,11 +215,11 @@ void iwlagn_tx_queue_set_status(struct iwl_priv *priv,  	int txq_id = txq->q.id;  	int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; -	iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), -			(active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | -			(tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) | -			(1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) | -			IWL50_SCD_QUEUE_STTS_REG_MSK); +	iwl_write_prph(priv, IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id), +			(active << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE) | +			(tx_fifo_id << IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF) | +			(1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL) | +			IWLAGN_SCD_QUEUE_STTS_REG_MSK);  	txq->sched_retry = scd_retry; @@ -250,10 +259,10 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,  	iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id);  	/* Set this queue as a chain-building queue */ -	iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<<txq_id)); +	iwl_set_bits_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, (1<<txq_id));  	/* enable aggregations for the queue */ -	iwl_set_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1<<txq_id)); +	iwl_set_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1<<txq_id));  	/* Place first TFD at index corresponding to start sequence number.  	 * Assumes that ssn_idx is valid (!= 0xFFF) */ @@ -263,16 +272,16 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,  	/* Set up Tx window size and frame limit for this queue */  	iwl_write_targ_mem(priv, priv->scd_base_addr + -			IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + +			IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) +  			sizeof(u32),  			((SCD_WIN_SIZE << -			IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & -			IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | +			IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & +			IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |  			((SCD_FRAME_LIMIT << -			IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & -			IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); +			IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & +			IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); -	iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); +	iwl_set_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id));  	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */  	iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); @@ -298,14 +307,14 @@ int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,  	iwlagn_tx_queue_stop_scheduler(priv, txq_id); -	iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); +	iwl_clear_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1 << txq_id));  	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);  	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);  	/* supposes that ssn_idx is valid (!= 0xFFF) */  	iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); -	iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); +	iwl_clear_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id));  	iwl_txq_ctx_deactivate(priv, txq_id);  	iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); @@ -318,7 +327,7 @@ int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,   */  void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask)  { -	iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); +	iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask);  }  static inline int get_queue_from_ac(u16 ac) @@ -991,7 +1000,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)  	tid_data = &priv->stations[sta_id].tid[tid];  	*ssn = SEQ_TO_SN(tid_data->seq_number);  	tid_data->agg.txq_id = txq_id; -	priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id); +	priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(get_ac_from_tid(tid), txq_id);  	spin_unlock_irqrestore(&priv->sta_lock, flags);  	ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, @@ -1224,8 +1233,9 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,  	memset(&info->status, 0, sizeof(info->status));  	info->flags |= IEEE80211_TX_STAT_ACK;  	info->flags |= IEEE80211_TX_STAT_AMPDU; -	info->status.ampdu_ack_map = successes; -	info->status.ampdu_ack_len = agg->frame_count; +	info->status.ampdu_ack_len = successes; +	info->status.ampdu_ack_map = bitmap; +	info->status.ampdu_len = agg->frame_count;  	iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);  	IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 52ae157968b..ae476c234a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -207,7 +207,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)  {  	struct iwl_calib_xtal_freq_cmd cmd;  	__le16 *xtal_calib = -		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); +		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL);  	cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;  	cmd.hdr.first_group = 0; @@ -329,19 +329,19 @@ int iwlagn_alive_notify(struct iwl_priv *priv)  	spin_lock_irqsave(&priv->lock, flags); -	priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); -	a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; -	for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; +	priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR); +	a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_DATA_OFFSET; +	for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_BITMAP_OFFSET;  		a += 4)  		iwl_write_targ_mem(priv, a, 0); -	for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; +	for (; a < priv->scd_base_addr + IWLAGN_SCD_TRANSLATE_TBL_OFFSET;  		a += 4)  		iwl_write_targ_mem(priv, a, 0);  	for (; a < priv->scd_base_addr + -	       IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) +	       IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)  		iwl_write_targ_mem(priv, a, 0); -	iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, +	iwl_write_prph(priv, IWLAGN_SCD_DRAM_BASE_ADDR,  		       priv->scd_bc_tbls.dma >> 10);  	/* Enable DMA channel */ @@ -355,28 +355,28 @@ int iwlagn_alive_notify(struct iwl_priv *priv)  	iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,  			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); -	iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, -		IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); -	iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); +	iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, +		IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); +	iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);  	/* initiate the queues */  	for (i = 0; i < priv->hw_params.max_txq_num; i++) { -		iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0); +		iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(i), 0);  		iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));  		iwl_write_targ_mem(priv, priv->scd_base_addr + -				IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0); +				IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i), 0);  		iwl_write_targ_mem(priv, priv->scd_base_addr + -				IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) + +				IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i) +  				sizeof(u32),  				((SCD_WIN_SIZE << -				IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & -				IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | +				IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & +				IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |  				((SCD_FRAME_LIMIT << -				IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & -				IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); +				IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & +				IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));  	} -	iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, +	iwl_write_prph(priv, IWLAGN_SCD_INTERRUPT_MASK,  			IWL_MASK(0, priv->hw_params.max_txq_num));  	/* Activate all Tx DMA/FIFO channels */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0b497d4bc65..a672d3379cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2174,7 +2174,7 @@ static void iwl_alive_start(struct iwl_priv *priv)  	}  	/* Configure Bluetooth device coexistence support */ -	iwl_send_bt_config(priv); +	priv->cfg->ops->hcmd->send_bt_config(priv);  	iwl_reset_run_time_calib(priv); @@ -2654,7 +2654,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv)  	/* Tell mac80211 our characteristics */  	hw->flags = IEEE80211_HW_SIGNAL_DBM | -		    IEEE80211_HW_NOISE_DBM |  		    IEEE80211_HW_AMPDU_AGGREGATION |  		    IEEE80211_HW_SPECTRUM_MGMT; @@ -3002,18 +3001,6 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,  	return 0;  } -static int iwl_mac_get_stats(struct ieee80211_hw *hw, -			     struct ieee80211_low_level_stats *stats) -{ -	struct iwl_priv *priv = hw->priv; - -	priv = hw->priv; -	IWL_DEBUG_MAC80211(priv, "enter\n"); -	IWL_DEBUG_MAC80211(priv, "leave\n"); - -	return 0; -} -  static void iwl_mac_sta_notify(struct ieee80211_hw *hw,  			       struct ieee80211_vif *vif,  			       enum sta_notify_cmd cmd, @@ -3178,44 +3165,6 @@ static ssize_t store_tx_power(struct device *d,  static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); -static ssize_t show_statistics(struct device *d, -			       struct device_attribute *attr, char *buf) -{ -	struct iwl_priv *priv = dev_get_drvdata(d); -	u32 size = sizeof(struct iwl_notif_statistics); -	u32 len = 0, ofs = 0; -	u8 *data = (u8 *)&priv->statistics; -	int rc = 0; - -	if (!iwl_is_alive(priv)) -		return -EAGAIN; - -	mutex_lock(&priv->mutex); -	rc = iwl_send_statistics_request(priv, CMD_SYNC, false); -	mutex_unlock(&priv->mutex); - -	if (rc) { -		len = sprintf(buf, -			      "Error sending statistics request: 0x%08X\n", rc); -		return len; -	} - -	while (size && (PAGE_SIZE - len)) { -		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, -				   PAGE_SIZE - len, 1); -		len = strlen(buf); -		if (PAGE_SIZE - len) -			buf[len++] = '\n'; - -		ofs += 16; -		size -= min(size, 16U); -	} - -	return len; -} - -static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); -  static ssize_t show_rts_ht_protection(struct device *d,  			     struct device_attribute *attr, char *buf)  { @@ -3305,6 +3254,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)  	cancel_delayed_work_sync(&priv->init_alive_start);  	cancel_delayed_work(&priv->scan_check); +	cancel_work_sync(&priv->start_internal_scan);  	cancel_delayed_work(&priv->alive_start);  	cancel_work_sync(&priv->beacon_update);  	del_timer_sync(&priv->statistics_periodic); @@ -3400,11 +3350,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)  	iwl_calib_free_results(priv);  	iwlcore_free_geos(priv);  	iwl_free_channel_map(priv); -	kfree(priv->scan); +	kfree(priv->scan_cmd);  }  static struct attribute *iwl_sysfs_entries[] = { -	&dev_attr_statistics.attr,  	&dev_attr_temperature.attr,  	&dev_attr_tx_power.attr,  	&dev_attr_rts_ht_protection.attr, @@ -3429,7 +3378,6 @@ static struct ieee80211_ops iwl_hw_ops = {  	.configure_filter = iwl_configure_filter,  	.set_key = iwl_mac_set_key,  	.update_tkip_key = iwl_mac_update_tkip_key, -	.get_stats = iwl_mac_get_stats,  	.conf_tx = iwl_mac_conf_tx,  	.reset_tsf = iwl_mac_reset_tsf,  	.bss_info_changed = iwl_bss_info_changed, @@ -3835,7 +3783,12 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {  	{IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},  	{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},  	{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000i_g2_2agn_cfg)}, + +/* 6x00 Series Gen2 */ +	{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2_2agn_cfg)},  /* 6x50 WiFi/WiMax Series */  	{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 5d3142287e1..cfee9994383 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -171,4 +171,7 @@ static inline bool iwl_is_tx_success(u32 status)  	       (status == TX_STATUS_DIRECT_DONE);  } +/* scan */ +void iwlagn_request_scan(struct iwl_priv *priv); +  #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 0471c3f8713..f1fd00b1a65 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c @@ -808,6 +808,18 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,  		}  	} +	/* +	 * The above algorithm sometimes fails when the ucode +	 * reports 0 for all chains. It's not clear why that +	 * happens to start with, but it is then causing trouble +	 * because this can make us enable more chains than the +	 * hardware really has. +	 * +	 * To be safe, simply mask out any chains that we know +	 * are not on the device. +	 */ +	active_chains &= priv->hw_params.valid_rx_ant; +  	num_tx_chains = 0;  	for (i = 0; i < NUM_RX_CHAINS; i++) {  		/* loops on all the bits of diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index d830086ca19..0086019b7a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -1443,7 +1443,7 @@ struct iwl4965_rx_mpdu_res_start {  /* 1: Ignore Bluetooth priority for this frame.   * 0: Delay Tx until Bluetooth device is done (normal usage). */ -#define TX_CMD_FLG_BT_DIS_MSK cpu_to_le32(1 << 12) +#define TX_CMD_FLG_IGNORE_BT cpu_to_le32(1 << 12)  /* 1: uCode overrides sequence control field in MAC header.   * 0: Driver provides sequence control field in MAC header. @@ -2663,7 +2663,9 @@ struct iwl_ssid_ie {  #define PROBE_OPTION_MAX_3945		4  #define PROBE_OPTION_MAX		20  #define TX_CMD_LIFE_TIME_INFINITE	cpu_to_le32(0xFFFFFFFF) -#define IWL_GOOD_CRC_TH			cpu_to_le16(1) +#define IWL_GOOD_CRC_TH_DISABLED	0 +#define IWL_GOOD_CRC_TH_DEFAULT		cpu_to_le16(1) +#define IWL_GOOD_CRC_TH_NEVER		cpu_to_le16(0xffff)  #define IWL_MAX_SCAN_SIZE 1024  #define IWL_MAX_CMD_SIZE 4096  #define IWL_MAX_PROBE_REQUEST		200 diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 2a89747d347..4cdf4d3a9dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -829,19 +829,6 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap)  }  /** - * iwl_is_monitor_mode - Determine if interface in monitor mode - * - * priv->iw_mode is set in add_interface, but add_interface is - * never called for monitor mode. The only way mac80211 informs us about - * monitor mode is through configuring filters (call to configure_filter). - */ -bool iwl_is_monitor_mode(struct iwl_priv *priv) -{ -	return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK); -} -EXPORT_SYMBOL(iwl_is_monitor_mode); - -/**   * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image   *   * Selects how many and which Rx receivers/antennas/chains to use. @@ -884,19 +871,6 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)  	rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;  	rx_chain |= idle_rx_cnt  << RXON_RX_CHAIN_CNT_POS; -	/* copied from 'iwl_bg_request_scan()' */ -	/* Force use of chains B and C (0x6) for Rx -	 * Avoid A (0x1) for the device has off-channel reception on A-band. -	 * MIMO is not used here, but value is required */ -	if (iwl_is_monitor_mode(priv) && -	    !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && -	    priv->cfg->off_channel_workaround) { -		rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; -		rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; -		rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; -		rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; -	} -  	priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);  	if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) @@ -1480,7 +1454,7 @@ irqreturn_t iwl_isr_legacy(int irq, void *data)  }  EXPORT_SYMBOL(iwl_isr_legacy); -int iwl_send_bt_config(struct iwl_priv *priv) +void iwl_send_bt_config(struct iwl_priv *priv)  {  	struct iwl_bt_cmd bt_cmd = {  		.lead_time = BT_LEAD_TIME_DEF, @@ -1497,8 +1471,9 @@ int iwl_send_bt_config(struct iwl_priv *priv)  	IWL_DEBUG_INFO(priv, "BT coex %s\n",  		(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); -	return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, -				sizeof(struct iwl_bt_cmd), &bt_cmd); +	if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, +			     sizeof(struct iwl_bt_cmd), &bt_cmd)) +		IWL_ERR(priv, "failed to send BT Coex Config\n");  }  EXPORT_SYMBOL(iwl_send_bt_config); @@ -1868,7 +1843,6 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv)  	iwlcore_commit_rxon(priv);  } -#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)  void iwl_bss_info_changed(struct ieee80211_hw *hw,  			  struct ieee80211_vif *vif,  			  struct ieee80211_bss_conf *bss_conf, @@ -1989,14 +1963,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,  			iwl_led_associate(priv); -			/* -			 * We have just associated, don't start scan too early -			 * leave time for EAPOL exchange to complete. -			 * -			 * XXX: do this in mac80211 -			 */ -			priv->next_scan_jiffies = jiffies + -					IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;  			if (!iwl_is_rfkill(priv))  				priv->cfg->ops->lib->post_associate(priv);  		} else @@ -2151,10 +2117,6 @@ EXPORT_SYMBOL(iwl_mac_remove_interface);  /**   * iwl_mac_config - mac80211 config callback - * - * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to - * be set inappropriately and the driver currently sets the hardware up to - * use it whenever needed.   */  int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)  { @@ -2383,11 +2345,11 @@ EXPORT_SYMBOL(iwl_free_txq_mem);  int iwl_send_wimax_coex(struct iwl_priv *priv)  { -	struct iwl_wimax_coex_cmd uninitialized_var(coex_cmd); +	struct iwl_wimax_coex_cmd coex_cmd;  	if (priv->cfg->support_wimax_coexist) {  		/* UnMask wake up src at associated sleep */ -		coex_cmd.flags |= COEX_FLAGS_ASSOC_WA_UNMASK_MSK; +		coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;  		/* UnMask wake up src at unassociated sleep */  		coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; @@ -2802,7 +2764,6 @@ static void iwl_force_rf_reset(struct iwl_priv *priv)  	 */  	IWL_DEBUG_INFO(priv, "perform radio reset.\n");  	iwl_internal_short_hw_scan(priv); -	return;  } @@ -2970,6 +2931,12 @@ int iwl_pci_resume(struct pci_dev *pdev)  	struct iwl_priv *priv = pci_get_drvdata(pdev);  	int ret; +	/* +	 * We disable the RETRY_TIMEOUT register (0x41) to keep +	 * PCI Tx retries from interfering with C3 CPU state. +	 */ +	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); +  	pci_set_power_state(pdev, PCI_D0);  	ret = pci_enable_device(pdev);  	if (ret) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index d89755f5031..72736094485 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -90,6 +90,7 @@ struct iwl_hcmd_ops {  	int (*commit_rxon)(struct iwl_priv *priv);  	void (*set_rxon_chain)(struct iwl_priv *priv);  	int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant); +	void (*send_bt_config)(struct iwl_priv *priv);  };  struct iwl_hcmd_utils_ops { @@ -105,6 +106,7 @@ struct iwl_hcmd_utils_ops {  			__le32 *tx_flags);  	int  (*calc_rssi)(struct iwl_priv *priv,  			  struct iwl_rx_phy_res *rx_resp); +	void (*request_scan)(struct iwl_priv *priv);  };  struct iwl_apm_ops { @@ -114,6 +116,15 @@ struct iwl_apm_ops {  	int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);  }; +struct iwl_debugfs_ops { +	ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf, +				 size_t count, loff_t *ppos); +	ssize_t (*tx_stats_read)(struct file *file, char __user *user_buf, +				 size_t count, loff_t *ppos); +	ssize_t (*general_stats_read)(struct file *file, char __user *user_buf, +				      size_t count, loff_t *ppos); +}; +  struct iwl_temp_ops {  	void (*temperature)(struct iwl_priv *priv);  	void (*set_ct_kill)(struct iwl_priv *priv); @@ -199,6 +210,7 @@ struct iwl_lib_ops {  	/* check for ack health */  	bool (*check_ack_health)(struct iwl_priv *priv,  					struct iwl_rx_packet *pkt); +	struct iwl_debugfs_ops debugfs_ops;  };  struct iwl_led_ops { @@ -306,8 +318,8 @@ struct iwl_cfg {  	/* timer period for monitor the driver queues */  	u32 monitor_recover_period;  	bool temperature_kelvin; -	bool off_channel_workaround;  	u32 max_event_log_size; +	u8 scan_antennas[IEEE80211_NUM_BANDS];  };  /*************************** @@ -339,7 +351,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,  			  unsigned int changed_flags,  			  unsigned int *total_flags, u64 multicast);  int iwl_set_hw_params(struct iwl_priv *priv); -bool iwl_is_monitor_mode(struct iwl_priv *priv);  void iwl_post_associate(struct iwl_priv *priv);  void iwl_bss_info_changed(struct ieee80211_hw *hw,  				     struct ieee80211_vif *vif, @@ -501,8 +512,10 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)  void iwl_init_scan_params(struct iwl_priv *priv);  int iwl_scan_cancel(struct iwl_priv *priv);  int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); -int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); -int iwl_internal_short_hw_scan(struct iwl_priv *priv); +int iwl_mac_hw_scan(struct ieee80211_hw *hw, +		    struct ieee80211_vif *vif, +		    struct cfg80211_scan_request *req); +void iwl_internal_short_hw_scan(struct iwl_priv *priv);  int iwl_force_reset(struct iwl_priv *priv, int mode);  u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,  		       const u8 *ie, int ie_len, int left); @@ -526,6 +539,7 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv);  #define IWL_ACTIVE_QUIET_TIME       cpu_to_le16(10)  /* msec */  #define IWL_PLCP_QUIET_THRESH       cpu_to_le16(1)  /* packets */ +#define IWL_SCAN_CHECK_WATCHDOG		(HZ * 7)  /*******************************************************************************   * Calibrations - implemented in iwl-calib.c @@ -665,7 +679,7 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv)  }  extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); -extern int iwl_send_bt_config(struct iwl_priv *priv); +extern void iwl_send_bt_config(struct iwl_priv *priv);  extern int iwl_send_statistics_request(struct iwl_priv *priv,  				       u8 flags, bool clear);  extern int iwl_verify_ucode(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 808b7146bea..254c35ae8b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -298,6 +298,7 @@  #define CSR_HW_REV_TYPE_1000           (0x0000060)  #define CSR_HW_REV_TYPE_6x00           (0x0000070)  #define CSR_HW_REV_TYPE_6x50           (0x0000080) +#define CSR_HW_REV_TYPE_6x00g2         (0x00000B0)  #define CSR_HW_REV_TYPE_NONE           (0x00000F0)  /* EEPROM REG */ diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 1c7b53d511c..5c2bcef5df0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -78,6 +78,8 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,  #ifdef CONFIG_IWLWIFI_DEBUGFS  int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);  void iwl_dbgfs_unregister(struct iwl_priv *priv); +extern int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, +				     int bufsz);  #else  static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)  { diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 607a91f3eb6..4aabb542fcb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -106,6 +106,26 @@ static const struct file_operations iwl_dbgfs_##name##_ops = {          \  	.open = iwl_dbgfs_open_file_generic,                            \  }; +int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) +{ +	int p = 0; + +	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", +		       le32_to_cpu(priv->statistics.flag)); +	if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) +		p += scnprintf(buf + p, bufsz - p, +			       "\tStatistics have been cleared\n"); +	p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", +		       (le32_to_cpu(priv->statistics.flag) & +			UCODE_STATISTICS_FREQUENCY_MSK) +			? "2.4 GHz" : "5.2 GHz"); +	p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", +		       (le32_to_cpu(priv->statistics.flag) & +			UCODE_STATISTICS_NARROW_BAND_MSK) +			? "enabled" : "disabled"); +	return p; +} +EXPORT_SYMBOL(iwl_dbgfs_statistics_flag);  static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,  						char __user *user_buf, @@ -1034,474 +1054,13 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,  	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);  } -static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, -				     int bufsz) -{ -	int p = 0; - -	p += scnprintf(buf + p, bufsz - p, -		"Statistics Flag(0x%X):\n", -		le32_to_cpu(priv->statistics.flag)); -	if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) -		p += scnprintf(buf + p, bufsz - p, -		"\tStatistics have been cleared\n"); -	p += scnprintf(buf + p, bufsz - p, -		"\tOperational Frequency: %s\n", -		(le32_to_cpu(priv->statistics.flag) & -		UCODE_STATISTICS_FREQUENCY_MSK) -		 ? "2.4 GHz" : "5.2 GHz"); -	p += scnprintf(buf + p, bufsz - p, -		"\tTGj Narrow Band: %s\n", -		(le32_to_cpu(priv->statistics.flag) & -		UCODE_STATISTICS_NARROW_BAND_MSK) -		 ? "enabled" : "disabled"); -	return p; -} - -static const char ucode_stats_header[] = -	"%-32s     current  acumulative       delta         max\n"; -static const char ucode_stats_short_format[] = -	"  %-30s %10u\n"; -static const char ucode_stats_format[] = -	"  %-30s %10u  %10u  %10u  %10u\n"; -  static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,  					char __user *user_buf,  					size_t count, loff_t *ppos)  {  	struct iwl_priv *priv = file->private_data; -	int pos = 0; -	char *buf; -	int bufsz = sizeof(struct statistics_rx_phy) * 40 + -		sizeof(struct statistics_rx_non_phy) * 40 + -		sizeof(struct statistics_rx_ht_phy) * 40 + 400; -	ssize_t ret; -	struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm; -	struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck; -	struct statistics_rx_non_phy *general, *accum_general; -	struct statistics_rx_non_phy *delta_general, *max_general; -	struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; - -	if (!iwl_is_alive(priv)) -		return -EAGAIN; - -	buf = kzalloc(bufsz, GFP_KERNEL); -	if (!buf) { -		IWL_ERR(priv, "Can not allocate Buffer\n"); -		return -ENOMEM; -	} - -	/* the statistic information display here is based on -	 * the last statistics notification from uCode -	 * might not reflect the current uCode activity -	 */ -	ofdm = &priv->statistics.rx.ofdm; -	cck = &priv->statistics.rx.cck; -	general = &priv->statistics.rx.general; -	ht = &priv->statistics.rx.ofdm_ht; -	accum_ofdm = &priv->accum_statistics.rx.ofdm; -	accum_cck = &priv->accum_statistics.rx.cck; -	accum_general = &priv->accum_statistics.rx.general; -	accum_ht = &priv->accum_statistics.rx.ofdm_ht; -	delta_ofdm = &priv->delta_statistics.rx.ofdm; -	delta_cck = &priv->delta_statistics.rx.cck; -	delta_general = &priv->delta_statistics.rx.general; -	delta_ht = &priv->delta_statistics.rx.ofdm_ht; -	max_ofdm = &priv->max_delta.rx.ofdm; -	max_cck = &priv->max_delta.rx.cck; -	max_general = &priv->max_delta.rx.general; -	max_ht = &priv->max_delta.rx.ofdm_ht; - -	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, -			 "Statistics_Rx - OFDM:"); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "ina_cnt:", le32_to_cpu(ofdm->ina_cnt), -			 accum_ofdm->ina_cnt, -			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "fina_cnt:", -			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt, -			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "plcp_err:", -			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err, -			 delta_ofdm->plcp_err, max_ofdm->plcp_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "crc32_err:", -			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err, -			 delta_ofdm->crc32_err, max_ofdm->crc32_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "overrun_err:", -			 le32_to_cpu(ofdm->overrun_err), -			 accum_ofdm->overrun_err, -			 delta_ofdm->overrun_err, max_ofdm->overrun_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "early_overrun_err:", -			 le32_to_cpu(ofdm->early_overrun_err), -			 accum_ofdm->early_overrun_err, -			 delta_ofdm->early_overrun_err, -			 max_ofdm->early_overrun_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "crc32_good:", -			 le32_to_cpu(ofdm->crc32_good), -			 accum_ofdm->crc32_good, -			 delta_ofdm->crc32_good, max_ofdm->crc32_good); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "false_alarm_cnt:", -			 le32_to_cpu(ofdm->false_alarm_cnt), -			 accum_ofdm->false_alarm_cnt, -			 delta_ofdm->false_alarm_cnt, -			 max_ofdm->false_alarm_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "fina_sync_err_cnt:", -			 le32_to_cpu(ofdm->fina_sync_err_cnt), -			 accum_ofdm->fina_sync_err_cnt, -			 delta_ofdm->fina_sync_err_cnt, -			 max_ofdm->fina_sync_err_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "sfd_timeout:", -			 le32_to_cpu(ofdm->sfd_timeout), -			 accum_ofdm->sfd_timeout, -			 delta_ofdm->sfd_timeout, -			 max_ofdm->sfd_timeout); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "fina_timeout:", -			 le32_to_cpu(ofdm->fina_timeout), -			 accum_ofdm->fina_timeout, -			 delta_ofdm->fina_timeout, -			 max_ofdm->fina_timeout); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "unresponded_rts:", -			 le32_to_cpu(ofdm->unresponded_rts), -			 accum_ofdm->unresponded_rts, -			 delta_ofdm->unresponded_rts, -			 max_ofdm->unresponded_rts); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			"rxe_frame_lmt_ovrun:", -			 le32_to_cpu(ofdm->rxe_frame_limit_overrun), -			 accum_ofdm->rxe_frame_limit_overrun, -			 delta_ofdm->rxe_frame_limit_overrun, -			 max_ofdm->rxe_frame_limit_overrun); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "sent_ack_cnt:", -			 le32_to_cpu(ofdm->sent_ack_cnt), -			 accum_ofdm->sent_ack_cnt, -			 delta_ofdm->sent_ack_cnt, -			 max_ofdm->sent_ack_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "sent_cts_cnt:", -			 le32_to_cpu(ofdm->sent_cts_cnt), -			 accum_ofdm->sent_cts_cnt, -			 delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "sent_ba_rsp_cnt:", -			 le32_to_cpu(ofdm->sent_ba_rsp_cnt), -			 accum_ofdm->sent_ba_rsp_cnt, -			 delta_ofdm->sent_ba_rsp_cnt, -			 max_ofdm->sent_ba_rsp_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "dsp_self_kill:", -			 le32_to_cpu(ofdm->dsp_self_kill), -			 accum_ofdm->dsp_self_kill, -			 delta_ofdm->dsp_self_kill, -			 max_ofdm->dsp_self_kill); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "mh_format_err:", -			 le32_to_cpu(ofdm->mh_format_err), -			 accum_ofdm->mh_format_err, -			 delta_ofdm->mh_format_err, -			 max_ofdm->mh_format_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "re_acq_main_rssi_sum:", -			 le32_to_cpu(ofdm->re_acq_main_rssi_sum), -			 accum_ofdm->re_acq_main_rssi_sum, -			 delta_ofdm->re_acq_main_rssi_sum, -			max_ofdm->re_acq_main_rssi_sum); - -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, -			 "Statistics_Rx - CCK:"); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "ina_cnt:", -			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt, -			 delta_cck->ina_cnt, max_cck->ina_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "fina_cnt:", -			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt, -			 delta_cck->fina_cnt, max_cck->fina_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "plcp_err:", -			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err, -			 delta_cck->plcp_err, max_cck->plcp_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "crc32_err:", -			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err, -			 delta_cck->crc32_err, max_cck->crc32_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "overrun_err:", -			 le32_to_cpu(cck->overrun_err), -			 accum_cck->overrun_err, -			 delta_cck->overrun_err, max_cck->overrun_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "early_overrun_err:", -			 le32_to_cpu(cck->early_overrun_err), -			 accum_cck->early_overrun_err, -			 delta_cck->early_overrun_err, -			 max_cck->early_overrun_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "crc32_good:", -			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good, -			 delta_cck->crc32_good, -			 max_cck->crc32_good); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "false_alarm_cnt:", -			 le32_to_cpu(cck->false_alarm_cnt), -			 accum_cck->false_alarm_cnt, -			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "fina_sync_err_cnt:", -			 le32_to_cpu(cck->fina_sync_err_cnt), -			 accum_cck->fina_sync_err_cnt, -			 delta_cck->fina_sync_err_cnt, -			 max_cck->fina_sync_err_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "sfd_timeout:", -			 le32_to_cpu(cck->sfd_timeout), -			 accum_cck->sfd_timeout, -			 delta_cck->sfd_timeout, max_cck->sfd_timeout); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "fina_timeout:", -			 le32_to_cpu(cck->fina_timeout), -			 accum_cck->fina_timeout, -			 delta_cck->fina_timeout, max_cck->fina_timeout); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "unresponded_rts:", -			 le32_to_cpu(cck->unresponded_rts), -			 accum_cck->unresponded_rts, -			 delta_cck->unresponded_rts, -			 max_cck->unresponded_rts); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			"rxe_frame_lmt_ovrun:", -			 le32_to_cpu(cck->rxe_frame_limit_overrun), -			 accum_cck->rxe_frame_limit_overrun, -			 delta_cck->rxe_frame_limit_overrun, -			 max_cck->rxe_frame_limit_overrun); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "sent_ack_cnt:", -			 le32_to_cpu(cck->sent_ack_cnt), -			 accum_cck->sent_ack_cnt, -			 delta_cck->sent_ack_cnt, -			 max_cck->sent_ack_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "sent_cts_cnt:", -			 le32_to_cpu(cck->sent_cts_cnt), -			 accum_cck->sent_cts_cnt, -			 delta_cck->sent_cts_cnt, -			 max_cck->sent_cts_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "sent_ba_rsp_cnt:", -			 le32_to_cpu(cck->sent_ba_rsp_cnt), -			 accum_cck->sent_ba_rsp_cnt, -			 delta_cck->sent_ba_rsp_cnt, -			 max_cck->sent_ba_rsp_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "dsp_self_kill:", -			 le32_to_cpu(cck->dsp_self_kill), -			 accum_cck->dsp_self_kill, -			 delta_cck->dsp_self_kill, -			 max_cck->dsp_self_kill); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "mh_format_err:", -			 le32_to_cpu(cck->mh_format_err), -			 accum_cck->mh_format_err, -			 delta_cck->mh_format_err, max_cck->mh_format_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "re_acq_main_rssi_sum:", -			 le32_to_cpu(cck->re_acq_main_rssi_sum), -			 accum_cck->re_acq_main_rssi_sum, -			 delta_cck->re_acq_main_rssi_sum, -			 max_cck->re_acq_main_rssi_sum); - -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, -			"Statistics_Rx - GENERAL:"); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "bogus_cts:", -			 le32_to_cpu(general->bogus_cts), -			 accum_general->bogus_cts, -			 delta_general->bogus_cts, max_general->bogus_cts); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "bogus_ack:", -			 le32_to_cpu(general->bogus_ack), -			 accum_general->bogus_ack, -			 delta_general->bogus_ack, max_general->bogus_ack); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "non_bssid_frames:", -			 le32_to_cpu(general->non_bssid_frames), -			 accum_general->non_bssid_frames, -			 delta_general->non_bssid_frames, -			 max_general->non_bssid_frames); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "filtered_frames:", -			 le32_to_cpu(general->filtered_frames), -			 accum_general->filtered_frames, -			 delta_general->filtered_frames, -			 max_general->filtered_frames); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "non_channel_beacons:", -			 le32_to_cpu(general->non_channel_beacons), -			 accum_general->non_channel_beacons, -			 delta_general->non_channel_beacons, -			 max_general->non_channel_beacons); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "channel_beacons:", -			 le32_to_cpu(general->channel_beacons), -			 accum_general->channel_beacons, -			 delta_general->channel_beacons, -			 max_general->channel_beacons); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "num_missed_bcon:", -			 le32_to_cpu(general->num_missed_bcon), -			 accum_general->num_missed_bcon, -			 delta_general->num_missed_bcon, -			 max_general->num_missed_bcon); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			"adc_rx_saturation_time:", -			 le32_to_cpu(general->adc_rx_saturation_time), -			 accum_general->adc_rx_saturation_time, -			 delta_general->adc_rx_saturation_time, -			 max_general->adc_rx_saturation_time); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			"ina_detect_search_tm:", -			 le32_to_cpu(general->ina_detection_search_time), -			 accum_general->ina_detection_search_time, -			 delta_general->ina_detection_search_time, -			 max_general->ina_detection_search_time); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "beacon_silence_rssi_a:", -			 le32_to_cpu(general->beacon_silence_rssi_a), -			 accum_general->beacon_silence_rssi_a, -			 delta_general->beacon_silence_rssi_a, -			 max_general->beacon_silence_rssi_a); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "beacon_silence_rssi_b:", -			 le32_to_cpu(general->beacon_silence_rssi_b), -			 accum_general->beacon_silence_rssi_b, -			 delta_general->beacon_silence_rssi_b, -			 max_general->beacon_silence_rssi_b); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "beacon_silence_rssi_c:", -			 le32_to_cpu(general->beacon_silence_rssi_c), -			 accum_general->beacon_silence_rssi_c, -			 delta_general->beacon_silence_rssi_c, -			 max_general->beacon_silence_rssi_c); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			"interference_data_flag:", -			 le32_to_cpu(general->interference_data_flag), -			 accum_general->interference_data_flag, -			 delta_general->interference_data_flag, -			 max_general->interference_data_flag); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "channel_load:", -			 le32_to_cpu(general->channel_load), -			 accum_general->channel_load, -			 delta_general->channel_load, -			 max_general->channel_load); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "dsp_false_alarms:", -			 le32_to_cpu(general->dsp_false_alarms), -			 accum_general->dsp_false_alarms, -			 delta_general->dsp_false_alarms, -			 max_general->dsp_false_alarms); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "beacon_rssi_a:", -			 le32_to_cpu(general->beacon_rssi_a), -			 accum_general->beacon_rssi_a, -			 delta_general->beacon_rssi_a, -			 max_general->beacon_rssi_a); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "beacon_rssi_b:", -			 le32_to_cpu(general->beacon_rssi_b), -			 accum_general->beacon_rssi_b, -			 delta_general->beacon_rssi_b, -			 max_general->beacon_rssi_b); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "beacon_rssi_c:", -			 le32_to_cpu(general->beacon_rssi_c), -			 accum_general->beacon_rssi_c, -			 delta_general->beacon_rssi_c, -			 max_general->beacon_rssi_c); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "beacon_energy_a:", -			 le32_to_cpu(general->beacon_energy_a), -			 accum_general->beacon_energy_a, -			 delta_general->beacon_energy_a, -			 max_general->beacon_energy_a); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "beacon_energy_b:", -			 le32_to_cpu(general->beacon_energy_b), -			 accum_general->beacon_energy_b, -			 delta_general->beacon_energy_b, -			 max_general->beacon_energy_b); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "beacon_energy_c:", -			 le32_to_cpu(general->beacon_energy_c), -			 accum_general->beacon_energy_c, -			 delta_general->beacon_energy_c, -			 max_general->beacon_energy_c); - -	pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, -			"Statistics_Rx - OFDM_HT:"); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "plcp_err:", -			 le32_to_cpu(ht->plcp_err), accum_ht->plcp_err, -			 delta_ht->plcp_err, max_ht->plcp_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "overrun_err:", -			 le32_to_cpu(ht->overrun_err), accum_ht->overrun_err, -			 delta_ht->overrun_err, max_ht->overrun_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "early_overrun_err:", -			 le32_to_cpu(ht->early_overrun_err), -			 accum_ht->early_overrun_err, -			 delta_ht->early_overrun_err, -			 max_ht->early_overrun_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "crc32_good:", -			 le32_to_cpu(ht->crc32_good), accum_ht->crc32_good, -			 delta_ht->crc32_good, max_ht->crc32_good); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "crc32_err:", -			 le32_to_cpu(ht->crc32_err), accum_ht->crc32_err, -			 delta_ht->crc32_err, max_ht->crc32_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "mh_format_err:", -			 le32_to_cpu(ht->mh_format_err), -			 accum_ht->mh_format_err, -			 delta_ht->mh_format_err, max_ht->mh_format_err); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "agg_crc32_good:", -			 le32_to_cpu(ht->agg_crc32_good), -			 accum_ht->agg_crc32_good, -			 delta_ht->agg_crc32_good, max_ht->agg_crc32_good); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "agg_mpdu_cnt:", -			 le32_to_cpu(ht->agg_mpdu_cnt), -			 accum_ht->agg_mpdu_cnt, -			 delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "agg_cnt:", -			 le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt, -			 delta_ht->agg_cnt, max_ht->agg_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "unsupport_mcs:", -			 le32_to_cpu(ht->unsupport_mcs), -			 accum_ht->unsupport_mcs, -			 delta_ht->unsupport_mcs, max_ht->unsupport_mcs); - -	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -	kfree(buf); -	return ret; +	return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file, +			user_buf, count, ppos);  }  static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, @@ -1509,173 +1068,8 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,  					size_t count, loff_t *ppos)  {  	struct iwl_priv *priv = file->private_data; -	int pos = 0; -	char *buf; -	int bufsz = (sizeof(struct statistics_tx) * 48) + 250; -	ssize_t ret; -	struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; - -	if (!iwl_is_alive(priv)) -		return -EAGAIN; - -	buf = kzalloc(bufsz, GFP_KERNEL); -	if (!buf) { -		IWL_ERR(priv, "Can not allocate Buffer\n"); -		return -ENOMEM; -	} - -	/* the statistic information display here is based on -	 * the last statistics notification from uCode -	 * might not reflect the current uCode activity -	 */ -	tx = &priv->statistics.tx; -	accum_tx = &priv->accum_statistics.tx; -	delta_tx = &priv->delta_statistics.tx; -	max_tx = &priv->max_delta.tx; -	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); -	pos += scnprintf(buf + pos, bufsz - pos,  ucode_stats_header, -			"Statistics_Tx:"); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "preamble:", -			 le32_to_cpu(tx->preamble_cnt), -			 accum_tx->preamble_cnt, -			 delta_tx->preamble_cnt, max_tx->preamble_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "rx_detected_cnt:", -			 le32_to_cpu(tx->rx_detected_cnt), -			 accum_tx->rx_detected_cnt, -			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "bt_prio_defer_cnt:", -			 le32_to_cpu(tx->bt_prio_defer_cnt), -			 accum_tx->bt_prio_defer_cnt, -			 delta_tx->bt_prio_defer_cnt, -			 max_tx->bt_prio_defer_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "bt_prio_kill_cnt:", -			 le32_to_cpu(tx->bt_prio_kill_cnt), -			 accum_tx->bt_prio_kill_cnt, -			 delta_tx->bt_prio_kill_cnt, -			 max_tx->bt_prio_kill_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "few_bytes_cnt:", -			 le32_to_cpu(tx->few_bytes_cnt), -			 accum_tx->few_bytes_cnt, -			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "cts_timeout:", -			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout, -			 delta_tx->cts_timeout, max_tx->cts_timeout); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "ack_timeout:", -			 le32_to_cpu(tx->ack_timeout), -			 accum_tx->ack_timeout, -			 delta_tx->ack_timeout, max_tx->ack_timeout); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "expected_ack_cnt:", -			 le32_to_cpu(tx->expected_ack_cnt), -			 accum_tx->expected_ack_cnt, -			 delta_tx->expected_ack_cnt, -			 max_tx->expected_ack_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "actual_ack_cnt:", -			 le32_to_cpu(tx->actual_ack_cnt), -			 accum_tx->actual_ack_cnt, -			 delta_tx->actual_ack_cnt, -			 max_tx->actual_ack_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "dump_msdu_cnt:", -			 le32_to_cpu(tx->dump_msdu_cnt), -			 accum_tx->dump_msdu_cnt, -			 delta_tx->dump_msdu_cnt, -			 max_tx->dump_msdu_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "abort_nxt_frame_mismatch:", -			 le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt), -			 accum_tx->burst_abort_next_frame_mismatch_cnt, -			 delta_tx->burst_abort_next_frame_mismatch_cnt, -			 max_tx->burst_abort_next_frame_mismatch_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "abort_missing_nxt_frame:", -			 le32_to_cpu(tx->burst_abort_missing_next_frame_cnt), -			 accum_tx->burst_abort_missing_next_frame_cnt, -			 delta_tx->burst_abort_missing_next_frame_cnt, -			 max_tx->burst_abort_missing_next_frame_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "cts_timeout_collision:", -			 le32_to_cpu(tx->cts_timeout_collision), -			 accum_tx->cts_timeout_collision, -			 delta_tx->cts_timeout_collision, -			 max_tx->cts_timeout_collision); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			"ack_ba_timeout_collision:", -			 le32_to_cpu(tx->ack_or_ba_timeout_collision), -			 accum_tx->ack_or_ba_timeout_collision, -			 delta_tx->ack_or_ba_timeout_collision, -			 max_tx->ack_or_ba_timeout_collision); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "agg ba_timeout:", -			 le32_to_cpu(tx->agg.ba_timeout), -			 accum_tx->agg.ba_timeout, -			 delta_tx->agg.ba_timeout, -			 max_tx->agg.ba_timeout); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			"agg ba_resched_frames:", -			 le32_to_cpu(tx->agg.ba_reschedule_frames), -			 accum_tx->agg.ba_reschedule_frames, -			 delta_tx->agg.ba_reschedule_frames, -			 max_tx->agg.ba_reschedule_frames); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			"agg scd_query_agg_frame:", -			 le32_to_cpu(tx->agg.scd_query_agg_frame_cnt), -			 accum_tx->agg.scd_query_agg_frame_cnt, -			 delta_tx->agg.scd_query_agg_frame_cnt, -			 max_tx->agg.scd_query_agg_frame_cnt); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "agg scd_query_no_agg:", -			 le32_to_cpu(tx->agg.scd_query_no_agg), -			 accum_tx->agg.scd_query_no_agg, -			 delta_tx->agg.scd_query_no_agg, -			 max_tx->agg.scd_query_no_agg); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "agg scd_query_agg:", -			 le32_to_cpu(tx->agg.scd_query_agg), -			 accum_tx->agg.scd_query_agg, -			 delta_tx->agg.scd_query_agg, -			 max_tx->agg.scd_query_agg); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			"agg scd_query_mismatch:", -			 le32_to_cpu(tx->agg.scd_query_mismatch), -			 accum_tx->agg.scd_query_mismatch, -			 delta_tx->agg.scd_query_mismatch, -			 max_tx->agg.scd_query_mismatch); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "agg frame_not_ready:", -			 le32_to_cpu(tx->agg.frame_not_ready), -			 accum_tx->agg.frame_not_ready, -			 delta_tx->agg.frame_not_ready, -			 max_tx->agg.frame_not_ready); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "agg underrun:", -			 le32_to_cpu(tx->agg.underrun), -			 accum_tx->agg.underrun, -			 delta_tx->agg.underrun, max_tx->agg.underrun); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "agg bt_prio_kill:", -			 le32_to_cpu(tx->agg.bt_prio_kill), -			 accum_tx->agg.bt_prio_kill, -			 delta_tx->agg.bt_prio_kill, -			 max_tx->agg.bt_prio_kill); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "agg rx_ba_rsp_cnt:", -			 le32_to_cpu(tx->agg.rx_ba_rsp_cnt), -			 accum_tx->agg.rx_ba_rsp_cnt, -			 delta_tx->agg.rx_ba_rsp_cnt, -			 max_tx->agg.rx_ba_rsp_cnt); - -	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -	kfree(buf); -	return ret; +	return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file, +			user_buf, count, ppos);  }  static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, @@ -1683,107 +1077,8 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,  					size_t count, loff_t *ppos)  {  	struct iwl_priv *priv = file->private_data; -	int pos = 0; -	char *buf; -	int bufsz = sizeof(struct statistics_general) * 10 + 300; -	ssize_t ret; -	struct statistics_general *general, *accum_general; -	struct statistics_general *delta_general, *max_general; -	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; -	struct statistics_div *div, *accum_div, *delta_div, *max_div; - -	if (!iwl_is_alive(priv)) -		return -EAGAIN; - -	buf = kzalloc(bufsz, GFP_KERNEL); -	if (!buf) { -		IWL_ERR(priv, "Can not allocate Buffer\n"); -		return -ENOMEM; -	} - -	/* the statistic information display here is based on -	 * the last statistics notification from uCode -	 * might not reflect the current uCode activity -	 */ -	general = &priv->statistics.general; -	dbg = &priv->statistics.general.dbg; -	div = &priv->statistics.general.div; -	accum_general = &priv->accum_statistics.general; -	delta_general = &priv->delta_statistics.general; -	max_general = &priv->max_delta.general; -	accum_dbg = &priv->accum_statistics.general.dbg; -	delta_dbg = &priv->delta_statistics.general.dbg; -	max_dbg = &priv->max_delta.general.dbg; -	accum_div = &priv->accum_statistics.general.div; -	delta_div = &priv->delta_statistics.general.div; -	max_div = &priv->max_delta.general.div; -	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header, -			"Statistics_General:"); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, -			 "temperature:", -			 le32_to_cpu(general->temperature)); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format, -			 "temperature_m:", -			 le32_to_cpu(general->temperature_m)); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "burst_check:", -			 le32_to_cpu(dbg->burst_check), -			 accum_dbg->burst_check, -			 delta_dbg->burst_check, max_dbg->burst_check); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "burst_count:", -			 le32_to_cpu(dbg->burst_count), -			 accum_dbg->burst_count, -			 delta_dbg->burst_count, max_dbg->burst_count); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "sleep_time:", -			 le32_to_cpu(general->sleep_time), -			 accum_general->sleep_time, -			 delta_general->sleep_time, max_general->sleep_time); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "slots_out:", -			 le32_to_cpu(general->slots_out), -			 accum_general->slots_out, -			 delta_general->slots_out, max_general->slots_out); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "slots_idle:", -			 le32_to_cpu(general->slots_idle), -			 accum_general->slots_idle, -			 delta_general->slots_idle, max_general->slots_idle); -	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n", -			 le32_to_cpu(general->ttl_timestamp)); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "tx_on_a:", -			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a, -			 delta_div->tx_on_a, max_div->tx_on_a); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "tx_on_b:", -			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b, -			 delta_div->tx_on_b, max_div->tx_on_b); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "exec_time:", -			 le32_to_cpu(div->exec_time), accum_div->exec_time, -			 delta_div->exec_time, max_div->exec_time); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "probe_time:", -			 le32_to_cpu(div->probe_time), accum_div->probe_time, -			 delta_div->probe_time, max_div->probe_time); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "rx_enable_counter:", -			 le32_to_cpu(general->rx_enable_counter), -			 accum_general->rx_enable_counter, -			 delta_general->rx_enable_counter, -			 max_general->rx_enable_counter); -	pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format, -			 "num_of_sos_states:", -			 le32_to_cpu(general->num_of_sos_states), -			 accum_general->num_of_sos_states, -			 delta_general->num_of_sos_states, -			 max_general->num_of_sos_states); -	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -	kfree(buf); -	return ret; +	return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file, +			user_buf, count, ppos);  }  static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, @@ -2341,10 +1636,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)  	DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);  	DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);  	DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR); +	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); +	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); +	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR); +  	if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { -		DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR); -		DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR); -		DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);  		DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);  		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);  		DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9466e909f55..58c69a5798d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -58,7 +58,7 @@ extern struct iwl_cfg iwl5100_abg_cfg;  extern struct iwl_cfg iwl5150_agn_cfg;  extern struct iwl_cfg iwl5150_abg_cfg;  extern struct iwl_cfg iwl6000i_2agn_cfg; -extern struct iwl_cfg iwl6000i_g2_2agn_cfg; +extern struct iwl_cfg iwl6000g2_2agn_cfg;  extern struct iwl_cfg iwl6000i_2abg_cfg;  extern struct iwl_cfg iwl6000i_2bg_cfg;  extern struct iwl_cfg iwl6000_3agn_cfg; @@ -1049,12 +1049,10 @@ struct iwl_priv {  	struct iwl_calib_result calib_results[IWL_CALIB_MAX];  	/* Scan related variables */ -	unsigned long next_scan_jiffies;  	unsigned long scan_start; -	unsigned long scan_pass_start;  	unsigned long scan_start_tsf; -	void *scan; -	int scan_bands; +	void *scan_cmd; +	enum ieee80211_band scan_band;  	struct cfg80211_scan_request *scan_request;  	bool is_internal_short_scan;  	u8 scan_tx_ant[IEEE80211_NUM_BANDS]; @@ -1204,6 +1202,11 @@ struct iwl_priv {  			struct delayed_work rfkill_poll;  			struct iwl3945_notif_statistics statistics; +#ifdef CONFIG_IWLWIFI_DEBUG +			struct iwl3945_notif_statistics accum_statistics; +			struct iwl3945_notif_statistics delta_statistics; +			struct iwl3945_notif_statistics max_delta; +#endif  			u32 sta_supp_rates;  			int last_rx_rssi;	/* From Rx packet statistics */ @@ -1259,11 +1262,11 @@ struct iwl_priv {  	struct work_struct scan_completed;  	struct work_struct rx_replenish;  	struct work_struct abort_scan; -	struct work_struct request_scan;  	struct work_struct beacon_update;  	struct work_struct tt_work;  	struct work_struct ct_enter;  	struct work_struct ct_exit; +	struct work_struct start_internal_scan;  	struct tasklet_struct irq_tasklet; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index cb6d50b7814..95aa202c85e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -172,22 +172,22 @@ struct iwl_eeprom_enhanced_txpwr {  #define EEPROM_5000_TX_POWER_VERSION    (4)  #define EEPROM_5000_EEPROM_VERSION	(0x11A) -/*5000 calibrations */ -#define EEPROM_5000_CALIB_ALL	(INDIRECT_ADDRESS | INDIRECT_CALIBRATION) -#define EEPROM_5000_XTAL	((2*0x128) | EEPROM_5000_CALIB_ALL) -#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_5000_CALIB_ALL) +/* 5000 and up calibration */ +#define EEPROM_CALIB_ALL	(INDIRECT_ADDRESS | INDIRECT_CALIBRATION) +#define EEPROM_XTAL		((2*0x128) | EEPROM_CALIB_ALL) -/* 5000 links */ -#define EEPROM_5000_LINK_HOST             (2*0x64) -#define EEPROM_5000_LINK_GENERAL          (2*0x65) -#define EEPROM_5000_LINK_REGULATORY       (2*0x66) -#define EEPROM_5000_LINK_CALIBRATION      (2*0x67) -#define EEPROM_5000_LINK_PROCESS_ADJST    (2*0x68) -#define EEPROM_5000_LINK_OTHERS           (2*0x69) +/* 5000 temperature */ +#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) -/* 5000 regulatory - indirect access */ -#define EEPROM_5000_REG_SKU_ID ((0x02)\ -		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 4  bytes */ +/* agn links */ +#define EEPROM_LINK_HOST             (2*0x64) +#define EEPROM_LINK_GENERAL          (2*0x65) +#define EEPROM_LINK_REGULATORY       (2*0x66) +#define EEPROM_LINK_CALIBRATION      (2*0x67) +#define EEPROM_LINK_PROCESS_ADJST    (2*0x68) +#define EEPROM_LINK_OTHERS           (2*0x69) + +/* agn regulatory - indirect access */  #define EEPROM_REG_BAND_1_CHANNELS       ((0x08)\  		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 28 bytes */  #define EEPROM_REG_BAND_2_CHANNELS       ((0x26)\ @@ -203,6 +203,10 @@ struct iwl_eeprom_enhanced_txpwr {  #define EEPROM_REG_BAND_52_HT40_CHANNELS  ((0x92)\  		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 22  bytes */ +/* 6000 regulatory - indirect access */ +#define EEPROM_6000_REG_BAND_24_HT40_CHANNELS  ((0x80)\ +		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 14  bytes */ +  /* 6000 and up regulatory tx power - indirect access */  /* max. elements per section */  #define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS	(8) @@ -272,6 +276,10 @@ struct iwl_eeprom_enhanced_txpwr {  #define EEPROM_6050_TX_POWER_VERSION    (4)  #define EEPROM_6050_EEPROM_VERSION	(0x532) +/* 6x00g2 Specific */ +#define EEPROM_6000G2_TX_POWER_VERSION    (6) +#define EEPROM_6000G2_EEPROM_VERSION	(0x709) +  /* OTP */  /* lower blocks contain EEPROM image and calibration data */  #define OTP_LOW_IMAGE_SIZE		(2 * 512 * sizeof(u16)) /* 2 KB */ diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 5944de7a98a..b1f101caf19 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -529,48 +529,48 @@  #define IWL_SCD_TXFIFO_POS_RA			(4)  #define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK	(0x01FF) -/* 5000 SCD */ -#define IWL50_SCD_QUEUE_STTS_REG_POS_TXF	(0) -#define IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE	(3) -#define IWL50_SCD_QUEUE_STTS_REG_POS_WSL	(4) -#define IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) -#define IWL50_SCD_QUEUE_STTS_REG_MSK		(0x00FF0000) +/* agn SCD */ +#define IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF	(0) +#define IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE	(3) +#define IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL	(4) +#define IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) +#define IWLAGN_SCD_QUEUE_STTS_REG_MSK		(0x00FF0000) -#define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_POS		(8) -#define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_MSK		(0x00FFFF00) -#define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS	(24) -#define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK	(0xFF000000) -#define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS		(0) -#define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK		(0x0000007F) -#define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS	(16) -#define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK	(0x007F0000) +#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_POS		(8) +#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_MSK		(0x00FFFF00) +#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS	(24) +#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK	(0xFF000000) +#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS		(0) +#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK		(0x0000007F) +#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS	(16) +#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK	(0x007F0000) -#define IWL50_SCD_CONTEXT_DATA_OFFSET		(0x600) -#define IWL50_SCD_TX_STTS_BITMAP_OFFSET		(0x7B1) -#define IWL50_SCD_TRANSLATE_TBL_OFFSET		(0x7E0) +#define IWLAGN_SCD_CONTEXT_DATA_OFFSET		(0x600) +#define IWLAGN_SCD_TX_STTS_BITMAP_OFFSET		(0x7B1) +#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET		(0x7E0) -#define IWL50_SCD_CONTEXT_QUEUE_OFFSET(x)\ -	(IWL50_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) +#define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\ +	(IWLAGN_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) -#define IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ -	((IWL50_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) +#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ +	((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) -#define IWL50_SCD_QUEUECHAIN_SEL_ALL(x)		(((1<<(x)) - 1) &\ +#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(x)		(((1<<(x)) - 1) &\  	(~(1<<IWL_CMD_QUEUE_NUM))) -#define IWL50_SCD_BASE			(PRPH_BASE + 0xa02c00) +#define IWLAGN_SCD_BASE			(PRPH_BASE + 0xa02c00) -#define IWL50_SCD_SRAM_BASE_ADDR         (IWL50_SCD_BASE + 0x0) -#define IWL50_SCD_DRAM_BASE_ADDR	 (IWL50_SCD_BASE + 0x8) -#define IWL50_SCD_AIT                    (IWL50_SCD_BASE + 0x0c) -#define IWL50_SCD_TXFACT                 (IWL50_SCD_BASE + 0x10) -#define IWL50_SCD_ACTIVE		 (IWL50_SCD_BASE + 0x14) -#define IWL50_SCD_QUEUE_WRPTR(x)         (IWL50_SCD_BASE + 0x18 + (x) * 4) -#define IWL50_SCD_QUEUE_RDPTR(x)         (IWL50_SCD_BASE + 0x68 + (x) * 4) -#define IWL50_SCD_QUEUECHAIN_SEL         (IWL50_SCD_BASE + 0xe8) -#define IWL50_SCD_AGGR_SEL	     	 (IWL50_SCD_BASE + 0x248) -#define IWL50_SCD_INTERRUPT_MASK         (IWL50_SCD_BASE + 0x108) -#define IWL50_SCD_QUEUE_STATUS_BITS(x)   (IWL50_SCD_BASE + 0x10c + (x) * 4) +#define IWLAGN_SCD_SRAM_BASE_ADDR	(IWLAGN_SCD_BASE + 0x0) +#define IWLAGN_SCD_DRAM_BASE_ADDR	(IWLAGN_SCD_BASE + 0x8) +#define IWLAGN_SCD_AIT			(IWLAGN_SCD_BASE + 0x0c) +#define IWLAGN_SCD_TXFACT		(IWLAGN_SCD_BASE + 0x10) +#define IWLAGN_SCD_ACTIVE		(IWLAGN_SCD_BASE + 0x14) +#define IWLAGN_SCD_QUEUE_WRPTR(x)	(IWLAGN_SCD_BASE + 0x18 + (x) * 4) +#define IWLAGN_SCD_QUEUE_RDPTR(x)	(IWLAGN_SCD_BASE + 0x68 + (x) * 4) +#define IWLAGN_SCD_QUEUECHAIN_SEL	(IWLAGN_SCD_BASE + 0xe8) +#define IWLAGN_SCD_AGGR_SEL		(IWLAGN_SCD_BASE + 0x248) +#define IWLAGN_SCD_INTERRUPT_MASK	(IWLAGN_SCD_BASE + 0x108) +#define IWLAGN_SCD_QUEUE_STATUS_BITS(x)	(IWLAGN_SCD_BASE + 0x10c + (x) * 4)  /*********************** END TX SCHEDULER *************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index ae981932ce6..d12fd555384 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -69,9 +69,8 @@ int iwl_scan_cancel(struct iwl_priv *priv)  	}  	if (test_bit(STATUS_SCANNING, &priv->status)) { -		if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) { +		if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {  			IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n"); -			set_bit(STATUS_SCAN_ABORTING, &priv->status);  			queue_work(priv->workqueue, &priv->abort_scan);  		} else @@ -201,9 +200,6 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,  		       le32_to_cpu(notif->statistics[0]),  		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);  #endif - -	if (!priv->is_internal_short_scan) -		priv->next_scan_jiffies = 0;  }  /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ @@ -223,49 +219,24 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,  	/* The HW is no longer scanning */  	clear_bit(STATUS_SCAN_HW, &priv->status); -	IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n", -		       (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? -						"2.4" : "5.2", +	IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n", +		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",  		       jiffies_to_msecs(elapsed_jiffies -					(priv->scan_pass_start, jiffies))); - -	/* Remove this scanned band from the list of pending -	 * bands to scan, band G precedes A in order of scanning -	 * as seen in iwl_bg_request_scan */ -	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) -		priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ); -	else if (priv->scan_bands &  BIT(IEEE80211_BAND_5GHZ)) -		priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ); +					(priv->scan_start, jiffies))); -	/* If a request to abort was given, or the scan did not succeed +	/* +	 * If a request to abort was given, or the scan did not succeed  	 * then we reset the scan state machine and terminate, -	 * re-queuing another scan if one has been requested */ -	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { +	 * re-queuing another scan if one has been requested +	 */ +	if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status))  		IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); -		clear_bit(STATUS_SCAN_ABORTING, &priv->status); -	} else { -		/* If there are more bands on this scan pass reschedule */ -		if (priv->scan_bands) -			goto reschedule; -	} - -	if (!priv->is_internal_short_scan) -		priv->next_scan_jiffies = 0;  	IWL_DEBUG_INFO(priv, "Setting scan to off\n");  	clear_bit(STATUS_SCANNING, &priv->status); -	IWL_DEBUG_INFO(priv, "Scan took %dms\n", -		jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies))); -  	queue_work(priv->workqueue, &priv->scan_completed); - -	return; - -reschedule: -	priv->scan_pass_start = jiffies; -	queue_work(priv->workqueue, &priv->request_scan);  }  void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) @@ -314,150 +285,6 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,  }  EXPORT_SYMBOL(iwl_get_passive_dwell_time); -static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, -				     enum ieee80211_band band, -				     struct iwl_scan_channel *scan_ch) -{ -	const struct ieee80211_supported_band *sband; -	const struct iwl_channel_info *ch_info; -	u16 passive_dwell = 0; -	u16 active_dwell = 0; -	int i, added = 0; -	u16 channel = 0; - -	sband = iwl_get_hw_mode(priv, band); -	if (!sband) { -		IWL_ERR(priv, "invalid band\n"); -		return added; -	} - -	active_dwell = iwl_get_active_dwell_time(priv, band, 0); -	passive_dwell = iwl_get_passive_dwell_time(priv, band); - -	if (passive_dwell <= active_dwell) -		passive_dwell = active_dwell + 1; - -	/* only scan single channel, good enough to reset the RF */ -	/* pick the first valid not in-use channel */ -	if (band == IEEE80211_BAND_5GHZ) { -		for (i = 14; i < priv->channel_count; i++) { -			if (priv->channel_info[i].channel != -			    le16_to_cpu(priv->staging_rxon.channel)) { -				channel = priv->channel_info[i].channel; -				ch_info = iwl_get_channel_info(priv, -					band, channel); -				if (is_channel_valid(ch_info)) -					break; -			} -		} -	} else { -		for (i = 0; i < 14; i++) { -			if (priv->channel_info[i].channel != -			    le16_to_cpu(priv->staging_rxon.channel)) { -					channel = -						priv->channel_info[i].channel; -					ch_info = iwl_get_channel_info(priv, -						band, channel); -					if (is_channel_valid(ch_info)) -						break; -			} -		} -	} -	if (channel) { -		scan_ch->channel = cpu_to_le16(channel); -		scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; -		scan_ch->active_dwell = cpu_to_le16(active_dwell); -		scan_ch->passive_dwell = cpu_to_le16(passive_dwell); -		/* Set txpower levels to defaults */ -		scan_ch->dsp_atten = 110; -		if (band == IEEE80211_BAND_5GHZ) -			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; -		else -			scan_ch->tx_gain = ((1 << 5) | (5 << 3)); -		added++; -	} else -		IWL_ERR(priv, "no valid channel found\n"); -	return added; -} - -static int iwl_get_channels_for_scan(struct iwl_priv *priv, -				     enum ieee80211_band band, -				     u8 is_active, u8 n_probes, -				     struct iwl_scan_channel *scan_ch) -{ -	struct ieee80211_channel *chan; -	const struct ieee80211_supported_band *sband; -	const struct iwl_channel_info *ch_info; -	u16 passive_dwell = 0; -	u16 active_dwell = 0; -	int added, i; -	u16 channel; - -	sband = iwl_get_hw_mode(priv, band); -	if (!sband) -		return 0; - -	active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); -	passive_dwell = iwl_get_passive_dwell_time(priv, band); - -	if (passive_dwell <= active_dwell) -		passive_dwell = active_dwell + 1; - -	for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { -		chan = priv->scan_request->channels[i]; - -		if (chan->band != band) -			continue; - -		channel = ieee80211_frequency_to_channel(chan->center_freq); -		scan_ch->channel = cpu_to_le16(channel); - -		ch_info = iwl_get_channel_info(priv, band, channel); -		if (!is_channel_valid(ch_info)) { -			IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", -					channel); -			continue; -		} - -		if (!is_active || is_channel_passive(ch_info) || -		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) -			scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; -		else -			scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; - -		if (n_probes) -			scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); - -		scan_ch->active_dwell = cpu_to_le16(active_dwell); -		scan_ch->passive_dwell = cpu_to_le16(passive_dwell); - -		/* Set txpower levels to defaults */ -		scan_ch->dsp_atten = 110; - -		/* NOTE: if we were doing 6Mb OFDM for scans we'd use -		 * power level: -		 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; -		 */ -		if (band == IEEE80211_BAND_5GHZ) -			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; -		else -			scan_ch->tx_gain = ((1 << 5) | (5 << 3)); - -		IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", -			       channel, le32_to_cpu(scan_ch->type), -			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? -				"ACTIVE" : "PASSIVE", -			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? -			       active_dwell : passive_dwell); - -		scan_ch++; -		added++; -	} - -	IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); -	return added; -} -  void iwl_init_scan_params(struct iwl_priv *priv)  {  	u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; @@ -470,30 +297,34 @@ EXPORT_SYMBOL(iwl_init_scan_params);  static int iwl_scan_initiate(struct iwl_priv *priv)  { +	WARN_ON(!mutex_is_locked(&priv->mutex)); +  	IWL_DEBUG_INFO(priv, "Starting scan...\n");  	set_bit(STATUS_SCANNING, &priv->status);  	priv->is_internal_short_scan = false;  	priv->scan_start = jiffies; -	priv->scan_pass_start = priv->scan_start; -	queue_work(priv->workqueue, &priv->request_scan); +	if (WARN_ON(!priv->cfg->ops->utils->request_scan)) +		return -EOPNOTSUPP; + +	priv->cfg->ops->utils->request_scan(priv);  	return 0;  } -#define IWL_DELAY_NEXT_SCAN (HZ*2) -  int iwl_mac_hw_scan(struct ieee80211_hw *hw, -		     struct cfg80211_scan_request *req) +		    struct ieee80211_vif *vif, +		    struct cfg80211_scan_request *req)  { -	unsigned long flags;  	struct iwl_priv *priv = hw->priv; -	int ret, i; +	int ret;  	IWL_DEBUG_MAC80211(priv, "enter\n"); +	if (req->n_channels == 0) +		return -EINVAL; +  	mutex_lock(&priv->mutex); -	spin_lock_irqsave(&priv->lock, flags);  	if (!iwl_is_ready_rf(priv)) {  		ret = -EIO; @@ -513,22 +344,8 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,  		goto out_unlock;  	} -	/* We don't schedule scan within next_scan_jiffies period. -	 * Avoid scanning during possible EAPOL exchange, return -	 * success immediately. -	 */ -	if (priv->next_scan_jiffies && -	    time_after(priv->next_scan_jiffies, jiffies)) { -		IWL_DEBUG_SCAN(priv, "scan rejected: within next scan period\n"); -		queue_work(priv->workqueue, &priv->scan_completed); -		ret = 0; -		goto out_unlock; -	} - -	priv->scan_bands = 0; -	for (i = 0; i < req->n_channels; i++) -		priv->scan_bands |= BIT(req->channels[i]->band); - +	/* mac80211 will only ask for one band at a time */ +	priv->scan_band = req->channels[0]->band;  	priv->scan_request = req;  	ret = iwl_scan_initiate(priv); @@ -536,7 +353,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,  	IWL_DEBUG_MAC80211(priv, "leave\n");  out_unlock: -	spin_unlock_irqrestore(&priv->lock, flags);  	mutex_unlock(&priv->mutex);  	return ret; @@ -547,42 +363,46 @@ EXPORT_SYMBOL(iwl_mac_hw_scan);   * internal short scan, this function should only been called while associated.   * It will reset and tune the radio to prevent possible RF related problem   */ -int iwl_internal_short_hw_scan(struct iwl_priv *priv) +void iwl_internal_short_hw_scan(struct iwl_priv *priv)  { -	int ret = 0; +	queue_work(priv->workqueue, &priv->start_internal_scan); +} + +static void iwl_bg_start_internal_scan(struct work_struct *work) +{ +	struct iwl_priv *priv = +		container_of(work, struct iwl_priv, start_internal_scan); + +	mutex_lock(&priv->mutex);  	if (!iwl_is_ready_rf(priv)) { -		ret = -EIO;  		IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); -		goto out; +		goto unlock;  	} +  	if (test_bit(STATUS_SCANNING, &priv->status)) {  		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); -		ret = -EAGAIN; -		goto out; +		goto unlock;  	} +  	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {  		IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); -		ret = -EAGAIN; -		goto out; +		goto unlock;  	} -	priv->scan_bands = 0; -	if (priv->band == IEEE80211_BAND_5GHZ) -		priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); -	else -		priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); +	priv->scan_band = priv->band;  	IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");  	set_bit(STATUS_SCANNING, &priv->status);  	priv->is_internal_short_scan = true; -	queue_work(priv->workqueue, &priv->request_scan); -out: -	return ret; -} +	if (WARN_ON(!priv->cfg->ops->utils->request_scan)) +		goto unlock; -#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) +	priv->cfg->ops->utils->request_scan(priv); + unlock: +	mutex_unlock(&priv->mutex); +}  void iwl_bg_scan_check(struct work_struct *data)  { @@ -645,275 +465,15 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,  	if (WARN_ON(left < ie_len))  		return len; -	if (ies) +	if (ies && ie_len) {  		memcpy(pos, ies, ie_len); -	len += ie_len; -	left -= ie_len; +		len += ie_len; +	}  	return (u16)len;  }  EXPORT_SYMBOL(iwl_fill_probe_req); -static void iwl_bg_request_scan(struct work_struct *data) -{ -	struct iwl_priv *priv = -	    container_of(data, struct iwl_priv, request_scan); -	struct iwl_host_cmd cmd = { -		.id = REPLY_SCAN_CMD, -		.len = sizeof(struct iwl_scan_cmd), -		.flags = CMD_SIZE_HUGE, -	}; -	struct iwl_scan_cmd *scan; -	struct ieee80211_conf *conf = NULL; -	u32 rate_flags = 0; -	u16 cmd_len; -	u16 rx_chain = 0; -	enum ieee80211_band band; -	u8 n_probes = 0; -	u8 rx_ant = priv->hw_params.valid_rx_ant; -	u8 rate; -	bool is_active = false; -	int  chan_mod; -	u8 active_chains; - -	conf = ieee80211_get_hw_conf(priv->hw); - -	mutex_lock(&priv->mutex); - -	cancel_delayed_work(&priv->scan_check); - -	if (!iwl_is_ready(priv)) { -		IWL_WARN(priv, "request scan called when driver not ready.\n"); -		goto done; -	} - -	/* Make sure the scan wasn't canceled before this queued work -	 * was given the chance to run... */ -	if (!test_bit(STATUS_SCANNING, &priv->status)) -		goto done; - -	/* This should never be called or scheduled if there is currently -	 * a scan active in the hardware. */ -	if (test_bit(STATUS_SCAN_HW, &priv->status)) { -		IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " -			       "Ignoring second request.\n"); -		goto done; -	} - -	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { -		IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); -		goto done; -	} - -	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { -		IWL_DEBUG_HC(priv, "Scan request while abort pending.  Queuing.\n"); -		goto done; -	} - -	if (iwl_is_rfkill(priv)) { -		IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); -		goto done; -	} - -	if (!test_bit(STATUS_READY, &priv->status)) { -		IWL_DEBUG_HC(priv, "Scan request while uninitialized.  Queuing.\n"); -		goto done; -	} - -	if (!priv->scan_bands) { -		IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n"); -		goto done; -	} - -	if (!priv->scan) { -		priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) + -				     IWL_MAX_SCAN_SIZE, GFP_KERNEL); -		if (!priv->scan) { -			IWL_DEBUG_SCAN(priv, -				       "fail to allocate memory for scan\n"); -			goto done; -		} -	} -	scan = priv->scan; -	memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); - -	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; -	scan->quiet_time = IWL_ACTIVE_QUIET_TIME; - -	if (iwl_is_associated(priv)) { -		u16 interval = 0; -		u32 extra; -		u32 suspend_time = 100; -		u32 scan_suspend_time = 100; -		unsigned long flags; - -		IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); -		spin_lock_irqsave(&priv->lock, flags); -		interval = priv->beacon_int; -		spin_unlock_irqrestore(&priv->lock, flags); - -		scan->suspend_time = 0; -		scan->max_out_time = cpu_to_le32(200 * 1024); -		if (!interval) -			interval = suspend_time; - -		extra = (suspend_time / interval) << 22; -		scan_suspend_time = (extra | -		    ((suspend_time % interval) * 1024)); -		scan->suspend_time = cpu_to_le32(scan_suspend_time); -		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", -			       scan_suspend_time, interval); -	} - -	if (priv->is_internal_short_scan) { -		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); -	} else if (priv->scan_request->n_ssids) { -		int i, p = 0; -		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); -		for (i = 0; i < priv->scan_request->n_ssids; i++) { -			/* always does wildcard anyway */ -			if (!priv->scan_request->ssids[i].ssid_len) -				continue; -			scan->direct_scan[p].id = WLAN_EID_SSID; -			scan->direct_scan[p].len = -				priv->scan_request->ssids[i].ssid_len; -			memcpy(scan->direct_scan[p].ssid, -			       priv->scan_request->ssids[i].ssid, -			       priv->scan_request->ssids[i].ssid_len); -			n_probes++; -			p++; -		} -		is_active = true; -	} else -		IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); - -	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; -	scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; -	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - -	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { -		band = IEEE80211_BAND_2GHZ; -		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; -		chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) -				       >> RXON_FLG_CHANNEL_MODE_POS; -		if (chan_mod == CHANNEL_MODE_PURE_40) { -			rate = IWL_RATE_6M_PLCP; -		} else { -			rate = IWL_RATE_1M_PLCP; -			rate_flags = RATE_MCS_CCK_MSK; -		} -		scan->good_CRC_th = 0; -	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { -		band = IEEE80211_BAND_5GHZ; -		rate = IWL_RATE_6M_PLCP; -		/* -		 * If active scaning is requested but a certain channel -		 * is marked passive, we can do active scanning if we -		 * detect transmissions. -		 */ -		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; - -		/* Force use of chains B and C (0x6) for scan Rx -		 * Avoid A (0x1) for the device has off-channel reception -		 * on A-band. -		 */ -		if (priv->cfg->off_channel_workaround) -			rx_ant = ANT_BC; -	} else { -		IWL_WARN(priv, "Invalid scan band count\n"); -		goto done; -	} - -	priv->scan_tx_ant[band] = -			 iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); -	rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); -	scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); - -	/* In power save mode use one chain, otherwise use all chains */ -	if (test_bit(STATUS_POWER_PMI, &priv->status)) { -		/* rx_ant has been set to all valid chains previously */ -		active_chains = rx_ant & -				((u8)(priv->chain_noise_data.active_chains)); -		if (!active_chains) -			active_chains = rx_ant; - -		IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", -				priv->chain_noise_data.active_chains); - -		rx_ant = first_antenna(active_chains); -	} -	/* MIMO is not used here, but value is required */ -	rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; -	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; -	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; -	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; -	scan->rx_chain = cpu_to_le16(rx_chain); -	if (!priv->is_internal_short_scan) { -		cmd_len = iwl_fill_probe_req(priv, -					(struct ieee80211_mgmt *)scan->data, -					priv->scan_request->ie, -					priv->scan_request->ie_len, -					IWL_MAX_SCAN_SIZE - sizeof(*scan)); -	} else { -		cmd_len = iwl_fill_probe_req(priv, -					(struct ieee80211_mgmt *)scan->data, -					NULL, 0, -					IWL_MAX_SCAN_SIZE - sizeof(*scan)); - -	} -	scan->tx_cmd.len = cpu_to_le16(cmd_len); -	if (iwl_is_monitor_mode(priv)) -		scan->filter_flags = RXON_FILTER_PROMISC_MSK; - -	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | -			       RXON_FILTER_BCON_AWARE_MSK); - -	if (priv->is_internal_short_scan) { -		scan->channel_count = -			iwl_get_single_channel_for_scan(priv, band, -				(void *)&scan->data[le16_to_cpu( -				scan->tx_cmd.len)]); -	} else { -		scan->channel_count = -			iwl_get_channels_for_scan(priv, band, -				is_active, n_probes, -				(void *)&scan->data[le16_to_cpu( -				scan->tx_cmd.len)]); -	} -	if (scan->channel_count == 0) { -		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); -		goto done; -	} - -	cmd.len += le16_to_cpu(scan->tx_cmd.len) + -	    scan->channel_count * sizeof(struct iwl_scan_channel); -	cmd.data = scan; -	scan->len = cpu_to_le16(cmd.len); - -	set_bit(STATUS_SCAN_HW, &priv->status); -	if (iwl_send_cmd_sync(priv, &cmd)) -		goto done; - -	queue_delayed_work(priv->workqueue, &priv->scan_check, -			   IWL_SCAN_CHECK_WATCHDOG); - -	mutex_unlock(&priv->mutex); -	return; - - done: -	/* Cannot perform scan. Make sure we clear scanning -	* bits from status so next scan request can be performed. -	* If we don't clear scanning status bit here all next scan -	* will fail -	*/ -	clear_bit(STATUS_SCAN_HW, &priv->status); -	clear_bit(STATUS_SCANNING, &priv->status); -	/* inform mac80211 scan aborted */ -	queue_work(priv->workqueue, &priv->scan_completed); -	mutex_unlock(&priv->mutex); -} -  void iwl_bg_abort_scan(struct work_struct *work)  {  	struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); @@ -961,8 +521,8 @@ EXPORT_SYMBOL(iwl_bg_scan_completed);  void iwl_setup_scan_deferred_work(struct iwl_priv *priv)  {  	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); -	INIT_WORK(&priv->request_scan, iwl_bg_request_scan);  	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); +	INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);  	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);  }  EXPORT_SYMBOL(iwl_setup_scan_deferred_work); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index d86ecd2f9ec..db934476b5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -451,7 +451,17 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap)  	link_cmd.general_params.single_stream_ant_msk =  				first_antenna(priv->hw_params.valid_tx_ant); -	link_cmd.general_params.dual_stream_ant_msk = 3; + +	link_cmd.general_params.dual_stream_ant_msk = +		priv->hw_params.valid_tx_ant & +		~first_antenna(priv->hw_params.valid_tx_ant); +	if (!link_cmd.general_params.dual_stream_ant_msk) { +		link_cmd.general_params.dual_stream_ant_msk = ANT_AB; +	} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { +		link_cmd.general_params.dual_stream_ant_msk = +			priv->hw_params.valid_tx_ant; +	} +  	link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;  	link_cmd.agg_params.agg_time_limit =  		cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); @@ -1196,7 +1206,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,  	iwl_dump_lq_cmd(priv, lq);  	BUG_ON(init && (cmd.flags & CMD_ASYNC)); -	iwl_dump_lq_cmd(priv, lq);  	ret = iwl_send_cmd(priv, &cmd);  	if (ret || (cmd.flags & CMD_ASYNC))  		return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 9f362024a29..c7e1d7d09e0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -957,7 +957,7 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)  	 * statistics request from the host as well as for the periodic  	 * statistics notifications (after received beacons) from the uCode.  	 */ -	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; +	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics;  	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;  	iwl_setup_rx_scan_handlers(priv); @@ -2527,7 +2527,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)  	}  	/* Configure Bluetooth device coexistence support */ -	iwl_send_bt_config(priv); +	priv->cfg->ops->hcmd->send_bt_config(priv);  	/* Configure the adapter for unassociated operation */  	iwlcore_commit_rxon(priv); @@ -2791,11 +2791,8 @@ static void iwl3945_rfkill_poll(struct work_struct *data)  } -#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) -static void iwl3945_bg_request_scan(struct work_struct *data) +void iwl3945_request_scan(struct iwl_priv *priv)  { -	struct iwl_priv *priv = -	    container_of(data, struct iwl_priv, request_scan);  	struct iwl_host_cmd cmd = {  		.id = REPLY_SCAN_CMD,  		.len = sizeof(struct iwl3945_scan_cmd), @@ -2809,8 +2806,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)  	conf = ieee80211_get_hw_conf(priv->hw); -	mutex_lock(&priv->mutex); -  	cancel_delayed_work(&priv->scan_check);  	if (!iwl_is_ready(priv)) { @@ -2853,20 +2848,15 @@ static void iwl3945_bg_request_scan(struct work_struct *data)  		goto done;  	} -	if (!priv->scan_bands) { -		IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n"); -		goto done; -	} - -	if (!priv->scan) { -		priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) + -				     IWL_MAX_SCAN_SIZE, GFP_KERNEL); -		if (!priv->scan) { +	if (!priv->scan_cmd) { +		priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) + +					 IWL_MAX_SCAN_SIZE, GFP_KERNEL); +		if (!priv->scan_cmd) {  			IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");  			goto done;  		}  	} -	scan = priv->scan; +	scan = priv->scan_cmd;  	memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);  	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; @@ -2935,22 +2925,26 @@ static void iwl3945_bg_request_scan(struct work_struct *data)  	/* flags + rate selection */ -	if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { +	switch (priv->scan_band) { +	case IEEE80211_BAND_2GHZ:  		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;  		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;  		scan->good_CRC_th = 0;  		band = IEEE80211_BAND_2GHZ; -	} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { +		break; +	case IEEE80211_BAND_5GHZ:  		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;  		/*  		 * If active scaning is requested but a certain channel  		 * is marked passive, we can do active scanning if we  		 * detect transmissions.  		 */ -		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; +		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : +						IWL_GOOD_CRC_TH_DISABLED;  		band = IEEE80211_BAND_5GHZ; -	} else { -		IWL_WARN(priv, "Invalid scan band count\n"); +		break; +	default: +		IWL_WARN(priv, "Invalid scan band\n");  		goto done;  	} @@ -2971,9 +2965,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)  	/* select Rx antennas */  	scan->flags |= iwl3945_get_antenna_flags(priv); -	if (iwl_is_monitor_mode(priv)) -		scan->filter_flags = RXON_FILTER_PROMISC_MSK; -  	scan->channel_count =  		iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,  			(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); @@ -2995,7 +2986,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)  	queue_delayed_work(priv->workqueue, &priv->scan_check,  			   IWL_SCAN_CHECK_WATCHDOG); -	mutex_unlock(&priv->mutex);  	return;   done: @@ -3009,7 +2999,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)  	/* inform mac80211 scan aborted */  	queue_work(priv->workqueue, &priv->scan_completed); -	mutex_unlock(&priv->mutex);  }  static void iwl3945_bg_restart(struct work_struct *data) @@ -3051,8 +3040,6 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)  	mutex_unlock(&priv->mutex);  } -#define IWL_DELAY_NEXT_SCAN (HZ*2) -  void iwl3945_post_associate(struct iwl_priv *priv)  {  	int rc = 0; @@ -3137,9 +3124,6 @@ void iwl3945_post_associate(struct iwl_priv *priv)  			   __func__, priv->iw_mode);  		break;  	} - -	/* we have just associated, don't start scan too early */ -	priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;  }  /***************************************************************************** @@ -3672,44 +3656,6 @@ static ssize_t show_channels(struct device *d,  static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); -static ssize_t show_statistics(struct device *d, -			       struct device_attribute *attr, char *buf) -{ -	struct iwl_priv *priv = dev_get_drvdata(d); -	u32 size = sizeof(struct iwl3945_notif_statistics); -	u32 len = 0, ofs = 0; -	u8 *data = (u8 *)&priv->_3945.statistics; -	int rc = 0; - -	if (!iwl_is_alive(priv)) -		return -EAGAIN; - -	mutex_lock(&priv->mutex); -	rc = iwl_send_statistics_request(priv, CMD_SYNC, false); -	mutex_unlock(&priv->mutex); - -	if (rc) { -		len = sprintf(buf, -			      "Error sending statistics request: 0x%08X\n", rc); -		return len; -	} - -	while (size && (PAGE_SIZE - len)) { -		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, -				   PAGE_SIZE - len, 1); -		len = strlen(buf); -		if (PAGE_SIZE - len) -			buf[len++] = '\n'; - -		ofs += 16; -		size -= min(size, 16U); -	} - -	return len; -} - -static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); -  static ssize_t show_antenna(struct device *d,  			    struct device_attribute *attr, char *buf)  { @@ -3793,7 +3739,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)  	INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);  	INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);  	INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); -	INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);  	INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);  	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); @@ -3830,7 +3775,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {  	&dev_attr_filter_flags.attr,  	&dev_attr_measurement.attr,  	&dev_attr_retry_rate.attr, -	&dev_attr_statistics.attr,  	&dev_attr_status.attr,  	&dev_attr_temperature.attr,  	&dev_attr_tx_power.attr, @@ -3930,7 +3874,6 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)  	/* Tell mac80211 our characteristics */  	hw->flags = IEEE80211_HW_SIGNAL_DBM | -		    IEEE80211_HW_NOISE_DBM |  		    IEEE80211_HW_SPECTRUM_MGMT;  	if (!priv->cfg->broken_powersave) @@ -4253,7 +4196,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)  	iwl_free_channel_map(priv);  	iwlcore_free_geos(priv); -	kfree(priv->scan); +	kfree(priv->scan_cmd);  	if (priv->ibss_beacon)  		dev_kfree_skb(priv->ibss_beacon); diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile index aeed5cd8081..cdc7e07ba11 100644 --- a/drivers/net/wireless/iwmc3200wifi/Makefile +++ b/drivers/net/wireless/iwmc3200wifi/Makefile @@ -6,3 +6,5 @@ iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o  iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o  CFLAGS_trace.o := -I$(src) + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/iwmc3200wifi/bus.h b/drivers/net/wireless/iwmc3200wifi/bus.h index 836663eec25..62edd5888a7 100644 --- a/drivers/net/wireless/iwmc3200wifi/bus.h +++ b/drivers/net/wireless/iwmc3200wifi/bus.h @@ -31,7 +31,7 @@ struct iwm_if_ops {  	int (*disable)(struct iwm_priv *iwm);  	int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count); -	int (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir); +	void (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir);  	void (*debugfs_exit)(struct iwm_priv *iwm);  	const char *umac_name; diff --git a/drivers/net/wireless/iwmc3200wifi/debug.h b/drivers/net/wireless/iwmc3200wifi/debug.h index e35c9b693d1..a0c13a49ab3 100644 --- a/drivers/net/wireless/iwmc3200wifi/debug.h +++ b/drivers/net/wireless/iwmc3200wifi/debug.h @@ -113,13 +113,10 @@ struct iwm_debugfs {  };  #ifdef CONFIG_IWM_DEBUG -int iwm_debugfs_init(struct iwm_priv *iwm); +void iwm_debugfs_init(struct iwm_priv *iwm);  void iwm_debugfs_exit(struct iwm_priv *iwm);  #else -static inline int iwm_debugfs_init(struct iwm_priv *iwm) -{ -	return 0; -} +static inline void iwm_debugfs_init(struct iwm_priv *iwm) {}  static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {}  #endif diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c index 724441368a1..53b0b7711f0 100644 --- a/drivers/net/wireless/iwmc3200wifi/debugfs.c +++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c @@ -48,12 +48,11 @@ static struct {  #define add_dbg_module(dbg, name, id, initlevel) 	\  do {							\ -	struct dentry *d;				\  	dbg.dbg_module[id] = (initlevel);		\ -	d = debugfs_create_x8(name, 0600, dbg.dbgdir,	\ -			     &(dbg.dbg_module[id]));	\ -	if (!IS_ERR(d))					\ -		dbg.dbg_module_dentries[id] = d;        \ +	dbg.dbg_module_dentries[id] =			\ +		debugfs_create_x8(name, 0600,		\ +				dbg.dbgdir,		\ +				&(dbg.dbg_module[id]));	\  } while (0)  static int iwm_debugfs_u32_read(void *data, u64 *val) @@ -423,89 +422,29 @@ static const struct file_operations iwm_debugfs_fw_err_fops = {  	.read =		iwm_debugfs_fw_err_read,  }; -int iwm_debugfs_init(struct iwm_priv *iwm) +void iwm_debugfs_init(struct iwm_priv *iwm)  { -	int i, result; -	char devdir[16]; +	int i;  	iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); -	result = PTR_ERR(iwm->dbg.rootdir); -	if (!result || IS_ERR(iwm->dbg.rootdir)) { -		if (result == -ENODEV) { -			IWM_ERR(iwm, "DebugFS (CONFIG_DEBUG_FS) not " -				"enabled in kernel config\n"); -			result = 0;	/* No debugfs support */ -		} -		IWM_ERR(iwm, "Couldn't create rootdir: %d\n", result); -		goto error; -	} - -	snprintf(devdir, sizeof(devdir), "%s", wiphy_name(iwm_to_wiphy(iwm))); - -	iwm->dbg.devdir = debugfs_create_dir(devdir, iwm->dbg.rootdir); -	result = PTR_ERR(iwm->dbg.devdir); -	if (IS_ERR(iwm->dbg.devdir) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create devdir: %d\n", result); -		goto error; -	} - +	iwm->dbg.devdir = debugfs_create_dir(wiphy_name(iwm_to_wiphy(iwm)), +					     iwm->dbg.rootdir);  	iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir); -	result = PTR_ERR(iwm->dbg.dbgdir); -	if (IS_ERR(iwm->dbg.dbgdir) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create dbgdir: %d\n", result); -		goto error; -	} -  	iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir); -	result = PTR_ERR(iwm->dbg.rxdir); -	if (IS_ERR(iwm->dbg.rxdir) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create rx dir: %d\n", result); -		goto error; -	} -  	iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir); -	result = PTR_ERR(iwm->dbg.txdir); -	if (IS_ERR(iwm->dbg.txdir) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create tx dir: %d\n", result); -		goto error; -	} -  	iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir); -	result = PTR_ERR(iwm->dbg.busdir); -	if (IS_ERR(iwm->dbg.busdir) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create bus dir: %d\n", result); -		goto error; -	} - -	if (iwm->bus_ops->debugfs_init) { -		result = iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir); -		if (result < 0) { -			IWM_ERR(iwm, "Couldn't create bus entry: %d\n", result); -			goto error; -		} -	} - +	if (iwm->bus_ops->debugfs_init) +		iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir);  	iwm->dbg.dbg_level = IWM_DL_NONE;  	iwm->dbg.dbg_level_dentry =  		debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm,  				    &fops_iwm_dbg_level); -	result = PTR_ERR(iwm->dbg.dbg_level_dentry); -	if (IS_ERR(iwm->dbg.dbg_level_dentry) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create dbg_level: %d\n", result); -		goto error; -	} -  	iwm->dbg.dbg_modules = IWM_DM_DEFAULT;  	iwm->dbg.dbg_modules_dentry =  		debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm,  				    &fops_iwm_dbg_modules); -	result = PTR_ERR(iwm->dbg.dbg_modules_dentry); -	if (IS_ERR(iwm->dbg.dbg_modules_dentry) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create dbg_modules: %d\n", result); -		goto error; -	}  	for (i = 0; i < __IWM_DM_NR; i++)  		add_dbg_module(iwm->dbg, iwm_debug_module[i].name, @@ -514,44 +453,15 @@ int iwm_debugfs_init(struct iwm_priv *iwm)  	iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200,  						  iwm->dbg.txdir, iwm,  						  &iwm_debugfs_txq_fops); -	result = PTR_ERR(iwm->dbg.txq_dentry); -	if (IS_ERR(iwm->dbg.txq_dentry) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create tx queue: %d\n", result); -		goto error; -	} -  	iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200,  						   iwm->dbg.txdir, iwm,  						   &iwm_debugfs_tx_credit_fops); -	result = PTR_ERR(iwm->dbg.tx_credit_dentry); -	if (IS_ERR(iwm->dbg.tx_credit_dentry) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create tx credit: %d\n", result); -		goto error; -	} -  	iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200,  						  iwm->dbg.rxdir, iwm,  						  &iwm_debugfs_rx_ticket_fops); -	result = PTR_ERR(iwm->dbg.rx_ticket_dentry); -	if (IS_ERR(iwm->dbg.rx_ticket_dentry) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create rx ticket: %d\n", result); -		goto error; -	} -  	iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200,  						     iwm->dbg.dbgdir, iwm,  						     &iwm_debugfs_fw_err_fops); -	result = PTR_ERR(iwm->dbg.fw_err_dentry); -	if (IS_ERR(iwm->dbg.fw_err_dentry) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create last FW err: %d\n", result); -		goto error; -	} - - -	return 0; - - error: -	return result;  }  void iwm_debugfs_exit(struct iwm_priv *iwm) diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index ad539877924..e1184deca55 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -431,7 +431,8 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,  				return PTR_ERR(ticket_node);  			IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n", -				   ticket->action ==  IWM_RX_TICKET_RELEASE ? +				   __le16_to_cpu(ticket->action) == +							IWM_RX_TICKET_RELEASE ?  				   "RELEASE" : "DROP",  				   ticket->id);  			spin_lock(&iwm->ticket_lock); diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c index 1eafd6dec3f..1acea37f39f 100644 --- a/drivers/net/wireless/iwmc3200wifi/sdio.c +++ b/drivers/net/wireless/iwmc3200wifi/sdio.c @@ -366,21 +366,13 @@ static const struct file_operations iwm_debugfs_sdio_fops = {  	.read =		iwm_debugfs_sdio_read,  }; -static int if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir) +static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)  { -	int result;  	struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);  	hw->cccr_dentry = debugfs_create_file("cccr", 0200,  					      parent_dir, iwm,  					      &iwm_debugfs_sdio_fops); -	result = PTR_ERR(hw->cccr_dentry); -	if (IS_ERR(hw->cccr_dentry) && (result != -ENODEV)) { -		IWM_ERR(iwm, "Couldn't create CCCR entry: %d\n", result); -		return result; -	} - -	return 0;  }  static void if_sdio_debugfs_exit(struct iwm_priv *iwm) @@ -440,11 +432,7 @@ static int iwm_sdio_probe(struct sdio_func *func,  	hw = iwm_private(iwm);  	hw->iwm = iwm; -	ret = iwm_debugfs_init(iwm); -	if (ret < 0) { -		IWM_ERR(iwm, "Debugfs registration failed\n"); -		goto if_free; -	} +	iwm_debugfs_init(iwm);  	sdio_set_drvdata(func, hw); @@ -473,7 +461,6 @@ static int iwm_sdio_probe(struct sdio_func *func,  	destroy_workqueue(hw->isr_wq);   debugfs_exit:  	iwm_debugfs_exit(iwm); - if_free:  	iwm_if_free(iwm);  	return ret;  } diff --git a/drivers/net/wireless/iwmc3200wifi/trace.h b/drivers/net/wireless/iwmc3200wifi/trace.h index 320e54fbb38..abb4805fa8d 100644 --- a/drivers/net/wireless/iwmc3200wifi/trace.h +++ b/drivers/net/wireless/iwmc3200wifi/trace.h @@ -76,7 +76,7 @@ TRACE_EVENT(iwm_tx_wifi_cmd,  		IWM_ASSIGN;  		__entry->opcode = hdr->sw_hdr.cmd.cmd;  		__entry->lmac = 0; -		__entry->seq = hdr->sw_hdr.cmd.seq_num; +		__entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num);  		__entry->resp = GET_VAL8(hdr->sw_hdr.cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ);  		__entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);  		__entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT); @@ -123,7 +123,7 @@ TRACE_EVENT(iwm_tx_packets,  		__entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID);  		__entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP);  		__entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR); -		__entry->seq = hdr->sw_hdr.cmd.seq_num; +		__entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num);  		__entry->npkt = 1;  		__entry->bytes = len; diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c index 9537cdb13d3..3216621fc55 100644 --- a/drivers/net/wireless/iwmc3200wifi/tx.c +++ b/drivers/net/wireless/iwmc3200wifi/tx.c @@ -302,8 +302,8 @@ void iwm_tx_credit_init_pools(struct iwm_priv *iwm,  #define IWM_UDMA_HDR_LEN	sizeof(struct iwm_umac_wifi_out_hdr) -static int iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb, -			       int pool_id, u8 *buf) +static __le16 iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb, +				  int pool_id, u8 *buf)  {  	struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf;  	struct iwm_udma_wifi_cmd udma_cmd; diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index cd464a2589b..64dd345d30f 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -315,12 +315,30 @@ out:  	return ret;  } +static int if_sdio_wait_status(struct if_sdio_card *card, const u8 condition) +{ +	u8 status; +	unsigned long timeout; +	int ret = 0; + +	timeout = jiffies + HZ; +	while (1) { +		status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); +		if (ret) +			return ret; +		if ((status & condition) == condition) +			break; +		if (time_after(jiffies, timeout)) +			return -ETIMEDOUT; +		mdelay(1); +	} +	return ret; +} +  static int if_sdio_card_to_host(struct if_sdio_card *card)  {  	int ret; -	u8 status;  	u16 size, type, chunk; -	unsigned long timeout;  	lbs_deb_enter(LBS_DEB_SDIO); @@ -335,19 +353,9 @@ static int if_sdio_card_to_host(struct if_sdio_card *card)  		goto out;  	} -	timeout = jiffies + HZ; -	while (1) { -		status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); -		if (ret) -			goto out; -		if (status & IF_SDIO_IO_RDY) -			break; -		if (time_after(jiffies, timeout)) { -			ret = -ETIMEDOUT; -			goto out; -		} -		mdelay(1); -	} +	ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY); +	if (ret) +		goto out;  	/*  	 * The transfer must be in one transaction or the firmware @@ -414,8 +422,6 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)  {  	struct if_sdio_card *card;  	struct if_sdio_packet *packet; -	unsigned long timeout; -	u8 status;  	int ret;  	unsigned long flags; @@ -435,25 +441,15 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)  		sdio_claim_host(card->func); -		timeout = jiffies + HZ; -		while (1) { -			status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); -			if (ret) -				goto release; -			if (status & IF_SDIO_IO_RDY) -				break; -			if (time_after(jiffies, timeout)) { -				ret = -ETIMEDOUT; -				goto release; -			} -			mdelay(1); +		ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY); +		if (ret == 0) { +			ret = sdio_writesb(card->func, card->ioport, +					   packet->buffer, packet->nb);  		} -		ret = sdio_writesb(card->func, card->ioport, -				packet->buffer, packet->nb);  		if (ret) -			goto release; -release: +			lbs_pr_err("error %d sending packet to firmware\n", ret); +  		sdio_release_host(card->func);  		kfree(packet); @@ -466,10 +462,11 @@ release:  /* Firmware                                                         */  /********************************************************************/ +#define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) +  static int if_sdio_prog_helper(struct if_sdio_card *card)  {  	int ret; -	u8 status;  	const struct firmware *fw;  	unsigned long timeout;  	u8 *chunk_buffer; @@ -501,20 +498,14 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)  	size = fw->size;  	while (size) { -		timeout = jiffies + HZ; -		while (1) { -			status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); -			if (ret) -				goto release; -			if ((status & IF_SDIO_IO_RDY) && -					(status & IF_SDIO_DL_RDY)) -				break; -			if (time_after(jiffies, timeout)) { -				ret = -ETIMEDOUT; -				goto release; -			} -			mdelay(1); -		} +		ret = if_sdio_wait_status(card, FW_DL_READY_STATUS); +		if (ret) +			goto release; + +		/* On some platforms (like Davinci) the chip needs more time +		 * between helper blocks. +		 */ +		mdelay(2);  		chunk_size = min(size, (size_t)60); @@ -584,7 +575,6 @@ out:  static int if_sdio_prog_real(struct if_sdio_card *card)  {  	int ret; -	u8 status;  	const struct firmware *fw;  	unsigned long timeout;  	u8 *chunk_buffer; @@ -616,20 +606,9 @@ static int if_sdio_prog_real(struct if_sdio_card *card)  	size = fw->size;  	while (size) { -		timeout = jiffies + HZ; -		while (1) { -			status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); -			if (ret) -				goto release; -			if ((status & IF_SDIO_IO_RDY) && -					(status & IF_SDIO_DL_RDY)) -				break; -			if (time_after(jiffies, timeout)) { -				ret = -ETIMEDOUT; -				goto release; -			} -			mdelay(1); -		} +		ret = if_sdio_wait_status(card, FW_DL_READY_STATUS); +		if (ret) +			goto release;  		req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);  		if (ret) diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c index b620daf59ef..8945afd6ce3 100644 --- a/drivers/net/wireless/libertas_tf/cmd.c +++ b/drivers/net/wireless/libertas_tf/cmd.c @@ -7,6 +7,8 @@   *  the Free Software Foundation; either version 2 of the License, or (at   *  your option) any later version.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/slab.h>  #include "libertas_tf.h" @@ -82,6 +84,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)  	int ret = -1;  	u32 i; +	lbtf_deb_enter(LBTF_DEB_CMD); +  	memset(&cmd, 0, sizeof(cmd));  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN); @@ -104,6 +108,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)  		priv->fwrelease >>  8 & 0xff,  		priv->fwrelease       & 0xff,  		priv->fwcapinfo); +	lbtf_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", +		    cmd.hwifversion, cmd.version);  	/* Clamp region code to 8-bit since FW spec indicates that it should  	 * only ever be 8-bit, even though the field size is 16-bit.  Some @@ -118,8 +124,10 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)  	}  	/* if it's unidentified region code, use the default (USA) */ -	if (i >= MRVDRV_MAX_REGION_CODE) +	if (i >= MRVDRV_MAX_REGION_CODE) {  		priv->regioncode = 0x10; +		pr_info("unidentified region code; using the default (USA)\n"); +	}  	if (priv->current_addr[0] == 0xff)  		memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); @@ -128,6 +136,7 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)  	lbtf_geo_init(priv);  out: +	lbtf_deb_leave(LBTF_DEB_CMD);  	return ret;  } @@ -141,13 +150,18 @@ out:   */  int lbtf_set_channel(struct lbtf_private *priv, u8 channel)  { +	int ret = 0;  	struct cmd_ds_802_11_rf_channel cmd; +	lbtf_deb_enter(LBTF_DEB_CMD); +  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);  	cmd.channel = cpu_to_le16(channel); -	return lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); +	ret = lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); +	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret); +	return ret;  }  int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon) @@ -155,20 +169,28 @@ int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)  	struct cmd_ds_802_11_beacon_set cmd;  	int size; -	if (beacon->len > MRVL_MAX_BCN_SIZE) +	lbtf_deb_enter(LBTF_DEB_CMD); + +	if (beacon->len > MRVL_MAX_BCN_SIZE) { +		lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", -1);  		return -1; +	}  	size =  sizeof(cmd) - sizeof(cmd.beacon) + beacon->len;  	cmd.hdr.size = cpu_to_le16(size);  	cmd.len = cpu_to_le16(beacon->len);  	memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len);  	lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size); + +	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", 0);  	return 0;  }  int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable, -		     int beacon_int) { +		     int beacon_int) +{  	struct cmd_ds_802_11_beacon_control cmd; +	lbtf_deb_enter(LBTF_DEB_CMD);  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.action = cpu_to_le16(CMD_ACT_SET); @@ -176,6 +198,8 @@ int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,  	cmd.beacon_period = cpu_to_le16(beacon_int);  	lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd)); + +	lbtf_deb_leave(LBTF_DEB_CMD);  	return 0;  } @@ -183,17 +207,28 @@ static void lbtf_queue_cmd(struct lbtf_private *priv,  			  struct cmd_ctrl_node *cmdnode)  {  	unsigned long flags; +	lbtf_deb_enter(LBTF_DEB_HOST); -	if (!cmdnode) -		return; +	if (!cmdnode) { +		lbtf_deb_host("QUEUE_CMD: cmdnode is NULL\n"); +		goto qcmd_done; +	} -	if (!cmdnode->cmdbuf->size) -		return; +	if (!cmdnode->cmdbuf->size) { +		lbtf_deb_host("DNLD_CMD: cmd size is zero\n"); +		goto qcmd_done; +	}  	cmdnode->result = 0;  	spin_lock_irqsave(&priv->driver_lock, flags);  	list_add_tail(&cmdnode->list, &priv->cmdpendingq);  	spin_unlock_irqrestore(&priv->driver_lock, flags); + +	lbtf_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n", +		     le16_to_cpu(cmdnode->cmdbuf->command)); + +qcmd_done: +	lbtf_deb_leave(LBTF_DEB_HOST);  }  static void lbtf_submit_command(struct lbtf_private *priv, @@ -206,22 +241,33 @@ static void lbtf_submit_command(struct lbtf_private *priv,  	int timeo = 5 * HZ;  	int ret; +	lbtf_deb_enter(LBTF_DEB_HOST); +  	cmd = cmdnode->cmdbuf;  	spin_lock_irqsave(&priv->driver_lock, flags);  	priv->cur_cmd = cmdnode;  	cmdsize = le16_to_cpu(cmd->size);  	command = le16_to_cpu(cmd->command); + +	lbtf_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n", +		     command, le16_to_cpu(cmd->seqnum), cmdsize); +	lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize); +  	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);  	spin_unlock_irqrestore(&priv->driver_lock, flags); -	if (ret) +	if (ret) { +		pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);  		/* Let the timer kick in and retry, and potentially reset  		   the whole thing if the condition persists */  		timeo = HZ; +	}  	/* Setup the timer after transmit command */  	mod_timer(&priv->command_timer, jiffies + timeo); + +	lbtf_deb_leave(LBTF_DEB_HOST);  }  /** @@ -231,8 +277,10 @@ static void lbtf_submit_command(struct lbtf_private *priv,  static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,  					 struct cmd_ctrl_node *cmdnode)  { +	lbtf_deb_enter(LBTF_DEB_HOST); +  	if (!cmdnode) -		return; +		goto cl_ins_out;  	cmdnode->callback = NULL;  	cmdnode->callback_arg = 0; @@ -240,6 +288,9 @@ static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,  	memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);  	list_add_tail(&cmdnode->list, &priv->cmdfreeq); + +cl_ins_out: +	lbtf_deb_leave(LBTF_DEB_HOST);  }  static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv, @@ -268,29 +319,41 @@ int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv)  {  	struct cmd_ds_mac_multicast_addr cmd; +	lbtf_deb_enter(LBTF_DEB_CMD); +  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.action = cpu_to_le16(CMD_ACT_SET);  	cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr); + +	lbtf_deb_cmd("MULTICAST_ADR: setting %d addresses\n", cmd.nr_of_adrs); +  	memcpy(cmd.maclist, priv->multicastlist,  	       priv->nr_of_multicastmacaddr * ETH_ALEN);  	lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd)); + +	lbtf_deb_leave(LBTF_DEB_CMD);  	return 0;  }  void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode)  {  	struct cmd_ds_set_mode cmd; +	lbtf_deb_enter(LBTF_DEB_WEXT);  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.mode = cpu_to_le16(mode); +	lbtf_deb_wext("Switching to mode: 0x%x\n", mode);  	lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd)); + +	lbtf_deb_leave(LBTF_DEB_WEXT);  }  void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)  {  	struct cmd_ds_set_bssid cmd; +	lbtf_deb_enter(LBTF_DEB_CMD);  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.activate = activate ? 1 : 0; @@ -298,11 +361,13 @@ void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)  		memcpy(cmd.bssid, bssid, ETH_ALEN);  	lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd)); +	lbtf_deb_leave(LBTF_DEB_CMD);  }  int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)  {  	struct cmd_ds_802_11_mac_address cmd; +	lbtf_deb_enter(LBTF_DEB_CMD);  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.action = cpu_to_le16(CMD_ACT_SET); @@ -310,6 +375,7 @@ int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)  	memcpy(cmd.macadd, mac_addr, ETH_ALEN);  	lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd)); +	lbtf_deb_leave(LBTF_DEB_CMD);  	return 0;  } @@ -318,6 +384,8 @@ int lbtf_set_radio_control(struct lbtf_private *priv)  	int ret = 0;  	struct cmd_ds_802_11_radio_control cmd; +	lbtf_deb_enter(LBTF_DEB_CMD); +  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.action = cpu_to_le16(CMD_ACT_SET); @@ -341,19 +409,28 @@ int lbtf_set_radio_control(struct lbtf_private *priv)  	else  		cmd.control &= cpu_to_le16(~TURN_ON_RF); +	lbtf_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon, +		    priv->preamble); +  	ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd); + +	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);  	return ret;  }  void lbtf_set_mac_control(struct lbtf_private *priv)  {  	struct cmd_ds_mac_control cmd; +	lbtf_deb_enter(LBTF_DEB_CMD); +  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.action = cpu_to_le16(priv->mac_control);  	cmd.reserved = 0;  	lbtf_cmd_async(priv, CMD_MAC_CONTROL,  		&cmd.hdr, sizeof(cmd)); + +	lbtf_deb_leave(LBTF_DEB_CMD);  }  /** @@ -365,29 +442,43 @@ void lbtf_set_mac_control(struct lbtf_private *priv)   */  int lbtf_allocate_cmd_buffer(struct lbtf_private *priv)  { +	int ret = 0;  	u32 bufsize;  	u32 i;  	struct cmd_ctrl_node *cmdarray; +	lbtf_deb_enter(LBTF_DEB_HOST); +  	/* Allocate and initialize the command array */  	bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;  	cmdarray = kzalloc(bufsize, GFP_KERNEL); -	if (!cmdarray) -		return -1; +	if (!cmdarray) { +		lbtf_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n"); +		ret = -1; +		goto done; +	}  	priv->cmd_array = cmdarray;  	/* Allocate and initialize each command buffer in the command array */  	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {  		cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL); -		if (!cmdarray[i].cmdbuf) -			return -1; +		if (!cmdarray[i].cmdbuf) { +			lbtf_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n"); +			ret = -1; +			goto done; +		}  	}  	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {  		init_waitqueue_head(&cmdarray[i].cmdwait_q);  		lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]);  	} -	return 0; + +	ret = 0; + +done: +	lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret); +	return ret;  }  /** @@ -402,9 +493,13 @@ int lbtf_free_cmd_buffer(struct lbtf_private *priv)  	struct cmd_ctrl_node *cmdarray;  	unsigned int i; +	lbtf_deb_enter(LBTF_DEB_HOST); +  	/* need to check if cmd array is allocated or not */ -	if (priv->cmd_array == NULL) -		return 0; +	if (priv->cmd_array == NULL) { +		lbtf_deb_host("FREE_CMD_BUF: cmd_array is NULL\n"); +		goto done; +	}  	cmdarray = priv->cmd_array; @@ -418,6 +513,8 @@ int lbtf_free_cmd_buffer(struct lbtf_private *priv)  	kfree(priv->cmd_array);  	priv->cmd_array = NULL; +done: +	lbtf_deb_leave(LBTF_DEB_HOST);  	return 0;  } @@ -433,6 +530,8 @@ static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)  	struct cmd_ctrl_node *tempnode;  	unsigned long flags; +	lbtf_deb_enter(LBTF_DEB_HOST); +  	if (!priv)  		return NULL; @@ -442,11 +541,14 @@ static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)  		tempnode = list_first_entry(&priv->cmdfreeq,  					    struct cmd_ctrl_node, list);  		list_del(&tempnode->list); -	} else +	} else { +		lbtf_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");  		tempnode = NULL; +	}  	spin_unlock_irqrestore(&priv->driver_lock, flags); +	lbtf_deb_leave(LBTF_DEB_HOST);  	return tempnode;  } @@ -462,16 +564,20 @@ int lbtf_execute_next_command(struct lbtf_private *priv)  	struct cmd_ctrl_node *cmdnode = NULL;  	struct cmd_header *cmd;  	unsigned long flags; +	int ret = 0; -	/* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the +	/* Debug group is lbtf_deb_THREAD and not lbtf_deb_HOST, because the  	 * only caller to us is lbtf_thread() and we get even when a  	 * data packet is received */ +	lbtf_deb_enter(LBTF_DEB_THREAD);  	spin_lock_irqsave(&priv->driver_lock, flags);  	if (priv->cur_cmd) { +		pr_alert("EXEC_NEXT_CMD: already processing command!\n");  		spin_unlock_irqrestore(&priv->driver_lock, flags); -		return -1; +		ret = -1; +		goto done;  	}  	if (!list_empty(&priv->cmdpendingq)) { @@ -483,11 +589,17 @@ int lbtf_execute_next_command(struct lbtf_private *priv)  		cmd = cmdnode->cmdbuf;  		list_del(&cmdnode->list); +		lbtf_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n", +			    le16_to_cpu(cmd->command));  		spin_unlock_irqrestore(&priv->driver_lock, flags);  		lbtf_submit_command(priv, cmdnode);  	} else  		spin_unlock_irqrestore(&priv->driver_lock, flags); -	return 0; + +	ret = 0; +done: +	lbtf_deb_leave(LBTF_DEB_THREAD); +	return ret;  }  static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv, @@ -498,14 +610,22 @@ static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,  {  	struct cmd_ctrl_node *cmdnode; -	if (priv->surpriseremoved) -		return ERR_PTR(-ENOENT); +	lbtf_deb_enter(LBTF_DEB_HOST); + +	if (priv->surpriseremoved) { +		lbtf_deb_host("PREP_CMD: card removed\n"); +		cmdnode = ERR_PTR(-ENOENT); +		goto done; +	}  	cmdnode = lbtf_get_cmd_ctrl_node(priv);  	if (cmdnode == NULL) { +		lbtf_deb_host("PREP_CMD: cmdnode is NULL\n"); +  		/* Wake up main thread to execute next command */  		queue_work(lbtf_wq, &priv->cmd_work); -		return ERR_PTR(-ENOBUFS); +		cmdnode = ERR_PTR(-ENOBUFS); +		goto done;  	}  	cmdnode->callback = callback; @@ -520,17 +640,24 @@ static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,  	cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);  	cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);  	cmdnode->cmdbuf->result  = 0; + +	lbtf_deb_host("PREP_CMD: command 0x%04x\n", command); +  	cmdnode->cmdwaitqwoken = 0;  	lbtf_queue_cmd(priv, cmdnode);  	queue_work(lbtf_wq, &priv->cmd_work); + done: +	lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %p", cmdnode);  	return cmdnode;  }  void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,  	struct cmd_header *in_cmd, int in_cmd_size)  { +	lbtf_deb_enter(LBTF_DEB_CMD);  	__lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0); +	lbtf_deb_leave(LBTF_DEB_CMD);  }  int __lbtf_cmd(struct lbtf_private *priv, uint16_t command, @@ -543,30 +670,35 @@ int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,  	unsigned long flags;  	int ret = 0; +	lbtf_deb_enter(LBTF_DEB_HOST); +  	cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size,  				  callback, callback_arg); -	if (IS_ERR(cmdnode)) -		return PTR_ERR(cmdnode); +	if (IS_ERR(cmdnode)) { +		ret = PTR_ERR(cmdnode); +		goto done; +	}  	might_sleep();  	ret = wait_event_interruptible(cmdnode->cmdwait_q,  				       cmdnode->cmdwaitqwoken); -       if (ret)	{ -		printk(KERN_DEBUG -		       "libertastf: command 0x%04x interrupted by signal", -		       command); -		return ret; +	if (ret) { +		pr_info("PREP_CMD: command 0x%04x interrupted by signal: %d\n", +			    command, ret); +		goto done;  	}  	spin_lock_irqsave(&priv->driver_lock, flags);  	ret = cmdnode->result;  	if (ret) -		printk(KERN_DEBUG "libertastf: command 0x%04x failed: %d\n", +		pr_info("PREP_CMD: command 0x%04x failed: %d\n",  			    command, ret);  	__lbtf_cleanup_and_insert_cmd(priv, cmdnode);  	spin_unlock_irqrestore(&priv->driver_lock, flags); +done: +	lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);  	return ret;  }  EXPORT_SYMBOL_GPL(__lbtf_cmd); @@ -587,6 +719,8 @@ int lbtf_process_rx_command(struct lbtf_private *priv)  	unsigned long flags;  	uint16_t result; +	lbtf_deb_enter(LBTF_DEB_CMD); +  	mutex_lock(&priv->lock);  	spin_lock_irqsave(&priv->driver_lock, flags); @@ -602,7 +736,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv)  	result = le16_to_cpu(resp->result);  	if (net_ratelimit()) -		printk(KERN_DEBUG "libertastf: cmd response 0x%04x, seq %d, size %d\n", +		pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n",  			respcmd, le16_to_cpu(resp->seqnum),  			le16_to_cpu(resp->size)); @@ -639,7 +773,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv)  		switch (respcmd) {  		case CMD_RET(CMD_GET_HW_SPEC):  		case CMD_RET(CMD_802_11_RESET): -			printk(KERN_DEBUG "libertastf: reset failed\n"); +			pr_info("libertastf: reset failed\n");  			break;  		} @@ -666,5 +800,6 @@ int lbtf_process_rx_command(struct lbtf_private *priv)  done:  	mutex_unlock(&priv->lock); +	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);  	return ret;  } diff --git a/drivers/net/wireless/libertas_tf/deb_defs.h b/drivers/net/wireless/libertas_tf/deb_defs.h new file mode 100644 index 00000000000..ae753962d8b --- /dev/null +++ b/drivers/net/wireless/libertas_tf/deb_defs.h @@ -0,0 +1,104 @@ +/** +  * This header file contains global constant/enum definitions, +  * global variable declaration. +  */ +#ifndef _LBS_DEB_DEFS_H_ +#define _LBS_DEB_EFS_H_ + +#ifndef DRV_NAME +#define DRV_NAME "libertas_tf" +#endif + +#include <linux/spinlock.h> + +#ifdef CONFIG_LIBERTAS_THINFIRM_DEBUG +#define DEBUG +#define PROC_DEBUG +#endif + +#define LBTF_DEB_ENTER	0x00000001 +#define LBTF_DEB_LEAVE	0x00000002 +#define LBTF_DEB_MAIN	0x00000004 +#define LBTF_DEB_NET	0x00000008 +#define LBTF_DEB_MESH	0x00000010 +#define LBTF_DEB_WEXT	0x00000020 +#define LBTF_DEB_IOCTL	0x00000040 +#define LBTF_DEB_SCAN	0x00000080 +#define LBTF_DEB_ASSOC	0x00000100 +#define LBTF_DEB_JOIN	0x00000200 +#define LBTF_DEB_11D	0x00000400 +#define LBTF_DEB_DEBUGFS	0x00000800 +#define LBTF_DEB_ETHTOOL	0x00001000 +#define LBTF_DEB_HOST	0x00002000 +#define LBTF_DEB_CMD	0x00004000 +#define LBTF_DEB_RX	0x00008000 +#define LBTF_DEB_TX	0x00010000 +#define LBTF_DEB_USB	0x00020000 +#define LBTF_DEB_CS	0x00040000 +#define LBTF_DEB_FW	0x00080000 +#define LBTF_DEB_THREAD	0x00100000 +#define LBTF_DEB_HEX	0x00200000 +#define LBTF_DEB_SDIO	0x00400000 +#define LBTF_DEB_MACOPS	0x00800000 + +extern unsigned int lbtf_debug; + + +#ifdef DEBUG +#define LBTF_DEB_LL(grp, grpnam, fmt, args...) \ +do { if ((lbtf_debug & (grp)) == (grp)) \ +  printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \ +         in_interrupt() ? " (INT)" : "", ## args); } while (0) +#else +#define LBTF_DEB_LL(grp, grpnam, fmt, args...) do {} while (0) +#endif + +#define lbtf_deb_enter(grp) \ +  LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s()\n", __func__); +#define lbtf_deb_enter_args(grp, fmt, args...) \ +  LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args); +#define lbtf_deb_leave(grp) \ +  LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s()\n", __func__); +#define lbtf_deb_leave_args(grp, fmt, args...) \ +  LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s(), " fmt "\n", \ +  __func__, ##args); +#define lbtf_deb_main(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MAIN, " main", fmt, ##args) +#define lbtf_deb_net(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_NET, " net", fmt, ##args) +#define lbtf_deb_mesh(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MESH, " mesh", fmt, ##args) +#define lbtf_deb_wext(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_WEXT, " wext", fmt, ##args) +#define lbtf_deb_ioctl(fmt, args...)     LBTF_DEB_LL(LBTF_DEB_IOCTL, " ioctl", fmt, ##args) +#define lbtf_deb_scan(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_SCAN, " scan", fmt, ##args) +#define lbtf_deb_assoc(fmt, args...)     LBTF_DEB_LL(LBTF_DEB_ASSOC, " assoc", fmt, ##args) +#define lbtf_deb_join(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_JOIN, " join", fmt, ##args) +#define lbtf_deb_11d(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_11D, " 11d", fmt, ##args) +#define lbtf_deb_debugfs(fmt, args...)   LBTF_DEB_LL(LBTF_DEB_DEBUGFS, " debugfs", fmt, ##args) +#define lbtf_deb_ethtool(fmt, args...)   LBTF_DEB_LL(LBTF_DEB_ETHTOOL, " ethtool", fmt, ##args) +#define lbtf_deb_host(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_HOST, " host", fmt, ##args) +#define lbtf_deb_cmd(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_CMD, " cmd", fmt, ##args) +#define lbtf_deb_rx(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_RX, " rx", fmt, ##args) +#define lbtf_deb_tx(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_TX, " tx", fmt, ##args) +#define lbtf_deb_fw(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_FW, " fw", fmt, ##args) +#define lbtf_deb_usb(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_USB, " usb", fmt, ##args) +#define lbtf_deb_usbd(dev, fmt, args...) LBTF_DEB_LL(LBTF_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args) +#define lbtf_deb_cs(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_CS, " cs", fmt, ##args) +#define lbtf_deb_thread(fmt, args...)    LBTF_DEB_LL(LBTF_DEB_THREAD, " thread", fmt, ##args) +#define lbtf_deb_sdio(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_SDIO, " thread", fmt, ##args) +#define lbtf_deb_macops(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MACOPS, " thread", fmt, ##args) + +#ifdef DEBUG +static inline void lbtf_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len) +{ +	char newprompt[32]; + +	if (len && +	    (lbtf_debug & LBTF_DEB_HEX) && +	    (lbtf_debug & grp))	{ +		snprintf(newprompt, sizeof(newprompt), DRV_NAME " %s: ", prompt); +		print_hex_dump_bytes(prompt, DUMP_PREFIX_NONE, buf, len); +	} +} +#else +#define lbtf_deb_hex(grp, prompt, buf, len)	do {} while (0) +#endif + +#endif diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index 8cc9db60c14..4412c279ca9 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -7,6 +7,13 @@   *  the Free Software Foundation; either version 2 of the License, or (at   *  your option) any later version.   */ +#define DRV_NAME "lbtf_usb" + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include "libertas_tf.h" +#include "if_usb.h" +  #include <linux/delay.h>  #include <linux/moduleparam.h>  #include <linux/firmware.h> @@ -14,10 +21,8 @@  #include <linux/slab.h>  #include <linux/usb.h> -#define DRV_NAME "lbtf_usb" - -#include "libertas_tf.h" -#include "if_usb.h" +#define INSANEDEBUG	0 +#define lbtf_deb_usb2(...) do { if (INSANEDEBUG) lbtf_deb_usbd(__VA_ARGS__); } while (0)  #define MESSAGE_HEADER_LEN	4 @@ -53,9 +58,14 @@ static int if_usb_reset_device(struct if_usb_card *cardp);   */  static void if_usb_write_bulk_callback(struct urb *urb)  { -	if (urb->status != 0) -		printk(KERN_INFO "libertastf: URB in failure status: %d\n", -		       urb->status); +	if (urb->status != 0) { +		/* print the failure status number for debug */ +		pr_info("URB in failure status: %d\n", urb->status); +	} else { +		lbtf_deb_usb2(&urb->dev->dev, "URB status is successful\n"); +		lbtf_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n", +			     urb->actual_length); +	}  }  /** @@ -65,6 +75,8 @@ static void if_usb_write_bulk_callback(struct urb *urb)   */  static void if_usb_free(struct if_usb_card *cardp)  { +	lbtf_deb_enter(LBTF_DEB_USB); +  	/* Unlink tx & rx urb */  	usb_kill_urb(cardp->tx_urb);  	usb_kill_urb(cardp->rx_urb); @@ -81,6 +93,8 @@ static void if_usb_free(struct if_usb_card *cardp)  	kfree(cardp->ep_out_buf);  	cardp->ep_out_buf = NULL; + +	lbtf_deb_leave(LBTF_DEB_USB);  }  static void if_usb_setup_firmware(struct lbtf_private *priv) @@ -88,23 +102,33 @@ static void if_usb_setup_firmware(struct lbtf_private *priv)  	struct if_usb_card *cardp = priv->card;  	struct cmd_ds_set_boot2_ver b2_cmd; +	lbtf_deb_enter(LBTF_DEB_USB); +  	if_usb_submit_rx_urb(cardp);  	b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));  	b2_cmd.action = 0;  	b2_cmd.version = cardp->boot2_version;  	if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd)) -		printk(KERN_INFO "libertastf: setting boot2 version failed\n"); +		lbtf_deb_usb("Setting boot2 version failed\n"); + +	lbtf_deb_leave(LBTF_DEB_USB);  }  static void if_usb_fw_timeo(unsigned long priv)  {  	struct if_usb_card *cardp = (void *)priv; -	if (!cardp->fwdnldover) +	lbtf_deb_enter(LBTF_DEB_USB); +	if (!cardp->fwdnldover) {  		/* Download timed out */  		cardp->priv->surpriseremoved = 1; +		pr_err("Download timed out\n"); +	} else { +		lbtf_deb_usb("Download complete, no event. Assuming success\n"); +	}  	wake_up(&cardp->fw_wq); +	lbtf_deb_leave(LBTF_DEB_USB);  }  /** @@ -125,11 +149,14 @@ static int if_usb_probe(struct usb_interface *intf,  	struct if_usb_card *cardp;  	int i; +	lbtf_deb_enter(LBTF_DEB_USB);  	udev = interface_to_usbdev(intf);  	cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL); -	if (!cardp) +	if (!cardp) { +		pr_err("Out of memory allocating private data.\n");  		goto error; +	}  	setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);  	init_waitqueue_head(&cardp->fw_wq); @@ -137,38 +164,62 @@ static int if_usb_probe(struct usb_interface *intf,  	cardp->udev = udev;  	iface_desc = intf->cur_altsetting; +	lbtf_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" +		     " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n", +		     le16_to_cpu(udev->descriptor.bcdUSB), +		     udev->descriptor.bDeviceClass, +		     udev->descriptor.bDeviceSubClass, +		     udev->descriptor.bDeviceProtocol); +  	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {  		endpoint = &iface_desc->endpoint[i].desc;  		if (usb_endpoint_is_bulk_in(endpoint)) {  			cardp->ep_in_size =  				le16_to_cpu(endpoint->wMaxPacketSize);  			cardp->ep_in = usb_endpoint_num(endpoint); + +			lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in); +			lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size);  		} else if (usb_endpoint_is_bulk_out(endpoint)) {  			cardp->ep_out_size =  				le16_to_cpu(endpoint->wMaxPacketSize);  			cardp->ep_out = usb_endpoint_num(endpoint); + +			lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out); +			lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n", +			              cardp->ep_out_size);  		}  	} -	if (!cardp->ep_out_size || !cardp->ep_in_size) +	if (!cardp->ep_out_size || !cardp->ep_in_size) { +		lbtf_deb_usbd(&udev->dev, "Endpoints not found\n");  		/* Endpoints not found */  		goto dealloc; +	}  	cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL); -	if (!cardp->rx_urb) +	if (!cardp->rx_urb) { +		lbtf_deb_usbd(&udev->dev, "Rx URB allocation failed\n");  		goto dealloc; +	}  	cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL); -	if (!cardp->tx_urb) +	if (!cardp->tx_urb) { +		lbtf_deb_usbd(&udev->dev, "Tx URB allocation failed\n");  		goto dealloc; +	}  	cardp->cmd_urb = usb_alloc_urb(0, GFP_KERNEL); -	if (!cardp->cmd_urb) +	if (!cardp->cmd_urb) { +		lbtf_deb_usbd(&udev->dev, "Cmd URB allocation failed\n");  		goto dealloc; +	}  	cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,  				    GFP_KERNEL); -	if (!cardp->ep_out_buf) +	if (!cardp->ep_out_buf) { +		lbtf_deb_usbd(&udev->dev, "Could not allocate buffer\n");  		goto dealloc; +	}  	priv = lbtf_add_card(cardp, &udev->dev);  	if (!priv) @@ -189,6 +240,7 @@ static int if_usb_probe(struct usb_interface *intf,  dealloc:  	if_usb_free(cardp);  error: +lbtf_deb_leave(LBTF_DEB_MAIN);  	return -ENOMEM;  } @@ -202,6 +254,8 @@ static void if_usb_disconnect(struct usb_interface *intf)  	struct if_usb_card *cardp = usb_get_intfdata(intf);  	struct lbtf_private *priv = (struct lbtf_private *) cardp->priv; +	lbtf_deb_enter(LBTF_DEB_MAIN); +  	if_usb_reset_device(cardp);  	if (priv) @@ -212,6 +266,8 @@ static void if_usb_disconnect(struct usb_interface *intf)  	usb_set_intfdata(intf, NULL);  	usb_put_dev(interface_to_usbdev(intf)); + +	lbtf_deb_leave(LBTF_DEB_MAIN);  }  /** @@ -226,6 +282,8 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)  	struct fwdata *fwdata = cardp->ep_out_buf;  	u8 *firmware = (u8 *) cardp->fw->data; +	lbtf_deb_enter(LBTF_DEB_FW); +  	/* If we got a CRC failure on the last block, back  	   up and retry it */  	if (!cardp->CRC_OK) { @@ -233,6 +291,9 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)  		cardp->fwseqnum--;  	} +	lbtf_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n", +		     cardp->totalbytes); +  	/* struct fwdata (which we sent to the card) has an  	   extra __le32 field in between the header and the data,  	   which is not in the struct fwheader in the actual @@ -246,18 +307,33 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)  	memcpy(fwdata->data, &firmware[cardp->totalbytes],  	       le32_to_cpu(fwdata->hdr.datalength)); +	lbtf_deb_usb2(&cardp->udev->dev, "Data length = %d\n", +		     le32_to_cpu(fwdata->hdr.datalength)); +  	fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);  	cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);  	usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +  		     le32_to_cpu(fwdata->hdr.datalength), 0); -	if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) +	if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) { +		lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n"); +		lbtf_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n", +			     cardp->fwseqnum, cardp->totalbytes); +	} else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { +		lbtf_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n"); +		lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n"); +  		/* Host has finished FW downloading  		 * Donwloading FW JUMP BLOCK  		 */  		cardp->fwfinalblk = 1; +	} +	lbtf_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n", +		     cardp->totalbytes); + +	lbtf_deb_leave(LBTF_DEB_FW);  	return 0;  } @@ -266,6 +342,8 @@ static int if_usb_reset_device(struct if_usb_card *cardp)  	struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;  	int ret; +	lbtf_deb_enter(LBTF_DEB_USB); +  	*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);  	cmd->hdr.command = cpu_to_le16(CMD_802_11_RESET); @@ -280,6 +358,8 @@ static int if_usb_reset_device(struct if_usb_card *cardp)  	ret = usb_reset_device(cardp->udev);  	msleep(100); +	lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret); +  	return ret;  }  EXPORT_SYMBOL_GPL(if_usb_reset_device); @@ -297,11 +377,15 @@ EXPORT_SYMBOL_GPL(if_usb_reset_device);  static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,  			uint16_t nb, u8 data)  { +	int ret = -1;  	struct urb *urb; +	lbtf_deb_enter(LBTF_DEB_USB);  	/* check if device is removed */ -	if (cardp->priv->surpriseremoved) -		return -1; +	if (cardp->priv->surpriseremoved) { +		lbtf_deb_usbd(&cardp->udev->dev, "Device removed\n"); +		goto tx_ret; +	}  	if (data)  		urb = cardp->tx_urb; @@ -315,19 +399,34 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,  	urb->transfer_flags |= URB_ZERO_PACKET; -	if (usb_submit_urb(urb, GFP_ATOMIC)) -		return -1; -	return 0; +	if (usb_submit_urb(urb, GFP_ATOMIC)) { +		lbtf_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret); +		goto tx_ret; +	} + +	lbtf_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n"); + +	ret = 0; + +tx_ret: +	lbtf_deb_leave(LBTF_DEB_USB); +	return ret;  }  static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,  				  void (*callbackfn)(struct urb *urb))  {  	struct sk_buff *skb; +	int ret = -1; + +	lbtf_deb_enter(LBTF_DEB_USB);  	skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); -	if (!skb) +	if (!skb) { +		pr_err("No free skb\n"); +		lbtf_deb_leave(LBTF_DEB_USB);  		return -1; +	}  	cardp->rx_skb = skb; @@ -339,12 +438,19 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,  	cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; -	if (usb_submit_urb(cardp->rx_urb, GFP_ATOMIC)) { +	lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); +	ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC); +	if (ret) { +		lbtf_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);  		kfree_skb(skb);  		cardp->rx_skb = NULL; +		lbtf_deb_leave(LBTF_DEB_USB);  		return -1; -	} else +	} else { +		lbtf_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n"); +		lbtf_deb_leave(LBTF_DEB_USB);  		return 0; +	}  }  static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp) @@ -364,8 +470,12 @@ static void if_usb_receive_fwload(struct urb *urb)  	struct fwsyncheader *syncfwheader;  	struct bootcmdresp bcmdresp; +	lbtf_deb_enter(LBTF_DEB_USB);  	if (urb->status) { +		lbtf_deb_usbd(&cardp->udev->dev, +			     "URB status is failed during fw load\n");  		kfree_skb(skb); +		lbtf_deb_leave(LBTF_DEB_USB);  		return;  	} @@ -373,12 +483,17 @@ static void if_usb_receive_fwload(struct urb *urb)  		__le32 *tmp = (__le32 *)(skb->data);  		if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) && -		    tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) +		    tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) {  			/* Firmware ready event received */ +			pr_info("Firmware ready event received\n");  			wake_up(&cardp->fw_wq); -		else +		} else { +			lbtf_deb_usb("Waiting for confirmation; got %x %x\n", +				    le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1]));  			if_usb_submit_rx_urb_fwload(cardp); +		}  		kfree_skb(skb); +		lbtf_deb_leave(LBTF_DEB_USB);  		return;  	}  	if (cardp->bootcmdresp <= 0) { @@ -389,34 +504,60 @@ static void if_usb_receive_fwload(struct urb *urb)  			if_usb_submit_rx_urb_fwload(cardp);  			cardp->bootcmdresp = 1;  			/* Received valid boot command response */ +			lbtf_deb_usbd(&cardp->udev->dev, +				     "Received valid boot command response\n"); +			lbtf_deb_leave(LBTF_DEB_USB);  			return;  		}  		if (bcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {  			if (bcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||  			    bcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) || -			    bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) +			    bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) { +				if (!cardp->bootcmdresp) +					pr_info("Firmware already seems alive; resetting\n");  				cardp->bootcmdresp = -1; -		} else if (bcmdresp.cmd == BOOT_CMD_FW_BY_USB && -			   bcmdresp.result == BOOT_CMD_RESP_OK) +			} else { +				pr_info("boot cmd response wrong magic number (0x%x)\n", +					    le32_to_cpu(bcmdresp.magic)); +			} +		} else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) { +			pr_info("boot cmd response cmd_tag error (%d)\n", +				    bcmdresp.cmd); +		} else if (bcmdresp.result != BOOT_CMD_RESP_OK) { +			pr_info("boot cmd response result error (%d)\n", +				    bcmdresp.result); +		} else {  			cardp->bootcmdresp = 1; +			lbtf_deb_usbd(&cardp->udev->dev, +				     "Received valid boot command response\n"); +		}  		kfree_skb(skb);  		if_usb_submit_rx_urb_fwload(cardp); +		lbtf_deb_leave(LBTF_DEB_USB);  		return;  	}  	syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);  	if (!syncfwheader) { +		lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");  		kfree_skb(skb); +		lbtf_deb_leave(LBTF_DEB_USB);  		return;  	}  	memcpy(syncfwheader, skb->data, sizeof(struct fwsyncheader)); -	if (!syncfwheader->cmd) +	if (!syncfwheader->cmd) { +		lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); +		lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", +			     le32_to_cpu(syncfwheader->seqnum));  		cardp->CRC_OK = 1; -	else +	} else { +		lbtf_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n");  		cardp->CRC_OK = 0; +	} +  	kfree_skb(skb);  	/* reschedule timer for 200ms hence */ @@ -434,6 +575,7 @@ static void if_usb_receive_fwload(struct urb *urb)  	kfree(syncfwheader); +	lbtf_deb_leave(LBTF_DEB_USB);  	return;  } @@ -445,6 +587,7 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,  {  	if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN  	    || recvlength < MRVDRV_MIN_PKT_LEN) { +		lbtf_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n");  		kfree_skb(skb);  		return;  	} @@ -460,6 +603,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,  				      struct lbtf_private *priv)  {  	if (recvlength > LBS_CMD_BUFFER_SIZE) { +		lbtf_deb_usbd(&cardp->udev->dev, +			     "The receive buffer is too large\n");  		kfree_skb(skb);  		return;  	} @@ -489,16 +634,24 @@ static void if_usb_receive(struct urb *urb)  	uint32_t recvtype = 0;  	__le32 *pkt = (__le32 *) skb->data; +	lbtf_deb_enter(LBTF_DEB_USB); +  	if (recvlength) {  		if (urb->status) { +			lbtf_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n", +				     urb->status);  			kfree_skb(skb);  			goto setup_for_next;  		}  		recvbuff = skb->data;  		recvtype = le32_to_cpu(pkt[0]); +		lbtf_deb_usbd(&cardp->udev->dev, +			    "Recv length = 0x%x, Recv type = 0x%X\n", +			    recvlength, recvtype);  	} else if (urb->status) {  		kfree_skb(skb); +		lbtf_deb_leave(LBTF_DEB_USB);  		return;  	} @@ -515,6 +668,7 @@ static void if_usb_receive(struct urb *urb)  	{  		/* Event cause handling */  		u32 event_cause = le32_to_cpu(pkt[1]); +		lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event_cause);  		/* Icky undocumented magic special case */  		if (event_cause & 0xffff0000) { @@ -529,21 +683,22 @@ static void if_usb_receive(struct urb *urb)  		} else if (event_cause == LBTF_EVENT_BCN_SENT)  			lbtf_bcn_sent(priv);  		else -			printk(KERN_DEBUG +			lbtf_deb_usbd(&cardp->udev->dev,  			       "Unsupported notification %d received\n",  			       event_cause);  		kfree_skb(skb);  		break;  	}  	default: -		printk(KERN_DEBUG "libertastf: unknown command type 0x%X\n", -			     recvtype); +		lbtf_deb_usbd(&cardp->udev->dev, +		         "libertastf: unknown command type 0x%X\n", recvtype);  		kfree_skb(skb);  		break;  	}  setup_for_next:  	if_usb_submit_rx_urb(cardp); +	lbtf_deb_leave(LBTF_DEB_USB);  }  /** @@ -562,6 +717,9 @@ static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,  	struct if_usb_card *cardp = priv->card;  	u8 data = 0; +	lbtf_deb_usbd(&cardp->udev->dev, "*** type = %u\n", type); +	lbtf_deb_usbd(&cardp->udev->dev, "size after = %d\n", nb); +  	if (type == MVMS_CMD) {  		*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);  	} else { @@ -639,8 +797,10 @@ static int check_fwfile_format(const u8 *data, u32 totlen)  	} while (!exit);  	if (ret) -		printk(KERN_INFO -		       "libertastf: firmware file format check failed\n"); +		pr_err("firmware file format check FAIL\n"); +	else +		lbtf_deb_fw("firmware file format check PASS\n"); +  	return ret;  } @@ -651,10 +811,12 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)  	static int reset_count = 10;  	int ret = 0; +	lbtf_deb_enter(LBTF_DEB_USB); +  	ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);  	if (ret < 0) { -		printk(KERN_INFO "libertastf: firmware %s not found\n", -		       lbtf_fw_name); +		pr_err("request_firmware() failed with %#x\n", ret); +		pr_err("firmware %s not found\n", lbtf_fw_name);  		goto done;  	} @@ -663,6 +825,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)  restart:  	if (if_usb_submit_rx_urb_fwload(cardp) < 0) { +		lbtf_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");  		ret = -1;  		goto release_fw;  	} @@ -709,14 +872,13 @@ restart:  	usb_kill_urb(cardp->rx_urb);  	if (!cardp->fwdnldover) { -		printk(KERN_INFO "libertastf: failed to load fw," -				 " resetting device!\n"); +		pr_info("failed to load fw, resetting device!\n");  		if (--reset_count >= 0) {  			if_usb_reset_device(cardp);  			goto restart;  		} -		printk(KERN_INFO "libertastf: fw download failure\n"); +		pr_info("FW download failure, time = %d ms\n", i * 100);  		ret = -1;  		goto release_fw;  	} @@ -730,6 +892,7 @@ restart:  	if_usb_setup_firmware(cardp->priv);   done: +	lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret);  	return ret;  }  EXPORT_SYMBOL_GPL(if_usb_prog_firmware); @@ -751,13 +914,19 @@ static int __init if_usb_init_module(void)  {  	int ret = 0; +	lbtf_deb_enter(LBTF_DEB_MAIN); +  	ret = usb_register(&if_usb_driver); + +	lbtf_deb_leave_args(LBTF_DEB_MAIN, "ret %d", ret);  	return ret;  }  static void __exit if_usb_exit_module(void)  { +	lbtf_deb_enter(LBTF_DEB_MAIN);  	usb_deregister(&if_usb_driver); +	lbtf_deb_leave(LBTF_DEB_MAIN);  }  module_init(if_usb_init_module); diff --git a/drivers/net/wireless/libertas_tf/libertas_tf.h b/drivers/net/wireless/libertas_tf/libertas_tf.h index 4cc42dd5a00..fbbaaae7a1a 100644 --- a/drivers/net/wireless/libertas_tf/libertas_tf.h +++ b/drivers/net/wireless/libertas_tf/libertas_tf.h @@ -13,6 +13,8 @@  #include <linux/kthread.h>  #include <net/mac80211.h> +#include "deb_defs.h" +  #ifndef DRV_NAME  #define DRV_NAME "libertas_tf"  #endif diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 7533a23e050..60787de56f3 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -7,10 +7,12 @@   *  the Free Software Foundation; either version 2 of the License, or (at   *  your option) any later version.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/slab.h> +#include <linux/etherdevice.h>  #include "libertas_tf.h" -#include "linux/etherdevice.h"  #define DRIVER_RELEASE_VERSION "004.p0"  /* thinfirm version: 5.132.X.pX */ @@ -18,7 +20,17 @@  #define LBTF_FW_VER_MAX		0x0584ffff  #define QOS_CONTROL_LEN		2 -static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION; +/* Module parameters */ +unsigned int lbtf_debug; +EXPORT_SYMBOL_GPL(lbtf_debug); +module_param_named(libertas_tf_debug, lbtf_debug, int, 0644); + +static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION +#ifdef DEBUG +	"-dbg" +#endif +	""; +  struct workqueue_struct *lbtf_wq;  static const struct ieee80211_channel lbtf_channels[] = { @@ -81,6 +93,9 @@ static void lbtf_cmd_work(struct work_struct *work)  {  	struct lbtf_private *priv = container_of(work, struct lbtf_private,  					 cmd_work); + +	lbtf_deb_enter(LBTF_DEB_CMD); +  	spin_lock_irq(&priv->driver_lock);  	/* command response? */  	if (priv->cmd_response_rxed) { @@ -108,11 +123,16 @@ static void lbtf_cmd_work(struct work_struct *work)  	priv->cmd_timed_out = 0;  	spin_unlock_irq(&priv->driver_lock); -	if (!priv->fw_ready) +	if (!priv->fw_ready) { +		lbtf_deb_leave_args(LBTF_DEB_CMD, "fw not ready");  		return; +	} +  	/* Execute the next command */  	if (!priv->cur_cmd)  		lbtf_execute_next_command(priv); + +	lbtf_deb_leave(LBTF_DEB_CMD);  }  /** @@ -126,6 +146,7 @@ static int lbtf_setup_firmware(struct lbtf_private *priv)  {  	int ret = -1; +	lbtf_deb_enter(LBTF_DEB_FW);  	/*  	 * Read priv address from HW  	 */ @@ -141,6 +162,7 @@ static int lbtf_setup_firmware(struct lbtf_private *priv)  	ret = 0;  done: +	lbtf_deb_leave_args(LBTF_DEB_FW, "ret: %d", ret);  	return ret;  } @@ -152,6 +174,7 @@ static void command_timer_fn(unsigned long data)  {  	struct lbtf_private *priv = (struct lbtf_private *)data;  	unsigned long flags; +	lbtf_deb_enter(LBTF_DEB_CMD);  	spin_lock_irqsave(&priv->driver_lock, flags); @@ -168,10 +191,12 @@ static void command_timer_fn(unsigned long data)  	queue_work(lbtf_wq, &priv->cmd_work);  out:  	spin_unlock_irqrestore(&priv->driver_lock, flags); +	lbtf_deb_leave(LBTF_DEB_CMD);  }  static int lbtf_init_adapter(struct lbtf_private *priv)  { +	lbtf_deb_enter(LBTF_DEB_MAIN);  	memset(priv->current_addr, 0xff, ETH_ALEN);  	mutex_init(&priv->lock); @@ -188,13 +213,16 @@ static int lbtf_init_adapter(struct lbtf_private *priv)  	if (lbtf_allocate_cmd_buffer(priv))  		return -1; +	lbtf_deb_leave(LBTF_DEB_MAIN);  	return 0;  }  static void lbtf_free_adapter(struct lbtf_private *priv)  { +	lbtf_deb_enter(LBTF_DEB_MAIN);  	lbtf_free_cmd_buffer(priv);  	del_timer(&priv->command_timer); +	lbtf_deb_leave(LBTF_DEB_MAIN);  }  static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) @@ -221,14 +249,18 @@ static void lbtf_tx_work(struct work_struct *work)  	struct sk_buff *skb = NULL;  	int err; +	lbtf_deb_enter(LBTF_DEB_MACOPS | LBTF_DEB_TX); +  	if ((priv->vif->type == NL80211_IFTYPE_AP) &&  	    (!skb_queue_empty(&priv->bc_ps_buf)))  		skb = skb_dequeue(&priv->bc_ps_buf);  	else if (priv->skb_to_tx) {  		skb = priv->skb_to_tx;  		priv->skb_to_tx = NULL; -	} else +	} else { +		lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);  		return; +	}  	len = skb->len;  	info  = IEEE80211_SKB_CB(skb); @@ -236,6 +268,7 @@ static void lbtf_tx_work(struct work_struct *work)  	if (priv->surpriseremoved) {  		dev_kfree_skb_any(skb); +		lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);  		return;  	} @@ -249,6 +282,7 @@ static void lbtf_tx_work(struct work_struct *work)  		ETH_ALEN);  	txpd->tx_packet_length = cpu_to_le16(len);  	txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); +	lbtf_deb_hex(LBTF_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));  	BUG_ON(priv->tx_skb);  	spin_lock_irq(&priv->driver_lock);  	priv->tx_skb = skb; @@ -257,7 +291,9 @@ static void lbtf_tx_work(struct work_struct *work)  	if (err) {  		dev_kfree_skb_any(skb);  		priv->tx_skb = NULL; +		pr_err("TX error: %d", err);  	} +	lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);  }  static int lbtf_op_start(struct ieee80211_hw *hw) @@ -266,6 +302,8 @@ static int lbtf_op_start(struct ieee80211_hw *hw)  	void *card = priv->card;  	int ret = -1; +	lbtf_deb_enter(LBTF_DEB_MACOPS); +  	if (!priv->fw_ready)  		/* Upload firmware */  		if (priv->hw_prog_firmware(card)) @@ -286,10 +324,12 @@ static int lbtf_op_start(struct ieee80211_hw *hw)  	}  	printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n"); +	lbtf_deb_leave(LBTF_DEB_MACOPS);  	return 0;  err_prog_firmware:  	priv->hw_reset_device(card); +	lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programing fw; ret=%d", ret);  	return ret;  } @@ -300,6 +340,9 @@ static void lbtf_op_stop(struct ieee80211_hw *hw)  	struct sk_buff *skb;  	struct cmd_ctrl_node *cmdnode; + +	lbtf_deb_enter(LBTF_DEB_MACOPS); +  	/* Flush pending command nodes */  	spin_lock_irqsave(&priv->driver_lock, flags);  	list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { @@ -316,6 +359,7 @@ static void lbtf_op_stop(struct ieee80211_hw *hw)  	priv->radioon = RADIO_OFF;  	lbtf_set_radio_control(priv); +	lbtf_deb_leave(LBTF_DEB_MACOPS);  	return;  } @@ -323,6 +367,7 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw,  			struct ieee80211_vif *vif)  {  	struct lbtf_private *priv = hw->priv; +	lbtf_deb_enter(LBTF_DEB_MACOPS);  	if (priv->vif != NULL)  		return -EOPNOTSUPP; @@ -340,6 +385,7 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw,  		return -EOPNOTSUPP;  	}  	lbtf_set_mac_address(priv, (u8 *) vif->addr); +	lbtf_deb_leave(LBTF_DEB_MACOPS);  	return 0;  } @@ -347,6 +393,7 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw,  			struct ieee80211_vif *vif)  {  	struct lbtf_private *priv = hw->priv; +	lbtf_deb_enter(LBTF_DEB_MACOPS);  	if (priv->vif->type == NL80211_IFTYPE_AP ||  	    priv->vif->type == NL80211_IFTYPE_MESH_POINT) @@ -354,17 +401,20 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw,  	lbtf_set_mode(priv, LBTF_PASSIVE_MODE);  	lbtf_set_bssid(priv, 0, NULL);  	priv->vif = NULL; +	lbtf_deb_leave(LBTF_DEB_MACOPS);  }  static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)  {  	struct lbtf_private *priv = hw->priv;  	struct ieee80211_conf *conf = &hw->conf; +	lbtf_deb_enter(LBTF_DEB_MACOPS);  	if (conf->channel->center_freq != priv->cur_freq) {  		priv->cur_freq = conf->channel->center_freq;  		lbtf_set_channel(priv, conf->channel->hw_value);  	} +	lbtf_deb_leave(LBTF_DEB_MACOPS);  	return 0;  } @@ -395,11 +445,16 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,  {  	struct lbtf_private *priv = hw->priv;  	int old_mac_control = priv->mac_control; + +	lbtf_deb_enter(LBTF_DEB_MACOPS); +  	changed_flags &= SUPPORTED_FIF_FLAGS;  	*new_flags &= SUPPORTED_FIF_FLAGS; -	if (!changed_flags) +	if (!changed_flags) { +		lbtf_deb_leave(LBTF_DEB_MACOPS);  		return; +	}  	if (*new_flags & (FIF_PROMISC_IN_BSS))  		priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE; @@ -425,6 +480,8 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,  	if (priv->mac_control != old_mac_control)  		lbtf_set_mac_control(priv); + +	lbtf_deb_leave(LBTF_DEB_MACOPS);  }  static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw, @@ -434,6 +491,7 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,  {  	struct lbtf_private *priv = hw->priv;  	struct sk_buff *beacon; +	lbtf_deb_enter(LBTF_DEB_MACOPS);  	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) {  		switch (priv->vif->type) { @@ -464,6 +522,8 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,  			priv->preamble = CMD_TYPE_LONG_PREAMBLE;  		lbtf_set_radio_control(priv);  	} + +	lbtf_deb_leave(LBTF_DEB_MACOPS);  }  static const struct ieee80211_ops lbtf_ops = { @@ -486,6 +546,8 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)  	unsigned int flags;  	struct ieee80211_hdr *hdr; +	lbtf_deb_enter(LBTF_DEB_RX); +  	prxpd = (struct rxpd *) skb->data;  	stats.flag = 0; @@ -494,7 +556,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)  	stats.freq = priv->cur_freq;  	stats.band = IEEE80211_BAND_2GHZ;  	stats.signal = prxpd->snr; -	stats.noise = prxpd->nf;  	/* Marvell rate index has a hole at value 4 */  	if (prxpd->rx_rate > 4)  		--prxpd->rx_rate; @@ -516,7 +577,15 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)  	}  	memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats)); + +	lbtf_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", +	       skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); +	lbtf_deb_hex(LBTF_DEB_RX, "RX Data", skb->data, +	             min_t(unsigned int, skb->len, 100)); +  	ieee80211_rx_irqsafe(priv->hw, skb); + +	lbtf_deb_leave(LBTF_DEB_RX);  	return 0;  }  EXPORT_SYMBOL_GPL(lbtf_rx); @@ -533,6 +602,8 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)  	struct ieee80211_hw *hw;  	struct lbtf_private *priv = NULL; +	lbtf_deb_enter(LBTF_DEB_MAIN); +  	hw = ieee80211_alloc_hw(sizeof(struct lbtf_private), &lbtf_ops);  	if (!hw)  		goto done; @@ -575,6 +646,7 @@ err_init_adapter:  	priv = NULL;  done: +	lbtf_deb_leave_args(LBTF_DEB_MAIN, "priv %p", priv);  	return priv;  }  EXPORT_SYMBOL_GPL(lbtf_add_card); @@ -584,6 +656,8 @@ int lbtf_remove_card(struct lbtf_private *priv)  {  	struct ieee80211_hw *hw = priv->hw; +	lbtf_deb_enter(LBTF_DEB_MAIN); +  	priv->surpriseremoved = 1;  	del_timer(&priv->command_timer);  	lbtf_free_adapter(priv); @@ -591,6 +665,7 @@ int lbtf_remove_card(struct lbtf_private *priv)  	ieee80211_unregister_hw(hw);  	ieee80211_free_hw(hw); +    lbtf_deb_leave(LBTF_DEB_MAIN);  	return 0;  }  EXPORT_SYMBOL_GPL(lbtf_remove_card); @@ -649,17 +724,21 @@ EXPORT_SYMBOL_GPL(lbtf_bcn_sent);  static int __init lbtf_init_module(void)  { +	lbtf_deb_enter(LBTF_DEB_MAIN);  	lbtf_wq = create_workqueue("libertastf");  	if (lbtf_wq == NULL) {  		printk(KERN_ERR "libertastf: couldn't create workqueue\n");  		return -ENOMEM;  	} +	lbtf_deb_leave(LBTF_DEB_MAIN);  	return 0;  }  static void __exit lbtf_exit_module(void)  { +	lbtf_deb_enter(LBTF_DEB_MAIN);  	destroy_workqueue(lbtf_wq); +	lbtf_deb_leave(LBTF_DEB_MAIN);  }  module_init(lbtf_init_module); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index dfff02f5c86..9fd2beadb6f 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -830,6 +830,33 @@ static int mac80211_hwsim_conf_tx(  	return 0;  } +static int mac80211_hwsim_get_survey( +	struct ieee80211_hw *hw, int idx, +	struct survey_info *survey) +{ +	struct ieee80211_conf *conf = &hw->conf; + +	printk(KERN_DEBUG "%s:%s (idx=%d)\n", +	       wiphy_name(hw->wiphy), __func__, idx); + +	if (idx != 0) +		return -ENOENT; + +	/* Current channel */ +	survey->channel = conf->channel; + +	/* +	 * Magically conjured noise level --- this is only ok for simulated hardware. +	 * +	 * A real driver which cannot determine the real channel noise MUST NOT +	 * report any noise, especially not a magically conjured one :-) +	 */ +	survey->filled = SURVEY_INFO_NOISE_DBM; +	survey->noise = -92; + +	return 0; +} +  #ifdef CONFIG_NL80211_TESTMODE  /*   * This section contains example code for using netlink @@ -947,6 +974,7 @@ static void hw_scan_done(struct work_struct *work)  }  static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, +				  struct ieee80211_vif *vif,  				  struct cfg80211_scan_request *req)  {  	struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL); @@ -993,7 +1021,7 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw)  	mutex_lock(&hwsim->mutex);  	printk(KERN_DEBUG "hwsim sw_scan_complete\n"); -	hwsim->scanning = true; +	hwsim->scanning = false;  	mutex_unlock(&hwsim->mutex);  } @@ -1013,6 +1041,7 @@ static struct ieee80211_ops mac80211_hwsim_ops =  	.sta_notify = mac80211_hwsim_sta_notify,  	.set_tim = mac80211_hwsim_set_tim,  	.conf_tx = mac80211_hwsim_conf_tx, +	.get_survey = mac80211_hwsim_get_survey,  	CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)  	.ampdu_action = mac80211_hwsim_ampdu_action,  	.sw_scan_start = mac80211_hwsim_sw_scan, @@ -1271,7 +1300,8 @@ static int __init init_mac80211_hwsim(void)  		hw->flags = IEEE80211_HW_MFP_CAPABLE |  			    IEEE80211_HW_SIGNAL_DBM |  			    IEEE80211_HW_SUPPORTS_STATIC_SMPS | -			    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; +			    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | +			    IEEE80211_HW_AMPDU_AGGREGATION;  		/* ask mac80211 to reserve space for magic */  		hw->vif_data_size = sizeof(struct hwsim_vif_priv); diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 73bbd080c6e..808adb90909 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -750,7 +750,6 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,  	memset(status, 0, sizeof(*status));  	status->signal = -rxd->rssi; -	status->noise = -rxd->noise_floor;  	if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) {  		status->flag |= RX_FLAG_HT; @@ -852,7 +851,6 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,  	memset(status, 0, sizeof(*status));  	status->signal = -rxd->rssi; -	status->noise = -rxd->noise_level;  	status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info);  	status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info); @@ -3984,8 +3982,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,  	hw->queues = MWL8K_TX_QUEUES; -	/* Set rssi and noise values to dBm */ -	hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; +	/* Set rssi values to dBm */ +	hw->flags |= IEEE80211_HW_SIGNAL_DBM;  	hw->vif_data_size = sizeof(struct mwl8k_vif);  	hw->sta_data_size = sizeof(struct mwl8k_sta); diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig index 6116b546861..60819bcf437 100644 --- a/drivers/net/wireless/orinoco/Kconfig +++ b/drivers/net/wireless/orinoco/Kconfig @@ -132,3 +132,10 @@ config PCMCIA_SPECTRUM  	  This driver requires firmware download on startup.  Utilities  	  for downloading Symbol firmware are available at  	  <http://sourceforge.net/projects/orinoco/> + +config ORINOCO_USB +	tristate "Agere Orinoco USB support" +	depends on USB && HERMES +	select FW_LOADER +	---help--- +	  This driver is for USB versions of the Agere Orinoco card. diff --git a/drivers/net/wireless/orinoco/Makefile b/drivers/net/wireless/orinoco/Makefile index 9abd6329bcb..bfdefb85abc 100644 --- a/drivers/net/wireless/orinoco/Makefile +++ b/drivers/net/wireless/orinoco/Makefile @@ -11,3 +11,7 @@ obj-$(CONFIG_PCI_HERMES)	+= orinoco_pci.o  obj-$(CONFIG_TMD_HERMES)	+= orinoco_tmd.o  obj-$(CONFIG_NORTEL_HERMES)	+= orinoco_nortel.o  obj-$(CONFIG_PCMCIA_SPECTRUM)	+= spectrum_cs.o +obj-$(CONFIG_ORINOCO_USB)	+= orinoco_usb.o + +# Orinoco should be endian clean. +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c index c60df2c1aca..9bcee10c930 100644 --- a/drivers/net/wireless/orinoco/airport.c +++ b/drivers/net/wireless/orinoco/airport.c @@ -77,9 +77,9 @@ airport_resume(struct macio_dev *mdev)  	enable_irq(card->irq); -	spin_lock_irqsave(&priv->lock, flags); +	priv->hw.ops->lock_irqsave(&priv->lock, &flags);  	err = orinoco_up(priv); -	spin_unlock_irqrestore(&priv->lock, flags); +	priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);  	return err;  } @@ -195,7 +195,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)  	ssleep(1);  	/* Reset it before we get the interrupt */ -	hermes_init(hw); +	hw->ops->init(hw);  	if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) {  		printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq); @@ -210,7 +210,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)  	}  	/* Register an interface with the stack */ -	if (orinoco_if_add(priv, phys_addr, card->irq) != 0) { +	if (orinoco_if_add(priv, phys_addr, card->irq, NULL) != 0) {  		printk(KERN_ERR PFX "orinoco_if_add() failed\n");  		goto failed;  	} diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c index 27f2d334264..81d228de9e5 100644 --- a/drivers/net/wireless/orinoco/cfg.c +++ b/drivers/net/wireless/orinoco/cfg.c @@ -88,7 +88,9 @@ int orinoco_wiphy_register(struct wiphy *wiphy)  	wiphy->rts_threshold = priv->rts_thresh;  	if (!priv->has_mwo) -		wiphy->frag_threshold = priv->frag_thresh; +		wiphy->frag_threshold = priv->frag_thresh + 1; +	wiphy->retry_short = priv->short_retry_limit; +	wiphy->retry_long = priv->long_retry_limit;  	return wiphy_register(wiphy);  } @@ -187,7 +189,7 @@ static int orinoco_set_channel(struct wiphy *wiphy,  	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {  		/* Fast channel change - no commit if successful */  		hermes_t *hw = &priv->hw; -		err = hermes_docmd_wait(hw, HERMES_CMD_TEST | +		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |  					    HERMES_TEST_SET_CHANNEL,  					channel, NULL);  	} @@ -196,8 +198,92 @@ static int orinoco_set_channel(struct wiphy *wiphy,  	return err;  } +static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ +	struct orinoco_private *priv = wiphy_priv(wiphy); +	int frag_value = -1; +	int rts_value = -1; +	int err = 0; + +	if (changed & WIPHY_PARAM_RETRY_SHORT) { +		/* Setting short retry not supported */ +		err = -EINVAL; +	} + +	if (changed & WIPHY_PARAM_RETRY_LONG) { +		/* Setting long retry not supported */ +		err = -EINVAL; +	} + +	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { +		/* Set fragmentation */ +		if (priv->has_mwo) { +			if (wiphy->frag_threshold < 0) +				frag_value = 0; +			else { +				printk(KERN_WARNING "%s: Fixed fragmentation " +				       "is not supported on this firmware. " +				       "Using MWO robust instead.\n", +				       priv->ndev->name); +				frag_value = 1; +			} +		} else { +			if (wiphy->frag_threshold < 0) +				frag_value = 2346; +			else if ((wiphy->frag_threshold < 257) || +				 (wiphy->frag_threshold > 2347)) +				err = -EINVAL; +			else +				/* cfg80211 value is 257-2347 (odd only) +				 * orinoco rid has range 256-2346 (even only) */ +				frag_value = wiphy->frag_threshold & ~0x1; +		} +	} + +	if (changed & WIPHY_PARAM_RTS_THRESHOLD) { +		/* Set RTS. +		 * +		 * Prism documentation suggests default of 2432, +		 * and a range of 0-3000. +		 * +		 * Current implementation uses 2347 as the default and +		 * the upper limit. +		 */ + +		if (wiphy->rts_threshold < 0) +			rts_value = 2347; +		else if (wiphy->rts_threshold > 2347) +			err = -EINVAL; +		else +			rts_value = wiphy->rts_threshold; +	} + +	if (!err) { +		unsigned long flags; + +		if (orinoco_lock(priv, &flags) != 0) +			return -EBUSY; + +		if (frag_value >= 0) { +			if (priv->has_mwo) +				priv->mwo_robust = frag_value; +			else +				priv->frag_thresh = frag_value; +		} +		if (rts_value >= 0) +			priv->rts_thresh = rts_value; + +		err = orinoco_commit(priv); + +		orinoco_unlock(priv, &flags); +	} + +	return err; +} +  const struct cfg80211_ops orinoco_cfg_ops = {  	.change_virtual_intf = orinoco_change_vif,  	.set_channel = orinoco_set_channel,  	.scan = orinoco_scan, +	.set_wiphy_params = orinoco_set_wiphy_params,  }; diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c index 5ea0f7cf85b..3e1947d097c 100644 --- a/drivers/net/wireless/orinoco/fw.c +++ b/drivers/net/wireless/orinoco/fw.c @@ -122,7 +122,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,  	dev_dbg(dev, "Attempting to download firmware %s\n", firmware);  	/* Read current plug data */ -	err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0); +	err = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);  	dev_dbg(dev, "Read PDA returned %d\n", err);  	if (err)  		goto free; @@ -149,7 +149,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,  	}  	/* Enable aux port to allow programming */ -	err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point)); +	err = hw->ops->program_init(hw, le32_to_cpu(hdr->entry_point));  	dev_dbg(dev, "Program init returned %d\n", err);  	if (err != 0)  		goto abort; @@ -177,7 +177,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,  		goto abort;  	/* Tell card we've finished */ -	err = hermesi_program_end(hw); +	err = hw->ops->program_end(hw);  	dev_dbg(dev, "Program end returned %d\n", err);  	if (err != 0)  		goto abort; @@ -224,7 +224,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,  		if (!pda)  			return -ENOMEM; -		ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1); +		ret = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);  		if (ret)  			goto free;  	} @@ -260,7 +260,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,  	}  	/* Reset hermes chip and make sure it responds */ -	ret = hermes_init(hw); +	ret = hw->ops->init(hw);  	/* hermes_reset() should return 0 with the secondary firmware */  	if (secondary && ret != 0) diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c index 1a2fca76fd3..6c6a23e08df 100644 --- a/drivers/net/wireless/orinoco/hermes.c +++ b/drivers/net/wireless/orinoco/hermes.c @@ -52,6 +52,26 @@  #define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */  /* + * AUX port access.  To unlock the AUX port write the access keys to the + * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL + * register.  Then read it and make sure it's HERMES_AUX_ENABLED. + */ +#define HERMES_AUX_ENABLE	0x8000	/* Enable auxiliary port access */ +#define HERMES_AUX_DISABLE	0x4000	/* Disable to auxiliary port access */ +#define HERMES_AUX_ENABLED	0xC000	/* Auxiliary port is open */ +#define HERMES_AUX_DISABLED	0x0000	/* Auxiliary port is closed */ + +#define HERMES_AUX_PW0	0xFE01 +#define HERMES_AUX_PW1	0xDC23 +#define HERMES_AUX_PW2	0xBA45 + +/* HERMES_CMD_DOWNLD */ +#define HERMES_PROGRAM_DISABLE             (0x0000 | HERMES_CMD_DOWNLD) +#define HERMES_PROGRAM_ENABLE_VOLATILE     (0x0100 | HERMES_CMD_DOWNLD) +#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD) +#define HERMES_PROGRAM_NON_VOLATILE        (0x0300 | HERMES_CMD_DOWNLD) + +/*   * Debugging helpers   */ @@ -70,6 +90,7 @@  #endif /* ! HERMES_DEBUG */ +static const struct hermes_ops hermes_ops_local;  /*   * Internal functions @@ -111,9 +132,9 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,   */  /* For doing cmds that wipe the magic constant in SWSUPPORT0 */ -int hermes_doicmd_wait(hermes_t *hw, u16 cmd, -		       u16 parm0, u16 parm1, u16 parm2, -		       struct hermes_response *resp) +static int hermes_doicmd_wait(hermes_t *hw, u16 cmd, +			      u16 parm0, u16 parm1, u16 parm2, +			      struct hermes_response *resp)  {  	int err = 0;  	int k; @@ -163,17 +184,18 @@ int hermes_doicmd_wait(hermes_t *hw, u16 cmd,  out:  	return err;  } -EXPORT_SYMBOL(hermes_doicmd_wait);  void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)  {  	hw->iobase = address;  	hw->reg_spacing = reg_spacing;  	hw->inten = 0x0; +	hw->eeprom_pda = false; +	hw->ops = &hermes_ops_local;  }  EXPORT_SYMBOL(hermes_struct_init); -int hermes_init(hermes_t *hw) +static int hermes_init(hermes_t *hw)  {  	u16 reg;  	int err = 0; @@ -217,7 +239,6 @@ int hermes_init(hermes_t *hw)  	return err;  } -EXPORT_SYMBOL(hermes_init);  /* Issue a command to the chip, and (busy!) wait for it to   * complete. @@ -228,8 +249,8 @@ EXPORT_SYMBOL(hermes_init);   *     > 0 on error returned by the firmware   *   * Callable from any context, but locking is your problem. */ -int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, -		      struct hermes_response *resp) +static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, +			     struct hermes_response *resp)  {  	int err;  	int k; @@ -291,9 +312,8 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,   out:  	return err;  } -EXPORT_SYMBOL(hermes_docmd_wait); -int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) +static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)  {  	int err = 0;  	int k; @@ -333,7 +353,6 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)  	return 0;  } -EXPORT_SYMBOL(hermes_allocate);  /* Set up a BAP to read a particular chunk of data from card's internal buffer.   * @@ -403,8 +422,8 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)   *       0 on success   *     > 0 on error from firmware   */ -int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, -		     u16 id, u16 offset) +static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, +			    u16 id, u16 offset)  {  	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;  	int err = 0; @@ -422,7 +441,6 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,   out:  	return err;  } -EXPORT_SYMBOL(hermes_bap_pread);  /* Write a block of data to the chip's buffer, via the   * BAP. Synchronization/serialization is the caller's problem. @@ -432,8 +450,8 @@ EXPORT_SYMBOL(hermes_bap_pread);   *       0 on success   *     > 0 on error from firmware   */ -int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, -		      u16 id, u16 offset) +static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, +			     u16 id, u16 offset)  {  	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;  	int err = 0; @@ -451,7 +469,6 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,   out:  	return err;  } -EXPORT_SYMBOL(hermes_bap_pwrite);  /* Read a Length-Type-Value record from the card.   * @@ -461,8 +478,8 @@ EXPORT_SYMBOL(hermes_bap_pwrite);   * practice.   *   * Callable from user or bh context.  */ -int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, -		    u16 *length, void *buf) +static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, +			   u16 *length, void *buf)  {  	int err = 0;  	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; @@ -505,10 +522,9 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,  	return 0;  } -EXPORT_SYMBOL(hermes_read_ltv); -int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, -		     u16 length, const void *value) +static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, +			    u16 length, const void *value)  {  	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;  	int err = 0; @@ -533,4 +549,228 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,  	return err;  } -EXPORT_SYMBOL(hermes_write_ltv); + +/*** Hermes AUX control ***/ + +static inline void +hermes_aux_setaddr(hermes_t *hw, u32 addr) +{ +	hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); +	hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); +} + +static inline int +hermes_aux_control(hermes_t *hw, int enabled) +{ +	int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED; +	int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE; +	int i; + +	/* Already open? */ +	if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state) +		return 0; + +	hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); +	hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); +	hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); +	hermes_write_reg(hw, HERMES_CONTROL, action); + +	for (i = 0; i < 20; i++) { +		udelay(10); +		if (hermes_read_reg(hw, HERMES_CONTROL) == +		    desired_state) +			return 0; +	} + +	return -EBUSY; +} + +/*** Hermes programming ***/ + +/* About to start programming data (Hermes I) + * offset is the entry point + * + * Spectrum_cs' Symbol fw does not require this + * wl_lkm Agere fw does + * Don't know about intersil + */ +static int hermesi_program_init(hermes_t *hw, u32 offset) +{ +	int err; + +	/* Disable interrupts?*/ +	/*hw->inten = 0x0;*/ +	/*hermes_write_regn(hw, INTEN, 0);*/ +	/*hermes_set_irqmask(hw, 0);*/ + +	/* Acknowledge any outstanding command */ +	hermes_write_regn(hw, EVACK, 0xFFFF); + +	/* Using init_cmd_wait rather than cmd_wait */ +	err = hw->ops->init_cmd_wait(hw, +				     0x0100 | HERMES_CMD_INIT, +				     0, 0, 0, NULL); +	if (err) +		return err; + +	err = hw->ops->init_cmd_wait(hw, +				     0x0000 | HERMES_CMD_INIT, +				     0, 0, 0, NULL); +	if (err) +		return err; + +	err = hermes_aux_control(hw, 1); +	pr_debug("AUX enable returned %d\n", err); + +	if (err) +		return err; + +	pr_debug("Enabling volatile, EP 0x%08x\n", offset); +	err = hw->ops->init_cmd_wait(hw, +				     HERMES_PROGRAM_ENABLE_VOLATILE, +				     offset & 0xFFFFu, +				     offset >> 16, +				     0, +				     NULL); +	pr_debug("PROGRAM_ENABLE returned %d\n", err); + +	return err; +} + +/* Done programming data (Hermes I) + * + * Spectrum_cs' Symbol fw does not require this + * wl_lkm Agere fw does + * Don't know about intersil + */ +static int hermesi_program_end(hermes_t *hw) +{ +	struct hermes_response resp; +	int rc = 0; +	int err; + +	rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp); + +	pr_debug("PROGRAM_DISABLE returned %d, " +		 "r0 0x%04x, r1 0x%04x, r2 0x%04x\n", +		 rc, resp.resp0, resp.resp1, resp.resp2); + +	if ((rc == 0) && +	    ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD)) +		rc = -EIO; + +	err = hermes_aux_control(hw, 0); +	pr_debug("AUX disable returned %d\n", err); + +	/* Acknowledge any outstanding command */ +	hermes_write_regn(hw, EVACK, 0xFFFF); + +	/* Reinitialise, ignoring return */ +	(void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT, +				      0, 0, 0, NULL); + +	return rc ? rc : err; +} + +static int hermes_program_bytes(struct hermes *hw, const char *data, +				u32 addr, u32 len) +{ +	/* wl lkm splits the programming into chunks of 2000 bytes. +	 * This restriction appears to come from USB. The PCMCIA +	 * adapters can program the whole lot in one go */ +	hermes_aux_setaddr(hw, addr); +	hermes_write_bytes(hw, HERMES_AUXDATA, data, len); +	return 0; +} + +/* Read PDA from the adapter */ +static int hermes_read_pda(hermes_t *hw, __le16 *pda, u32 pda_addr, u16 pda_len) +{ +	int ret; +	u16 pda_size; +	u16 data_len = pda_len; +	__le16 *data = pda; + +	if (hw->eeprom_pda) { +		/* PDA of spectrum symbol is in eeprom */ + +		/* Issue command to read EEPROM */ +		ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); +		if (ret) +			return ret; +	} else { +		/* wl_lkm does not include PDA size in the PDA area. +		 * We will pad the information into pda, so other routines +		 * don't have to be modified */ +		pda[0] = cpu_to_le16(pda_len - 2); +			/* Includes CFG_PROD_DATA but not itself */ +		pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */ +		data_len = pda_len - 4; +		data = pda + 2; +	} + +	/* Open auxiliary port */ +	ret = hermes_aux_control(hw, 1); +	pr_debug("AUX enable returned %d\n", ret); +	if (ret) +		return ret; + +	/* Read PDA */ +	hermes_aux_setaddr(hw, pda_addr); +	hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2); + +	/* Close aux port */ +	ret = hermes_aux_control(hw, 0); +	pr_debug("AUX disable returned %d\n", ret); + +	/* Check PDA length */ +	pda_size = le16_to_cpu(pda[0]); +	pr_debug("Actual PDA length %d, Max allowed %d\n", +		 pda_size, pda_len); +	if (pda_size > pda_len) +		return -EINVAL; + +	return 0; +} + +static void hermes_lock_irqsave(spinlock_t *lock, +				unsigned long *flags) __acquires(lock) +{ +	spin_lock_irqsave(lock, *flags); +} + +static void hermes_unlock_irqrestore(spinlock_t *lock, +				     unsigned long *flags) __releases(lock) +{ +	spin_unlock_irqrestore(lock, *flags); +} + +static void hermes_lock_irq(spinlock_t *lock) __acquires(lock) +{ +	spin_lock_irq(lock); +} + +static void hermes_unlock_irq(spinlock_t *lock) __releases(lock) +{ +	spin_unlock_irq(lock); +} + +/* Hermes operations for local buses */ +static const struct hermes_ops hermes_ops_local = { +	.init = hermes_init, +	.cmd_wait = hermes_docmd_wait, +	.init_cmd_wait = hermes_doicmd_wait, +	.allocate = hermes_allocate, +	.read_ltv = hermes_read_ltv, +	.write_ltv = hermes_write_ltv, +	.bap_pread = hermes_bap_pread, +	.bap_pwrite = hermes_bap_pwrite, +	.read_pda = hermes_read_pda, +	.program_init = hermesi_program_init, +	.program_end = hermesi_program_end, +	.program = hermes_program_bytes, +	.lock_irqsave = hermes_lock_irqsave, +	.unlock_irqrestore = hermes_unlock_irqrestore, +	.lock_irq = hermes_lock_irq, +	.unlock_irq = hermes_unlock_irq, +}; diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h index 2dddbb597c4..9ca34e722b4 100644 --- a/drivers/net/wireless/orinoco/hermes.h +++ b/drivers/net/wireless/orinoco/hermes.h @@ -374,6 +374,37 @@ struct hermes_multicast {  /* Timeouts */  #define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */ +struct hermes; + +/* Functions to access hardware */ +struct hermes_ops { +	int (*init)(struct hermes *hw); +	int (*cmd_wait)(struct hermes *hw, u16 cmd, u16 parm0, +			struct hermes_response *resp); +	int (*init_cmd_wait)(struct hermes *hw, u16 cmd, +			     u16 parm0, u16 parm1, u16 parm2, +			     struct hermes_response *resp); +	int (*allocate)(struct hermes *hw, u16 size, u16 *fid); +	int (*read_ltv)(struct hermes *hw, int bap, u16 rid, unsigned buflen, +			u16 *length, void *buf); +	int (*write_ltv)(struct hermes *hw, int bap, u16 rid, +			 u16 length, const void *value); +	int (*bap_pread)(struct hermes *hw, int bap, void *buf, int len, +			 u16 id, u16 offset); +	int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf, +			  int len, u16 id, u16 offset); +	int (*read_pda)(struct hermes *hw, __le16 *pda, +			u32 pda_addr, u16 pda_len); +	int (*program_init)(struct hermes *hw, u32 entry_point); +	int (*program_end)(struct hermes *hw); +	int (*program)(struct hermes *hw, const char *buf, +		       u32 addr, u32 len); +	void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags); +	void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags); +	void (*lock_irq)(spinlock_t *lock); +	void (*unlock_irq)(spinlock_t *lock); +}; +  /* Basic control structure */  typedef struct hermes {  	void __iomem *iobase; @@ -381,6 +412,9 @@ typedef struct hermes {  #define HERMES_16BIT_REGSPACING	0  #define HERMES_32BIT_REGSPACING	1  	u16 inten; /* Which interrupts should be enabled? */ +	bool eeprom_pda; +	const struct hermes_ops *ops; +	void *priv;  } hermes_t;  /* Register access convenience macros */ @@ -394,22 +428,6 @@ typedef struct hermes {  /* Function prototypes */  void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing); -int hermes_init(hermes_t *hw); -int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, -		      struct hermes_response *resp); -int hermes_doicmd_wait(hermes_t *hw, u16 cmd, -		       u16 parm0, u16 parm1, u16 parm2, -		       struct hermes_response *resp); -int hermes_allocate(hermes_t *hw, u16 size, u16 *fid); - -int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, -		       u16 id, u16 offset); -int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, -			u16 id, u16 offset); -int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen, -		    u16 *length, void *buf); -int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, -		      u16 length, const void *value);  /* Inline functions */ @@ -426,13 +444,13 @@ static inline void hermes_set_irqmask(hermes_t *hw, u16 events)  static inline int hermes_enable_port(hermes_t *hw, int port)  { -	return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8), +	return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),  				 0, NULL);  }  static inline int hermes_disable_port(hermes_t *hw, int port)  { -	return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8), +	return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),  				 0, NULL);  } @@ -440,7 +458,7 @@ static inline int hermes_disable_port(hermes_t *hw, int port)   * information frame in __orinoco_ev_info() */  static inline int hermes_inquire(hermes_t *hw, u16 rid)  { -	return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL); +	return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);  }  #define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1) @@ -475,10 +493,10 @@ static inline void hermes_clear_words(struct hermes *hw, int off,  }  #define HERMES_READ_RECORD(hw, bap, rid, buf) \ -	(hermes_read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf))) +	(hw->ops->read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))  #define HERMES_WRITE_RECORD(hw, bap, rid, buf) \ -	(hermes_write_ltv((hw), (bap), (rid), \ -			  HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf))) +	(hw->ops->write_ltv((hw), (bap), (rid), \ +			    HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))  static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)  { diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c index fb157eb889c..6da85e75fce 100644 --- a/drivers/net/wireless/orinoco/hermes_dld.c +++ b/drivers/net/wireless/orinoco/hermes_dld.c @@ -46,37 +46,11 @@  #define PFX "hermes_dld: " -/* - * AUX port access.  To unlock the AUX port write the access keys to the - * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL - * register.  Then read it and make sure it's HERMES_AUX_ENABLED. - */ -#define HERMES_AUX_ENABLE	0x8000	/* Enable auxiliary port access */ -#define HERMES_AUX_DISABLE	0x4000	/* Disable to auxiliary port access */ -#define HERMES_AUX_ENABLED	0xC000	/* Auxiliary port is open */ -#define HERMES_AUX_DISABLED	0x0000	/* Auxiliary port is closed */ - -#define HERMES_AUX_PW0	0xFE01 -#define HERMES_AUX_PW1	0xDC23 -#define HERMES_AUX_PW2	0xBA45 - -/* HERMES_CMD_DOWNLD */ -#define HERMES_PROGRAM_DISABLE             (0x0000 | HERMES_CMD_DOWNLD) -#define HERMES_PROGRAM_ENABLE_VOLATILE     (0x0100 | HERMES_CMD_DOWNLD) -#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD) -#define HERMES_PROGRAM_NON_VOLATILE        (0x0300 | HERMES_CMD_DOWNLD) -  /* End markers used in dblocks */  #define PDI_END		0x00000000	/* End of PDA */  #define BLOCK_END	0xFFFFFFFF	/* Last image block */  #define TEXT_END	0x1A		/* End of text header */ -/* Limit the amout we try to download in a single shot. - * Size is in bytes. - */ -#define MAX_DL_SIZE 1024 -#define LIMIT_PROGRAM_SIZE 0 -  /*   * The following structures have little-endian fields denoted by   * the leading underscore.  Don't access them directly - use inline @@ -165,41 +139,6 @@ pdi_len(const struct pdi *pdi)  	return 2 * (le16_to_cpu(pdi->len) - 1);  } -/*** Hermes AUX control ***/ - -static inline void -hermes_aux_setaddr(hermes_t *hw, u32 addr) -{ -	hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); -	hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); -} - -static inline int -hermes_aux_control(hermes_t *hw, int enabled) -{ -	int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED; -	int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE; -	int i; - -	/* Already open? */ -	if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state) -		return 0; - -	hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); -	hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); -	hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); -	hermes_write_reg(hw, HERMES_CONTROL, action); - -	for (i = 0; i < 20; i++) { -		udelay(10); -		if (hermes_read_reg(hw, HERMES_CONTROL) == -		    desired_state) -			return 0; -	} - -	return -EBUSY; -} -  /*** Plug Data Functions ***/  /* @@ -271,62 +210,7 @@ hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,  		return -EINVAL;  	/* do the actual plugging */ -	hermes_aux_setaddr(hw, pdr_addr(pdr)); -	hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi)); - -	return 0; -} - -/* Read PDA from the adapter */ -int hermes_read_pda(hermes_t *hw, -		    __le16 *pda, -		    u32 pda_addr, -		    u16 pda_len, -		    int use_eeprom) /* can we get this into hw? */ -{ -	int ret; -	u16 pda_size; -	u16 data_len = pda_len; -	__le16 *data = pda; - -	if (use_eeprom) { -		/* PDA of spectrum symbol is in eeprom */ - -		/* Issue command to read EEPROM */ -		ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); -		if (ret) -			return ret; -	} else { -		/* wl_lkm does not include PDA size in the PDA area. -		 * We will pad the information into pda, so other routines -		 * don't have to be modified */ -		pda[0] = cpu_to_le16(pda_len - 2); -			/* Includes CFG_PROD_DATA but not itself */ -		pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */ -		data_len = pda_len - 4; -		data = pda + 2; -	} - -	/* Open auxiliary port */ -	ret = hermes_aux_control(hw, 1); -	pr_debug(PFX "AUX enable returned %d\n", ret); -	if (ret) -		return ret; - -	/* read PDA from EEPROM */ -	hermes_aux_setaddr(hw, pda_addr); -	hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2); - -	/* Close aux port */ -	ret = hermes_aux_control(hw, 0); -	pr_debug(PFX "AUX disable returned %d\n", ret); - -	/* Check PDA length */ -	pda_size = le16_to_cpu(pda[0]); -	pr_debug(PFX "Actual PDA length %d, Max allowed %d\n", -		 pda_size, pda_len); -	if (pda_size > pda_len) -		return -EINVAL; +	hw->ops->program(hw, pdi->data, pdr_addr(pdr), pdi_len(pdi));  	return 0;  } @@ -389,101 +273,13 @@ hermes_blocks_length(const char *first_block, const void *end)  /*** Hermes programming ***/ -/* About to start programming data (Hermes I) - * offset is the entry point - * - * Spectrum_cs' Symbol fw does not require this - * wl_lkm Agere fw does - * Don't know about intersil - */ -int hermesi_program_init(hermes_t *hw, u32 offset) -{ -	int err; - -	/* Disable interrupts?*/ -	/*hw->inten = 0x0;*/ -	/*hermes_write_regn(hw, INTEN, 0);*/ -	/*hermes_set_irqmask(hw, 0);*/ - -	/* Acknowledge any outstanding command */ -	hermes_write_regn(hw, EVACK, 0xFFFF); - -	/* Using doicmd_wait rather than docmd_wait */ -	err = hermes_doicmd_wait(hw, -				 0x0100 | HERMES_CMD_INIT, -				 0, 0, 0, NULL); -	if (err) -		return err; - -	err = hermes_doicmd_wait(hw, -				 0x0000 | HERMES_CMD_INIT, -				 0, 0, 0, NULL); -	if (err) -		return err; - -	err = hermes_aux_control(hw, 1); -	pr_debug(PFX "AUX enable returned %d\n", err); - -	if (err) -		return err; - -	pr_debug(PFX "Enabling volatile, EP 0x%08x\n", offset); -	err = hermes_doicmd_wait(hw, -				 HERMES_PROGRAM_ENABLE_VOLATILE, -				 offset & 0xFFFFu, -				 offset >> 16, -				 0, -				 NULL); -	pr_debug(PFX "PROGRAM_ENABLE returned %d\n", err); - -	return err; -} - -/* Done programming data (Hermes I) - * - * Spectrum_cs' Symbol fw does not require this - * wl_lkm Agere fw does - * Don't know about intersil - */ -int hermesi_program_end(hermes_t *hw) -{ -	struct hermes_response resp; -	int rc = 0; -	int err; - -	rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp); - -	pr_debug(PFX "PROGRAM_DISABLE returned %d, " -		 "r0 0x%04x, r1 0x%04x, r2 0x%04x\n", -		 rc, resp.resp0, resp.resp1, resp.resp2); - -	if ((rc == 0) && -	    ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD)) -		rc = -EIO; - -	err = hermes_aux_control(hw, 0); -	pr_debug(PFX "AUX disable returned %d\n", err); - -	/* Acknowledge any outstanding command */ -	hermes_write_regn(hw, EVACK, 0xFFFF); - -	/* Reinitialise, ignoring return */ -	(void) hermes_doicmd_wait(hw, 0x0000 | HERMES_CMD_INIT, -				  0, 0, 0, NULL); - -	return rc ? rc : err; -} -  /* Program the data blocks */  int hermes_program(hermes_t *hw, const char *first_block, const void *end)  {  	const struct dblock *blk;  	u32 blkaddr;  	u32 blklen; -#if LIMIT_PROGRAM_SIZE -	u32 addr; -	u32 len; -#endif +	int err = 0;  	blk = (const struct dblock *) first_block; @@ -498,30 +294,10 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)  		pr_debug(PFX "Programming block of length %d "  			 "to address 0x%08x\n", blklen, blkaddr); -#if !LIMIT_PROGRAM_SIZE -		/* wl_lkm driver splits this into writes of 2000 bytes */ -		hermes_aux_setaddr(hw, blkaddr); -		hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, -				   blklen); -#else -		len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE; -		addr = blkaddr; - -		while (addr < (blkaddr + blklen)) { -			pr_debug(PFX "Programming subblock of length %d " -				 "to address 0x%08x. Data @ %p\n", -				 len, addr, &blk->data[addr - blkaddr]); - -			hermes_aux_setaddr(hw, addr); -			hermes_write_bytes(hw, HERMES_AUXDATA, -					   &blk->data[addr - blkaddr], -					   len); +		err = hw->ops->program(hw, blk->data, blkaddr, blklen); +		if (err) +			break; -			addr += len; -			len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ? -				(blkaddr + blklen - addr) : MAX_DL_SIZE; -		} -#endif  		blk = (const struct dblock *) &blk->data[blklen];  		if ((void *) blk > (end - sizeof(*blk))) @@ -530,7 +306,7 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)  		blkaddr = dblock_addr(blk);  		blklen = dblock_len(blk);  	} -	return 0; +	return err;  }  /*** Default plugging data for Hermes I ***/ @@ -690,9 +466,8 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,  			if ((pdi_len(pdi) == pdr_len(pdr)) &&  			    ((void *) pdi->data + pdi_len(pdi) < pda_end)) {  				/* do the actual plugging */ -				hermes_aux_setaddr(hw, pdr_addr(pdr)); -				hermes_write_bytes(hw, HERMES_AUXDATA, -						   pdi->data, pdi_len(pdi)); +				hw->ops->program(hw, pdi->data, pdr_addr(pdr), +						 pdi_len(pdi));  			}  		} diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c index 9f657afaa3e..6fbd7885012 100644 --- a/drivers/net/wireless/orinoco/hw.c +++ b/drivers/net/wireless/orinoco/hw.c @@ -177,9 +177,9 @@ int determine_fw_capabilities(struct orinoco_private *priv,  		/* 3Com MAC : 00:50:DA:* */  		memset(tmp, 0, sizeof(tmp));  		/* Get the Symbol firmware version */ -		err = hermes_read_ltv(hw, USER_BAP, -				      HERMES_RID_SECONDARYVERSION_SYMBOL, -				      SYMBOL_MAX_VER_LEN, NULL, &tmp); +		err = hw->ops->read_ltv(hw, USER_BAP, +					HERMES_RID_SECONDARYVERSION_SYMBOL, +					SYMBOL_MAX_VER_LEN, NULL, &tmp);  		if (err) {  			dev_warn(dev, "Error %d reading Symbol firmware info. "  				 "Wildly guessing capabilities...\n", err); @@ -286,8 +286,8 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)  	u16 reclen;  	/* Get the MAC address */ -	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, -			      ETH_ALEN, NULL, dev_addr); +	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, +				ETH_ALEN, NULL, dev_addr);  	if (err) {  		dev_warn(dev, "Failed to read MAC address!\n");  		goto out; @@ -296,8 +296,8 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)  	dev_dbg(dev, "MAC address %pM\n", dev_addr);  	/* Get the station name */ -	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, -			      sizeof(nickbuf), &reclen, &nickbuf); +	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, +				sizeof(nickbuf), &reclen, &nickbuf);  	if (err) {  		dev_err(dev, "failed to read station name\n");  		goto out; @@ -374,6 +374,32 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)  		err = hermes_read_wordrec(hw, USER_BAP,  					  HERMES_RID_CNFPREAMBLE_SYMBOL,  					  &priv->preamble); +		if (err) { +			dev_err(dev, "Failed to read preamble setup\n"); +			goto out; +		} +	} + +	/* Retry settings */ +	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT, +				  &priv->short_retry_limit); +	if (err) { +		dev_err(dev, "Failed to read short retry limit\n"); +		goto out; +	} + +	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT, +				  &priv->long_retry_limit); +	if (err) { +		dev_err(dev, "Failed to read long retry limit\n"); +		goto out; +	} + +	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME, +				  &priv->retry_lifetime); +	if (err) { +		dev_err(dev, "Failed to read max retry lifetime\n"); +		goto out;  	}  out: @@ -387,11 +413,11 @@ int orinoco_hw_allocate_fid(struct orinoco_private *priv)  	struct hermes *hw = &priv->hw;  	int err; -	err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); +	err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);  	if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {  		/* Try workaround for old Symbol firmware bug */  		priv->nicbuf_size = TX_NICBUF_SIZE_BUG; -		err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); +		err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);  		dev_warn(dev, "Firmware ALLOC bug detected "  			 "(old Symbol firmware?). Work around %s\n", @@ -437,8 +463,9 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)  	struct hermes_idstring idbuf;  	/* Set the MAC address */ -	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, -			       HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr); +	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, +				 HERMES_BYTES_TO_RECLEN(ETH_ALEN), +				 dev->dev_addr);  	if (err) {  		printk(KERN_ERR "%s: Error %d setting MAC address\n",  		       dev->name, err); @@ -501,7 +528,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)  	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));  	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));  	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */ -	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID, +	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,  			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),  			&idbuf);  	if (err) { @@ -509,7 +536,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)  		       dev->name, err);  		return err;  	} -	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID, +	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,  			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),  			&idbuf);  	if (err) { @@ -521,9 +548,9 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)  	/* Set the station name */  	idbuf.len = cpu_to_le16(strlen(priv->nick));  	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val)); -	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, -			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2), -			       &idbuf); +	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, +				 HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2), +				 &idbuf);  	if (err) {  		printk(KERN_ERR "%s: Error %d setting nickname\n",  		       dev->name, err); @@ -638,12 +665,12 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)  	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {  		/* Enable monitor mode */  		dev->type = ARPHRD_IEEE80211; -		err = hermes_docmd_wait(hw, HERMES_CMD_TEST | +		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |  					    HERMES_TEST_MONITOR, 0, NULL);  	} else {  		/* Disable monitor mode */  		dev->type = ARPHRD_ETHER; -		err = hermes_docmd_wait(hw, HERMES_CMD_TEST | +		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |  					    HERMES_TEST_STOP, 0, NULL);  	}  	if (err) @@ -669,8 +696,8 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)  	if ((key < 0) || (key >= 4))  		return -EINVAL; -	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV, -			      sizeof(tsc_arr), NULL, &tsc_arr); +	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV, +				sizeof(tsc_arr), NULL, &tsc_arr);  	if (!err)  		memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0])); @@ -849,7 +876,7 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)  				memcpy(key, priv->keys[i].key,  				       priv->keys[i].key_len); -				err = hermes_write_ltv(hw, USER_BAP, +				err = hw->ops->write_ltv(hw, USER_BAP,  						HERMES_RID_CNFDEFAULTKEY0 + i,  						HERMES_BYTES_TO_RECLEN(keylen),  						key); @@ -1066,7 +1093,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,  			memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);  		} -		err = hermes_write_ltv(hw, USER_BAP, +		err = hw->ops->write_ltv(hw, USER_BAP,  				   HERMES_RID_CNFGROUPADDRESSES,  				   HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),  				   &mclist); @@ -1108,15 +1135,15 @@ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,  		rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :  			HERMES_RID_CNFDESIREDSSID; -		err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), -				      NULL, &essidbuf); +		err = hw->ops->read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), +					NULL, &essidbuf);  		if (err)  			goto fail_unlock;  	} else {  		*active = 0; -		err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, -				      sizeof(essidbuf), NULL, &essidbuf); +		err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, +					sizeof(essidbuf), NULL, &essidbuf);  		if (err)  			goto fail_unlock;  	} @@ -1187,8 +1214,8 @@ int orinoco_hw_get_bitratelist(struct orinoco_private *priv,  	if (orinoco_lock(priv, &flags) != 0)  		return -EBUSY; -	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES, -			      sizeof(list), NULL, &list); +	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES, +				sizeof(list), NULL, &list);  	orinoco_unlock(priv, &flags);  	if (err) @@ -1255,7 +1282,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,  				idbuf.len = cpu_to_le16(len);  				memcpy(idbuf.val, ssid->ssid, len); -				err = hermes_write_ltv(hw, USER_BAP, +				err = hw->ops->write_ltv(hw, USER_BAP,  					       HERMES_RID_CNFSCANSSID_AGERE,  					       HERMES_BYTES_TO_RECLEN(len + 2),  					       &idbuf); @@ -1319,8 +1346,8 @@ int orinoco_hw_get_current_bssid(struct orinoco_private *priv,  	hermes_t *hw = &priv->hw;  	int err; -	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, -			      ETH_ALEN, NULL, addr); +	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, +				ETH_ALEN, NULL, addr);  	return err;  } diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 413e9ab6cab..1d60c7e4392 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -254,7 +254,7 @@ void set_port_type(struct orinoco_private *priv)  /* Device methods                                                   */  /********************************************************************/ -static int orinoco_open(struct net_device *dev) +int orinoco_open(struct net_device *dev)  {  	struct orinoco_private *priv = ndev_priv(dev);  	unsigned long flags; @@ -272,8 +272,9 @@ static int orinoco_open(struct net_device *dev)  	return err;  } +EXPORT_SYMBOL(orinoco_open); -static int orinoco_stop(struct net_device *dev) +int orinoco_stop(struct net_device *dev)  {  	struct orinoco_private *priv = ndev_priv(dev);  	int err = 0; @@ -281,25 +282,27 @@ static int orinoco_stop(struct net_device *dev)  	/* We mustn't use orinoco_lock() here, because we need to be  	   able to close the interface even if hw_unavailable is set  	   (e.g. as we're released after a PC Card removal) */ -	spin_lock_irq(&priv->lock); +	orinoco_lock_irq(priv);  	priv->open = 0;  	err = __orinoco_down(priv); -	spin_unlock_irq(&priv->lock); +	orinoco_unlock_irq(priv);  	return err;  } +EXPORT_SYMBOL(orinoco_stop); -static struct net_device_stats *orinoco_get_stats(struct net_device *dev) +struct net_device_stats *orinoco_get_stats(struct net_device *dev)  {  	struct orinoco_private *priv = ndev_priv(dev);  	return &priv->stats;  } +EXPORT_SYMBOL(orinoco_get_stats); -static void orinoco_set_multicast_list(struct net_device *dev) +void orinoco_set_multicast_list(struct net_device *dev)  {  	struct orinoco_private *priv = ndev_priv(dev);  	unsigned long flags; @@ -313,8 +316,9 @@ static void orinoco_set_multicast_list(struct net_device *dev)  	__orinoco_set_multicast_list(dev);  	orinoco_unlock(priv, &flags);  } +EXPORT_SYMBOL(orinoco_set_multicast_list); -static int orinoco_change_mtu(struct net_device *dev, int new_mtu) +int orinoco_change_mtu(struct net_device *dev, int new_mtu)  {  	struct orinoco_private *priv = ndev_priv(dev); @@ -330,6 +334,7 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu)  	return 0;  } +EXPORT_SYMBOL(orinoco_change_mtu);  /********************************************************************/  /* Tx path                                                          */ @@ -400,8 +405,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)  		memset(&desc, 0, sizeof(desc));  		*txcntl = cpu_to_le16(tx_control); -		err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), -					txfid, 0); +		err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), +					  txfid, 0);  		if (err) {  			if (net_ratelimit())  				printk(KERN_ERR "%s: Error %d writing Tx " @@ -414,8 +419,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)  		memset(&desc, 0, sizeof(desc));  		desc.tx_control = cpu_to_le16(tx_control); -		err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), -					txfid, 0); +		err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), +					  txfid, 0);  		if (err) {  			if (net_ratelimit())  				printk(KERN_ERR "%s: Error %d writing Tx " @@ -458,8 +463,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)  		memcpy(eh, &hdr, sizeof(hdr));  	} -	err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, -				txfid, HERMES_802_3_OFFSET); +	err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len, +				  txfid, HERMES_802_3_OFFSET);  	if (err) {  		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",  		       dev->name, err); @@ -490,8 +495,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)  			    skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);  		/* Write the MIC */ -		err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len, -					txfid, HERMES_802_3_OFFSET + offset); +		err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len, +					  txfid, HERMES_802_3_OFFSET + offset);  		if (err) {  			printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",  			       dev->name, err); @@ -502,7 +507,7 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)  	/* Finally, we actually initiate the send */  	netif_stop_queue(dev); -	err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, +	err = hw->ops->cmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,  				txfid, NULL);  	if (err) {  		netif_start_queue(dev); @@ -572,9 +577,9 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)  		return; /* Nothing's really happened */  	/* Read part of the frame header - we need status and addr1 */ -	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, -			       sizeof(struct hermes_txexc_data), -			       fid, 0); +	err = hw->ops->bap_pread(hw, IRQ_BAP, &hdr, +				 sizeof(struct hermes_txexc_data), +				 fid, 0);  	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);  	stats->tx_errors++; @@ -615,7 +620,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)  	netif_wake_queue(dev);  } -static void orinoco_tx_timeout(struct net_device *dev) +void orinoco_tx_timeout(struct net_device *dev)  {  	struct orinoco_private *priv = ndev_priv(dev);  	struct net_device_stats *stats = &priv->stats; @@ -630,6 +635,7 @@ static void orinoco_tx_timeout(struct net_device *dev)  	schedule_work(&priv->reset_work);  } +EXPORT_SYMBOL(orinoco_tx_timeout);  /********************************************************************/  /* Rx path (data frames)                                            */ @@ -764,9 +770,9 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,  	/* If any, copy the data from the card to the skb */  	if (datalen > 0) { -		err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), -				       ALIGN(datalen, 2), rxfid, -				       HERMES_802_2_OFFSET); +		err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), +					 ALIGN(datalen, 2), rxfid, +					 HERMES_802_2_OFFSET);  		if (err) {  			printk(KERN_ERR "%s: error %d reading monitor frame\n",  			       dev->name, err); @@ -792,7 +798,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,  	stats->rx_dropped++;  } -static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) +void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)  {  	struct orinoco_private *priv = ndev_priv(dev);  	struct net_device_stats *stats = &priv->stats; @@ -814,8 +820,8 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)  	rxfid = hermes_read_regn(hw, RXFID); -	err = hermes_bap_pread(hw, IRQ_BAP, desc, sizeof(*desc), -			       rxfid, 0); +	err = hw->ops->bap_pread(hw, IRQ_BAP, desc, sizeof(*desc), +				 rxfid, 0);  	if (err) {  		printk(KERN_ERR "%s: error %d reading Rx descriptor. "  		       "Frame dropped.\n", dev->name, err); @@ -882,9 +888,9 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)  	   nothing is removed.  2 is for aligning the IP header.  */  	skb_reserve(skb, ETH_HLEN + 2); -	err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length), -			       ALIGN(length, 2), rxfid, -			       HERMES_802_2_OFFSET); +	err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, length), +				 ALIGN(length, 2), rxfid, +				 HERMES_802_2_OFFSET);  	if (err) {  		printk(KERN_ERR "%s: error %d reading frame. "  		       "Frame dropped.\n", dev->name, err); @@ -913,6 +919,7 @@ update_stats:  out:  	kfree(desc);  } +EXPORT_SYMBOL(__orinoco_ev_rx);  static void orinoco_rx(struct net_device *dev,  		       struct hermes_rx_descriptor *desc, @@ -1145,9 +1152,9 @@ static void orinoco_join_ap(struct work_struct *work)  		goto out;  	/* Read scan results from the firmware */ -	err = hermes_read_ltv(hw, USER_BAP, -			      HERMES_RID_SCANRESULTSTABLE, -			      MAX_SCAN_LEN, &len, buf); +	err = hw->ops->read_ltv(hw, USER_BAP, +				HERMES_RID_SCANRESULTSTABLE, +				MAX_SCAN_LEN, &len, buf);  	if (err) {  		printk(KERN_ERR "%s: Cannot read scan results\n",  		       dev->name); @@ -1194,8 +1201,8 @@ static void orinoco_send_bssid_wevent(struct orinoco_private *priv)  	union iwreq_data wrqu;  	int err; -	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, -			      ETH_ALEN, NULL, wrqu.ap_addr.sa_data); +	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, +				ETH_ALEN, NULL, wrqu.ap_addr.sa_data);  	if (err != 0)  		return; @@ -1217,8 +1224,8 @@ static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)  	if (!priv->has_wpa)  		return; -	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO, -			      sizeof(buf), NULL, &buf); +	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO, +				sizeof(buf), NULL, &buf);  	if (err != 0)  		return; @@ -1247,8 +1254,9 @@ static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)  	if (!priv->has_wpa)  		return; -	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO, -			      sizeof(buf), NULL, &buf); +	err = hw->ops->read_ltv(hw, USER_BAP, +				HERMES_RID_CURRENT_ASSOC_RESP_INFO, +				sizeof(buf), NULL, &buf);  	if (err != 0)  		return; @@ -1353,7 +1361,7 @@ static void orinoco_process_scan_results(struct work_struct *work)  	spin_unlock_irqrestore(&priv->scan_lock, flags);  } -static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) +void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)  {  	struct orinoco_private *priv = ndev_priv(dev);  	u16 infofid; @@ -1371,8 +1379,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)  	infofid = hermes_read_regn(hw, INFOFID);  	/* Read the info frame header - don't try too hard */ -	err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info), -			       infofid, 0); +	err = hw->ops->bap_pread(hw, IRQ_BAP, &info, sizeof(info), +				 infofid, 0);  	if (err) {  		printk(KERN_ERR "%s: error %d reading info frame. "  		       "Frame dropped.\n", dev->name, err); @@ -1393,8 +1401,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)  			len = sizeof(tallies);  		} -		err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len, -				       infofid, sizeof(info)); +		err = hw->ops->bap_pread(hw, IRQ_BAP, &tallies, len, +					 infofid, sizeof(info));  		if (err)  			break; @@ -1429,8 +1437,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)  			break;  		} -		err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len, -				       infofid, sizeof(info)); +		err = hw->ops->bap_pread(hw, IRQ_BAP, &linkstatus, len, +					 infofid, sizeof(info));  		if (err)  			break;  		newstatus = le16_to_cpu(linkstatus.linkstatus); @@ -1494,8 +1502,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)  		}  		/* Read scan data */ -		err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, -				       infofid, sizeof(info)); +		err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) buf, len, +					 infofid, sizeof(info));  		if (err) {  			kfree(buf);  			qabort_scan(priv); @@ -1547,8 +1555,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)  			break;  		/* Read scan data */ -		err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len, -				       infofid, sizeof(info)); +		err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) bss, len, +					 infofid, sizeof(info));  		if (err)  			kfree(bss);  		else @@ -1571,6 +1579,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)  	return;  } +EXPORT_SYMBOL(__orinoco_ev_info);  static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)  { @@ -1647,7 +1656,7 @@ static int orinoco_reinit_firmware(struct orinoco_private *priv)  	struct hermes *hw = &priv->hw;  	int err; -	err = hermes_init(hw); +	err = hw->ops->init(hw);  	if (priv->do_fw_download && !err) {  		err = orinoco_download(priv);  		if (err) @@ -1735,7 +1744,7 @@ void orinoco_reset(struct work_struct *work)  	}  	/* This has to be called from user context */ -	spin_lock_irq(&priv->lock); +	orinoco_lock_irq(priv);  	priv->hw_unavailable--; @@ -1750,7 +1759,7 @@ void orinoco_reset(struct work_struct *work)  			dev->trans_start = jiffies;  	} -	spin_unlock_irq(&priv->lock); +	orinoco_unlock_irq(priv);  	return;   disable: @@ -1984,7 +1993,7 @@ int orinoco_init(struct orinoco_private *priv)  	priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;  	/* Initialize the firmware */ -	err = hermes_init(hw); +	err = hw->ops->init(hw);  	if (err != 0) {  		dev_err(dev, "Failed to initialize firmware (err = %d)\n",  			err); @@ -2067,9 +2076,9 @@ int orinoco_init(struct orinoco_private *priv)  	/* Make the hardware available, as long as it hasn't been  	 * removed elsewhere (e.g. by PCMCIA hot unplug) */ -	spin_lock_irq(&priv->lock); +	orinoco_lock_irq(priv);  	priv->hw_unavailable--; -	spin_unlock_irq(&priv->lock); +	orinoco_unlock_irq(priv);  	dev_dbg(dev, "Ready\n"); @@ -2192,7 +2201,8 @@ EXPORT_SYMBOL(alloc_orinocodev);   */  int orinoco_if_add(struct orinoco_private *priv,  		   unsigned long base_addr, -		   unsigned int irq) +		   unsigned int irq, +		   const struct net_device_ops *ops)  {  	struct wiphy *wiphy = priv_to_wiphy(priv);  	struct wireless_dev *wdev; @@ -2211,12 +2221,17 @@ int orinoco_if_add(struct orinoco_private *priv,  	/* Setup / override net_device fields */  	dev->ieee80211_ptr = wdev; -	dev->netdev_ops = &orinoco_netdev_ops;  	dev->watchdog_timeo = HZ; /* 1 second timeout */  	dev->wireless_handlers = &orinoco_handler_def;  #ifdef WIRELESS_SPY  	dev->wireless_data = &priv->wireless_data;  #endif +	/* Default to standard ops if not set */ +	if (ops) +		dev->netdev_ops = ops; +	else +		dev->netdev_ops = &orinoco_netdev_ops; +  	/* we use the default eth_mac_addr for setting the MAC addr */  	/* Reserve space in skb for the SNAP header */ @@ -2305,7 +2320,7 @@ int orinoco_up(struct orinoco_private *priv)  	unsigned long flags;  	int err; -	spin_lock_irqsave(&priv->lock, flags); +	priv->hw.ops->lock_irqsave(&priv->lock, &flags);  	err = orinoco_reinit_firmware(priv);  	if (err) { @@ -2325,7 +2340,7 @@ int orinoco_up(struct orinoco_private *priv)  	}  exit: -	spin_unlock_irqrestore(&priv->lock, flags); +	priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);  	return 0;  } @@ -2337,7 +2352,7 @@ void orinoco_down(struct orinoco_private *priv)  	unsigned long flags;  	int err; -	spin_lock_irqsave(&priv->lock, flags); +	priv->hw.ops->lock_irqsave(&priv->lock, &flags);  	err = __orinoco_down(priv);  	if (err)  		printk(KERN_WARNING "%s: Error %d downing interface\n", @@ -2345,7 +2360,7 @@ void orinoco_down(struct orinoco_private *priv)  	netif_device_detach(dev);  	priv->hw_unavailable++; -	spin_unlock_irqrestore(&priv->lock, flags); +	priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);  }  EXPORT_SYMBOL(orinoco_down); diff --git a/drivers/net/wireless/orinoco/main.h b/drivers/net/wireless/orinoco/main.h index 21ab36cd76c..4dadf9880a9 100644 --- a/drivers/net/wireless/orinoco/main.h +++ b/drivers/net/wireless/orinoco/main.h @@ -33,18 +33,6 @@ int orinoco_commit(struct orinoco_private *priv);  void orinoco_reset(struct work_struct *work);  /* Information element helpers - find a home for these... */ -static inline u8 *orinoco_get_ie(u8 *data, size_t len, -				 enum ieee80211_eid eid) -{ -	u8 *p = data; -	while ((p + 2) < (data + len)) { -		if (p[0] == eid) -			return p; -		p += p[1] + 2; -	} -	return NULL; -} -  #define WPA_OUI_TYPE	"\x00\x50\xF2\x01"  #define WPA_SELECTOR_LEN 4  static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len) diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index 665ef56f838..e9f415a56d4 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h @@ -131,6 +131,8 @@ struct orinoco_private {  	u16 ap_density, rts_thresh;  	u16 pm_on, pm_mcast, pm_period, pm_timeout;  	u16 preamble; +	u16 short_retry_limit, long_retry_limit; +	u16 retry_lifetime;  #ifdef WIRELESS_SPY  	struct iw_spy_data spy_data; /* iwspy support */  	struct iw_public_data	wireless_data; @@ -188,12 +190,24 @@ extern void free_orinocodev(struct orinoco_private *priv);  extern int orinoco_init(struct orinoco_private *priv);  extern int orinoco_if_add(struct orinoco_private *priv,  			  unsigned long base_addr, -			  unsigned int irq); +			  unsigned int irq, +			  const struct net_device_ops *ops);  extern void orinoco_if_del(struct orinoco_private *priv);  extern int orinoco_up(struct orinoco_private *priv);  extern void orinoco_down(struct orinoco_private *priv);  extern irqreturn_t orinoco_interrupt(int irq, void *dev_id); +extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw); +extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw); + +/* Common ndo functions exported for reuse by orinoco_usb */ +int orinoco_open(struct net_device *dev); +int orinoco_stop(struct net_device *dev); +struct net_device_stats *orinoco_get_stats(struct net_device *dev); +void orinoco_set_multicast_list(struct net_device *dev); +int orinoco_change_mtu(struct net_device *dev, int new_mtu); +void orinoco_tx_timeout(struct net_device *dev); +  /********************************************************************/  /* Locking and synchronization functions                            */  /********************************************************************/ @@ -201,11 +215,11 @@ extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);  static inline int orinoco_lock(struct orinoco_private *priv,  			       unsigned long *flags)  { -	spin_lock_irqsave(&priv->lock, *flags); +	priv->hw.ops->lock_irqsave(&priv->lock, flags);  	if (priv->hw_unavailable) {  		DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n",  		       priv->ndev); -		spin_unlock_irqrestore(&priv->lock, *flags); +		priv->hw.ops->unlock_irqrestore(&priv->lock, flags);  		return -EBUSY;  	}  	return 0; @@ -214,7 +228,17 @@ static inline int orinoco_lock(struct orinoco_private *priv,  static inline void orinoco_unlock(struct orinoco_private *priv,  				  unsigned long *flags)  { -	spin_unlock_irqrestore(&priv->lock, *flags); +	priv->hw.ops->unlock_irqrestore(&priv->lock, flags); +} + +static inline void orinoco_lock_irq(struct orinoco_private *priv) +{ +	priv->hw.ops->lock_irq(&priv->lock); +} + +static inline void orinoco_unlock_irq(struct orinoco_private *priv) +{ +	priv->hw.ops->unlock_irq(&priv->lock);  }  /*** Navigate from net_device to orinoco_private ***/ diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index fdc96137917..f99b13ba92b 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -296,7 +296,7 @@ orinoco_cs_config(struct pcmcia_device *link)  	/* Register an interface with the stack */  	if (orinoco_if_add(priv, link->io.BasePort1, -			   link->irq.AssignedIRQ) != 0) { +			   link->irq.AssignedIRQ, NULL) != 0) {  		printk(KERN_ERR PFX "orinoco_if_add() failed\n");  		goto failed;  	} @@ -327,9 +327,9 @@ orinoco_cs_release(struct pcmcia_device *link)  	/* We're committed to taking the device away now, so mark the  	 * hardware as unavailable */ -	spin_lock_irqsave(&priv->lock, flags); +	priv->hw.ops->lock_irqsave(&priv->lock, &flags);  	priv->hw_unavailable++; -	spin_unlock_irqrestore(&priv->lock, flags); +	priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);  	pcmcia_disable_device(link);  	if (priv->hw.iobase) diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c index 075f446b313..bc3ea0b67a4 100644 --- a/drivers/net/wireless/orinoco/orinoco_nortel.c +++ b/drivers/net/wireless/orinoco/orinoco_nortel.c @@ -220,7 +220,7 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,  		goto fail;  	} -	err = orinoco_if_add(priv, 0, 0); +	err = orinoco_if_add(priv, 0, 0, NULL);  	if (err) {  		printk(KERN_ERR PFX "orinoco_if_add() failed\n");  		goto fail; diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c index bda5317cc59..468197f8667 100644 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ b/drivers/net/wireless/orinoco/orinoco_pci.c @@ -170,7 +170,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,  		goto fail;  	} -	err = orinoco_if_add(priv, 0, 0); +	err = orinoco_if_add(priv, 0, 0, NULL);  	if (err) {  		printk(KERN_ERR PFX "orinoco_if_add() failed\n");  		goto fail; diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c index e0d5874ab42..9358f4d2307 100644 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ b/drivers/net/wireless/orinoco/orinoco_plx.c @@ -259,7 +259,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,  		goto fail;  	} -	err = orinoco_if_add(priv, 0, 0); +	err = orinoco_if_add(priv, 0, 0, NULL);  	if (err) {  		printk(KERN_ERR PFX "orinoco_if_add() failed\n");  		goto fail; diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c index 88cbc7902aa..784605f0af1 100644 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ b/drivers/net/wireless/orinoco/orinoco_tmd.c @@ -156,7 +156,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,  		goto fail;  	} -	err = orinoco_if_add(priv, 0, 0); +	err = orinoco_if_add(priv, 0, 0, NULL);  	if (err) {  		printk(KERN_ERR PFX "orinoco_if_add() failed\n");  		goto fail; diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c new file mode 100644 index 00000000000..e22093359f3 --- /dev/null +++ b/drivers/net/wireless/orinoco/orinoco_usb.c @@ -0,0 +1,1800 @@ +/* + * USB Orinoco driver + * + * Copyright (c) 2003 Manuel Estrada Sainz + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License version 2 (the "GPL"), in + * which case the provisions of the GPL are applicable instead of the + * above.  If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the MPL, indicate your decision by + * deleting the provisions above and replace them with the notice and + * other provisions required by the GPL.  If you do not delete the + * provisions above, a recipient may use your version of this file + * under either the MPL or the GPL. + * + * Queueing code based on linux-wlan-ng 0.2.1-pre5 + * + * Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved. + * + *	The license is the same as above. + * + * Initialy based on USB Skeleton driver - 0.7 + * + * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * + *	This program is free software; you can redistribute it and/or + *	modify it under the terms of the GNU General Public License as + *	published by the Free Software Foundation; either version 2 of + *	the License, or (at your option) any later version. + * + * NOTE: The original USB Skeleton driver is GPL, but all that code is + * gone so MPL/GPL applies. + */ + +#define DRIVER_NAME "orinoco_usb" +#define PFX DRIVER_NAME ": " + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/errno.h> +#include <linux/poll.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/fcntl.h> +#include <linux/spinlock.h> +#include <linux/list.h> +#include <linux/smp_lock.h> +#include <linux/usb.h> +#include <linux/timer.h> + +#include <linux/netdevice.h> +#include <linux/if_arp.h> +#include <linux/etherdevice.h> +#include <linux/wireless.h> +#include <linux/firmware.h> + +#include "orinoco.h" + +#ifndef URB_ASYNC_UNLINK +#define URB_ASYNC_UNLINK 0 +#endif + +/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ +static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; +#define ENCAPS_OVERHEAD		(sizeof(encaps_hdr) + 2) + +struct header_struct { +	/* 802.3 */ +	u8 dest[ETH_ALEN]; +	u8 src[ETH_ALEN]; +	__be16 len; +	/* 802.2 */ +	u8 dsap; +	u8 ssap; +	u8 ctrl; +	/* SNAP */ +	u8 oui[3]; +	__be16 ethertype; +} __attribute__ ((packed)); + +struct ez_usb_fw { +	u16 size; +	const u8 *code; +}; + +static struct ez_usb_fw firmware = { +	.size = 0, +	.code = NULL, +}; + +#ifdef CONFIG_USB_DEBUG +static int debug = 1; +#else +static int debug; +#endif + +/* Debugging macros */ +#undef dbg +#define dbg(format, arg...) \ +	do { if (debug) printk(KERN_DEBUG PFX "%s: " format "\n", \ +			       __func__ , ## arg); } while (0) +#undef err +#define err(format, arg...) \ +	do { printk(KERN_ERR PFX format "\n", ## arg); } while (0) + +/* Module paramaters */ +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + +MODULE_FIRMWARE("orinoco_ezusb_fw"); + +/* + * Under some conditions, the card gets stuck and stops paying attention + * to the world (i.e. data communication stalls) until we do something to + * it.  Sending an INQ_TALLIES command seems to be enough and should be + * harmless otherwise.  This behaviour has been observed when using the + * driver on a systemimager client during installation.  In the past a + * timer was used to send INQ_TALLIES commands when there was no other + * activity, but it was troublesome and was removed. + */ + +#define USB_COMPAQ_VENDOR_ID     0x049f /* Compaq Computer Corp. */ +#define USB_COMPAQ_WL215_ID      0x001f /* Compaq WL215 USB Adapter */ +#define USB_COMPAQ_W200_ID       0x0076 /* Compaq W200 USB Adapter */ +#define USB_HP_WL215_ID          0x0082 /* Compaq WL215 USB Adapter */ + +#define USB_MELCO_VENDOR_ID      0x0411 +#define USB_BUFFALO_L11_ID       0x0006 /* BUFFALO WLI-USB-L11 */ +#define USB_BUFFALO_L11G_WR_ID   0x000B /* BUFFALO WLI-USB-L11G-WR */ +#define USB_BUFFALO_L11G_ID      0x000D /* BUFFALO WLI-USB-L11G */ + +#define USB_LUCENT_VENDOR_ID     0x047E /* Lucent Technologies */ +#define USB_LUCENT_ORINOCO_ID    0x0300 /* Lucent/Agere Orinoco USB Client */ + +#define USB_AVAYA8_VENDOR_ID     0x0D98 +#define USB_AVAYAE_VENDOR_ID     0x0D9E +#define USB_AVAYA_WIRELESS_ID    0x0300 /* Avaya Wireless USB Card */ + +#define USB_AGERE_VENDOR_ID      0x0D4E /* Agere Systems */ +#define USB_AGERE_MODEL0801_ID   0x1000 /* Wireless USB Card Model 0801 */ +#define USB_AGERE_MODEL0802_ID   0x1001 /* Wireless USB Card Model 0802 */ +#define USB_AGERE_REBRANDED_ID   0x047A /* WLAN USB Card */ + +#define USB_ELSA_VENDOR_ID       0x05CC +#define USB_ELSA_AIRLANCER_ID    0x3100 /* ELSA AirLancer USB-11 */ + +#define USB_LEGEND_VENDOR_ID     0x0E7C +#define USB_LEGEND_JOYNET_ID     0x0300 /* Joynet WLAN USB Card */ + +#define USB_SAMSUNG_VENDOR_ID    0x04E8 +#define USB_SAMSUNG_SEW2001U1_ID 0x5002 /* Samsung SEW-2001u Card */ +#define USB_SAMSUNG_SEW2001U2_ID 0x5B11 /* Samsung SEW-2001u Card */ +#define USB_SAMSUNG_SEW2003U_ID  0x7011 /* Samsung SEW-2003U Card */ + +#define USB_IGATE_VENDOR_ID      0x0681 +#define USB_IGATE_IGATE_11M_ID   0x0012 /* I-GATE 11M USB Card */ + +#define USB_FUJITSU_VENDOR_ID    0x0BF8 +#define USB_FUJITSU_E1100_ID     0x1002 /* connect2AIR WLAN E-1100 USB */ + +#define USB_2WIRE_VENDOR_ID      0x1630 +#define USB_2WIRE_WIRELESS_ID    0xff81 /* 2Wire Wireless USB adapter */ + + +#define EZUSB_REQUEST_FW_TRANS		0xA0 +#define EZUSB_REQUEST_TRIGER		0xAA +#define EZUSB_REQUEST_TRIG_AC		0xAC +#define EZUSB_CPUCS_REG			0x7F92 + +#define EZUSB_RID_TX			0x0700 +#define EZUSB_RID_RX			0x0701 +#define EZUSB_RID_INIT1			0x0702 +#define EZUSB_RID_ACK			0x0710 +#define EZUSB_RID_READ_PDA		0x0800 +#define EZUSB_RID_PROG_INIT		0x0852 +#define EZUSB_RID_PROG_SET_ADDR		0x0853 +#define EZUSB_RID_PROG_BYTES		0x0854 +#define EZUSB_RID_PROG_END		0x0855 +#define EZUSB_RID_DOCMD			0x0860 + +/* Recognize info frames */ +#define EZUSB_IS_INFO(id)		((id >= 0xF000) && (id <= 0xF2FF)) + +#define EZUSB_MAGIC			0x0210 + +#define EZUSB_FRAME_DATA		1 +#define EZUSB_FRAME_CONTROL		2 + +#define DEF_TIMEOUT			(3*HZ) + +#define BULK_BUF_SIZE			2048 + +#define MAX_DL_SIZE (BULK_BUF_SIZE - sizeof(struct ezusb_packet)) + +#define FW_BUF_SIZE			64 +#define FW_VAR_OFFSET_PTR		0x359 +#define FW_VAR_VALUE			0 +#define FW_HOLE_START			0x100 +#define FW_HOLE_END			0x300 + +struct ezusb_packet { +	__le16 magic;		/* 0x0210 */ +	u8 req_reply_count; +	u8 ans_reply_count; +	__le16 frame_type;	/* 0x01 for data frames, 0x02 otherwise */ +	__le16 size;		/* transport size */ +	__le16 crc;		/* CRC up to here */ +	__le16 hermes_len; +	__le16 hermes_rid; +	u8 data[0]; +} __attribute__ ((packed)); + +/* Table of devices that work or may work with this driver */ +static struct usb_device_id ezusb_table[] = { +	{USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_COMPAQ_WL215_ID)}, +	{USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_HP_WL215_ID)}, +	{USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_COMPAQ_W200_ID)}, +	{USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11_ID)}, +	{USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11G_WR_ID)}, +	{USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11G_ID)}, +	{USB_DEVICE(USB_LUCENT_VENDOR_ID, USB_LUCENT_ORINOCO_ID)}, +	{USB_DEVICE(USB_AVAYA8_VENDOR_ID, USB_AVAYA_WIRELESS_ID)}, +	{USB_DEVICE(USB_AVAYAE_VENDOR_ID, USB_AVAYA_WIRELESS_ID)}, +	{USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_MODEL0801_ID)}, +	{USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_MODEL0802_ID)}, +	{USB_DEVICE(USB_ELSA_VENDOR_ID, USB_ELSA_AIRLANCER_ID)}, +	{USB_DEVICE(USB_LEGEND_VENDOR_ID, USB_LEGEND_JOYNET_ID)}, +	{USB_DEVICE_VER(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2001U1_ID, +			0, 0)}, +	{USB_DEVICE(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2001U2_ID)}, +	{USB_DEVICE(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2003U_ID)}, +	{USB_DEVICE(USB_IGATE_VENDOR_ID, USB_IGATE_IGATE_11M_ID)}, +	{USB_DEVICE(USB_FUJITSU_VENDOR_ID, USB_FUJITSU_E1100_ID)}, +	{USB_DEVICE(USB_2WIRE_VENDOR_ID, USB_2WIRE_WIRELESS_ID)}, +	{USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_REBRANDED_ID)}, +	{}			/* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, ezusb_table); + +/* Structure to hold all of our device specific stuff */ +struct ezusb_priv { +	struct usb_device *udev; +	struct net_device *dev; +	struct mutex mtx; +	spinlock_t req_lock; +	struct list_head req_pending; +	struct list_head req_active; +	spinlock_t reply_count_lock; +	u16 hermes_reg_fake[0x40]; +	u8 *bap_buf; +	struct urb *read_urb; +	int read_pipe; +	int write_pipe; +	u8 reply_count; +}; + +enum ezusb_state { +	EZUSB_CTX_START, +	EZUSB_CTX_QUEUED, +	EZUSB_CTX_REQ_SUBMITTED, +	EZUSB_CTX_REQ_COMPLETE, +	EZUSB_CTX_RESP_RECEIVED, +	EZUSB_CTX_REQ_TIMEOUT, +	EZUSB_CTX_REQ_FAILED, +	EZUSB_CTX_RESP_TIMEOUT, +	EZUSB_CTX_REQSUBMIT_FAIL, +	EZUSB_CTX_COMPLETE, +}; + +struct request_context { +	struct list_head list; +	atomic_t refcount; +	struct completion done;	/* Signals that CTX is dead */ +	int killed; +	struct urb *outurb;	/* OUT for req pkt */ +	struct ezusb_priv *upriv; +	struct ezusb_packet *buf; +	int buf_length; +	struct timer_list timer;	/* Timeout handling */ +	enum ezusb_state state;	/* Current state */ +	/* the RID that we will wait for */ +	u16 out_rid; +	u16 in_rid; +}; + + +/* Forward declarations */ +static void ezusb_ctx_complete(struct request_context *ctx); +static void ezusb_req_queue_run(struct ezusb_priv *upriv); +static void ezusb_bulk_in_callback(struct urb *urb); + +static inline u8 ezusb_reply_inc(u8 count) +{ +	if (count < 0x7F) +		return count + 1; +	else +		return 1; +} + +static void ezusb_request_context_put(struct request_context *ctx) +{ +	if (!atomic_dec_and_test(&ctx->refcount)) +		return; + +	WARN_ON(!ctx->done.done); +	BUG_ON(ctx->outurb->status == -EINPROGRESS); +	BUG_ON(timer_pending(&ctx->timer)); +	usb_free_urb(ctx->outurb); +	kfree(ctx->buf); +	kfree(ctx); +} + +static inline void ezusb_mod_timer(struct ezusb_priv *upriv, +				   struct timer_list *timer, +				   unsigned long expire) +{ +	if (!upriv->udev) +		return; +	mod_timer(timer, expire); +} + +static void ezusb_request_timerfn(u_long _ctx) +{ +	struct request_context *ctx = (void *) _ctx; + +	ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK; +	if (usb_unlink_urb(ctx->outurb) == -EINPROGRESS) { +		ctx->state = EZUSB_CTX_REQ_TIMEOUT; +	} else { +		ctx->state = EZUSB_CTX_RESP_TIMEOUT; +		dbg("couldn't unlink"); +		atomic_inc(&ctx->refcount); +		ctx->killed = 1; +		ezusb_ctx_complete(ctx); +		ezusb_request_context_put(ctx); +	} +}; + +static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv, +					       u16 out_rid, u16 in_rid) +{ +	struct request_context *ctx; + +	ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); +	if (!ctx) +		return NULL; + +	memset(ctx, 0, sizeof(*ctx)); + +	ctx->buf = kmalloc(BULK_BUF_SIZE, GFP_ATOMIC); +	if (!ctx->buf) { +		kfree(ctx); +		return NULL; +	} +	ctx->outurb = usb_alloc_urb(0, GFP_ATOMIC); +	if (!ctx->outurb) { +		kfree(ctx->buf); +		kfree(ctx); +		return NULL; +	} + +	ctx->upriv = upriv; +	ctx->state = EZUSB_CTX_START; +	ctx->out_rid = out_rid; +	ctx->in_rid = in_rid; + +	atomic_set(&ctx->refcount, 1); +	init_completion(&ctx->done); + +	init_timer(&ctx->timer); +	ctx->timer.function = ezusb_request_timerfn; +	ctx->timer.data = (u_long) ctx; +	return ctx; +} + + +/* Hopefully the real complete_all will soon be exported, in the mean + * while this should work. */ +static inline void ezusb_complete_all(struct completion *comp) +{ +	complete(comp); +	complete(comp); +	complete(comp); +	complete(comp); +} + +static void ezusb_ctx_complete(struct request_context *ctx) +{ +	struct ezusb_priv *upriv = ctx->upriv; +	unsigned long flags; + +	spin_lock_irqsave(&upriv->req_lock, flags); + +	list_del_init(&ctx->list); +	if (upriv->udev) { +		spin_unlock_irqrestore(&upriv->req_lock, flags); +		ezusb_req_queue_run(upriv); +		spin_lock_irqsave(&upriv->req_lock, flags); +	} + +	switch (ctx->state) { +	case EZUSB_CTX_COMPLETE: +	case EZUSB_CTX_REQSUBMIT_FAIL: +	case EZUSB_CTX_REQ_FAILED: +	case EZUSB_CTX_REQ_TIMEOUT: +	case EZUSB_CTX_RESP_TIMEOUT: +		spin_unlock_irqrestore(&upriv->req_lock, flags); + +		if ((ctx->out_rid == EZUSB_RID_TX) && upriv->dev) { +			struct net_device *dev = upriv->dev; +			struct orinoco_private *priv = ndev_priv(dev); +			struct net_device_stats *stats = &priv->stats; + +			if (ctx->state != EZUSB_CTX_COMPLETE) +				stats->tx_errors++; +			else +				stats->tx_packets++; + +			netif_wake_queue(dev); +		} +		ezusb_complete_all(&ctx->done); +		ezusb_request_context_put(ctx); +		break; + +	default: +		spin_unlock_irqrestore(&upriv->req_lock, flags); +		if (!upriv->udev) { +			/* This is normal, as all request contexts get flushed +			 * when the device is disconnected */ +			err("Called, CTX not terminating, but device gone"); +			ezusb_complete_all(&ctx->done); +			ezusb_request_context_put(ctx); +			break; +		} + +		err("Called, CTX not in terminating state."); +		/* Things are really bad if this happens. Just leak +		 * the CTX because it may still be linked to the +		 * queue or the OUT urb may still be active. +		 * Just leaking at least prevents an Oops or Panic. +		 */ +		break; +	} +} + +/** + * ezusb_req_queue_run: + * Description: + *	Note: Only one active CTX at any one time, because there's no + *	other (reliable) way to match the response URB to the correct + *	CTX. + **/ +static void ezusb_req_queue_run(struct ezusb_priv *upriv) +{ +	unsigned long flags; +	struct request_context *ctx; +	int result; + +	spin_lock_irqsave(&upriv->req_lock, flags); + +	if (!list_empty(&upriv->req_active)) +		goto unlock; + +	if (list_empty(&upriv->req_pending)) +		goto unlock; + +	ctx = +	    list_entry(upriv->req_pending.next, struct request_context, +		       list); + +	if (!ctx->upriv->udev) +		goto unlock; + +	/* We need to split this off to avoid a race condition */ +	list_move_tail(&ctx->list, &upriv->req_active); + +	if (ctx->state == EZUSB_CTX_QUEUED) { +		atomic_inc(&ctx->refcount); +		result = usb_submit_urb(ctx->outurb, GFP_ATOMIC); +		if (result) { +			ctx->state = EZUSB_CTX_REQSUBMIT_FAIL; + +			spin_unlock_irqrestore(&upriv->req_lock, flags); + +			err("Fatal, failed to submit command urb." +			    " error=%d\n", result); + +			ezusb_ctx_complete(ctx); +			ezusb_request_context_put(ctx); +			goto done; +		} + +		ctx->state = EZUSB_CTX_REQ_SUBMITTED; +		ezusb_mod_timer(ctx->upriv, &ctx->timer, +				jiffies + DEF_TIMEOUT); +	} + + unlock: +	spin_unlock_irqrestore(&upriv->req_lock, flags); + + done: +	return; +} + +static void ezusb_req_enqueue_run(struct ezusb_priv *upriv, +				  struct request_context *ctx) +{ +	unsigned long flags; + +	spin_lock_irqsave(&upriv->req_lock, flags); + +	if (!ctx->upriv->udev) { +		spin_unlock_irqrestore(&upriv->req_lock, flags); +		goto done; +	} +	atomic_inc(&ctx->refcount); +	list_add_tail(&ctx->list, &upriv->req_pending); +	spin_unlock_irqrestore(&upriv->req_lock, flags); + +	ctx->state = EZUSB_CTX_QUEUED; +	ezusb_req_queue_run(upriv); + + done: +	return; +} + +static void ezusb_request_out_callback(struct urb *urb) +{ +	unsigned long flags; +	enum ezusb_state state; +	struct request_context *ctx = urb->context; +	struct ezusb_priv *upriv = ctx->upriv; + +	spin_lock_irqsave(&upriv->req_lock, flags); + +	del_timer(&ctx->timer); + +	if (ctx->killed) { +		spin_unlock_irqrestore(&upriv->req_lock, flags); +		pr_warning("interrupt called with dead ctx"); +		goto out; +	} + +	state = ctx->state; + +	if (urb->status == 0) { +		switch (state) { +		case EZUSB_CTX_REQ_SUBMITTED: +			if (ctx->in_rid) { +				ctx->state = EZUSB_CTX_REQ_COMPLETE; +				/* reply URB still pending */ +				ezusb_mod_timer(upriv, &ctx->timer, +						jiffies + DEF_TIMEOUT); +				spin_unlock_irqrestore(&upriv->req_lock, +						       flags); +				break; +			} +			/* fall through */ +		case EZUSB_CTX_RESP_RECEIVED: +			/* IN already received before this OUT-ACK */ +			ctx->state = EZUSB_CTX_COMPLETE; +			spin_unlock_irqrestore(&upriv->req_lock, flags); +			ezusb_ctx_complete(ctx); +			break; + +		default: +			spin_unlock_irqrestore(&upriv->req_lock, flags); +			err("Unexpected state(0x%x, %d) in OUT URB", +			    state, urb->status); +			break; +		} +	} else { +		/* If someone cancels the OUT URB then its status +		 * should be either -ECONNRESET or -ENOENT. +		 */ +		switch (state) { +		case EZUSB_CTX_REQ_SUBMITTED: +		case EZUSB_CTX_RESP_RECEIVED: +			ctx->state = EZUSB_CTX_REQ_FAILED; +			/* fall through */ + +		case EZUSB_CTX_REQ_FAILED: +		case EZUSB_CTX_REQ_TIMEOUT: +			spin_unlock_irqrestore(&upriv->req_lock, flags); + +			ezusb_ctx_complete(ctx); +			break; + +		default: +			spin_unlock_irqrestore(&upriv->req_lock, flags); + +			err("Unexpected state(0x%x, %d) in OUT URB", +			    state, urb->status); +			break; +		} +	} + out: +	ezusb_request_context_put(ctx); +} + +static void ezusb_request_in_callback(struct ezusb_priv *upriv, +				      struct urb *urb) +{ +	struct ezusb_packet *ans = urb->transfer_buffer; +	struct request_context *ctx = NULL; +	enum ezusb_state state; +	unsigned long flags; + +	/* Find the CTX on the active queue that requested this URB */ +	spin_lock_irqsave(&upriv->req_lock, flags); +	if (upriv->udev) { +		struct list_head *item; + +		list_for_each(item, &upriv->req_active) { +			struct request_context *c; +			int reply_count; + +			c = list_entry(item, struct request_context, list); +			reply_count = +			    ezusb_reply_inc(c->buf->req_reply_count); +			if ((ans->ans_reply_count == reply_count) +			    && (le16_to_cpu(ans->hermes_rid) == c->in_rid)) { +				ctx = c; +				break; +			} +			dbg("Skipped (0x%x/0x%x) (%d/%d)", +			    le16_to_cpu(ans->hermes_rid), +			    c->in_rid, ans->ans_reply_count, reply_count); +		} +	} + +	if (ctx == NULL) { +		spin_unlock_irqrestore(&upriv->req_lock, flags); +		err("%s: got unexpected RID: 0x%04X", __func__, +		    le16_to_cpu(ans->hermes_rid)); +		ezusb_req_queue_run(upriv); +		return; +	} + +	/* The data we want is in the in buffer, exchange */ +	urb->transfer_buffer = ctx->buf; +	ctx->buf = (void *) ans; +	ctx->buf_length = urb->actual_length; + +	state = ctx->state; +	switch (state) { +	case EZUSB_CTX_REQ_SUBMITTED: +		/* We have received our response URB before +		 * our request has been acknowledged. Do NOT +		 * destroy our CTX yet, because our OUT URB +		 * is still alive ... +		 */ +		ctx->state = EZUSB_CTX_RESP_RECEIVED; +		spin_unlock_irqrestore(&upriv->req_lock, flags); + +		/* Let the machine continue running. */ +		break; + +	case EZUSB_CTX_REQ_COMPLETE: +		/* This is the usual path: our request +		 * has already been acknowledged, and +		 * we have now received the reply. +		 */ +		ctx->state = EZUSB_CTX_COMPLETE; + +		/* Stop the intimer */ +		del_timer(&ctx->timer); +		spin_unlock_irqrestore(&upriv->req_lock, flags); + +		/* Call the completion handler */ +		ezusb_ctx_complete(ctx); +		break; + +	default: +		spin_unlock_irqrestore(&upriv->req_lock, flags); + +		pr_warning("Matched IN URB, unexpected context state(0x%x)", +		     state); +		/* Throw this CTX away and try submitting another */ +		del_timer(&ctx->timer); +		ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK; +		usb_unlink_urb(ctx->outurb); +		ezusb_req_queue_run(upriv); +		break; +	}			/* switch */ +} + + +static void ezusb_req_ctx_wait(struct ezusb_priv *upriv, +			       struct request_context *ctx) +{ +	switch (ctx->state) { +	case EZUSB_CTX_QUEUED: +	case EZUSB_CTX_REQ_SUBMITTED: +	case EZUSB_CTX_REQ_COMPLETE: +	case EZUSB_CTX_RESP_RECEIVED: +		if (in_softirq()) { +			/* If we get called from a timer, timeout timers don't +			 * get the chance to run themselves. So we make sure +			 * that we don't sleep for ever */ +			int msecs = DEF_TIMEOUT * (1000 / HZ); +			while (!ctx->done.done && msecs--) +				udelay(1000); +		} else { +			wait_event_interruptible(ctx->done.wait, +						 ctx->done.done); +		} +		break; +	default: +		/* Done or failed - nothing to wait for */ +		break; +	} +} + +static inline u16 build_crc(struct ezusb_packet *data) +{ +	u16 crc = 0; +	u8 *bytes = (u8 *)data; +	int i; + +	for (i = 0; i < 8; i++) +		crc = (crc << 1) + bytes[i]; + +	return crc; +} + +/** + * ezusb_fill_req: + * + * if data == NULL and length > 0 the data is assumed to be already in + * the target buffer and only the header is filled. + * + */ +static int ezusb_fill_req(struct ezusb_packet *req, u16 length, u16 rid, +			  const void *data, u16 frame_type, u8 reply_count) +{ +	int total_size = sizeof(*req) + length; + +	BUG_ON(total_size > BULK_BUF_SIZE); + +	req->magic = cpu_to_le16(EZUSB_MAGIC); +	req->req_reply_count = reply_count; +	req->ans_reply_count = 0; +	req->frame_type = cpu_to_le16(frame_type); +	req->size = cpu_to_le16(length + 4); +	req->crc = cpu_to_le16(build_crc(req)); +	req->hermes_len = cpu_to_le16(HERMES_BYTES_TO_RECLEN(length)); +	req->hermes_rid = cpu_to_le16(rid); +	if (data) +		memcpy(req->data, data, length); +	return total_size; +} + +static int ezusb_submit_in_urb(struct ezusb_priv *upriv) +{ +	int retval = 0; +	void *cur_buf = upriv->read_urb->transfer_buffer; + +	if (upriv->read_urb->status == -EINPROGRESS) { +		dbg("urb busy, not resubmiting"); +		retval = -EBUSY; +		goto exit; +	} +	usb_fill_bulk_urb(upriv->read_urb, upriv->udev, upriv->read_pipe, +			  cur_buf, BULK_BUF_SIZE, +			  ezusb_bulk_in_callback, upriv); +	upriv->read_urb->transfer_flags = 0; +	retval = usb_submit_urb(upriv->read_urb, GFP_ATOMIC); +	if (retval) +		err("%s submit failed %d", __func__, retval); + + exit: +	return retval; +} + +static inline int ezusb_8051_cpucs(struct ezusb_priv *upriv, int reset) +{ +	u8 res_val = reset;	/* avoid argument promotion */ + +	if (!upriv->udev) { +		err("%s: !upriv->udev", __func__); +		return -EFAULT; +	} +	return usb_control_msg(upriv->udev, +			       usb_sndctrlpipe(upriv->udev, 0), +			       EZUSB_REQUEST_FW_TRANS, +			       USB_TYPE_VENDOR | USB_RECIP_DEVICE | +			       USB_DIR_OUT, EZUSB_CPUCS_REG, 0, &res_val, +			       sizeof(res_val), DEF_TIMEOUT); +} + +static int ezusb_firmware_download(struct ezusb_priv *upriv, +				   struct ez_usb_fw *fw) +{ +	u8 fw_buffer[FW_BUF_SIZE]; +	int retval, addr; +	int variant_offset; + +	/* +	 * This byte is 1 and should be replaced with 0.  The offset is +	 * 0x10AD in version 0.0.6.  The byte in question should follow +	 * the end of the code pointed to by the jump in the beginning +	 * of the firmware.  Also, it is read by code located at 0x358. +	 */ +	variant_offset = be16_to_cpup((__be16 *) &fw->code[FW_VAR_OFFSET_PTR]); +	if (variant_offset >= fw->size) { +		printk(KERN_ERR PFX "Invalid firmware variant offset: " +		       "0x%04x\n", variant_offset); +		retval = -EINVAL; +		goto fail; +	} + +	retval = ezusb_8051_cpucs(upriv, 1); +	if (retval < 0) +		goto fail; +	for (addr = 0; addr < fw->size; addr += FW_BUF_SIZE) { +		/* 0x100-0x300 should be left alone, it contains card +		 * specific data, like USB enumeration information */ +		if ((addr >= FW_HOLE_START) && (addr < FW_HOLE_END)) +			continue; + +		memcpy(fw_buffer, &fw->code[addr], FW_BUF_SIZE); +		if (variant_offset >= addr && +		    variant_offset < addr + FW_BUF_SIZE) { +			dbg("Patching card_variant byte at 0x%04X", +			    variant_offset); +			fw_buffer[variant_offset - addr] = FW_VAR_VALUE; +		} +		retval = usb_control_msg(upriv->udev, +					 usb_sndctrlpipe(upriv->udev, 0), +					 EZUSB_REQUEST_FW_TRANS, +					 USB_TYPE_VENDOR | USB_RECIP_DEVICE +					 | USB_DIR_OUT, +					 addr, 0x0, +					 fw_buffer, FW_BUF_SIZE, +					 DEF_TIMEOUT); + +		if (retval < 0) +			goto fail; +	} +	retval = ezusb_8051_cpucs(upriv, 0); +	if (retval < 0) +		goto fail; + +	goto exit; + fail: +	printk(KERN_ERR PFX "Firmware download failed, error %d\n", +	       retval); + exit: +	return retval; +} + +static int ezusb_access_ltv(struct ezusb_priv *upriv, +			    struct request_context *ctx, +			    u16 length, const void *data, u16 frame_type, +			    void *ans_buff, int ans_size, u16 *ans_length) +{ +	int req_size; +	int retval = 0; +	enum ezusb_state state; + +	BUG_ON(in_irq()); + +	if (!upriv->udev) { +		dbg("Device disconnected"); +		return -ENODEV; +	} + +	if (upriv->read_urb->status != -EINPROGRESS) +		err("%s: in urb not pending", __func__); + +	/* protect upriv->reply_count, guarantee sequential numbers */ +	spin_lock_bh(&upriv->reply_count_lock); +	req_size = ezusb_fill_req(ctx->buf, length, ctx->out_rid, data, +				  frame_type, upriv->reply_count); +	usb_fill_bulk_urb(ctx->outurb, upriv->udev, upriv->write_pipe, +			  ctx->buf, req_size, +			  ezusb_request_out_callback, ctx); + +	if (ctx->in_rid) +		upriv->reply_count = ezusb_reply_inc(upriv->reply_count); + +	ezusb_req_enqueue_run(upriv, ctx); + +	spin_unlock_bh(&upriv->reply_count_lock); + +	if (ctx->in_rid) +		ezusb_req_ctx_wait(upriv, ctx); + +	state = ctx->state; +	switch (state) { +	case EZUSB_CTX_COMPLETE: +		retval = ctx->outurb->status; +		break; + +	case EZUSB_CTX_QUEUED: +	case EZUSB_CTX_REQ_SUBMITTED: +		if (!ctx->in_rid) +			break; +	default: +		err("%s: Unexpected context state %d", __func__, +		    state); +		/* fall though */ +	case EZUSB_CTX_REQ_TIMEOUT: +	case EZUSB_CTX_REQ_FAILED: +	case EZUSB_CTX_RESP_TIMEOUT: +	case EZUSB_CTX_REQSUBMIT_FAIL: +		printk(KERN_ERR PFX "Access failed, resetting (state %d," +		       " reply_count %d)\n", state, upriv->reply_count); +		upriv->reply_count = 0; +		if (state == EZUSB_CTX_REQ_TIMEOUT +		    || state == EZUSB_CTX_RESP_TIMEOUT) { +			printk(KERN_ERR PFX "ctx timed out\n"); +			retval = -ETIMEDOUT; +		} else { +			printk(KERN_ERR PFX "ctx failed\n"); +			retval = -EFAULT; +		} +		goto exit; +		break; +	} +	if (ctx->in_rid) { +		struct ezusb_packet *ans = ctx->buf; +		int exp_len; + +		if (ans->hermes_len != 0) +			exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12; +		else +			exp_len = 14; + +		if (exp_len != ctx->buf_length) { +			err("%s: length mismatch for RID 0x%04x: " +			    "expected %d, got %d", __func__, +			    ctx->in_rid, exp_len, ctx->buf_length); +			retval = -EIO; +			goto exit; +		} + +		if (ans_buff) +			memcpy(ans_buff, ans->data, +			       min_t(int, exp_len, ans_size)); +		if (ans_length) +			*ans_length = le16_to_cpu(ans->hermes_len); +	} + exit: +	ezusb_request_context_put(ctx); +	return retval; +} + +static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid, +			   u16 length, const void *data) +{ +	struct ezusb_priv *upriv = hw->priv; +	u16 frame_type; +	struct request_context *ctx; + +	if (length == 0) +		return -EINVAL; + +	length = HERMES_RECLEN_TO_BYTES(length); + +	/* On memory mapped devices HERMES_RID_CNFGROUPADDRESSES can be +	 * set to be empty, but the USB bridge doesn't like it */ +	if (length == 0) +		return 0; + +	ctx = ezusb_alloc_ctx(upriv, rid, EZUSB_RID_ACK); +	if (!ctx) +		return -ENOMEM; + +	if (rid == EZUSB_RID_TX) +		frame_type = EZUSB_FRAME_DATA; +	else +		frame_type = EZUSB_FRAME_CONTROL; + +	return ezusb_access_ltv(upriv, ctx, length, data, frame_type, +				NULL, 0, NULL); +} + +static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid, +			  unsigned bufsize, u16 *length, void *buf) +{ +	struct ezusb_priv *upriv = hw->priv; +	struct request_context *ctx; + +	if ((bufsize < 0) || (bufsize % 2)) +		return -EINVAL; + +	ctx = ezusb_alloc_ctx(upriv, rid, rid); +	if (!ctx) +		return -ENOMEM; + +	return ezusb_access_ltv(upriv, ctx, 0, NULL, EZUSB_FRAME_CONTROL, +				buf, bufsize, length); +} + +static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1, +			     u16 parm2, struct hermes_response *resp) +{ +	struct ezusb_priv *upriv = hw->priv; +	struct request_context *ctx; + +	__le16 data[4] = { +		cpu_to_le16(cmd), +		cpu_to_le16(parm0), +		cpu_to_le16(parm1), +		cpu_to_le16(parm2), +	}; +	dbg("0x%04X, parm0 0x%04X, parm1 0x%04X, parm2 0x%04X", +	    cmd, parm0, parm1, parm2); +	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK); +	if (!ctx) +		return -ENOMEM; + +	return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, +				EZUSB_FRAME_CONTROL, NULL, 0, NULL); +} + +static int ezusb_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, +			    struct hermes_response *resp) +{ +	struct ezusb_priv *upriv = hw->priv; +	struct request_context *ctx; + +	__le16 data[4] = { +		cpu_to_le16(cmd), +		cpu_to_le16(parm0), +		0, +		0, +	}; +	dbg("0x%04X, parm0 0x%04X", cmd, parm0); +	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK); +	if (!ctx) +		return -ENOMEM; + +	return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, +				EZUSB_FRAME_CONTROL, NULL, 0, NULL); +} + +static int ezusb_bap_pread(struct hermes *hw, int bap, +			   void *buf, int len, u16 id, u16 offset) +{ +	struct ezusb_priv *upriv = hw->priv; +	struct ezusb_packet *ans = (void *) upriv->read_urb->transfer_buffer; +	int actual_length = upriv->read_urb->actual_length; + +	if (id == EZUSB_RID_RX) { +		if ((sizeof(*ans) + offset + len) > actual_length) { +			printk(KERN_ERR PFX "BAP read beyond buffer end " +			       "in rx frame\n"); +			return -EINVAL; +		} +		memcpy(buf, ans->data + offset, len); +		return 0; +	} + +	if (EZUSB_IS_INFO(id)) { +		/* Include 4 bytes for length/type */ +		if ((sizeof(*ans) + offset + len - 4) > actual_length) { +			printk(KERN_ERR PFX "BAP read beyond buffer end " +			       "in info frame\n"); +			return -EFAULT; +		} +		memcpy(buf, ans->data + offset - 4, len); +	} else { +		printk(KERN_ERR PFX "Unexpected fid 0x%04x\n", id); +		return -EINVAL; +	} + +	return 0; +} + +static int ezusb_read_pda(struct hermes *hw, __le16 *pda, +			  u32 pda_addr, u16 pda_len) +{ +	struct ezusb_priv *upriv = hw->priv; +	struct request_context *ctx; +	__le16 data[] = { +		cpu_to_le16(pda_addr & 0xffff), +		cpu_to_le16(pda_len - 4) +	}; +	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_READ_PDA, EZUSB_RID_READ_PDA); +	if (!ctx) +		return -ENOMEM; + +	/* wl_lkm does not include PDA size in the PDA area. +	 * We will pad the information into pda, so other routines +	 * don't have to be modified */ +	pda[0] = cpu_to_le16(pda_len - 2); +	/* Includes CFG_PROD_DATA but not itself */ +	pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */ + +	return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, +				EZUSB_FRAME_CONTROL, &pda[2], pda_len - 4, +				NULL); +} + +static int ezusb_program_init(struct hermes *hw, u32 entry_point) +{ +	struct ezusb_priv *upriv = hw->priv; +	struct request_context *ctx; +	__le32 data = cpu_to_le32(entry_point); + +	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_INIT, EZUSB_RID_ACK); +	if (!ctx) +		return -ENOMEM; + +	return ezusb_access_ltv(upriv, ctx, sizeof(data), &data, +				EZUSB_FRAME_CONTROL, NULL, 0, NULL); +} + +static int ezusb_program_end(struct hermes *hw) +{ +	struct ezusb_priv *upriv = hw->priv; +	struct request_context *ctx; + +	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_END, EZUSB_RID_ACK); +	if (!ctx) +		return -ENOMEM; + +	return ezusb_access_ltv(upriv, ctx, 0, NULL, +				EZUSB_FRAME_CONTROL, NULL, 0, NULL); +} + +static int ezusb_program_bytes(struct hermes *hw, const char *buf, +			       u32 addr, u32 len) +{ +	struct ezusb_priv *upriv = hw->priv; +	struct request_context *ctx; +	__le32 data = cpu_to_le32(addr); +	int err; + +	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_SET_ADDR, EZUSB_RID_ACK); +	if (!ctx) +		return -ENOMEM; + +	err = ezusb_access_ltv(upriv, ctx, sizeof(data), &data, +			       EZUSB_FRAME_CONTROL, NULL, 0, NULL); +	if (err) +		return err; + +	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_BYTES, EZUSB_RID_ACK); +	if (!ctx) +		return -ENOMEM; + +	return ezusb_access_ltv(upriv, ctx, len, buf, +				EZUSB_FRAME_CONTROL, NULL, 0, NULL); +} + +static int ezusb_program(struct hermes *hw, const char *buf, +			 u32 addr, u32 len) +{ +	u32 ch_addr; +	u32 ch_len; +	int err = 0; + +	/* We can only send 2048 bytes out of the bulk xmit at a time, +	 * so we have to split any programming into chunks of <2048 +	 * bytes. */ + +	ch_len = (len < MAX_DL_SIZE) ? len : MAX_DL_SIZE; +	ch_addr = addr; + +	while (ch_addr < (addr + len)) { +		pr_debug("Programming subblock of length %d " +			 "to address 0x%08x. Data @ %p\n", +			 ch_len, ch_addr, &buf[ch_addr - addr]); + +		err = ezusb_program_bytes(hw, &buf[ch_addr - addr], +					  ch_addr, ch_len); +		if (err) +			break; + +		ch_addr += ch_len; +		ch_len = ((addr + len - ch_addr) < MAX_DL_SIZE) ? +			(addr + len - ch_addr) : MAX_DL_SIZE; +	} + +	return err; +} + +static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) +{ +	struct orinoco_private *priv = ndev_priv(dev); +	struct net_device_stats *stats = &priv->stats; +	struct ezusb_priv *upriv = priv->card; +	int err = 0; +	char *p; +	struct ethhdr *eh; +	int len, data_len, data_off; +	__le16 tx_control; +	unsigned long flags; +	struct request_context *ctx; +	u8 *buf; +	int tx_size; + +	if (!netif_running(dev)) { +		printk(KERN_ERR "%s: Tx on stopped device!\n", +		       dev->name); +		return NETDEV_TX_BUSY; +	} + +	if (netif_queue_stopped(dev)) { +		printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", +		       dev->name); +		return NETDEV_TX_BUSY; +	} + +	if (orinoco_lock(priv, &flags) != 0) { +		printk(KERN_ERR +		       "%s: orinoco_xmit() called while hw_unavailable\n", +		       dev->name); +		return NETDEV_TX_BUSY; +	} + +	if (!netif_carrier_ok(dev) || +	    (priv->iw_mode == NL80211_IFTYPE_MONITOR)) { +		/* Oops, the firmware hasn't established a connection, +		   silently drop the packet (this seems to be the +		   safest approach). */ +		stats->tx_errors++; +		orinoco_unlock(priv, &flags); +		dev_kfree_skb(skb); +		return NETDEV_TX_OK; +	} + +	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0); +	if (!ctx) +		goto fail; + +	memset(ctx->buf, 0, BULK_BUF_SIZE); +	buf = ctx->buf->data; + +	/* Length of the packet body */ +	/* FIXME: what if the skb is smaller than this? */ +	len = max_t(int, skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN); + +	eh = (struct ethhdr *) skb->data; + +	tx_control = cpu_to_le16(0); +	memcpy(buf, &tx_control, sizeof(tx_control)); +	buf += sizeof(tx_control); +	/* Encapsulate Ethernet-II frames */ +	if (ntohs(eh->h_proto) > ETH_DATA_LEN) {	/* Ethernet-II frame */ +		struct header_struct *hdr = (void *) buf; +		buf += sizeof(*hdr); +		data_len = len; +		data_off = sizeof(tx_control) + sizeof(*hdr); +		p = skb->data + ETH_HLEN; + +		/* 802.3 header */ +		memcpy(hdr->dest, eh->h_dest, ETH_ALEN); +		memcpy(hdr->src, eh->h_source, ETH_ALEN); +		hdr->len = htons(data_len + ENCAPS_OVERHEAD); + +		/* 802.2 header */ +		memcpy(&hdr->dsap, &encaps_hdr, sizeof(encaps_hdr)); + +		hdr->ethertype = eh->h_proto; +	} else {		/* IEEE 802.3 frame */ +		data_len = len + ETH_HLEN; +		data_off = sizeof(tx_control); +		p = skb->data; +	} + +	memcpy(buf, p, data_len); +	buf += data_len; + +	/* Finally, we actually initiate the send */ +	netif_stop_queue(dev); + +	/* The card may behave better if we send evenly sized usb transfers */ +	tx_size = ALIGN(buf - ctx->buf->data, 2); + +	err = ezusb_access_ltv(upriv, ctx, tx_size, NULL, +			       EZUSB_FRAME_DATA, NULL, 0, NULL); + +	if (err) { +		netif_start_queue(dev); +		if (net_ratelimit()) +			printk(KERN_ERR "%s: Error %d transmitting packet\n", +				dev->name, err); +		stats->tx_errors++; +		goto fail; +	} + +	dev->trans_start = jiffies; +	stats->tx_bytes += data_off + data_len; + +	orinoco_unlock(priv, &flags); + +	dev_kfree_skb(skb); + +	return NETDEV_TX_OK; + + fail: +	orinoco_unlock(priv, &flags); +	return NETDEV_TX_BUSY; +} + +static int ezusb_allocate(struct hermes *hw, u16 size, u16 *fid) +{ +	*fid = EZUSB_RID_TX; +	return 0; +} + + +static int ezusb_hard_reset(struct orinoco_private *priv) +{ +	struct ezusb_priv *upriv = priv->card; +	int retval = ezusb_8051_cpucs(upriv, 1); + +	if (retval < 0) { +		err("Failed to reset"); +		return retval; +	} + +	retval = ezusb_8051_cpucs(upriv, 0); +	if (retval < 0) { +		err("Failed to unreset"); +		return retval; +	} + +	dbg("sending control message"); +	retval = usb_control_msg(upriv->udev, +				 usb_sndctrlpipe(upriv->udev, 0), +				 EZUSB_REQUEST_TRIGER, +				 USB_TYPE_VENDOR | USB_RECIP_DEVICE | +				 USB_DIR_OUT, 0x0, 0x0, NULL, 0, +				 DEF_TIMEOUT); +	if (retval < 0) { +		err("EZUSB_REQUEST_TRIGER failed retval %d", retval); +		return retval; +	} +#if 0 +	dbg("Sending EZUSB_REQUEST_TRIG_AC"); +	retval = usb_control_msg(upriv->udev, +				 usb_sndctrlpipe(upriv->udev, 0), +				 EZUSB_REQUEST_TRIG_AC, +				 USB_TYPE_VENDOR | USB_RECIP_DEVICE | +				 USB_DIR_OUT, 0x00FA, 0x0, NULL, 0, +				 DEF_TIMEOUT); +	if (retval < 0) { +		err("EZUSB_REQUEST_TRIG_AC failed retval %d", retval); +		return retval; +	} +#endif + +	return 0; +} + + +static int ezusb_init(hermes_t *hw) +{ +	struct ezusb_priv *upriv = hw->priv; +	int retval; + +	BUG_ON(in_interrupt()); +	BUG_ON(!upriv); + +	upriv->reply_count = 0; +	/* Write the MAGIC number on the simulated registers to keep +	 * orinoco.c happy */ +	hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC); +	hermes_write_regn(hw, RXFID, EZUSB_RID_RX); + +	usb_kill_urb(upriv->read_urb); +	ezusb_submit_in_urb(upriv); + +	retval = ezusb_write_ltv(hw, 0, EZUSB_RID_INIT1, +				 HERMES_BYTES_TO_RECLEN(2), "\x10\x00"); +	if (retval < 0) { +		printk(KERN_ERR PFX "EZUSB_RID_INIT1 error %d\n", retval); +		return retval; +	} + +	retval = ezusb_docmd_wait(hw, HERMES_CMD_INIT, 0, NULL); +	if (retval < 0) { +		printk(KERN_ERR PFX "HERMES_CMD_INIT error %d\n", retval); +		return retval; +	} + +	return 0; +} + +static void ezusb_bulk_in_callback(struct urb *urb) +{ +	struct ezusb_priv *upriv = (struct ezusb_priv *) urb->context; +	struct ezusb_packet *ans = urb->transfer_buffer; +	u16 crc; +	u16 hermes_rid; + +	if (upriv->udev == NULL) { +		dbg("disconnected"); +		return; +	} + +	if (urb->status == -ETIMEDOUT) { +		/* When a device gets unplugged we get this every time +		 * we resubmit, flooding the logs.  Since we don't use +		 * USB timeouts, it shouldn't happen any other time*/ +		pr_warning("%s: urb timed out, not resubmiting", __func__); +		return; +	} +	if (urb->status == -ECONNABORTED) { +		pr_warning("%s: connection abort, resubmiting urb", +		     __func__); +		goto resubmit; +	} +	if ((urb->status == -EILSEQ) +	    || (urb->status == -ENOENT) +	    || (urb->status == -ECONNRESET)) { +		dbg("status %d, not resubmiting", urb->status); +		return; +	} +	if (urb->status) +		dbg("status: %d length: %d", +		    urb->status, urb->actual_length); +	if (urb->actual_length < sizeof(*ans)) { +		err("%s: short read, ignoring", __func__); +		goto resubmit; +	} +	crc = build_crc(ans); +	if (le16_to_cpu(ans->crc) != crc) { +		err("CRC error, ignoring packet"); +		goto resubmit; +	} + +	hermes_rid = le16_to_cpu(ans->hermes_rid); +	if ((hermes_rid != EZUSB_RID_RX) && !EZUSB_IS_INFO(hermes_rid)) { +		ezusb_request_in_callback(upriv, urb); +	} else if (upriv->dev) { +		struct net_device *dev = upriv->dev; +		struct orinoco_private *priv = ndev_priv(dev); +		hermes_t *hw = &priv->hw; + +		if (hermes_rid == EZUSB_RID_RX) { +			__orinoco_ev_rx(dev, hw); +		} else { +			hermes_write_regn(hw, INFOFID, +					  le16_to_cpu(ans->hermes_rid)); +			__orinoco_ev_info(dev, hw); +		} +	} + + resubmit: +	if (upriv->udev) +		ezusb_submit_in_urb(upriv); +} + +static inline void ezusb_delete(struct ezusb_priv *upriv) +{ +	struct net_device *dev; +	struct list_head *item; +	struct list_head *tmp_item; +	unsigned long flags; + +	BUG_ON(in_interrupt()); +	BUG_ON(!upriv); + +	dev = upriv->dev; +	mutex_lock(&upriv->mtx); + +	upriv->udev = NULL;	/* No timer will be rearmed from here */ + +	usb_kill_urb(upriv->read_urb); + +	spin_lock_irqsave(&upriv->req_lock, flags); +	list_for_each_safe(item, tmp_item, &upriv->req_active) { +		struct request_context *ctx; +		int err; + +		ctx = list_entry(item, struct request_context, list); +		atomic_inc(&ctx->refcount); + +		ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK; +		err = usb_unlink_urb(ctx->outurb); + +		spin_unlock_irqrestore(&upriv->req_lock, flags); +		if (err == -EINPROGRESS) +			wait_for_completion(&ctx->done); + +		del_timer_sync(&ctx->timer); +		/* FIXME: there is an slight chance for the irq handler to +		 * be running */ +		if (!list_empty(&ctx->list)) +			ezusb_ctx_complete(ctx); + +		ezusb_request_context_put(ctx); +		spin_lock_irqsave(&upriv->req_lock, flags); +	} +	spin_unlock_irqrestore(&upriv->req_lock, flags); + +	list_for_each_safe(item, tmp_item, &upriv->req_pending) +	    ezusb_ctx_complete(list_entry(item, +					  struct request_context, list)); + +	if (upriv->read_urb->status == -EINPROGRESS) +		printk(KERN_ERR PFX "Some URB in progress\n"); + +	mutex_unlock(&upriv->mtx); + +	kfree(upriv->read_urb->transfer_buffer); +	if (upriv->bap_buf != NULL) +		kfree(upriv->bap_buf); +	if (upriv->read_urb != NULL) +		usb_free_urb(upriv->read_urb); +	if (upriv->dev) { +		struct orinoco_private *priv = ndev_priv(upriv->dev); +		orinoco_if_del(priv); +		free_orinocodev(priv); +	} +} + +static void ezusb_lock_irqsave(spinlock_t *lock, +			       unsigned long *flags) __acquires(lock) +{ +	spin_lock_bh(lock); +} + +static void ezusb_unlock_irqrestore(spinlock_t *lock, +				    unsigned long *flags) __releases(lock) +{ +	spin_unlock_bh(lock); +} + +static void ezusb_lock_irq(spinlock_t *lock) __acquires(lock) +{ +	spin_lock_bh(lock); +} + +static void ezusb_unlock_irq(spinlock_t *lock) __releases(lock) +{ +	spin_unlock_bh(lock); +} + +static const struct hermes_ops ezusb_ops = { +	.init = ezusb_init, +	.cmd_wait = ezusb_docmd_wait, +	.init_cmd_wait = ezusb_doicmd_wait, +	.allocate = ezusb_allocate, +	.read_ltv = ezusb_read_ltv, +	.write_ltv = ezusb_write_ltv, +	.bap_pread = ezusb_bap_pread, +	.read_pda = ezusb_read_pda, +	.program_init = ezusb_program_init, +	.program_end = ezusb_program_end, +	.program = ezusb_program, +	.lock_irqsave = ezusb_lock_irqsave, +	.unlock_irqrestore = ezusb_unlock_irqrestore, +	.lock_irq = ezusb_lock_irq, +	.unlock_irq = ezusb_unlock_irq, +}; + +static const struct net_device_ops ezusb_netdev_ops = { +	.ndo_open		= orinoco_open, +	.ndo_stop		= orinoco_stop, +	.ndo_start_xmit		= ezusb_xmit, +	.ndo_set_multicast_list	= orinoco_set_multicast_list, +	.ndo_change_mtu		= orinoco_change_mtu, +	.ndo_set_mac_address	= eth_mac_addr, +	.ndo_validate_addr	= eth_validate_addr, +	.ndo_tx_timeout		= orinoco_tx_timeout, +	.ndo_get_stats		= orinoco_get_stats, +}; + +static int ezusb_probe(struct usb_interface *interface, +		       const struct usb_device_id *id) +{ +	struct usb_device *udev = interface_to_usbdev(interface); +	struct orinoco_private *priv; +	hermes_t *hw; +	struct ezusb_priv *upriv = NULL; +	struct usb_interface_descriptor *iface_desc; +	struct usb_endpoint_descriptor *ep; +	const struct firmware *fw_entry; +	int retval = 0; +	int i; + +	priv = alloc_orinocodev(sizeof(*upriv), &udev->dev, +				ezusb_hard_reset, NULL); +	if (!priv) { +		err("Couldn't allocate orinocodev"); +		goto exit; +	} + +	hw = &priv->hw; + +	upriv = priv->card; + +	mutex_init(&upriv->mtx); +	spin_lock_init(&upriv->reply_count_lock); + +	spin_lock_init(&upriv->req_lock); +	INIT_LIST_HEAD(&upriv->req_pending); +	INIT_LIST_HEAD(&upriv->req_active); + +	upriv->udev = udev; + +	hw->iobase = (void __force __iomem *) &upriv->hermes_reg_fake; +	hw->reg_spacing = HERMES_16BIT_REGSPACING; +	hw->priv = upriv; +	hw->ops = &ezusb_ops; + +	/* set up the endpoint information */ +	/* check out the endpoints */ + +	iface_desc = &interface->altsetting[0].desc; +	for (i = 0; i < iface_desc->bNumEndpoints; ++i) { +		ep = &interface->altsetting[0].endpoint[i].desc; + +		if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) +		     == USB_DIR_IN) && +		    ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) +		     == USB_ENDPOINT_XFER_BULK)) { +			/* we found a bulk in endpoint */ +			if (upriv->read_urb != NULL) { +				pr_warning("Found a second bulk in ep, ignored"); +				continue; +			} + +			upriv->read_urb = usb_alloc_urb(0, GFP_KERNEL); +			if (!upriv->read_urb) { +				err("No free urbs available"); +				goto error; +			} +			if (le16_to_cpu(ep->wMaxPacketSize) != 64) +				pr_warning("bulk in: wMaxPacketSize!= 64"); +			if (ep->bEndpointAddress != (2 | USB_DIR_IN)) +				pr_warning("bulk in: bEndpointAddress: %d", +				     ep->bEndpointAddress); +			upriv->read_pipe = usb_rcvbulkpipe(udev, +							 ep-> +							 bEndpointAddress); +			upriv->read_urb->transfer_buffer = +			    kmalloc(BULK_BUF_SIZE, GFP_KERNEL); +			if (!upriv->read_urb->transfer_buffer) { +				err("Couldn't allocate IN buffer"); +				goto error; +			} +		} + +		if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) +		     == USB_DIR_OUT) && +		    ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) +		     == USB_ENDPOINT_XFER_BULK)) { +			/* we found a bulk out endpoint */ +			if (upriv->bap_buf != NULL) { +				pr_warning("Found a second bulk out ep, ignored"); +				continue; +			} + +			if (le16_to_cpu(ep->wMaxPacketSize) != 64) +				pr_warning("bulk out: wMaxPacketSize != 64"); +			if (ep->bEndpointAddress != 2) +				pr_warning("bulk out: bEndpointAddress: %d", +				     ep->bEndpointAddress); +			upriv->write_pipe = usb_sndbulkpipe(udev, +							  ep-> +							  bEndpointAddress); +			upriv->bap_buf = kmalloc(BULK_BUF_SIZE, GFP_KERNEL); +			if (!upriv->bap_buf) { +				err("Couldn't allocate bulk_out_buffer"); +				goto error; +			} +		} +	} +	if (!upriv->bap_buf || !upriv->read_urb) { +		err("Didn't find the required bulk endpoints"); +		goto error; +	} + +	if (request_firmware(&fw_entry, "orinoco_ezusb_fw", +			     &interface->dev) == 0) { +		firmware.size = fw_entry->size; +		firmware.code = fw_entry->data; +	} +	if (firmware.size && firmware.code) { +		ezusb_firmware_download(upriv, &firmware); +	} else { +		err("No firmware to download"); +		goto error; +	} + +	if (ezusb_hard_reset(priv) < 0) { +		err("Cannot reset the device"); +		goto error; +	} + +	/* If the firmware is already downloaded orinoco.c will call +	 * ezusb_init but if the firmware is not already there, that will make +	 * the kernel very unstable, so we try initializing here and quit in +	 * case of error */ +	if (ezusb_init(hw) < 0) { +		err("Couldn't initialize the device"); +		err("Firmware may not be downloaded or may be wrong."); +		goto error; +	} + +	/* Initialise the main driver */ +	if (orinoco_init(priv) != 0) { +		err("orinoco_init() failed\n"); +		goto error; +	} + +	if (orinoco_if_add(priv, 0, 0, &ezusb_netdev_ops) != 0) { +		upriv->dev = NULL; +		err("%s: orinoco_if_add() failed", __func__); +		goto error; +	} +	upriv->dev = priv->ndev; + +	goto exit; + + error: +	ezusb_delete(upriv); +	if (upriv->dev) { +		/* upriv->dev was 0, so ezusb_delete() didn't free it */ +		free_orinocodev(priv); +	} +	upriv = NULL; +	retval = -EFAULT; + exit: +	if (fw_entry) { +		firmware.code = NULL; +		firmware.size = 0; +		release_firmware(fw_entry); +	} +	usb_set_intfdata(interface, upriv); +	return retval; +} + + +static void ezusb_disconnect(struct usb_interface *intf) +{ +	struct ezusb_priv *upriv = usb_get_intfdata(intf); +	usb_set_intfdata(intf, NULL); +	ezusb_delete(upriv); +	printk(KERN_INFO PFX "Disconnected\n"); +} + + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver orinoco_driver = { +	.name = DRIVER_NAME, +	.probe = ezusb_probe, +	.disconnect = ezusb_disconnect, +	.id_table = ezusb_table, +}; + +/* Can't be declared "const" or the whole __initdata section will + * become const */ +static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION +    " (Manuel Estrada Sainz)"; + +static int __init ezusb_module_init(void) +{ +	int err; + +	printk(KERN_DEBUG "%s\n", version); + +	/* register this driver with the USB subsystem */ +	err = usb_register(&orinoco_driver); +	if (err < 0) { +		printk(KERN_ERR PFX "usb_register failed, error %d\n", +		       err); +		return err; +	} + +	return 0; +} + +static void __exit ezusb_module_exit(void) +{ +	/* deregister this driver with the USB subsystem */ +	usb_deregister(&orinoco_driver); +} + + +module_init(ezusb_module_init); +module_exit(ezusb_module_exit); + +MODULE_AUTHOR("Manuel Estrada Sainz"); +MODULE_DESCRIPTION +    ("Driver for Orinoco wireless LAN cards using EZUSB bridge"); +MODULE_LICENSE("Dual MPL/GPL"); diff --git a/drivers/net/wireless/orinoco/scan.c b/drivers/net/wireless/orinoco/scan.c index 330d42d4533..4300d9db7d8 100644 --- a/drivers/net/wireless/orinoco/scan.c +++ b/drivers/net/wireless/orinoco/scan.c @@ -127,7 +127,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,  {  	struct wiphy *wiphy = priv_to_wiphy(priv);  	struct ieee80211_channel *channel; -	u8 *ie; +	const u8 *ie;  	u64 timestamp;  	s32 signal;  	u16 capability; @@ -136,7 +136,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,  	int chan, freq;  	ie_len = len - sizeof(*bss); -	ie = orinoco_get_ie(bss->data, ie_len, WLAN_EID_DS_PARAMS); +	ie = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bss->data, ie_len);  	chan = ie ? ie[2] : 0;  	freq = ieee80211_dsss_chan_to_freq(chan);  	channel = ieee80211_get_channel(wiphy, freq); diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index 59bda240fdc..9b1af4976bf 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -349,6 +349,7 @@ spectrum_cs_config(struct pcmcia_device *link)  		goto failed;  	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); +	hw->eeprom_pda = true;  	/*  	 * This actually configures the PCMCIA socket -- setting up @@ -374,7 +375,7 @@ spectrum_cs_config(struct pcmcia_device *link)  	/* Register an interface with the stack */  	if (orinoco_if_add(priv, link->io.BasePort1, -			   link->irq.AssignedIRQ) != 0) { +			   link->irq.AssignedIRQ, NULL) != 0) {  		printk(KERN_ERR PFX "orinoco_if_add() failed\n");  		goto failed;  	} @@ -405,9 +406,9 @@ spectrum_cs_release(struct pcmcia_device *link)  	/* We're committed to taking the device away now, so mark the  	 * hardware as unavailable */ -	spin_lock_irqsave(&priv->lock, flags); +	priv->hw.ops->lock_irqsave(&priv->lock, &flags);  	priv->hw_unavailable++; -	spin_unlock_irqrestore(&priv->lock, flags); +	priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);  	pcmcia_disable_device(link);  	if (priv->hw.iobase) diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 57b850ebfeb..5775124e2ae 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c @@ -458,7 +458,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,  	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {  		/* Fast channel change - no commit if successful */  		hermes_t *hw = &priv->hw; -		err = hermes_docmd_wait(hw, HERMES_CMD_TEST | +		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |  					    HERMES_TEST_SET_CHANNEL,  					chan, NULL);  	} @@ -538,125 +538,6 @@ static int orinoco_ioctl_setsens(struct net_device *dev,  	return -EINPROGRESS;		/* Call commit handler */  } -static int orinoco_ioctl_setrts(struct net_device *dev, -				struct iw_request_info *info, -				struct iw_param *rrq, -				char *extra) -{ -	struct orinoco_private *priv = ndev_priv(dev); -	int val = rrq->value; -	unsigned long flags; - -	if (rrq->disabled) -		val = 2347; - -	if ((val < 0) || (val > 2347)) -		return -EINVAL; - -	if (orinoco_lock(priv, &flags) != 0) -		return -EBUSY; - -	priv->rts_thresh = val; -	orinoco_unlock(priv, &flags); - -	return -EINPROGRESS;		/* Call commit handler */ -} - -static int orinoco_ioctl_getrts(struct net_device *dev, -				struct iw_request_info *info, -				struct iw_param *rrq, -				char *extra) -{ -	struct orinoco_private *priv = ndev_priv(dev); - -	rrq->value = priv->rts_thresh; -	rrq->disabled = (rrq->value == 2347); -	rrq->fixed = 1; - -	return 0; -} - -static int orinoco_ioctl_setfrag(struct net_device *dev, -				 struct iw_request_info *info, -				 struct iw_param *frq, -				 char *extra) -{ -	struct orinoco_private *priv = ndev_priv(dev); -	int err = -EINPROGRESS;		/* Call commit handler */ -	unsigned long flags; - -	if (orinoco_lock(priv, &flags) != 0) -		return -EBUSY; - -	if (priv->has_mwo) { -		if (frq->disabled) -			priv->mwo_robust = 0; -		else { -			if (frq->fixed) -				printk(KERN_WARNING "%s: Fixed fragmentation " -				       "is not supported on this firmware. " -				       "Using MWO robust instead.\n", -				       dev->name); -			priv->mwo_robust = 1; -		} -	} else { -		if (frq->disabled) -			priv->frag_thresh = 2346; -		else { -			if ((frq->value < 256) || (frq->value > 2346)) -				err = -EINVAL; -			else -				/* must be even */ -				priv->frag_thresh = frq->value & ~0x1; -		} -	} - -	orinoco_unlock(priv, &flags); - -	return err; -} - -static int orinoco_ioctl_getfrag(struct net_device *dev, -				 struct iw_request_info *info, -				 struct iw_param *frq, -				 char *extra) -{ -	struct orinoco_private *priv = ndev_priv(dev); -	hermes_t *hw = &priv->hw; -	int err; -	u16 val; -	unsigned long flags; - -	if (orinoco_lock(priv, &flags) != 0) -		return -EBUSY; - -	if (priv->has_mwo) { -		err = hermes_read_wordrec(hw, USER_BAP, -					  HERMES_RID_CNFMWOROBUST_AGERE, -					  &val); -		if (err) -			val = 0; - -		frq->value = val ? 2347 : 0; -		frq->disabled = !val; -		frq->fixed = 0; -	} else { -		err = hermes_read_wordrec(hw, USER_BAP, -					  HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, -					  &val); -		if (err) -			val = 0; - -		frq->value = val; -		frq->disabled = (val >= 2346); -		frq->fixed = 1; -	} - -	orinoco_unlock(priv, &flags); - -	return err; -} -  static int orinoco_ioctl_setrate(struct net_device *dev,  				 struct iw_request_info *info,  				 struct iw_param *rrq, @@ -1201,60 +1082,6 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,  	return ret;  } -static int orinoco_ioctl_getretry(struct net_device *dev, -				  struct iw_request_info *info, -				  struct iw_param *rrq, -				  char *extra) -{ -	struct orinoco_private *priv = ndev_priv(dev); -	hermes_t *hw = &priv->hw; -	int err = 0; -	u16 short_limit, long_limit, lifetime; -	unsigned long flags; - -	if (orinoco_lock(priv, &flags) != 0) -		return -EBUSY; - -	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT, -				  &short_limit); -	if (err) -		goto out; - -	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT, -				  &long_limit); -	if (err) -		goto out; - -	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME, -				  &lifetime); -	if (err) -		goto out; - -	rrq->disabled = 0;		/* Can't be disabled */ - -	/* Note : by default, display the retry number */ -	if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { -		rrq->flags = IW_RETRY_LIFETIME; -		rrq->value = lifetime * 1000;	/* ??? */ -	} else { -		/* By default, display the min number */ -		if ((rrq->flags & IW_RETRY_LONG)) { -			rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; -			rrq->value = long_limit; -		} else { -			rrq->flags = IW_RETRY_LIMIT; -			rrq->value = short_limit; -			if (short_limit != long_limit) -				rrq->flags |= IW_RETRY_SHORT; -		} -	} - - out: -	orinoco_unlock(priv, &flags); - -	return err; -} -  static int orinoco_ioctl_reset(struct net_device *dev,  			       struct iw_request_info *info,  			       void *wrqu, @@ -1446,8 +1273,8 @@ static int orinoco_ioctl_getrid(struct net_device *dev,  	if (orinoco_lock(priv, &flags) != 0)  		return -EBUSY; -	err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, -			      extra); +	err = hw->ops->read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, +				extra);  	if (err)  		goto out; @@ -1528,11 +1355,11 @@ static const iw_handler	orinoco_handler[] = {  	IW_HANDLER(SIOCGIWESSID,	(iw_handler)orinoco_ioctl_getessid),  	IW_HANDLER(SIOCSIWRATE,		(iw_handler)orinoco_ioctl_setrate),  	IW_HANDLER(SIOCGIWRATE,		(iw_handler)orinoco_ioctl_getrate), -	IW_HANDLER(SIOCSIWRTS,		(iw_handler)orinoco_ioctl_setrts), -	IW_HANDLER(SIOCGIWRTS,		(iw_handler)orinoco_ioctl_getrts), -	IW_HANDLER(SIOCSIWFRAG,		(iw_handler)orinoco_ioctl_setfrag), -	IW_HANDLER(SIOCGIWFRAG,		(iw_handler)orinoco_ioctl_getfrag), -	IW_HANDLER(SIOCGIWRETRY,	(iw_handler)orinoco_ioctl_getretry), +	IW_HANDLER(SIOCSIWRTS,		(iw_handler)cfg80211_wext_siwrts), +	IW_HANDLER(SIOCGIWRTS,		(iw_handler)cfg80211_wext_giwrts), +	IW_HANDLER(SIOCSIWFRAG,		(iw_handler)cfg80211_wext_siwfrag), +	IW_HANDLER(SIOCGIWFRAG,		(iw_handler)cfg80211_wext_giwfrag), +	IW_HANDLER(SIOCGIWRETRY,	(iw_handler)cfg80211_wext_giwretry),  	IW_HANDLER(SIOCSIWENCODE,	(iw_handler)orinoco_ioctl_setiwencode),  	IW_HANDLER(SIOCGIWENCODE,	(iw_handler)orinoco_ioctl_getiwencode),  	IW_HANDLER(SIOCSIWPOWER,	(iw_handler)orinoco_ioctl_setpower), diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 7bbd9d3bba6..c072f41747c 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -546,8 +546,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)  		     IEEE80211_HW_SUPPORTS_PS |  		     IEEE80211_HW_PS_NULLFUNC_STACK |  		     IEEE80211_HW_BEACON_FILTER | -		     IEEE80211_HW_REPORTS_TX_ACK_STATUS | -		     IEEE80211_HW_NOISE_DBM; +		     IEEE80211_HW_REPORTS_TX_ACK_STATUS;  	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |  				      BIT(NL80211_IFTYPE_ADHOC) | diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 86f3e9ac4c7..07c4528f6e6 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -140,7 +140,7 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev,  	idx = le32_to_cpu(ring_control->host_idx[ring_index]);  	limit = idx; -	limit -= le32_to_cpu(index); +	limit -= index;  	limit = ring_limit - limit;  	i = idx % ring_limit; @@ -246,7 +246,7 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,  	u32 idx, i;  	i = (*index) % ring_limit; -	(*index) = idx = le32_to_cpu(ring_control->device_idx[1]); +	(*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);  	idx %= ring_limit;  	while (i != idx) { @@ -277,6 +277,14 @@ static void p54p_tasklet(unsigned long dev_id)  	struct p54p_priv *priv = dev->priv;  	struct p54p_ring_control *ring_control = priv->ring_control; +	p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt, +			   ARRAY_SIZE(ring_control->tx_mgmt), +			   priv->tx_buf_mgmt); + +	p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data, +			   ARRAY_SIZE(ring_control->tx_data), +			   priv->tx_buf_data); +  	p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,  		ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); @@ -285,14 +293,6 @@ static void p54p_tasklet(unsigned long dev_id)  	wmb();  	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); - -	p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt, -			   ARRAY_SIZE(ring_control->tx_mgmt), -			   priv->tx_buf_mgmt); - -	p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data, -			   ARRAY_SIZE(ring_control->tx_data), -			   priv->tx_buf_data);  }  static irqreturn_t p54p_interrupt(int irq, void *dev_id) diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 2ceff548035..4e6891099d4 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -350,7 +350,6 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)  		rx_status->flag |= RX_FLAG_MMIC_ERROR;  	rx_status->signal = p54_rssi_to_dbm(priv, hdr->rssi); -	rx_status->noise = priv->noise;  	if (hdr->rate & 0x10)  		rx_status->flag |= RX_FLAG_SHORTPRE;  	if (priv->hw->conf.channel->band == IEEE80211_BAND_5GHZ) diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 5239e082cd0..eea1ef2f502 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -87,7 +87,7 @@ if RT2800PCI  config RT2800PCI_RT30XX  	bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices" -	default n +	default y  	---help---  	  This adds support for rt30xx wireless chipset family to the  	  rt2800pci driver. @@ -156,7 +156,7 @@ if RT2800USB  config RT2800USB_RT30XX  	bool "rt2800usb - Include support for rt30xx (USB) devices" -	default n +	default y  	---help---  	  This adds support for rt30xx wireless chipset family to the  	  rt2800usb driver. diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index cdbf59108ef..06b92f8b7a5 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1018,8 +1018,8 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,  	rt2x00_desc_write(entry_priv->desc, 1, word);  	rt2x00_desc_read(txd, 2, &word); -	rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, skb->len); -	rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skb->len); +	rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length); +	rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, txdesc->length);  	rt2x00_desc_write(txd, 2, word);  	rt2x00_desc_read(txd, 3, &word); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 89e986f449d..ae8e205df26 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1209,7 +1209,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);  	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,  			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); -	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); +	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);  	rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);  	rt2x00_desc_write(txd, 0, word);  } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 7185cb05f25..41d9996c80e 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1072,7 +1072,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,  			   test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); -	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); +	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);  	rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);  	rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);  	rt2x00_desc_write(txd, 0, word); diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index ec893721cc8..2aa03751c34 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -107,7 +107,7 @@  /*   * INT_SOURCE_CSR: Interrupt source register.   * Write one to clear corresponding bit. - * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c + * TX_FIFO_STATUS: FIFO Statistics is full, sw should read TX_STA_FIFO   */  #define INT_SOURCE_CSR			0x0200  #define INT_SOURCE_CSR_RXDELAYINT	FIELD32(0x00000001) @@ -845,7 +845,7 @@   * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz   */  #define TX_BAND_CFG			0x132c -#define TX_BAND_CFG_HT40_PLUS		FIELD32(0x00000001) +#define TX_BAND_CFG_HT40_MINUS		FIELD32(0x00000001)  #define TX_BAND_CFG_A			FIELD32(0x00000002)  #define TX_BAND_CFG_BG			FIELD32(0x00000004) @@ -1519,7 +1519,7 @@ struct mac_iveiv_entry {   * BBP 3: RX Antenna   */  #define BBP3_RX_ANTENNA			FIELD8(0x18) -#define BBP3_HT40_PLUS			FIELD8(0x20) +#define BBP3_HT40_MINUS			FIELD8(0x20)  /*   * BBP 4: Bandwidth @@ -1566,6 +1566,11 @@ struct mac_iveiv_entry {  #define RFCSR12_TX_POWER		FIELD8(0x1f)  /* + * RFCSR 13: + */ +#define RFCSR13_TX_POWER		FIELD8(0x1f) + +/*   * RFCSR 15:   */  #define RFCSR15_TX_LO2_EN		FIELD8(0x08) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2648f315a93..e37bbeab923 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -41,9 +41,6 @@  #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)  #include "rt2x00usb.h"  #endif -#if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE) -#include "rt2x00pci.h" -#endif  #include "rt2800lib.h"  #include "rt2800.h"  #include "rt2800usb.h" @@ -76,6 +73,23 @@ MODULE_LICENSE("GPL");  	rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \  			    H2M_MAILBOX_CSR_OWNER, (__reg)) +static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev) +{ +	/* check for rt2872 on SoC */ +	if (!rt2x00_is_soc(rt2x00dev) || +	    !rt2x00_rt(rt2x00dev, RT2872)) +		return false; + +	/* we know for sure that these rf chipsets are used on rt305x boards */ +	if (rt2x00_rf(rt2x00dev, RF3020) || +	    rt2x00_rf(rt2x00dev, RF3021) || +	    rt2x00_rf(rt2x00dev, RF3022)) +		return true; + +	NOTICE(rt2x00dev, "Unknown RF chipset on rt305x\n"); +	return false; +} +  static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,  			     const unsigned int word, const u8 value)  { @@ -794,6 +808,11 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,  			  TXPOWER_G_TO_DEV(info->tx_power1));  	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); +	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, +			  TXPOWER_G_TO_DEV(info->tx_power2)); +	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); +  	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);  	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);  	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); @@ -849,7 +868,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	}  	rt2800_register_read(rt2x00dev, TX_BAND_CFG, ®); -	rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); +	rt2x00_set_field32(®, TX_BAND_CFG_HT40_MINUS, conf_is_ht40_minus(conf));  	rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14);  	rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14);  	rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg); @@ -882,7 +901,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	rt2800_bbp_write(rt2x00dev, 4, bbp);  	rt2800_bbp_read(rt2x00dev, 3, &bbp); -	rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); +	rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf));  	rt2800_bbp_write(rt2x00dev, 3, bbp);  	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { @@ -1551,6 +1570,9 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  		     rt2800_wait_bbp_ready(rt2x00dev)))  		return -EACCES; +	if (rt2800_is_305x_soc(rt2x00dev)) +		rt2800_bbp_write(rt2x00dev, 31, 0x08); +  	rt2800_bbp_write(rt2x00dev, 65, 0x2c);  	rt2800_bbp_write(rt2x00dev, 66, 0x38); @@ -1571,6 +1593,9 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  		rt2800_bbp_write(rt2x00dev, 79, 0x13);  		rt2800_bbp_write(rt2x00dev, 80, 0x05);  		rt2800_bbp_write(rt2x00dev, 81, 0x33); +	} else if (rt2800_is_305x_soc(rt2x00dev)) { +		rt2800_bbp_write(rt2x00dev, 78, 0x0e); +		rt2800_bbp_write(rt2x00dev, 80, 0x08);  	} else {  		rt2800_bbp_write(rt2x00dev, 81, 0x37);  	} @@ -1591,12 +1616,16 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  	if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||  	    rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||  	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || -	    rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E)) +	    rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) || +	    rt2800_is_305x_soc(rt2x00dev))  		rt2800_bbp_write(rt2x00dev, 103, 0xc0);  	else  		rt2800_bbp_write(rt2x00dev, 103, 0x00); -	rt2800_bbp_write(rt2x00dev, 105, 0x05); +	if (rt2800_is_305x_soc(rt2x00dev)) +		rt2800_bbp_write(rt2x00dev, 105, 0x01); +	else +		rt2800_bbp_write(rt2x00dev, 105, 0x05);  	rt2800_bbp_write(rt2x00dev, 106, 0x35);  	if (rt2x00_rt(rt2x00dev, RT3071) || @@ -1613,11 +1642,6 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  		rt2800_bbp_write(rt2x00dev, 138, value);  	} -	if (rt2x00_rt(rt2x00dev, RT2872)) { -		rt2800_bbp_write(rt2x00dev, 31, 0x08); -		rt2800_bbp_write(rt2x00dev, 78, 0x0e); -		rt2800_bbp_write(rt2x00dev, 80, 0x08); -	}  	for (i = 0; i < EEPROM_BBP_SIZE; i++) {  		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); @@ -1703,7 +1727,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  	if (!rt2x00_rt(rt2x00dev, RT3070) &&  	    !rt2x00_rt(rt2x00dev, RT3071) &&  	    !rt2x00_rt(rt2x00dev, RT3090) && -	    !rt2x00_rt(rt2x00dev, RT3390)) +	    !rt2x00_rt(rt2x00dev, RT3390) && +	    !rt2800_is_305x_soc(rt2x00dev))  		return 0;  	/* @@ -1771,6 +1796,40 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  		rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);  		rt2800_rfcsr_write(rt2x00dev, 30, 0x20);  		rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); +	} else if (rt2800_is_305x_soc(rt2x00dev)) { +		rt2800_rfcsr_write(rt2x00dev, 0, 0x50); +		rt2800_rfcsr_write(rt2x00dev, 1, 0x01); +		rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); +		rt2800_rfcsr_write(rt2x00dev, 3, 0x75); +		rt2800_rfcsr_write(rt2x00dev, 4, 0x40); +		rt2800_rfcsr_write(rt2x00dev, 5, 0x03); +		rt2800_rfcsr_write(rt2x00dev, 6, 0x02); +		rt2800_rfcsr_write(rt2x00dev, 7, 0x50); +		rt2800_rfcsr_write(rt2x00dev, 8, 0x39); +		rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); +		rt2800_rfcsr_write(rt2x00dev, 10, 0x60); +		rt2800_rfcsr_write(rt2x00dev, 11, 0x21); +		rt2800_rfcsr_write(rt2x00dev, 12, 0x75); +		rt2800_rfcsr_write(rt2x00dev, 13, 0x75); +		rt2800_rfcsr_write(rt2x00dev, 14, 0x90); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x58); +		rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x92); +		rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); +		rt2800_rfcsr_write(rt2x00dev, 19, 0x02); +		rt2800_rfcsr_write(rt2x00dev, 20, 0xba); +		rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); +		rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 23, 0x31); +		rt2800_rfcsr_write(rt2x00dev, 24, 0x08); +		rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +		rt2800_rfcsr_write(rt2x00dev, 26, 0x25); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x23); +		rt2800_rfcsr_write(rt2x00dev, 28, 0x13); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x83); +		rt2800_rfcsr_write(rt2x00dev, 30, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 31, 0x00); +		return 0;  	}  	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { @@ -1986,7 +2045,6 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);  	} else if (rt2x00_rt(rt2x00dev, RT2860) ||  		   rt2x00_rt(rt2x00dev, RT2870) || -		   rt2x00_rt(rt2x00dev, RT2872) ||  		   rt2x00_rt(rt2x00dev, RT2872)) {  		/*  		 * There is a max of 2 RX streams for RT28x0 series @@ -2318,8 +2376,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	else  		spec->ht.ht_supported = false; +	/* +	 * Don't set IEEE80211_HT_CAP_SUP_WIDTH_20_40 for now as it causes +	 * reception problems with HT40 capable 11n APs +	 */  	spec->ht.cap = -	    IEEE80211_HT_CAP_SUP_WIDTH_20_40 |  	    IEEE80211_HT_CAP_GRN_FLD |  	    IEEE80211_HT_CAP_SGI_20 |  	    IEEE80211_HT_CAP_SGI_40 | diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 2131f8f0c50..f08b6a37bf2 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -613,15 +613,23 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,  /*   * TX descriptor initialization   */ -static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, -				    struct sk_buff *skb, -				    struct txentry_desc *txdesc) +static int rt2800pci_write_tx_data(struct queue_entry* entry, +				   struct txentry_desc *txdesc)  { -	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); -	__le32 *txd = skbdesc->desc; -	__le32 *txwi = (__le32 *)(skb->data - rt2x00dev->ops->extra_tx_headroom); +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	struct sk_buff *skb = entry->skb; +	struct skb_frame_desc *skbdesc; +	int ret; +	__le32 *txwi;  	u32 word; +	ret = rt2x00pci_write_tx_data(entry, txdesc); +	if (ret) +		return ret; + +	skbdesc = get_skb_frame_desc(skb); +	txwi = (__le32 *)(skb->data - rt2x00dev->ops->extra_tx_headroom); +  	/*  	 * Initialize TX Info descriptor  	 */ @@ -655,7 +663,7 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,  			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?  			   txdesc->key_idx : 0xff);  	rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, -			   skb->len - txdesc->l2pad); +			   txdesc->length);  	rt2x00_set_field32(&word, TXWI_W1_PACKETID,  			   skbdesc->entry->queue->qid + 1);  	rt2x00_desc_write(txwi, 1, word); @@ -670,6 +678,18 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,  	_rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */);  	_rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); +	return 0; +} + + +static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, +				    struct sk_buff *skb, +				    struct txentry_desc *txdesc) +{ +	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); +	__le32 *txd = skbdesc->desc; +	u32 word; +  	/*  	 * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1  	 * must contains a TXWI structure + 802.11 header + padding + 802.11 @@ -875,10 +895,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,  	    (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +  	     rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; -	rxdesc->noise = -	    (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + -	     rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; -  	rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);  	/* @@ -1135,7 +1151,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {  	.reset_tuner		= rt2800_reset_tuner,  	.link_tuner		= rt2800_link_tuner,  	.write_tx_desc		= rt2800pci_write_tx_desc, -	.write_tx_data		= rt2x00pci_write_tx_data, +	.write_tx_data		= rt2800pci_write_tx_data,  	.write_beacon		= rt2800pci_write_beacon,  	.kick_tx_queue		= rt2800pci_kick_tx_queue,  	.kill_tx_queue		= rt2800pci_kill_tx_queue, diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6b809ab42c6..e3f3a97db80 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -437,7 +437,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,  			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?  			   txdesc->key_idx : 0xff);  	rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, -			   skb->len - txdesc->l2pad); +			   txdesc->length);  	rt2x00_set_field32(&word, TXWI_W1_PACKETID,  			   skbdesc->entry->queue->qid + 1);  	rt2x00_desc_write(txwi, 1, word); @@ -645,10 +645,6 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,  	    (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +  	     rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; -	rxdesc->noise = -	    (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + -	     rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; -  	rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);  	/* @@ -806,6 +802,10 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, +	/* Allwin */ +	{ USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Amit */  	{ USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Askey */ @@ -848,6 +848,11 @@ static struct usb_device_id rt2800usb_device_table[] = {  	/* Hawking */  	{ USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Linksys */  	{ USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -907,6 +912,10 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* AirTies */  	{ USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, +	/* Allwin */ +	{ USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* ASUS */  	{ USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* AzureWave */ @@ -991,6 +1000,8 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },  #endif  #ifdef CONFIG_RT2800USB_RT35XX +	/* Allwin */ +	{ USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Askey */  	{ USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Cisco */ @@ -1012,16 +1023,8 @@ static struct usb_device_id rt2800usb_device_table[] = {  #ifdef CONFIG_RT2800USB_UNKNOWN  	/*  	 * Unclear what kind of devices these are (they aren't supported by the -	 * vendor driver). +	 * vendor linux driver).  	 */ -	/* Allwin */ -	{ USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Amigo */  	{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -1033,6 +1036,7 @@ static struct usb_device_id rt2800usb_device_table[] = {  	/* AzureWave */  	{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Belkin */  	{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Buffalo */ @@ -1051,15 +1055,13 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Encore */  	{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Gemtek */  	{ USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Gigabyte */  	{ USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	/* Hawking */ -	{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* LevelOne */  	{ USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -1070,11 +1072,13 @@ static struct usb_device_id rt2800usb_device_table[] = {  	/* Motorola */  	{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Ovislink */ +	{ USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Pegatron */  	{ USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Planex */  	{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Qcom */ @@ -1083,6 +1087,7 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) },  	/* Sweex */  	{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },  	{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 4de505b9833..4f9b666f7a7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -549,7 +549,8 @@ struct rt2x00lib_ops {  	void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,  			       struct sk_buff *skb,  			       struct txentry_desc *txdesc); -	int (*write_tx_data) (struct queue_entry *entry); +	int (*write_tx_data) (struct queue_entry *entry, +			      struct txentry_desc *txdesc);  	void (*write_beacon) (struct queue_entry *entry);  	int (*get_tx_data_len) (struct queue_entry *entry);  	void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index eda73ba735a..3ae468c4d76 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -435,7 +435,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,  	rx_status->mactime = rxdesc.timestamp;  	rx_status->rate_idx = rate_idx;  	rx_status->signal = rxdesc.rssi; -	rx_status->noise = rxdesc.noise;  	rx_status->flag = rxdesc.flags;  	rx_status->antenna = rt2x00dev->link.ant.active.rx; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index cf3f1c0c438..4b941e9c794 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -63,7 +63,8 @@ EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);  /*   * TX data handlers.   */ -int rt2x00pci_write_tx_data(struct queue_entry *entry) +int rt2x00pci_write_tx_data(struct queue_entry *entry, +			    struct txentry_desc *txdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct queue_entry_priv_pci *entry_priv = entry->priv_data; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 8149ff68410..51bcef3839c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -92,7 +92,8 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,   * This function will initialize the DMA and skb descriptor   * to prepare the entry for the actual TX operation.   */ -int rt2x00pci_write_tx_data(struct queue_entry *entry); +int rt2x00pci_write_tx_data(struct queue_entry *entry, +			    struct txentry_desc *txdesc);  /**   * struct queue_entry_priv_pci: Per entry PCI specific information diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index a0bd36fc4d2..e22029fcf41 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -334,12 +334,10 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,  	txdesc->aifs = entry->queue->aifs;  	/* -	 * Header and alignment information. +	 * Header and frame information.  	 */ +	txdesc->length = entry->skb->len;  	txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); -	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags) && -	    (entry->skb->len > txdesc->header_length)) -		txdesc->l2pad = L2PAD_SIZE(txdesc->header_length);  	/*  	 * Check whether this frame is to be acked. @@ -526,7 +524,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	 * call failed. Since we always return NETDEV_TX_OK to mac80211,  	 * this frame will simply be dropped.  	 */ -	if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { +	if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry, +							       &txdesc))) {  		clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);  		entry->skb = NULL;  		return -EIO; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index c1e482bb37b..94a48c174d6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -183,7 +183,6 @@ enum rxdone_entry_desc_flags {   * @timestamp: RX Timestamp   * @signal: Signal of the received frame.   * @rssi: RSSI of the received frame. - * @noise: Measured noise during frame reception.   * @size: Data size of the received frame.   * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags).   * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags). @@ -197,7 +196,6 @@ struct rxdone_entry_desc {  	u64 timestamp;  	int signal;  	int rssi; -	int noise;  	int size;  	int flags;  	int dev_flags; @@ -287,8 +285,8 @@ enum txentry_desc_flags {   *   * @flags: Descriptor flags (See &enum queue_entry_flags).   * @queue: Queue identification (See &enum data_queue_qid). + * @length: Length of the entire frame.   * @header_length: Length of 802.11 header. - * @l2pad: Amount of padding to align 802.11 payload to 4-byte boundrary.   * @length_high: PLCP length high word.   * @length_low: PLCP length low word.   * @signal: PLCP signal. @@ -313,8 +311,8 @@ struct txentry_desc {  	enum data_queue_qid queue; +	u16 length;  	u16 header_length; -	u16 l2pad;  	u16 length_high;  	u16 length_low; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index f9a7f8b1741..da111c0c292 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -216,7 +216,8 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)  	rt2x00lib_txdone(entry, &txdesc);  } -int rt2x00usb_write_tx_data(struct queue_entry *entry) +int rt2x00usb_write_tx_data(struct queue_entry *entry, +			    struct txentry_desc *txdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 3da6841b5d4..621d0f82925 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -376,7 +376,8 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);   * This function will initialize the URB and skb descriptor   * to prepare the entry for the actual TX operation.   */ -int rt2x00usb_write_tx_data(struct queue_entry *entry); +int rt2x00usb_write_tx_data(struct queue_entry *entry, +			    struct txentry_desc *txdesc);  /**   * struct queue_entry_priv_usb: Per entry USB specific information diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b9885981f3a..26ee7911fba 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1809,7 +1809,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,  	if (skbdesc->desc_len > TXINFO_SIZE) {  		rt2x00_desc_read(txd, 11, &word); -		rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skb->len); +		rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, +				   txdesc->length);  		rt2x00_desc_write(txd, 11, word);  	} @@ -1832,7 +1833,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,  			   test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); -	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); +	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);  	rt2x00_set_field32(&word, TXD_W0_BURST,  			   test_bit(ENTRY_TXD_BURST, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 576ea9dd282..39b3c6d04af 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1495,7 +1495,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,  			   test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); -	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); +	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);  	rt2x00_set_field32(&word, TXD_W0_BURST2,  			   test_bit(ENTRY_TXD_BURST, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); diff --git a/drivers/net/wireless/rtl818x/Kconfig b/drivers/net/wireless/rtl818x/Kconfig new file mode 100644 index 00000000000..17d80fe556d --- /dev/null +++ b/drivers/net/wireless/rtl818x/Kconfig @@ -0,0 +1,88 @@ +# +# RTL818X Wireless LAN device configuration +# +config RTL8180 +	tristate "Realtek 8180/8185 PCI support" +	depends on MAC80211 && PCI && EXPERIMENTAL +	select EEPROM_93CX6 +	---help--- +	  This is a driver for RTL8180 and RTL8185 based cards. +	  These are PCI based chips found in cards such as: + +	  (RTL8185 802.11g) +	  A-Link WL54PC + +	  (RTL8180 802.11b) +	  Belkin F5D6020 v3 +	  Belkin F5D6020 v3 +	  Dlink DWL-610 +	  Dlink DWL-510 +	  Netgear MA521 +	  Level-One WPC-0101 +	  Acer Aspire 1357 LMi +	  VCTnet PC-11B1 +	  Ovislink AirLive WL-1120PCM +	  Mentor WL-PCI +	  Linksys WPC11 v4 +	  TrendNET TEW-288PI +	  D-Link DWL-520 Rev D +	  Repotec RP-WP7126 +	  TP-Link TL-WN250/251 +	  Zonet ZEW1000 +	  Longshine LCS-8031-R +	  HomeLine HLW-PCC200 +	  GigaFast WF721-AEX +	  Planet WL-3553 +	  Encore ENLWI-PCI1-NT +	  TrendNET TEW-266PC +	  Gigabyte GN-WLMR101 +	  Siemens-fujitsu Amilo D1840W +	  Edimax EW-7126 +	  PheeNet WL-11PCIR +	  Tonze PC-2100T +	  Planet WL-8303 +	  Dlink DWL-650 v M1 +	  Edimax EW-7106 +	  Q-Tec 770WC +	  Topcom Skyr@cer 4011b +	  Roper FreeLan 802.11b (edition 2004) +	  Wistron Neweb Corp CB-200B +	  Pentagram HorNET +	  QTec 775WC +	  TwinMOS Booming B Series +	  Micronet SP906BB +	  Sweex LC700010 +	  Surecom EP-9428 +	  Safecom SWLCR-1100 + +	  Thanks to Realtek for their support! + +config RTL8187 +	tristate "Realtek 8187 and 8187B USB support" +	depends on MAC80211 && USB +	select EEPROM_93CX6 +	---help--- +	  This is a driver for RTL8187 and RTL8187B based cards. +	  These are USB based chips found in devices such as: + +	  Netgear WG111v2 +	  Level 1 WNC-0301USB +	  Micronet SP907GK V5 +	  Encore ENUWI-G2 +	  Trendnet TEW-424UB +	  ASUS P5B Deluxe/P5K Premium motherboards +	  Toshiba Satellite Pro series of laptops +	  Asus Wireless Link +	  Linksys WUSB54GC-EU v2 +	    (v1 = rt73usb; v3 is rt2070-based, +	     use staging/rt3070 or try rt2800usb) + +	  Thanks to Realtek for their support! + +# If possible, automatically enable LEDs for RTL8187. + +config RTL8187_LEDS +	bool +	depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187) +	default y + diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 6b46329b732..21307f2412b 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c @@ -188,6 +188,7 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)  			info->flags |= IEEE80211_TX_STAT_ACK;  		info->status.rates[0].count = (flags & 0xFF) + 1; +		info->status.rates[1].idx = -1;  		ieee80211_tx_status_irqsafe(dev, skb);  		if (ring->entries - skb_queue_len(&ring->queue) == 2) @@ -297,7 +298,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)  	entry->flags = cpu_to_le32(tx_flags);  	__skb_queue_tail(&ring->queue, skb);  	if (ring->entries - skb_queue_len(&ring->queue) < 2) -		ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); +		ieee80211_stop_queue(dev, prio);  	spin_unlock_irqrestore(&priv->lock, flags);  	rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); @@ -827,6 +828,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,  	const char *chip_name, *rf_name = NULL;  	u32 reg;  	u16 eeprom_val; +	u8 mac_addr[ETH_ALEN];  	err = pci_enable_device(pdev);  	if (err) { @@ -987,12 +989,13 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,  		eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam);  	} -	eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)dev->wiphy->perm_addr, 3); -	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { +	eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)mac_addr, 3); +	if (!is_valid_ether_addr(mac_addr)) {  		printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using"  		       " randomly generated MAC addr\n", pci_name(pdev)); -		random_ether_addr(dev->wiphy->perm_addr); +		random_ether_addr(mac_addr);  	} +	SET_IEEE80211_PERM_ADDR(dev, mac_addr);  	/* CCK TX power */  	for (i = 0; i < 14; i += 2) { @@ -1024,7 +1027,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,  	}  	printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n", -	       wiphy_name(dev->wiphy), dev->wiphy->perm_addr, +	       wiphy_name(dev->wiphy), mac_addr,  	       chip_name, priv->rf->name);  	return 0; diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 738921fda02..891b8490e34 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c @@ -1333,6 +1333,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,  	u16 txpwr, reg;  	u16 product_id = le16_to_cpu(udev->descriptor.idProduct);  	int err, i; +	u8 mac_addr[ETH_ALEN];  	dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);  	if (!dev) { @@ -1390,12 +1391,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,  	udelay(10);  	eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR, -			       (__le16 __force *)dev->wiphy->perm_addr, 3); -	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { +			       (__le16 __force *)mac_addr, 3); +	if (!is_valid_ether_addr(mac_addr)) {  		printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly "  		       "generated MAC address\n"); -		random_ether_addr(dev->wiphy->perm_addr); +		random_ether_addr(mac_addr);  	} +	SET_IEEE80211_PERM_ADDR(dev, mac_addr);  	channel = priv->channels;  	for (i = 0; i < 3; i++) { @@ -1526,7 +1528,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,  	skb_queue_head_init(&priv->b_tx_status.queue);  	printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n", -	       wiphy_name(dev->wiphy), dev->wiphy->perm_addr, +	       wiphy_name(dev->wiphy), mac_addr,  	       chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask);  #ifdef CONFIG_RTL8187_LEDS diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 4d479708158..00b24282fc7 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -857,6 +857,7 @@ out:  }  static int wl1251_op_hw_scan(struct ieee80211_hw *hw, +			     struct ieee80211_vif *vif,  			     struct cfg80211_scan_request *req)  {  	struct wl1251 *wl = hw->priv; @@ -1196,6 +1197,66 @@ static const struct ieee80211_ops wl1251_ops = {  	.conf_tx = wl1251_op_conf_tx,  }; +static int wl1251_read_eeprom_byte(struct wl1251 *wl, off_t offset, u8 *data) +{ +	unsigned long timeout; + +	wl1251_reg_write32(wl, EE_ADDR, offset); +	wl1251_reg_write32(wl, EE_CTL, EE_CTL_READ); + +	/* EE_CTL_READ clears when data is ready */ +	timeout = jiffies + msecs_to_jiffies(100); +	while (1) { +		if (!(wl1251_reg_read32(wl, EE_CTL) & EE_CTL_READ)) +			break; + +		if (time_after(jiffies, timeout)) +			return -ETIMEDOUT; + +		msleep(1); +	} + +	*data = wl1251_reg_read32(wl, EE_DATA); +	return 0; +} + +static int wl1251_read_eeprom(struct wl1251 *wl, off_t offset, +			      u8 *data, size_t len) +{ +	size_t i; +	int ret; + +	wl1251_reg_write32(wl, EE_START, 0); + +	for (i = 0; i < len; i++) { +		ret = wl1251_read_eeprom_byte(wl, offset + i, &data[i]); +		if (ret < 0) +			return ret; +	} + +	return 0; +} + +static int wl1251_read_eeprom_mac(struct wl1251 *wl) +{ +	u8 mac[ETH_ALEN]; +	int i, ret; + +	wl1251_set_partition(wl, 0, 0, REGISTERS_BASE, REGISTERS_DOWN_SIZE); + +	ret = wl1251_read_eeprom(wl, 0x1c, mac, sizeof(mac)); +	if (ret < 0) { +		wl1251_warning("failed to read MAC address from EEPROM"); +		return ret; +	} + +	/* MAC is stored in reverse order */ +	for (i = 0; i < ETH_ALEN; i++) +		wl->mac_addr[i] = mac[ETH_ALEN - i - 1]; + +	return 0; +} +  static int wl1251_register_hw(struct wl1251 *wl)  {  	int ret; @@ -1231,7 +1292,6 @@ int wl1251_init_ieee80211(struct wl1251 *wl)  	wl->hw->channel_change_time = 10000;  	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | -		IEEE80211_HW_NOISE_DBM |  		IEEE80211_HW_SUPPORTS_PS |  		IEEE80211_HW_BEACON_FILTER |  		IEEE80211_HW_SUPPORTS_UAPSD; @@ -1242,6 +1302,9 @@ int wl1251_init_ieee80211(struct wl1251 *wl)  	wl->hw->queues = 4; +	if (wl->use_eeprom) +		wl1251_read_eeprom_mac(wl); +  	ret = wl1251_register_hw(wl);  	if (ret)  		goto out; diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h index 0ca3b432605..d16edd9bf06 100644 --- a/drivers/net/wireless/wl12xx/wl1251_reg.h +++ b/drivers/net/wireless/wl12xx/wl1251_reg.h @@ -46,7 +46,14 @@  #define SOR_CFG                        (REGISTERS_BASE + 0x0800)  #define ECPU_CTRL                      (REGISTERS_BASE + 0x0804)  #define HI_CFG                         (REGISTERS_BASE + 0x0808) + +/* EEPROM registers */  #define EE_START                       (REGISTERS_BASE + 0x080C) +#define EE_CTL                         (REGISTERS_BASE + 0x2000) +#define EE_DATA                        (REGISTERS_BASE + 0x2004) +#define EE_ADDR                        (REGISTERS_BASE + 0x2008) + +#define EE_CTL_READ                   2  #define CHIP_ID_B                      (REGISTERS_BASE + 0x5674) diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index 6f229e0990f..af5c67b4da9 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c @@ -74,12 +74,6 @@ static void wl1251_rx_status(struct wl1251 *wl,  	status->signal = desc->rssi; -	/* -	 * FIXME: guessing that snr needs to be divided by two, otherwise -	 * the values don't make any sense -	 */ -	status->noise = desc->rssi - desc->snr / 2; -  	status->freq = ieee80211_channel_to_frequency(desc->channel);  	status->flag |= RX_FLAG_TSFT; diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c index 2051ef06e9e..d234285c2c8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c @@ -23,6 +23,9 @@  #include <linux/mod_devicetable.h>  #include <linux/mmc/sdio_func.h>  #include <linux/mmc/sdio_ids.h> +#include <linux/platform_device.h> +#include <linux/spi/wl12xx.h> +#include <linux/irq.h>  #include "wl1251.h" @@ -34,6 +37,8 @@  #define SDIO_DEVICE_ID_TI_WL1251	0x9066  #endif +static struct wl12xx_platform_data *wl12xx_board_data; +  static struct sdio_func *wl_to_func(struct wl1251 *wl)  {  	return wl->if_priv; @@ -130,18 +135,60 @@ static void wl1251_sdio_disable_irq(struct wl1251 *wl)  	sdio_release_host(func);  } +/* Interrupts when using dedicated WLAN_IRQ pin */ +static irqreturn_t wl1251_line_irq(int irq, void *cookie) +{ +	struct wl1251 *wl = cookie; + +	ieee80211_queue_work(wl->hw, &wl->irq_work); + +	return IRQ_HANDLED; +} + +static void wl1251_enable_line_irq(struct wl1251 *wl) +{ +	return enable_irq(wl->irq); +} + +static void wl1251_disable_line_irq(struct wl1251 *wl) +{ +	return disable_irq(wl->irq); +} +  static void wl1251_sdio_set_power(bool enable)  {  } -static const struct wl1251_if_operations wl1251_sdio_ops = { +static struct wl1251_if_operations wl1251_sdio_ops = {  	.read = wl1251_sdio_read,  	.write = wl1251_sdio_write,  	.write_elp = wl1251_sdio_write_elp,  	.read_elp = wl1251_sdio_read_elp,  	.reset = wl1251_sdio_reset, -	.enable_irq = wl1251_sdio_enable_irq, -	.disable_irq = wl1251_sdio_disable_irq, +}; + +static int wl1251_platform_probe(struct platform_device *pdev) +{ +	if (pdev->id != -1) { +		wl1251_error("can only handle single device"); +		return -ENODEV; +	} + +	wl12xx_board_data = pdev->dev.platform_data; +	return 0; +} + +/* + * Dummy platform_driver for passing platform_data to this driver, + * until we have a way to pass this through SDIO subsystem or + * some other way. + */ +static struct platform_driver wl1251_platform_driver = { +	.driver = { +		.name	= "wl1251_data", +		.owner	= THIS_MODULE, +	}, +	.probe	= wl1251_platform_probe,  };  static int wl1251_sdio_probe(struct sdio_func *func, @@ -163,20 +210,50 @@ static int wl1251_sdio_probe(struct sdio_func *func,  		goto release;  	sdio_set_block_size(func, 512); +	sdio_release_host(func);  	SET_IEEE80211_DEV(hw, &func->dev);  	wl->if_priv = func;  	wl->if_ops = &wl1251_sdio_ops;  	wl->set_power = wl1251_sdio_set_power; -	sdio_release_host(func); +	if (wl12xx_board_data != NULL) { +		wl->set_power = wl12xx_board_data->set_power; +		wl->irq = wl12xx_board_data->irq; +		wl->use_eeprom = wl12xx_board_data->use_eeprom; +	} + +	if (wl->irq) { +		ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); +		if (ret < 0) { +			wl1251_error("request_irq() failed: %d", ret); +			goto disable; +		} + +		set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); +		disable_irq(wl->irq); + +		wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; +		wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; + +		wl1251_info("using dedicated interrupt line"); +	} else { +		wl1251_sdio_ops.enable_irq = wl1251_sdio_enable_irq; +		wl1251_sdio_ops.disable_irq = wl1251_sdio_disable_irq; + +		wl1251_info("using SDIO interrupt"); +	} +  	ret = wl1251_init_ieee80211(wl);  	if (ret) -		goto disable; +		goto out_free_irq;  	sdio_set_drvdata(func, wl);  	return ret; +out_free_irq: +	if (wl->irq) +		free_irq(wl->irq, wl);  disable:  	sdio_claim_host(func);  	sdio_disable_func(func); @@ -189,6 +266,8 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func)  {  	struct wl1251 *wl = sdio_get_drvdata(func); +	if (wl->irq) +		free_irq(wl->irq, wl);  	wl1251_free_hw(wl);  	sdio_claim_host(func); @@ -208,6 +287,12 @@ static int __init wl1251_sdio_init(void)  {  	int err; +	err = platform_driver_register(&wl1251_platform_driver); +	if (err) { +		wl1251_error("failed to register platform driver: %d", err); +		return err; +	} +  	err = sdio_register_driver(&wl1251_sdio_driver);  	if (err)  		wl1251_error("failed to register sdio driver: %d", err); @@ -217,6 +302,7 @@ static int __init wl1251_sdio_init(void)  static void __exit wl1251_sdio_exit(void)  {  	sdio_unregister_driver(&wl1251_sdio_driver); +	platform_driver_unregister(&wl1251_platform_driver);  	wl1251_notice("unloaded");  } diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 2ad086efe06..e19e2f8f1e5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c @@ -590,7 +590,7 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)  	/* BT-WLAN coext parameters */  	for (i = 0; i < CONF_SG_PARAMS_MAX; i++) -		param->params[i] = c->params[i]; +		param->params[i] = cpu_to_le32(c->params[i]);  	param->param_idx = CONF_SG_PARAMS_ALL;  	ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 8087dc17f29..acb1d9e6b7d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c @@ -351,7 +351,7 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)  static int wl1271_boot_run_firmware(struct wl1271 *wl)  {  	int loop, ret; -	u32 chip_id, interrupt; +	u32 chip_id, intr;  	wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); @@ -368,15 +368,15 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)  	loop = 0;  	while (loop++ < INIT_LOOP) {  		udelay(INIT_LOOP_DELAY); -		interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); +		intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); -		if (interrupt == 0xffffffff) { +		if (intr == 0xffffffff) {  			wl1271_error("error reading hardware complete "  				     "init indication");  			return -EIO;  		}  		/* check that ACX_INTR_INIT_COMPLETE is enabled */ -		else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { +		else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) {  			wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,  				       WL1271_ACX_INTR_INIT_COMPLETE);  			break; diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 6b5ba8ec94c..62c11af1d8e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -37,7 +37,7 @@  #include "wl1271_cmd.h"  #include "wl1271_event.h" -#define WL1271_CMD_POLL_COUNT       5 +#define WL1271_CMD_FAST_POLL_COUNT       50  /*   * send command to firmware @@ -77,11 +77,11 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,  			goto out;  		} -		udelay(10);  		poll_count++; -		if (poll_count == WL1271_CMD_POLL_COUNT) -			wl1271_info("cmd polling took over %d cycles", -				    poll_count); +		if (poll_count < WL1271_CMD_FAST_POLL_COUNT) +			udelay(10); +		else +			msleep(1);  		intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);  	} @@ -318,7 +318,7 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)  	join->rx_config_options = cpu_to_le32(wl->rx_config);  	join->rx_filter_options = cpu_to_le32(wl->rx_filter);  	join->bss_type = bss_type; -	join->basic_rate_set = wl->basic_rate_set; +	join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);  	if (wl->band == IEEE80211_BAND_5GHZ)  		join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; @@ -615,7 +615,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,  	params->params.scan_options = cpu_to_le16(scan_options);  	params->params.num_probe_requests = probe_requests; -	params->params.tx_rate = rate; +	params->params.tx_rate = cpu_to_le32(rate);  	params->params.tid_trigger = 0;  	params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index c44307c4bcf..d046d044b5b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -401,7 +401,7 @@ enum {  };  struct conf_sg_settings { -	__le32 params[CONF_SG_PARAMS_MAX]; +	u32 params[CONF_SG_PARAMS_MAX];  	u8 state;  }; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 814f300c3f1..62e544041d0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1118,14 +1118,13 @@ static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)  	}  } -static int wl1271_join_channel(struct wl1271 *wl, int channel) +static int wl1271_dummy_join(struct wl1271 *wl)  {  	int ret = 0;  	/* we need to use a dummy BSSID for now */  	static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,  						  0xad, 0xbe, 0xef }; -	wl->channel = channel;  	memcpy(wl->bssid, dummy_bssid, ETH_ALEN);  	/* pass through frames from all BSS */ @@ -1141,7 +1140,47 @@ out:  	return ret;  } -static int wl1271_unjoin_channel(struct wl1271 *wl) +static int wl1271_join(struct wl1271 *wl) +{ +	int ret; + +	ret = wl1271_cmd_join(wl, wl->set_bss_type); +	if (ret < 0) +		goto out; + +	set_bit(WL1271_FLAG_JOINED, &wl->flags); + +	if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) +		goto out; + +	/* +	 * The join command disable the keep-alive mode, shut down its process, +	 * and also clear the template config, so we need to reset it all after +	 * the join. The acx_aid starts the keep-alive process, and the order +	 * of the commands below is relevant. +	 */ +	ret = wl1271_acx_keep_alive_mode(wl, true); +	if (ret < 0) +		goto out; + +	ret = wl1271_acx_aid(wl, wl->aid); +	if (ret < 0) +		goto out; + +	ret = wl1271_cmd_build_klv_null_data(wl); +	if (ret < 0) +		goto out; + +	ret = wl1271_acx_keep_alive_config(wl, CMD_TEMPL_KLV_IDX_NULL_DATA, +					   ACX_KEEP_ALIVE_TPL_VALID); +	if (ret < 0) +		goto out; + +out: +	return ret; +} + +static int wl1271_unjoin(struct wl1271 *wl)  {  	int ret; @@ -1231,7 +1270,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)  				       "failed %d", ret);  		if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { -			ret = wl1271_cmd_join(wl, wl->set_bss_type); +			ret = wl1271_join(wl);  			if (ret < 0)  				wl1271_warning("cmd join to update channel "  					       "failed %d", ret); @@ -1241,9 +1280,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)  	if (changed & IEEE80211_CONF_CHANGE_IDLE) {  		if (conf->flags & IEEE80211_CONF_IDLE &&  		    test_bit(WL1271_FLAG_JOINED, &wl->flags)) -			wl1271_unjoin_channel(wl); +			wl1271_unjoin(wl);  		else if (!(conf->flags & IEEE80211_CONF_IDLE)) -			wl1271_join_channel(wl, channel); +			wl1271_dummy_join(wl);  		if (conf->flags & IEEE80211_CONF_IDLE) {  			wl->rate_set = wl1271_min_rate_get(wl); @@ -1311,7 +1350,6 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw,  	struct wl1271_filter_params *fp;  	struct netdev_hw_addr *ha;  	struct wl1271 *wl = hw->priv; -	int i;  	if (unlikely(wl->state == WL1271_STATE_OFF))  		return 0; @@ -1520,6 +1558,7 @@ out:  }  static int wl1271_op_hw_scan(struct ieee80211_hw *hw, +			     struct ieee80211_vif *vif,  			     struct cfg80211_scan_request *req)  {  	struct wl1271 *wl = hw->priv; @@ -1608,7 +1647,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,  	enum wl1271_cmd_ps_mode mode;  	struct wl1271 *wl = hw->priv;  	bool do_join = false; -	bool do_keepalive = false;  	int ret;  	wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); @@ -1703,6 +1741,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,  			if (ret < 0)  				goto out_sleep; +			ret = wl1271_build_qos_null_data(wl); +			if (ret < 0) +				goto out_sleep; +  			/* filter out all packets not from this BSSID */  			wl1271_configure_filters(wl, 0); @@ -1747,19 +1789,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,  			ret = wl1271_cmd_build_probe_req(wl, NULL, 0,  							 NULL, 0, wl->band); -			/* Enable the keep-alive feature */ -			ret = wl1271_acx_keep_alive_mode(wl, true); -			if (ret < 0) -				goto out_sleep; - -			/* -			 * This is awkward. The keep-alive configs must be done -			 * *after* the join command, because otherwise it will -			 * not work, but it must only be done *once* because -			 * otherwise the firmware will start complaining. -			 */ -			do_keepalive = true; -  			/* enable the connection monitoring feature */  			ret = wl1271_acx_conn_monit_params(wl, true);  			if (ret < 0) @@ -1827,35 +1856,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,  	}  	if (do_join) { -		ret = wl1271_cmd_join(wl, wl->set_bss_type); +		ret = wl1271_join(wl);  		if (ret < 0) {  			wl1271_warning("cmd join failed %d", ret);  			goto out_sleep;  		} -		set_bit(WL1271_FLAG_JOINED, &wl->flags); -	} - -	/* -	 * The JOIN operation shuts down the firmware keep-alive as a side -	 * effect, and the ACX_AID will start the keep-alive as a side effect. -	 * Hence, for non-IBSS, the ACX_AID must always happen *after* the -	 * JOIN operation, and the template config after the ACX_AID. -	 */ -	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { -		ret = wl1271_acx_aid(wl, wl->aid); -		if (ret < 0) -			goto out_sleep; -	} - -	if (do_keepalive) { -		ret = wl1271_cmd_build_klv_null_data(wl); -		if (ret < 0) -			goto out_sleep; -		ret = wl1271_acx_keep_alive_config( -			wl, CMD_TEMPL_KLV_IDX_NULL_DATA, -			ACX_KEEP_ALIVE_TPL_VALID); -		if (ret < 0) -			goto out_sleep;  	}  out_sleep: @@ -2266,7 +2271,6 @@ int wl1271_init_ieee80211(struct wl1271 *wl)  	wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval;  	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | -		IEEE80211_HW_NOISE_DBM |  		IEEE80211_HW_BEACON_FILTER |  		IEEE80211_HW_SUPPORTS_PS |  		IEEE80211_HW_SUPPORTS_UAPSD |  |