diff options
Diffstat (limited to 'drivers/net/wireless')
339 files changed, 28630 insertions, 6311 deletions
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index afe2cbc6cb2..43ebc44fc82 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -16,6 +16,7 @@   */  #include <linux/init.h> +#include <linux/interrupt.h>  #include <linux/if.h>  #include <linux/skbuff.h>  #include <linux/slab.h> diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 7cf4317a2a8..17c4b56c387 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -161,6 +161,7 @@ struct ath_common {  	const struct ath_bus_ops *bus_ops;  	bool btcoex_enabled; +	bool disable_ani;  };  struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index ea998278155..ba682a0b2dd 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -167,8 +167,8 @@ static int ath_ahb_probe(struct platform_device *pdev)  		 * driver for it  		 */  		if (to_platform_device(sc->dev)->id == 0 && -		    (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) == -		     (BD_WLAN1|BD_WLAN0)) +		    (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) == +		     (BD_WLAN1 | BD_WLAN0))  			__set_bit(ATH_STAT_2G_DISABLED, sc->status);  	} @@ -219,6 +219,7 @@ static int ath_ahb_remove(struct platform_device *pdev)  	ath5k_deinit_softc(sc);  	platform_set_drvdata(pdev, NULL); +	ieee80211_free_hw(hw);  	return 0;  } diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index f915f404302..2f0b967a6d8 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c @@ -74,7 +74,7 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)  	static const s8 fr[] = { -78, -80 };  #endif  	if (level < 0 || level >= ARRAY_SIZE(sz)) { -		ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range", +		ATH5K_ERR(ah->ah_sc, "noise immunity level %d out of range",  			  level);  		return;  	} @@ -630,6 +630,11 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)  	if (ah->ah_version < AR5K_AR5212)  		return; +	if (mode < ATH5K_ANI_MODE_OFF || mode > ATH5K_ANI_MODE_AUTO) { +		ATH5K_ERR(ah->ah_sc, "ANI mode %d out of range", mode); +		return; +	} +  	/* clear old state information */  	memset(&ah->ah_sc->ani_state, 0, sizeof(ah->ah_sc->ani_state)); @@ -642,7 +647,7 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)  	/* initial values for our ani parameters */  	if (mode == ATH5K_ANI_MODE_OFF) {  		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI off\n"); -	} else if  (mode == ATH5K_ANI_MODE_MANUAL_LOW) { +	} else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) {  		ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI,  			"ANI manual low -> high sensitivity\n");  		ath5k_ani_set_noise_immunity_level(ah, 0); diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index bb50700436f..8ff17941bb2 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -18,9 +18,9 @@  #ifndef _ATH5K_H  #define _ATH5K_H -/* TODO: Clean up channel debuging -doesn't work anyway- and start +/* TODO: Clean up channel debugging (doesn't work anyway) and start   * working on reg. control code using all available eeprom information - * -rev. engineering needed- */ + * (rev. engineering needed) */  #define CHAN_DEBUG	0  #include <linux/io.h> @@ -39,40 +39,41 @@  #include "../ath.h"  /* PCI IDs */ -#define PCI_DEVICE_ID_ATHEROS_AR5210 		0x0007 /* AR5210 */ -#define PCI_DEVICE_ID_ATHEROS_AR5311 		0x0011 /* AR5311 */ -#define PCI_DEVICE_ID_ATHEROS_AR5211 		0x0012 /* AR5211 */ -#define PCI_DEVICE_ID_ATHEROS_AR5212 		0x0013 /* AR5212 */ -#define PCI_DEVICE_ID_3COM_3CRDAG675 		0x0013 /* 3CRDAG675 (Atheros AR5212) */ -#define PCI_DEVICE_ID_3COM_2_3CRPAG175 		0x0013 /* 3CRPAG175 (Atheros AR5212) */ -#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 	0x0207 /* AR5210 (Early) */ +#define PCI_DEVICE_ID_ATHEROS_AR5210		0x0007 /* AR5210 */ +#define PCI_DEVICE_ID_ATHEROS_AR5311		0x0011 /* AR5311 */ +#define PCI_DEVICE_ID_ATHEROS_AR5211		0x0012 /* AR5211 */ +#define PCI_DEVICE_ID_ATHEROS_AR5212		0x0013 /* AR5212 */ +#define PCI_DEVICE_ID_3COM_3CRDAG675		0x0013 /* 3CRDAG675 (Atheros AR5212) */ +#define PCI_DEVICE_ID_3COM_2_3CRPAG175		0x0013 /* 3CRPAG175 (Atheros AR5212) */ +#define PCI_DEVICE_ID_ATHEROS_AR5210_AP		0x0207 /* AR5210 (Early) */  #define PCI_DEVICE_ID_ATHEROS_AR5212_IBM	0x1014 /* AR5212 (IBM MiniPCI) */ -#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 	0x1107 /* AR5210 (no eeprom) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 	0x1113 /* AR5212 (no eeprom) */ -#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 	0x1112 /* AR5211 (no eeprom) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 	0xf013 /* AR5212 (emulation board) */ -#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 	0xff12 /* AR5211 (emulation board) */ -#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 	0xf11b /* AR5211 (emulation board) */ -#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 	0x0052 /* AR5312 WMAC (AP31) */ -#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 	0x0057 /* AR5312 WMAC (AP30-040) */ -#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 	0x0058 /* AR5312 WMAC (AP43-030) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 	0x0014 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 	0x0015 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 	0x0016 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 	0x0017 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 	0x0018 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 	0x0019 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR2413 		0x001a /* AR2413 (Griffin-lite) */ -#define PCI_DEVICE_ID_ATHEROS_AR5413 		0x001b /* AR5413 (Eagle) */ -#define PCI_DEVICE_ID_ATHEROS_AR5424 		0x001c /* AR5424 (Condor PCI-E) */ -#define PCI_DEVICE_ID_ATHEROS_AR5416 		0x0023 /* AR5416 */ -#define PCI_DEVICE_ID_ATHEROS_AR5418 		0x0024 /* AR5418 */ +#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT	0x1107 /* AR5210 (no eeprom) */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT	0x1113 /* AR5212 (no eeprom) */ +#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT	0x1112 /* AR5211 (no eeprom) */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA	0xf013 /* AR5212 (emulation board) */ +#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY	0xff12 /* AR5211 (emulation board) */ +#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B	0xf11b /* AR5211 (emulation board) */ +#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2	0x0052 /* AR5312 WMAC (AP31) */ +#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7	0x0057 /* AR5312 WMAC (AP30-040) */ +#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8	0x0058 /* AR5312 WMAC (AP43-030) */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0014	0x0014 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0015	0x0015 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0016	0x0016 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0017	0x0017 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0018	0x0018 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR5212_0019	0x0019 /* AR5212 compatible */ +#define PCI_DEVICE_ID_ATHEROS_AR2413		0x001a /* AR2413 (Griffin-lite) */ +#define PCI_DEVICE_ID_ATHEROS_AR5413		0x001b /* AR5413 (Eagle) */ +#define PCI_DEVICE_ID_ATHEROS_AR5424		0x001c /* AR5424 (Condor PCI-E) */ +#define PCI_DEVICE_ID_ATHEROS_AR5416		0x0023 /* AR5416 */ +#define PCI_DEVICE_ID_ATHEROS_AR5418		0x0024 /* AR5418 */  /****************************\    GENERIC DRIVER DEFINITIONS  \****************************/ -#define ATH5K_PRINTF(fmt, ...)   printk("%s: " fmt, __func__, ##__VA_ARGS__) +#define ATH5K_PRINTF(fmt, ...) \ +	printk(KERN_WARNING "%s: " fmt, __func__, ##__VA_ARGS__)  #define ATH5K_PRINTK(_sc, _level, _fmt, ...) \  	printk(_level "ath5k %s: " _fmt, \ @@ -155,7 +156,7 @@  } while (0)  /* - * Some tuneable values (these should be changeable by the user) + * Some tunable values (these should be changeable by the user)   * TODO: Make use of them and add more options OR use debug/configfs   */  #define AR5K_TUNE_DMA_BEACON_RESP		2 @@ -170,8 +171,8 @@  #define AR5K_TUNE_RSSI_THRES			129  /* This must be set when setting the RSSI threshold otherwise it can   * prevent a reset. If AR5K_RSSI_THR is read after writing to it - * the BMISS_THRES will be seen as 0, seems harware doesn't keep - * track of it. Max value depends on harware. For AR5210 this is just 7. + * the BMISS_THRES will be seen as 0, seems hardware doesn't keep + * track of it. Max value depends on hardware. For AR5210 this is just 7.   * For AR5211+ this seems to be up to 255. */  #define AR5K_TUNE_BMISS_THRES			7  #define AR5K_TUNE_REGISTER_DWELL_TIME		20000 @@ -361,7 +362,7 @@ struct ath5k_srev_name {  /*   * Some of this information is based on Documentation from:   * - * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG  + * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG   *   * Modulation for Atheros' eXtended Range - range enhancing extension that is   * supposed to double the distance an Atheros client device can keep a @@ -374,12 +375,12 @@ struct ath5k_srev_name {   * they are exclusive.   *   */ -#define MODULATION_XR 		0x00000200 +#define MODULATION_XR		0x00000200  /*   * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a   * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s   * signaling rate achieved through the bonding of two 54Mbit/s 802.11g - * channels. To use this feature your Access Point must also suport it. + * channels. To use this feature your Access Point must also support it.   * There is also a distinction between "static" and "dynamic" turbo modes:   *   * - Static: is the dumb version: devices set to this mode stick to it until @@ -495,9 +496,9 @@ enum ath5k_tx_queue {   */  enum ath5k_tx_queue_subtype {  	AR5K_WME_AC_BK = 0,	/*Background traffic*/ -	AR5K_WME_AC_BE, 	/*Best-effort (normal) traffic)*/ -	AR5K_WME_AC_VI, 	/*Video traffic*/ -	AR5K_WME_AC_VO, 	/*Voice traffic*/ +	AR5K_WME_AC_BE,		/*Best-effort (normal) traffic*/ +	AR5K_WME_AC_VI,		/*Video traffic*/ +	AR5K_WME_AC_VO,		/*Voice traffic*/  };  /* @@ -616,8 +617,8 @@ struct ath5k_rx_status {  #define AR5K_RXERR_FIFO		0x04  #define AR5K_RXERR_DECRYPT	0x08  #define AR5K_RXERR_MIC		0x10 -#define AR5K_RXKEYIX_INVALID	((u8) - 1) -#define AR5K_TXKEYIX_INVALID	((u32) - 1) +#define AR5K_RXKEYIX_INVALID	((u8) -1) +#define AR5K_TXKEYIX_INVALID	((u32) -1)  /**************************\ @@ -678,17 +679,18 @@ struct ath5k_gain {  #define	CHANNEL_DYN	0x0400	/* Dynamic CCK-OFDM channel (for g operation) */  #define	CHANNEL_XR	0x0800	/* XR channel */ -#define	CHANNEL_A	(CHANNEL_5GHZ|CHANNEL_OFDM) -#define	CHANNEL_B	(CHANNEL_2GHZ|CHANNEL_CCK) -#define	CHANNEL_G	(CHANNEL_2GHZ|CHANNEL_OFDM) -#define	CHANNEL_X	(CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR) +#define	CHANNEL_A	(CHANNEL_5GHZ | CHANNEL_OFDM) +#define	CHANNEL_B	(CHANNEL_2GHZ | CHANNEL_CCK) +#define	CHANNEL_G	(CHANNEL_2GHZ | CHANNEL_OFDM) +#define	CHANNEL_X	(CHANNEL_5GHZ | CHANNEL_OFDM | CHANNEL_XR) -#define	CHANNEL_ALL	(CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ) +#define	CHANNEL_ALL	(CHANNEL_OFDM | CHANNEL_CCK | \ +			 CHANNEL_2GHZ | CHANNEL_5GHZ)  #define CHANNEL_MODES		CHANNEL_ALL  /* - * Used internaly for reset_tx_queue). + * Used internally for ath5k_hw_reset_tx_queue().   * Also see struct struct ieee80211_channel.   */  #define IS_CHAN_XR(_c)	((_c->hw_value & CHANNEL_XR) != 0) @@ -710,7 +712,7 @@ struct ath5k_athchan_2ghz {  \******************/  /** - * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32. + * Seems the ar5xxx hardware supports up to 32 rates, indexed by 1-32.   *   * The rate code is used to get the RX rate or set the TX rate on the   * hardware descriptors. It is also used for internal modulation control @@ -767,6 +769,7 @@ struct ath5k_athchan_2ghz {   */  #define AR5K_KEYCACHE_SIZE	8 +extern int ath5k_modparam_nohwcrypt;  /***********************\   HW RELATED DEFINITIONS @@ -775,11 +778,11 @@ struct ath5k_athchan_2ghz {  /*   * Misc definitions   */ -#define	AR5K_RSSI_EP_MULTIPLIER	(1<<7) +#define	AR5K_RSSI_EP_MULTIPLIER	(1 << 7)  #define AR5K_ASSERT_ENTRY(_e, _s) do {		\  	if (_e >= _s)				\ -		return (false);			\ +		return false;			\  } while (0)  /* @@ -790,52 +793,52 @@ struct ath5k_athchan_2ghz {   * enum ath5k_int - Hardware interrupt masks helpers   *   * @AR5K_INT_RX: mask to identify received frame interrupts, of type - * 	AR5K_ISR_RXOK or AR5K_ISR_RXERR + *	AR5K_ISR_RXOK or AR5K_ISR_RXERR   * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)   * @AR5K_INT_RXNOFRM: No frame received (?)   * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The - * 	Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's - * 	LinkPtr is NULL. For more details, refer to: - * 	http://www.freepatentsonline.com/20030225739.html + *	Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's + *	LinkPtr is NULL. For more details, refer to: + *	http://www.freepatentsonline.com/20030225739.html   * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors). - * 	Note that Rx overrun is not always fatal, on some chips we can continue - * 	operation without reseting the card, that's why int_fatal is not - * 	common for all chips. + *	Note that Rx overrun is not always fatal, on some chips we can continue + *	operation without resetting the card, that's why int_fatal is not + *	common for all chips.   * @AR5K_INT_TX: mask to identify received frame interrupts, of type - * 	AR5K_ISR_TXOK or AR5K_ISR_TXERR + *	AR5K_ISR_TXOK or AR5K_ISR_TXERR   * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)   * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold - * 	We currently do increments on interrupt by - * 	(AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 + *	We currently do increments on interrupt by + *	(AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2   * @AR5K_INT_MIB: Indicates the either Management Information Base counters or   *	one of the PHY error counters reached the maximum value and should be   *	read and cleared.   * @AR5K_INT_RXPHY: RX PHY Error   * @AR5K_INT_RXKCM: RX Key cache miss   * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a - * 	beacon that must be handled in software. The alternative is if you - * 	have VEOL support, in that case you let the hardware deal with things. + *	beacon that must be handled in software. The alternative is if you + *	have VEOL support, in that case you let the hardware deal with things.   * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing - * 	beacons from the AP have associated with, we should probably try to - * 	reassociate. When in IBSS mode this might mean we have not received - * 	any beacons from any local stations. Note that every station in an - * 	IBSS schedules to send beacons at the Target Beacon Transmission Time - * 	(TBTT) with a random backoff. + *	beacons from the AP have associated with, we should probably try to + *	reassociate. When in IBSS mode this might mean we have not received + *	any beacons from any local stations. Note that every station in an + *	IBSS schedules to send beacons at the Target Beacon Transmission Time + *	(TBTT) with a random backoff.   * @AR5K_INT_BNR: Beacon Not Ready interrupt - ??   * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now - * 	until properly handled + *	until properly handled   * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA - * 	errors. These types of errors we can enable seem to be of type - * 	AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR. + *	errors. These types of errors we can enable seem to be of type + *	AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.   * @AR5K_INT_GLOBAL: Used to clear and set the IER   * @AR5K_INT_NOCARD: signals the card has been removed - * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same - * 	bit value + * @AR5K_INT_COMMON: common interrupts shared among MACs with the same + *	bit value   *   * These are mapped to take advantage of some common bits   * between the MACs, to be able to set intr properties   * easier. Some of them are not used yet inside hw.c. Most map - * to the respective hw interrupt value as they are common amogst different + * to the respective hw interrupt value as they are common among different   * MACs.   */  enum ath5k_int { @@ -967,9 +970,9 @@ enum ath5k_capability_type {  	AR5K_CAP_MCAST_KEYSRCH		= 14,	/* Supports multicast key search */  	AR5K_CAP_TSF_ADJUST		= 15,	/* Supports beacon tsf adjust */  	AR5K_CAP_XR			= 16,	/* Supports XR mode */ -	AR5K_CAP_WME_TKIPMIC 		= 17,	/* Supports TKIP MIC when using WMM */ -	AR5K_CAP_CHAN_HALFRATE 		= 18,	/* Supports half rate channels */ -	AR5K_CAP_CHAN_QUARTERRATE 	= 19,	/* Supports quarter rate channels */ +	AR5K_CAP_WME_TKIPMIC		= 17,	/* Supports TKIP MIC when using WMM */ +	AR5K_CAP_CHAN_HALFRATE		= 18,	/* Supports half rate channels */ +	AR5K_CAP_CHAN_QUARTERRATE	= 19,	/* Supports quarter rate channels */  	AR5K_CAP_RFSILENT		= 20,	/* Supports RFsilent */  }; @@ -1009,8 +1012,7 @@ struct ath5k_capabilities {  /* size of noise floor history (keep it a power of two) */  #define ATH5K_NF_CAL_HIST_MAX	8 -struct ath5k_nfcal_hist -{ +struct ath5k_nfcal_hist {  	s16 index;				/* current index into nfval */  	s16 nfval[ATH5K_NF_CAL_HIST_MAX];	/* last few noise floors */  }; @@ -1065,6 +1067,8 @@ struct ath5k_hw {  	u8			ah_retry_long;  	u8			ah_retry_short; +	u32			ah_use_32khz_clock; +  	u8			ah_coverage_class;  	bool			ah_ack_bitrate_high;  	u8			ah_bwmode; @@ -1180,8 +1184,8 @@ void ath5k_sysfs_unregister(struct ath5k_softc *sc);  struct ath5k_buf;  struct ath5k_txq; -void set_beacon_filter(struct ieee80211_hw *hw, bool enable); -bool ath_any_vif_assoc(struct ath5k_softc *sc); +void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable); +bool ath5k_any_vif_assoc(struct ath5k_softc *sc);  void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,  		    struct ath5k_txq *txq);  int ath5k_init_hw(struct ath5k_softc *sc); @@ -1253,7 +1257,7 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,  		int len, struct ieee80211_rate *rate, bool shortpre);  unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);  unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); -extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); +int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);  void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);  /* RX filter control*/  int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); @@ -1356,17 +1360,17 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,  				u8 mode, bool fast);  /* - * Functions used internaly + * Functions used internally   */  static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah)  { -        return &ah->common; +	return &ah->common;  }  static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)  { -        return &(ath5k_hw_common(ah)->regulatory); +	return &(ath5k_hw_common(ah)->regulatory);  }  #ifdef CONFIG_ATHEROS_AR231X @@ -1377,7 +1381,7 @@ static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)  	/* On AR2315 and AR2317 the PCI clock domain registers  	 * are outside of the WMAC register space */  	if (unlikely((reg >= 0x4000) && (reg < 0x5000) && -		(ah->ah_mac_srev >= AR5K_SREV_AR2315_R6))) +	    (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))  		return AR5K_AR2315_PCI_BASE + reg;  	return ah->ah_iobase + reg; diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 1588401de3c..14dc52e4b50 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -104,6 +104,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah)   */  int ath5k_hw_init(struct ath5k_softc *sc)  { +	static const u8 zero_mac[ETH_ALEN] = { };  	struct ath5k_hw *ah = sc->ah;  	struct ath_common *common = ath5k_hw_common(ah);  	struct pci_dev *pdev = sc->pdev; @@ -191,7 +192,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)  		break;  	case AR5K_SREV_RAD_5424:  		if (ah->ah_mac_version == AR5K_SREV_AR2425 || -		ah->ah_mac_version == AR5K_SREV_AR2417){ +		    ah->ah_mac_version == AR5K_SREV_AR2417) {  			ah->ah_radio = AR5K_RF2425;  			ah->ah_single_chip = true;  		} else { @@ -210,28 +211,28 @@ int ath5k_hw_init(struct ath5k_softc *sc)  			ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,  								CHANNEL_2GHZ);  		} else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) || -		ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) || -		ah->ah_phy_revision == AR5K_SREV_PHY_2425) { +			   ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) || +			   ah->ah_phy_revision == AR5K_SREV_PHY_2425) {  			ah->ah_radio = AR5K_RF2425;  			ah->ah_single_chip = true;  			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;  		} else if (srev == AR5K_SREV_AR5213A && -		ah->ah_phy_revision == AR5K_SREV_PHY_5212B) { +			   ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {  			ah->ah_radio = AR5K_RF5112;  			ah->ah_single_chip = false;  			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;  		} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4) || -			ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) { +			   ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) {  			ah->ah_radio = AR5K_RF2316;  			ah->ah_single_chip = true;  			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;  		} else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) || -		ah->ah_phy_revision == AR5K_SREV_PHY_5413) { +			   ah->ah_phy_revision == AR5K_SREV_PHY_5413) {  			ah->ah_radio = AR5K_RF5413;  			ah->ah_single_chip = true;  			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;  		} else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) || -		ah->ah_phy_revision == AR5K_SREV_PHY_2413) { +			   ah->ah_phy_revision == AR5K_SREV_PHY_2413) {  			ah->ah_radio = AR5K_RF2413;  			ah->ah_single_chip = true;  			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413; @@ -243,9 +244,8 @@ int ath5k_hw_init(struct ath5k_softc *sc)  	} -	/* Return on unsuported chips (unsupported eeprom etc) */ -	if ((srev >= AR5K_SREV_AR5416) && -	(srev < AR5K_SREV_AR2425)) { +	/* Return on unsupported chips (unsupported eeprom etc) */ +	if ((srev >= AR5K_SREV_AR5416) && (srev < AR5K_SREV_AR2425)) {  		ATH5K_ERR(sc, "Device not yet supported.\n");  		ret = -ENODEV;  		goto err; @@ -285,7 +285,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)  		ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);  		ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES); -		/* If serdes programing is enabled, increase PCI-E +		/* If serdes programming is enabled, increase PCI-E  		 * tx power for systems with long trace from host  		 * to minicard connector. */  		if (ee->ee_serdes) @@ -334,7 +334,7 @@ int ath5k_hw_init(struct ath5k_softc *sc)  	}  	/* MAC address is cleared until add_interface */ -	ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); +	ath5k_hw_set_lladdr(ah, zero_mac);  	/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */  	memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index b6c5d3715b9..dce848f76d7 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -42,6 +42,7 @@  #include <linux/module.h>  #include <linux/delay.h> +#include <linux/dma-mapping.h>  #include <linux/hardirq.h>  #include <linux/if.h>  #include <linux/io.h> @@ -87,8 +88,6 @@ MODULE_LICENSE("Dual BSD/GPL");  static int ath5k_init(struct ieee80211_hw *hw);  static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,  								bool skip_pcu); -int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif); -void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);  /* Known SREVs */  static const struct ath5k_srev_name srev_names[] = { @@ -533,7 +532,7 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,  	if (iter_data.n_stas > 1) {  		/* If you have multiple STA interfaces connected to  		 * different APs, ARPs are not received (most of the time?) -		 * Enabling PROMISC appears to fix that probem. +		 * Enabling PROMISC appears to fix that problem.  		 */  		sc->filter_flags |= AR5K_RX_FILTER_PROM;  	} @@ -816,8 +815,7 @@ ath5k_desc_alloc(struct ath5k_softc *sc)  	INIT_LIST_HEAD(&sc->txbuf);  	sc->txbuf_len = ATH_TXBUF; -	for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, -			da += sizeof(*ds)) { +	for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, da += sizeof(*ds)) {  		bf->desc = ds;  		bf->daddr = da;  		list_add_tail(&bf->list, &sc->txbuf); @@ -983,7 +981,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc)  		goto err;  	if (sc->opmode == NL80211_IFTYPE_AP || -		sc->opmode == NL80211_IFTYPE_MESH_POINT) { +	    sc->opmode == NL80211_IFTYPE_MESH_POINT) {  		/*  		 * Always burst out beacon and CAB traffic  		 * (aifs = cwmin = cwmax = 0) @@ -1263,16 +1261,15 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi)   */  static int ath5k_common_padpos(struct sk_buff *skb)  { -	struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;  	__le16 frame_control = hdr->frame_control;  	int padpos = 24; -	if (ieee80211_has_a4(frame_control)) { +	if (ieee80211_has_a4(frame_control))  		padpos += ETH_ALEN; -	} -	if (ieee80211_is_data_qos(frame_control)) { + +	if (ieee80211_is_data_qos(frame_control))  		padpos += IEEE80211_QOS_CTL_LEN; -	}  	return padpos;  } @@ -1286,13 +1283,13 @@ static int ath5k_add_padding(struct sk_buff *skb)  	int padpos = ath5k_common_padpos(skb);  	int padsize = padpos & 3; -	if (padsize && skb->len>padpos) { +	if (padsize && skb->len > padpos) {  		if (skb_headroom(skb) < padsize)  			return -1;  		skb_push(skb, padsize); -		memmove(skb->data, skb->data+padsize, padpos); +		memmove(skb->data, skb->data + padsize, padpos);  		return padsize;  	} @@ -1317,7 +1314,7 @@ static int ath5k_remove_padding(struct sk_buff *skb)  	int padpos = ath5k_common_padpos(skb);  	int padsize = padpos & 3; -	if (padsize && skb->len>=padpos+padsize) { +	if (padsize && skb->len >= padpos + padsize) {  		memmove(skb->data + padsize, skb->data, padpos);  		skb_pull(skb, padsize);  		return padsize; @@ -1353,7 +1350,7 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,  	 * timestamp (beginning of phy frame, data frame, end of rx?).  	 * The only thing we know is that it is hardware specific...  	 * On AR5213 it seems the rx timestamp is at the end of the -	 * frame, but i'm not sure. +	 * frame, but I'm not sure.  	 *  	 * NOTE: mac80211 defines mactime at the beginning of the first  	 * data symbol. Since we don't have any time references it's @@ -1451,10 +1448,11 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)  static void  ath5k_set_current_imask(struct ath5k_softc *sc)  { -	enum ath5k_int imask = sc->imask; +	enum ath5k_int imask;  	unsigned long flags;  	spin_lock_irqsave(&sc->irqlock, flags); +	imask = sc->imask;  	if (sc->rx_pending)  		imask &= ~AR5K_INT_RX_ALL;  	if (sc->tx_pending) @@ -1557,7 +1555,8 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,  		goto drop_packet;  	} -	if (txq->txq_len >= txq->txq_max) +	if (txq->txq_len >= txq->txq_max && +	    txq->qnum <= AR5K_TX_QUEUE_ID_DATA_MAX)  		ieee80211_stop_queue(hw, txq->qnum);  	spin_lock_irqsave(&sc->txbuflock, flags); @@ -1712,7 +1711,7 @@ ath5k_tasklet_tx(unsigned long data)  	int i;  	struct ath5k_softc *sc = (void *)data; -	for (i=0; i < AR5K_NUM_TX_QUEUES; i++) +	for (i = 0; i < AR5K_NUM_TX_QUEUES; i++)  		if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))  			ath5k_tx_processq(sc, &sc->txqs[i]); @@ -1767,7 +1766,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)  	 * 4 beacons to make sure everybody hears our AP.  	 * When a client tries to associate, hw will keep  	 * track of the tx antenna to be used for this client -	 * automaticaly, based on ACKed packets. +	 * automatically, based on ACKed packets.  	 *  	 * Note: AP still listens and transmits RTS on the  	 * default antenna which is supposed to be an omni. @@ -1903,7 +1902,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)  	avf = (void *)vif->drv_priv;  	bf = avf->bbuf;  	if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || -			sc->opmode == NL80211_IFTYPE_MONITOR)) { +		     sc->opmode == NL80211_IFTYPE_MONITOR)) {  		ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);  		return;  	} @@ -1920,7 +1919,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)  	/* refresh the beacon for AP or MESH mode */  	if (sc->opmode == NL80211_IFTYPE_AP || -			sc->opmode == NL80211_IFTYPE_MESH_POINT) +	    sc->opmode == NL80211_IFTYPE_MESH_POINT)  		ath5k_beacon_update(sc->hw, vif);  	trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]); @@ -1933,6 +1932,10 @@ ath5k_beacon_send(struct ath5k_softc *sc)  	skb = ieee80211_get_buffered_bc(sc->hw, vif);  	while (skb) {  		ath5k_tx_queue(sc->hw, skb, sc->cabq); + +		if (sc->cabq->txq_len >= sc->cabq->txq_max) +			break; +  		skb = ieee80211_get_buffered_bc(sc->hw, vif);  	} @@ -1979,7 +1982,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)  	hw_tsf = ath5k_hw_get_tsf64(ah);  	hw_tu = TSF_TO_TU(hw_tsf); -#define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3 +#define FUDGE (AR5K_TUNE_SW_BEACON_RESP + 3)  	/* We use FUDGE to make sure the next TBTT is ahead of the current TU.  	 * Since we later subtract AR5K_TUNE_SW_BEACON_RESP (10) in the timer  	 * configuration we need to make sure it is bigger than that. */ @@ -2102,11 +2105,11 @@ static void ath5k_tasklet_beacon(unsigned long data)  	 *  	 * In IBSS mode we use this interrupt just to  	 * keep track of the next TBTT (target beacon -	 * transmission time) in order to detect wether +	 * transmission time) in order to detect whether  	 * automatic TSF updates happened.  	 */  	if (sc->opmode == NL80211_IFTYPE_ADHOC) { -		/* XXX: only if VEOL suppported */ +		/* XXX: only if VEOL supported */  		u64 tsf = ath5k_hw_get_tsf64(sc->ah);  		sc->nexttbtt += sc->bintval;  		ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, @@ -2161,7 +2164,7 @@ ath5k_schedule_tx(struct ath5k_softc *sc)  	tasklet_schedule(&sc->txtq);  } -irqreturn_t +static irqreturn_t  ath5k_intr(int irq, void *dev_id)  {  	struct ath5k_softc *sc = dev_id; @@ -2201,13 +2204,12 @@ ath5k_intr(int irq, void *dev_id)  				ATH5K_DBG(sc, ATH5K_DEBUG_RESET,  					  "rx overrun, resetting\n");  				ieee80211_queue_work(sc->hw, &sc->reset_work); -			} -			else +			} else  				ath5k_schedule_rx(sc);  		} else { -			if (status & AR5K_INT_SWBA) { +			if (status & AR5K_INT_SWBA)  				tasklet_hi_schedule(&sc->beacontq); -			} +  			if (status & AR5K_INT_RXEOL) {  				/*  				* NB: the hardware should re-read the link when @@ -2359,7 +2361,7 @@ ath5k_tx_complete_poll_work(struct work_struct *work)  * Initialization routines *  \*************************/ -int +int __devinit  ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)  {  	struct ieee80211_hw *hw = sc->hw; @@ -2424,6 +2426,7 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)  	common->ah = sc->ah;  	common->hw = hw;  	common->priv = sc; +	common->clockrate = 40;  	/*  	 * Cache line size is used to size and align various @@ -2470,7 +2473,7 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)  						sc->ah->ah_radio_5ghz_revision),  						sc->ah->ah_radio_5ghz_revision);  			/* No 2GHz support (5110 and some -			 * 5Ghz only cards) -> report 5Ghz radio */ +			 * 5GHz only cards) -> report 5GHz radio */  			} else if (!test_bit(AR5K_MODE_11B,  				sc->ah->ah_capabilities.cap_mode)) {  				ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", @@ -2489,7 +2492,7 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)  		/* Multi chip radio (RF5111 - RF2111) ->  		 * report both 2GHz/5GHz radios */  		else if (sc->ah->ah_radio_5ghz_revision && -				sc->ah->ah_radio_2ghz_revision){ +				sc->ah->ah_radio_2ghz_revision) {  			ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",  				ath5k_chip_name(AR5K_VERSION_RAD,  					sc->ah->ah_radio_5ghz_revision), @@ -2615,7 +2618,7 @@ done:  	return ret;  } -static void stop_tasklets(struct ath5k_softc *sc) +static void ath5k_stop_tasklets(struct ath5k_softc *sc)  {  	sc->rx_pending = false;  	sc->tx_pending = false; @@ -2669,7 +2672,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)  	mmiowb();  	mutex_unlock(&sc->lock); -	stop_tasklets(sc); +	ath5k_stop_tasklets(sc);  	cancel_delayed_work_sync(&sc->tx_complete_work); @@ -2697,7 +2700,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,  	ath5k_hw_set_imr(ah, 0);  	synchronize_irq(sc->irq); -	stop_tasklets(sc); +	ath5k_stop_tasklets(sc);  	/* Save ani mode and disable ANI during  	 * reset. If we don't we might get false @@ -2714,8 +2717,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,  	fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; -	ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, -								skip_pcu); +	ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, skip_pcu);  	if (ret) {  		ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);  		goto err; @@ -2729,7 +2731,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,  	ath5k_ani_init(ah, ani_mode); -	ah->ah_cal_next_full = jiffies; +	ah->ah_cal_next_full = jiffies + msecs_to_jiffies(100);  	ah->ah_cal_next_ani = jiffies;  	ah->ah_cal_next_nf = jiffies;  	ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8); @@ -2773,7 +2775,7 @@ static void ath5k_reset_work(struct work_struct *work)  	mutex_unlock(&sc->lock);  } -static int +static int __devinit  ath5k_init(struct ieee80211_hw *hw)  { @@ -2801,7 +2803,7 @@ ath5k_init(struct ieee80211_hw *hw)  	/*  	 * Collect the channel list.  The 802.11 layer -	 * is resposible for filtering this list based +	 * is responsible for filtering this list based  	 * on settings like the phy mode and regulatory  	 * domain restrictions.  	 */ @@ -2962,11 +2964,12 @@ ath5k_deinit_softc(struct ath5k_softc *sc)  	 * state and potentially want to use them.  	 */  	ath5k_hw_deinit(sc->ah); +	kfree(sc->ah);  	free_irq(sc->irq, sc);  }  bool -ath_any_vif_assoc(struct ath5k_softc *sc) +ath5k_any_vif_assoc(struct ath5k_softc *sc)  {  	struct ath5k_vif_iter_data iter_data;  	iter_data.hw_macaddr = NULL; @@ -2980,7 +2983,7 @@ ath_any_vif_assoc(struct ath5k_softc *sc)  }  void -set_beacon_filter(struct ieee80211_hw *hw, bool enable) +ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable)  {  	struct ath5k_softc *sc = hw->priv;  	struct ath5k_hw *ah = sc->ah; diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index b294f330501..0a98777b937 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h @@ -96,8 +96,7 @@ struct ath5k_txq {  /*   * State for LED triggers   */ -struct ath5k_led -{ +struct ath5k_led {  	char name[ATH5K_LED_MAX_NAME_LEN + 1];	/* name of the LED in sysfs */  	struct ath5k_softc *sc;			/* driver state */  	struct led_classdev led_dev;		/* led classdev */ @@ -122,7 +121,7 @@ struct ath5k_statistics {  	/* frame errors */  	unsigned int rx_all_count;	/* all RX frames, including errors */  	unsigned int tx_all_count;	/* all TX frames, including errors */ -	unsigned int rx_bytes_count;	/* all RX bytes, including errored pks +	unsigned int rx_bytes_count;	/* all RX bytes, including errored pkts  					 * and the MAC headers for each packet  					 */  	unsigned int tx_bytes_count;	/* all TX bytes, including errored pkts @@ -154,9 +153,9 @@ struct ath5k_statistics {  };  #if CHAN_DEBUG -#define ATH_CHAN_MAX	(26+26+26+200+200) +#define ATH_CHAN_MAX	(26 + 26 + 26 + 200 + 200)  #else -#define ATH_CHAN_MAX	(14+14+14+252+20) +#define ATH_CHAN_MAX	(14 + 14 + 14 + 252 + 20)  #endif  struct ath5k_vif { @@ -251,7 +250,7 @@ struct ath5k_softc {  	unsigned int		nexttbtt;	/* next beacon time in TU */  	struct ath5k_txq	*cabq;		/* content after beacon */ -	int 			power_level;	/* Requested tx power in dbm */ +	int			power_level;	/* Requested tx power in dBm */  	bool			assoc;		/* associate state */  	bool			enable_beacon;	/* true if beacons are on */ diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index 7dd88e1c3ff..c752982aec0 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c @@ -52,8 +52,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)  		__set_bit(AR5K_MODE_11A, caps->cap_mode);  	} else {  		/* -		 * XXX The tranceiver supports frequencies from 4920 to 6100GHz -		 * XXX and from 2312 to 2732GHz. There are problems with the +		 * XXX The transceiver supports frequencies from 4920 to 6100MHz +		 * XXX and from 2312 to 2732MHz. There are problems with the  		 * XXX current ieee80211 implementation because the IEEE  		 * XXX channel mapping does not support negative channel  		 * XXX numbers (2312MHz is channel -19). Of course, this diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 0bf7313b8a1..4edca7072d5 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -205,35 +205,35 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf,  	u64 tsf;  	v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",  		"AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,  		(v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S); -	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n", +	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n",  		"AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP)); -	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n", +	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\n\n",  		"AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT));  	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0); -	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", +	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",  		"AR5K_TIMER0 (TBTT)", v, v);  	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1); -	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", +	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",  		"AR5K_TIMER1 (DMA)", v, v >> 3);  	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2); -	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", +	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",  		"AR5K_TIMER2 (SWBA)", v, v >> 3);  	v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3); -	len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", +	len += snprintf(buf + len, sizeof(buf) - len, "%-24s0x%08x\tTU: %08x\n",  		"AR5K_TIMER3 (ATIM)", v, v);  	tsf = ath5k_hw_get_tsf64(sc->ah); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"TSF\t\t0x%016llx\tTU: %08x\n",  		(unsigned long long)tsf, TSF_TO_TU(tsf)); @@ -323,16 +323,16 @@ static ssize_t read_file_debug(struct file *file, char __user *user_buf,  	unsigned int len = 0;  	unsigned int i; -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"DEBUG LEVEL: 0x%08x\n\n", sc->debug.level);  	for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) { -		len += snprintf(buf+len, sizeof(buf)-len, +		len += snprintf(buf + len, sizeof(buf) - len,  			"%10s %c 0x%08x - %s\n", dbg_info[i].name,  			sc->debug.level & dbg_info[i].level ? '+' : ' ',  			dbg_info[i].level, dbg_info[i].desc);  	} -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"%10s %c 0x%08x - %s\n", dbg_info[i].name,  		sc->debug.level == dbg_info[i].level ? '+' : ' ',  		dbg_info[i].level, dbg_info[i].desc); @@ -384,60 +384,60 @@ static ssize_t read_file_antenna(struct file *file, char __user *user_buf,  	unsigned int i;  	unsigned int v; -	len += snprintf(buf+len, sizeof(buf)-len, "antenna mode\t%d\n", +	len += snprintf(buf + len, sizeof(buf) - len, "antenna mode\t%d\n",  		sc->ah->ah_ant_mode); -	len += snprintf(buf+len, sizeof(buf)-len, "default antenna\t%d\n", +	len += snprintf(buf + len, sizeof(buf) - len, "default antenna\t%d\n",  		sc->ah->ah_def_ant); -	len += snprintf(buf+len, sizeof(buf)-len, "tx antenna\t%d\n", +	len += snprintf(buf + len, sizeof(buf) - len, "tx antenna\t%d\n",  		sc->ah->ah_tx_ant); -	len += snprintf(buf+len, sizeof(buf)-len, "\nANTENNA\t\tRX\tTX\n"); +	len += snprintf(buf + len, sizeof(buf) - len, "\nANTENNA\t\tRX\tTX\n");  	for (i = 1; i < ARRAY_SIZE(sc->stats.antenna_rx); i++) { -		len += snprintf(buf+len, sizeof(buf)-len, +		len += snprintf(buf + len, sizeof(buf) - len,  			"[antenna %d]\t%d\t%d\n",  			i, sc->stats.antenna_rx[i], sc->stats.antenna_tx[i]);  	} -	len += snprintf(buf+len, sizeof(buf)-len, "[invalid]\t%d\t%d\n", +	len += snprintf(buf + len, sizeof(buf) - len, "[invalid]\t%d\t%d\n",  			sc->stats.antenna_rx[0], sc->stats.antenna_tx[0]);  	v = ath5k_hw_reg_read(sc->ah, AR5K_DEFAULT_ANTENNA); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"\nAR5K_DEFAULT_ANTENNA\t0x%08x\n", v);  	v = ath5k_hw_reg_read(sc->ah, AR5K_STA_ID1); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"AR5K_STA_ID1_DEFAULT_ANTENNA\t%d\n",  		(v & AR5K_STA_ID1_DEFAULT_ANTENNA) != 0); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"AR5K_STA_ID1_DESC_ANTENNA\t%d\n",  		(v & AR5K_STA_ID1_DESC_ANTENNA) != 0); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"AR5K_STA_ID1_RTS_DEF_ANTENNA\t%d\n",  		(v & AR5K_STA_ID1_RTS_DEF_ANTENNA) != 0); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"AR5K_STA_ID1_SELFGEN_DEF_ANT\t%d\n",  		(v & AR5K_STA_ID1_SELFGEN_DEF_ANT) != 0);  	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_AGCCTL); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"\nAR5K_PHY_AGCCTL_OFDM_DIV_DIS\t%d\n",  		(v & AR5K_PHY_AGCCTL_OFDM_DIV_DIS) != 0);  	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_RESTART); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"AR5K_PHY_RESTART_DIV_GC\t\t%x\n",  		(v & AR5K_PHY_RESTART_DIV_GC) >> AR5K_PHY_RESTART_DIV_GC_S);  	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_FAST_ANT_DIV); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"AR5K_PHY_FAST_ANT_DIV_EN\t%d\n",  		(v & AR5K_PHY_FAST_ANT_DIV_EN) != 0);  	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_0); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"\nAR5K_PHY_ANT_SWITCH_TABLE_0\t0x%08x\n", v);  	v = ath5k_hw_reg_read(sc->ah, AR5K_PHY_ANT_SWITCH_TABLE_1); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"AR5K_PHY_ANT_SWITCH_TABLE_1\t0x%08x\n", v);  	if (len > sizeof(buf)) @@ -494,36 +494,36 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,  	unsigned int len = 0;  	u32 filt = ath5k_hw_get_rx_filter(sc->ah); -	len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n", +	len += snprintf(buf + len, sizeof(buf) - len, "bssid-mask: %pM\n",  			sc->bssidmask); -	len += snprintf(buf+len, sizeof(buf)-len, "filter-flags: 0x%x ", +	len += snprintf(buf + len, sizeof(buf) - len, "filter-flags: 0x%x ",  			filt);  	if (filt & AR5K_RX_FILTER_UCAST) -		len += snprintf(buf+len, sizeof(buf)-len, " UCAST"); +		len += snprintf(buf + len, sizeof(buf) - len, " UCAST");  	if (filt & AR5K_RX_FILTER_MCAST) -		len += snprintf(buf+len, sizeof(buf)-len, " MCAST"); +		len += snprintf(buf + len, sizeof(buf) - len, " MCAST");  	if (filt & AR5K_RX_FILTER_BCAST) -		len += snprintf(buf+len, sizeof(buf)-len, " BCAST"); +		len += snprintf(buf + len, sizeof(buf) - len, " BCAST");  	if (filt & AR5K_RX_FILTER_CONTROL) -		len += snprintf(buf+len, sizeof(buf)-len, " CONTROL"); +		len += snprintf(buf + len, sizeof(buf) - len, " CONTROL");  	if (filt & AR5K_RX_FILTER_BEACON) -		len += snprintf(buf+len, sizeof(buf)-len, " BEACON"); +		len += snprintf(buf + len, sizeof(buf) - len, " BEACON");  	if (filt & AR5K_RX_FILTER_PROM) -		len += snprintf(buf+len, sizeof(buf)-len, " PROM"); +		len += snprintf(buf + len, sizeof(buf) - len, " PROM");  	if (filt & AR5K_RX_FILTER_XRPOLL) -		len += snprintf(buf+len, sizeof(buf)-len, " XRPOLL"); +		len += snprintf(buf + len, sizeof(buf) - len, " XRPOLL");  	if (filt & AR5K_RX_FILTER_PROBEREQ) -		len += snprintf(buf+len, sizeof(buf)-len, " PROBEREQ"); +		len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ");  	if (filt & AR5K_RX_FILTER_PHYERR_5212) -		len += snprintf(buf+len, sizeof(buf)-len, " PHYERR-5212"); +		len += snprintf(buf + len, sizeof(buf) - len, " PHYERR-5212");  	if (filt & AR5K_RX_FILTER_RADARERR_5212) -		len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5212"); +		len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5212");  	if (filt & AR5K_RX_FILTER_PHYERR_5211) -		snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211"); +		snprintf(buf + len, sizeof(buf) - len, " PHYERR-5211");  	if (filt & AR5K_RX_FILTER_RADARERR_5211) -		len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211"); +		len += snprintf(buf + len, sizeof(buf) - len, " RADARERR-5211"); -	len += snprintf(buf+len, sizeof(buf)-len, "\nopmode: %s (%d)\n", +	len += snprintf(buf + len, sizeof(buf) - len, "\nopmode: %s (%d)\n",  			ath_opmode_to_string(sc->opmode), sc->opmode);  	if (len > sizeof(buf)) @@ -550,65 +550,65 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,  	unsigned int len = 0;  	int i; -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"RX\n---------------------\n"); -	len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n", +	len += snprintf(buf + len, sizeof(buf) - len, "CRC\t%u\t(%u%%)\n",  			st->rxerr_crc,  			st->rx_all_count > 0 ? -				st->rxerr_crc*100/st->rx_all_count : 0); -	len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n", +				st->rxerr_crc * 100 / st->rx_all_count : 0); +	len += snprintf(buf + len, sizeof(buf) - len, "PHY\t%u\t(%u%%)\n",  			st->rxerr_phy,  			st->rx_all_count > 0 ? -				st->rxerr_phy*100/st->rx_all_count : 0); +				st->rxerr_phy * 100 / st->rx_all_count : 0);  	for (i = 0; i < 32; i++) {  		if (st->rxerr_phy_code[i]) -			len += snprintf(buf+len, sizeof(buf)-len, +			len += snprintf(buf + len, sizeof(buf) - len,  				" phy_err[%u]\t%u\n",  				i, st->rxerr_phy_code[i]);  	} -	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n", +	len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",  			st->rxerr_fifo,  			st->rx_all_count > 0 ? -				st->rxerr_fifo*100/st->rx_all_count : 0); -	len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n", +				st->rxerr_fifo * 100 / st->rx_all_count : 0); +	len += snprintf(buf + len, sizeof(buf) - len, "decrypt\t%u\t(%u%%)\n",  			st->rxerr_decrypt,  			st->rx_all_count > 0 ? -				st->rxerr_decrypt*100/st->rx_all_count : 0); -	len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n", +				st->rxerr_decrypt * 100 / st->rx_all_count : 0); +	len += snprintf(buf + len, sizeof(buf) - len, "MIC\t%u\t(%u%%)\n",  			st->rxerr_mic,  			st->rx_all_count > 0 ? -				st->rxerr_mic*100/st->rx_all_count : 0); -	len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n", +				st->rxerr_mic * 100 / st->rx_all_count : 0); +	len += snprintf(buf + len, sizeof(buf) - len, "process\t%u\t(%u%%)\n",  			st->rxerr_proc,  			st->rx_all_count > 0 ? -				st->rxerr_proc*100/st->rx_all_count : 0); -	len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n", +				st->rxerr_proc * 100 / st->rx_all_count : 0); +	len += snprintf(buf + len, sizeof(buf) - len, "jumbo\t%u\t(%u%%)\n",  			st->rxerr_jumbo,  			st->rx_all_count > 0 ? -				st->rxerr_jumbo*100/st->rx_all_count : 0); -	len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n", +				st->rxerr_jumbo * 100 / st->rx_all_count : 0); +	len += snprintf(buf + len, sizeof(buf) - len, "[RX all\t%u]\n",  			st->rx_all_count); -	len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n", +	len += snprintf(buf + len, sizeof(buf) - len, "RX-all-bytes\t%u\n",  			st->rx_bytes_count); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"\nTX\n---------------------\n"); -	len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n", +	len += snprintf(buf + len, sizeof(buf) - len, "retry\t%u\t(%u%%)\n",  			st->txerr_retry,  			st->tx_all_count > 0 ? -				st->txerr_retry*100/st->tx_all_count : 0); -	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n", +				st->txerr_retry * 100 / st->tx_all_count : 0); +	len += snprintf(buf + len, sizeof(buf) - len, "FIFO\t%u\t(%u%%)\n",  			st->txerr_fifo,  			st->tx_all_count > 0 ? -				st->txerr_fifo*100/st->tx_all_count : 0); -	len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n", +				st->txerr_fifo * 100 / st->tx_all_count : 0); +	len += snprintf(buf + len, sizeof(buf) - len, "filter\t%u\t(%u%%)\n",  			st->txerr_filt,  			st->tx_all_count > 0 ? -				st->txerr_filt*100/st->tx_all_count : 0); -	len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n", +				st->txerr_filt * 100 / st->tx_all_count : 0); +	len += snprintf(buf + len, sizeof(buf) - len, "[TX all\t%u]\n",  			st->tx_all_count); -	len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n", +	len += snprintf(buf + len, sizeof(buf) - len, "TX-all-bytes\t%u\n",  			st->tx_bytes_count);  	if (len > sizeof(buf)) @@ -667,89 +667,93 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf,  	char buf[700];  	unsigned int len = 0; -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"HW has PHY error counters:\t%s\n",  			sc->ah->ah_capabilities.cap_has_phyerr_counters ?  			"yes" : "no"); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"HW max spur immunity level:\t%d\n",  			as->max_spur_level); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  		"\nANI state\n--------------------------------------------\n"); -	len += snprintf(buf+len, sizeof(buf)-len, "operating mode:\t\t\t"); +	len += snprintf(buf + len, sizeof(buf) - len, "operating mode:\t\t\t");  	switch (as->ani_mode) {  	case ATH5K_ANI_MODE_OFF: -		len += snprintf(buf+len, sizeof(buf)-len, "OFF\n"); +		len += snprintf(buf + len, sizeof(buf) - len, "OFF\n");  		break;  	case ATH5K_ANI_MODE_MANUAL_LOW: -		len += snprintf(buf+len, sizeof(buf)-len, +		len += snprintf(buf + len, sizeof(buf) - len,  			"MANUAL LOW\n");  		break;  	case ATH5K_ANI_MODE_MANUAL_HIGH: -		len += snprintf(buf+len, sizeof(buf)-len, +		len += snprintf(buf + len, sizeof(buf) - len,  			"MANUAL HIGH\n");  		break;  	case ATH5K_ANI_MODE_AUTO: -		len += snprintf(buf+len, sizeof(buf)-len, "AUTO\n"); +		len += snprintf(buf + len, sizeof(buf) - len, "AUTO\n");  		break;  	default: -		len += snprintf(buf+len, sizeof(buf)-len, +		len += snprintf(buf + len, sizeof(buf) - len,  			"??? (not good)\n");  		break;  	} -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"noise immunity level:\t\t%d\n",  			as->noise_imm_level); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"spur immunity level:\t\t%d\n",  			as->spur_level); -	len += snprintf(buf+len, sizeof(buf)-len, "firstep level:\t\t\t%d\n", +	len += snprintf(buf + len, sizeof(buf) - len, +			"firstep level:\t\t\t%d\n",  			as->firstep_level); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"OFDM weak signal detection:\t%s\n",  			as->ofdm_weak_sig ? "on" : "off"); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"CCK weak signal detection:\t%s\n",  			as->cck_weak_sig ? "on" : "off"); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"\nMIB INTERRUPTS:\t\t%u\n",  			st->mib_intr); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"beacon RSSI average:\t%d\n",  			(int)ewma_read(&sc->ah->ah_beacon_rssi_avg));  #define CC_PRINT(_struct, _field) \  	_struct._field, \  	_struct.cycles > 0 ? \ -	_struct._field*100/_struct.cycles : 0 +	_struct._field * 100 / _struct.cycles : 0 -	len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n", +	len += snprintf(buf + len, sizeof(buf) - len, +			"profcnt tx\t\t%u\t(%d%%)\n",  			CC_PRINT(as->last_cc, tx_frame)); -	len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n", +	len += snprintf(buf + len, sizeof(buf) - len, +			"profcnt rx\t\t%u\t(%d%%)\n",  			CC_PRINT(as->last_cc, rx_frame)); -	len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n", +	len += snprintf(buf + len, sizeof(buf) - len, +			"profcnt busy\t\t%u\t(%d%%)\n",  			CC_PRINT(as->last_cc, rx_busy));  #undef CC_PRINT -	len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n", +	len += snprintf(buf + len, sizeof(buf) - len, "profcnt cycles\t\t%u\n",  			as->last_cc.cycles); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"listen time\t\t%d\tlast: %d\n",  			as->listen_time, as->last_listen); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"OFDM errors\t\t%u\tlast: %u\tsum: %u\n",  			as->ofdm_errors, as->last_ofdm_errors,  			as->sum_ofdm_errors); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"CCK errors\t\t%u\tlast: %u\tsum: %u\n",  			as->cck_errors, as->last_cck_errors,  			as->sum_cck_errors); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"AR5K_PHYERR_CNT1\t%x\t(=%d)\n",  			ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1),  			ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX -  			ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1))); -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"AR5K_PHYERR_CNT2\t%x\t(=%d)\n",  			ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2),  			ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - @@ -827,13 +831,13 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,  	struct ath5k_buf *bf, *bf0;  	int i, n; -	len += snprintf(buf+len, sizeof(buf)-len, +	len += snprintf(buf + len, sizeof(buf) - len,  			"available txbuffers: %d\n", sc->txbuf_len);  	for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) {  		txq = &sc->txqs[i]; -		len += snprintf(buf+len, sizeof(buf)-len, +		len += snprintf(buf + len, sizeof(buf) - len,  			"%02d: %ssetup\n", i, txq->setup ? "" : "not ");  		if (!txq->setup) @@ -845,9 +849,9 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf,  			n++;  		spin_unlock_bh(&txq->lock); -		len += snprintf(buf+len, sizeof(buf)-len, +		len += snprintf(buf + len, sizeof(buf) - len,  				"  len: %d bufs: %d\n", txq->txq_len, n); -		len += snprintf(buf+len, sizeof(buf)-len, +		len += snprintf(buf + len, sizeof(buf) - len,  				"  stuck: %d\n", txq->txq_stuck);  	} @@ -894,7 +898,7 @@ ath5k_debug_init_device(struct ath5k_softc *sc)  	phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir);  	if (!phydir) -	    return; +		return;  	debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc,  			    &fops_debug); @@ -918,6 +922,9 @@ ath5k_debug_init_device(struct ath5k_softc *sc)  	debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc,  			    &fops_queue); + +	debugfs_create_bool("32khz_clock", S_IWUSR | S_IRUSR, phydir, +			    &sc->ah->ah_use_32khz_clock);  }  /* functions used in other places */ diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 62172d58572..f82383b3ed3 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c @@ -107,10 +107,13 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,  		case AR5K_PKT_TYPE_BEACON:  		case AR5K_PKT_TYPE_PROBE_RESP:  			frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY; +			break;  		case AR5K_PKT_TYPE_PIFS:  			frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; +			break;  		default:  			frame_type = type; +			break;  		}  		tx_ctl->tx_control_0 |= diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index 2509d0bf037..cfd529b548f 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h @@ -58,11 +58,11 @@ struct ath5k_hw_rx_status {  #define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002 /* reception success */  #define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR		0x00000004 /* CRC error */  #define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210	0x00000008 /* [5210] FIFO overrun */ -#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010 /* decyption CRC failure */ +#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010 /* decryption CRC failure */  #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR		0x000000e0 /* PHY error */  #define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S		5  #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100 /* key index valid */ -#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX		0x00007e00 /* decyption key index */ +#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX		0x00007e00 /* decryption key index */  #define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S		9  #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000 /* 13 bit of TSF */  #define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15 diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 21091c26a9a..b788ecfbdaf 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -25,7 +25,7 @@   *   * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and   * handle queue setup for 5210 chipset (rest are handled on qcu.c). - * Also we setup interrupt mask register (IMR) and read the various iterrupt + * Also we setup interrupt mask register (IMR) and read the various interrupt   * status registers (ISR).   *   * TODO: Handle SISR on 5211+ and introduce a function to return the queue @@ -258,7 +258,7 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)  		/* For 2413+ order PCU to drop packets using  		 * QUIET mechanism */  		if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && -		pending){ +		    pending) {  			/* Set periodicity and duration */  			ath5k_hw_reg_write(ah,  				AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)| @@ -726,7 +726,7 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)  			int_mask |= AR5K_IMR_RXDOPPLER;  		/* Note: Per queue interrupt masks -		 * are set via reset_tx_queue (qcu.c) */ +		 * are set via ath5k_hw_reset_tx_queue() (qcu.c) */  		ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);  		ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2); @@ -783,7 +783,7 @@ void ath5k_hw_dma_init(struct ath5k_hw *ah)  	 * for all PCI-E cards to be safe).  	 *  	 * XXX: need to check 5210 for this -	 * TODO: Check out tx triger level, it's always 64 on dumps but I +	 * TODO: Check out tx trigger level, it's always 64 on dumps but I  	 * guess we can tweak it and see how it goes ;-)  	 */  	if (ah->ah_version != AR5K_AR5210) { diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 1fef84f87c7..d9e605e3700 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -223,14 +223,14 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,  	ah->ah_ant_ctl[mode][AR5K_ANT_CTL] =  	    (ee->ee_ant_control[mode][0] << 4);  	ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_A] = -	     ee->ee_ant_control[mode][1] 	| -	    (ee->ee_ant_control[mode][2] << 6) 	| +	     ee->ee_ant_control[mode][1]	| +	    (ee->ee_ant_control[mode][2] << 6)	|  	    (ee->ee_ant_control[mode][3] << 12) |  	    (ee->ee_ant_control[mode][4] << 18) |  	    (ee->ee_ant_control[mode][5] << 24);  	ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_B] = -	     ee->ee_ant_control[mode][6] 	| -	    (ee->ee_ant_control[mode][7] << 6) 	| +	     ee->ee_ant_control[mode][6]	| +	    (ee->ee_ant_control[mode][7] << 6)	|  	    (ee->ee_ant_control[mode][8] << 12) |  	    (ee->ee_ant_control[mode][9] << 18) |  	    (ee->ee_ant_control[mode][10] << 24); @@ -255,7 +255,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,  	ee->ee_n_piers[mode] = 0;  	AR5K_EEPROM_READ(o++, val);  	ee->ee_adc_desired_size[mode]	= (s8)((val >> 8) & 0xff); -	switch(mode) { +	switch (mode) {  	case AR5K_EEPROM_MODE_11A:  		ee->ee_ob[mode][3]	= (val >> 5) & 0x7;  		ee->ee_db[mode][3]	= (val >> 2) & 0x7; @@ -349,7 +349,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,  	/* Note: >= v5 have bg freq piers on another location  	 * so these freq piers are ignored for >= v5 (should be 0xff  	 * anyway) */ -	switch(mode) { +	switch (mode) {  	case AR5K_EEPROM_MODE_11A:  		if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)  			break; @@ -422,7 +422,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,  	if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)  		goto done; -	switch (mode){ +	switch (mode) {  	case AR5K_EEPROM_MODE_11A:  		ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f; @@ -436,7 +436,7 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,  		ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;  		ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff; -		if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2) +		if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >= 2)  			ee->ee_pd_gain_overlap = (val >> 9) & 0xf;  		break;  	case AR5K_EEPROM_MODE_11G: @@ -516,7 +516,7 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,  	u16 val;  	ee->ee_n_piers[mode] = 0; -	while(i < max) { +	while (i < max) {  		AR5K_EEPROM_READ(o++, val);  		freq1 = val & 0xff; @@ -602,7 +602,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)  	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;  	struct ath5k_chan_pcal_info *pcal; -	switch(mode) { +	switch (mode) {  	case AR5K_EEPROM_MODE_11B:  		pcal = ee->ee_pwr_cal_b;  		break; @@ -634,7 +634,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)  /* Used to match PCDAC steps with power values on RF5111 chips   * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC   * steps that match with the power values we read from eeprom. On - * older eeprom versions (< 3.2) these steps are equaly spaced at + * older eeprom versions (< 3.2) these steps are equally spaced at   * 10% of the pcdac curve -until the curve reaches its maximum-   * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)   * these 11 steps are spaced in a different way. This function returns @@ -644,10 +644,12 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)  static inline void  ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)  { -	static const u16 intercepts3[] = -		{ 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; -	static const u16 intercepts3_2[] = -		{ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; +	static const u16 intercepts3[] = { +		0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 +	}; +	static const u16 intercepts3_2[] = { +		0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 +	};  	const u16 *ip;  	int i; @@ -691,14 +693,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)  		if (!chinfo[pier].pd_curves)  			continue; -		for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { +		for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) {  			struct ath5k_pdgain_info *pd =  					&chinfo[pier].pd_curves[pdg]; -			if (pd != NULL) { -				kfree(pd->pd_step); -				kfree(pd->pd_pwr); -			} +			kfree(pd->pd_step); +			kfree(pd->pd_pwr);  		}  		kfree(chinfo[pier].pd_curves); @@ -764,7 +764,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,  		/* Fill raw dataset  		 * (convert power to 0.25dB units -		 * for RF5112 combatibility) */ +		 * for RF5112 compatibility) */  		for (point = 0; point < pd->pd_points; point++) {  			/* Absolute values */ @@ -798,7 +798,7 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)  	u16 val;  	offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); -	switch(mode) { +	switch (mode) {  	case AR5K_EEPROM_MODE_11A:  		if (!AR5K_EEPROM_HDR_11A(ee->ee_header))  			return 0; @@ -884,7 +884,7 @@ ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)   * Read power calibration for RF5112 chips   *   * For RF5112 we have 4 XPD -eXternal Power Detector- curves - * for each calibrated channel on 0, -6, -12 and -18dbm but we only + * for each calibrated channel on 0, -6, -12 and -18dBm but we only   * use the higher (3) and the lower (0) curves. Each curve has 0.5dB   * power steps on x axis and PCDAC steps on y axis and looks like a   * linear function. To recreate the curve and pass the power values @@ -1165,7 +1165,7 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)  {  	u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4); -	switch(mode) { +	switch (mode) {  	case AR5K_EEPROM_MODE_11G:  		if (AR5K_EEPROM_HDR_11B(ee->ee_header))  			offset += ath5k_pdgains_size_2413(ee, @@ -1241,7 +1241,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,  			/* Fill raw dataset  			 * convert all pwr levels to -			 * quarter dB for RF5112 combatibility */ +			 * quarter dB for RF5112 compatibility */  			pd->pd_step[0] = pcinfo->pddac_i[pdg];  			pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg]; @@ -1622,8 +1622,8 @@ ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)  		offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);  	rep = ee->ee_ctl_pwr; -	for(i = 0; i < ee->ee_ctls; i++) { -		switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) { +	for (i = 0; i < ee->ee_ctls; i++) { +		switch (ee->ee_ctl[i] & AR5K_CTL_MODE_M) {  		case AR5K_CTL_11A:  		case AR5K_CTL_TURBO:  			ctl_mode = AR5K_EEPROM_MODE_11A; diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 6511c27d938..dc2bcfeadeb 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h @@ -50,7 +50,7 @@  #define AR5K_EEPROM_VERSION		AR5K_EEPROM_INFO(1)	/* EEPROM Version */  #define AR5K_EEPROM_VERSION_3_0		0x3000	/* No idea what's going on before this version */ -#define AR5K_EEPROM_VERSION_3_1		0x3001	/* ob/db values for 2Ghz (ar5211_rfregs) */ +#define AR5K_EEPROM_VERSION_3_1		0x3001	/* ob/db values for 2GHz (ar5211_rfregs) */  #define AR5K_EEPROM_VERSION_3_2		0x3002	/* different frequency representation (eeprom_bin2freq) */  #define AR5K_EEPROM_VERSION_3_3		0x3003	/* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */  #define AR5K_EEPROM_VERSION_3_4		0x3004	/* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */ @@ -75,11 +75,11 @@  #define AR5K_EEPROM_HDR_11A(_v)		(((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)  #define AR5K_EEPROM_HDR_11B(_v)		(((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)  #define AR5K_EEPROM_HDR_11G(_v)		(((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) -#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v)	(((_v) >> 3) & 0x1)	/* Disable turbo for 2Ghz */ +#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v)	(((_v) >> 3) & 0x1)	/* Disable turbo for 2GHz */  #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v)	(((_v) >> 4) & 0x7f)	/* Max turbo power for < 2W power consumption */  #define AR5K_EEPROM_HDR_DEVICE(_v)	(((_v) >> 11) & 0x7)	/* Device type (1 Cardbus, 2 PCI, 3 MiniPCI, 4 AP) */  #define AR5K_EEPROM_HDR_RFKILL(_v)	(((_v) >> 14) & 0x1)	/* Device has RFKill support */ -#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v)	(((_v) >> 15) & 0x1)	/* Disable turbo for 5Ghz */ +#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v)	(((_v) >> 15) & 0x1)	/* Disable turbo for 5GHz */  /* Newer EEPROMs are using a different offset */  #define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \ @@ -120,7 +120,7 @@  #define AR5K_EEPROM_FF_DIS(_v)		(((_v) >> 2) & 0x1)	/* disable fast frames */  #define AR5K_EEPROM_BURST_DIS(_v)	(((_v) >> 3) & 0x1)	/* disable bursting */  #define AR5K_EEPROM_MAX_QCU(_v)		(((_v) >> 4) & 0xf)	/* max number of QCUs. defaults to 10 */ -#define AR5K_EEPROM_HEAVY_CLIP_EN(_v)	(((_v) >> 8) & 0x1)	/* enable heayy clipping */ +#define AR5K_EEPROM_HEAVY_CLIP_EN(_v)	(((_v) >> 8) & 0x1)	/* enable heavy clipping */  #define AR5K_EEPROM_KEY_CACHE_SIZE(_v)	(((_v) >> 12) & 0xf)	/* key cache size. defaults to 128 */  #define AR5K_EEPROM_MISC6		AR5K_EEPROM_INFO(10) @@ -223,7 +223,7 @@  #define AR5K_EEPROM_CCK_OFDM_DELTA	15  #define AR5K_EEPROM_N_IQ_CAL		2  /* 5GHz/2GHz */ -enum ath5k_eeprom_freq_bands{ +enum ath5k_eeprom_freq_bands {  	AR5K_EEPROM_BAND_5GHZ = 0,  	AR5K_EEPROM_BAND_2GHZ = 1,  	AR5K_EEPROM_N_FREQ_BANDS, @@ -270,7 +270,7 @@ enum ath5k_ctl_mode {  /* Per channel calibration data, used for power table setup */  struct ath5k_chan_pcal_info_rf5111 { -	/* Power levels in half dbm units +	/* Power levels in half dBm units  	 * for one power curve. */  	u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];  	/* PCDAC table steps diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index e49340d18df..855d1af3e71 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c @@ -113,8 +113,8 @@ static const struct ath5k_ini ar5210_ini[] = {  	{ AR5K_PHY(28),	0x0000000f },  	{ AR5K_PHY(29),	0x00000080 },  	{ AR5K_PHY(30),	0x00000004 }, -	{ AR5K_PHY(31),	0x00000018 }, 	/* 0x987c */ -	{ AR5K_PHY(64),	0x00000000 }, 	/* 0x9900 */ +	{ AR5K_PHY(31),	0x00000018 },	/* 0x987c */ +	{ AR5K_PHY(64),	0x00000000 },	/* 0x9900 */  	{ AR5K_PHY(65),	0x00000000 },  	{ AR5K_PHY(66),	0x00000000 },  	{ AR5K_PHY(67),	0x00800000 }, @@ -549,7 +549,7 @@ static const struct ath5k_ini ar5212_ini_common_start[] = {  	{ AR5K_DIAG_SW_5211,	0x00000000 },  	{ AR5K_ADDAC_TEST,	0x00000000 },  	{ AR5K_DEFAULT_ANTENNA,	0x00000000 }, -	{ AR5K_FRAME_CTL_QOSM, 	0x000fc78f }, +	{ AR5K_FRAME_CTL_QOSM,	0x000fc78f },  	{ AR5K_XRMODE,		0x2a82301a },  	{ AR5K_XRDELAY,		0x05dc01e0 },  	{ AR5K_XRTIMEOUT,	0x1f402710 }, @@ -760,9 +760,9 @@ static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {  static const struct ath5k_ini rf5111_ini_common_end[] = {  	{ AR5K_DCU_FP,		0x00000000 }, -	{ AR5K_PHY_AGC, 	0x00000000 }, -	{ AR5K_PHY_ADC_CTL, 	0x00022ffe }, -	{ 0x983c, 		0x00020100 }, +	{ AR5K_PHY_AGC,		0x00000000 }, +	{ AR5K_PHY_ADC_CTL,	0x00022ffe }, +	{ 0x983c,		0x00020100 },  	{ AR5K_PHY_GAIN_OFFSET,	0x1284613c },  	{ AR5K_PHY_PAPD_PROBE,	0x00004883 },  	{ 0x9940,		0x00000004 }, @@ -1409,7 +1409,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu)  	 * Write initial register settings  	 */ -	/* For AR5212 and combatible */ +	/* For AR5212 and compatible */  	if (ah->ah_version == AR5K_AR5212) {  		/* First set of mode-specific settings */ diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index 576edf2965d..127bfbd3517 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c @@ -43,16 +43,16 @@  #include "ath5k.h"  #include "base.h" -#define ATH_SDEVICE(subv,subd) \ +#define ATH_SDEVICE(subv, subd) \  	.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \  	.subvendor = (subv), .subdevice = (subd) -#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity)) +#define ATH_LED(pin, polarity) .driver_data = (((pin) << 8) | (polarity))  #define ATH_PIN(data) ((data) >> 8)  #define ATH_POLARITY(data) ((data) & 0xff)  /* Devices we match on for LED config info (typically laptops) */ -static const struct pci_device_id ath5k_led_devices[] = { +static DEFINE_PCI_DEVICE_TABLE(ath5k_led_devices) = {  	/* AR5211 */  	{ PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) },  	/* HP Compaq nc6xx, nc4000, nx6000 */ @@ -157,7 +157,7 @@ void ath5k_unregister_leds(struct ath5k_softc *sc)  	ath5k_unregister_led(&sc->tx_led);  } -int ath5k_init_leds(struct ath5k_softc *sc) +int __devinit ath5k_init_leds(struct ath5k_softc *sc)  {  	int ret = 0;  	struct ieee80211_hw *hw = sc->hw; diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 807bd644016..0d5ab3428be 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -46,8 +46,6 @@  #include "base.h"  #include "reg.h" -extern int ath5k_modparam_nohwcrypt; -  /********************\  * Mac80211 functions *  \********************/ @@ -296,10 +294,10 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  		if (bss_conf->assoc)  			sc->assoc = bss_conf->assoc;  		else -			sc->assoc = ath_any_vif_assoc(sc); +			sc->assoc = ath5k_any_vif_assoc(sc);  		if (sc->opmode == NL80211_IFTYPE_STATION) -			set_beacon_filter(hw, sc->assoc); +			ath5k_set_beacon_filter(hw, sc->assoc);  		ath5k_hw_set_ledstate(sc->ah, sc->assoc ?  			AR5K_LED_ASSOC : AR5K_LED_INIT);  		if (bss_conf->assoc) { @@ -350,7 +348,7 @@ ath5k_prepare_multicast(struct ieee80211_hw *hw,  		mfilt[pos / 32] |= (1 << (pos % 32));  		/* XXX: we might be able to just do this instead,  		* but not sure, needs testing, if we do use this we'd -		* neet to inform below to not reset the mcast */ +		* need to inform below not to reset the mcast */  		/* ath5k_hw_set_mcast_filterindex(ah,  		 *      ha->addr[5]); */  	} @@ -473,7 +471,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,  	if (iter_data.n_stas > 1) {  		/* If you have multiple STA interfaces connected to  		 * different APs, ARPs are not received (most of the time?) -		 * Enabling PROMISC appears to fix that probem. +		 * Enabling PROMISC appears to fix that problem.  		 */  		rfilt |= AR5K_RX_FILTER_PROM;  	} diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index 296c316a834..aac5b783194 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c @@ -34,12 +34,12 @@ static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = {  	{ PCI_VDEVICE(3COM_2,  0x0013) }, /* 3com 5212 */  	{ PCI_VDEVICE(3COM,    0x0013) }, /* 3com 3CRDAG675 5212 */  	{ PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ -	{ PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ -	{ PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ -	{ PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ -	{ PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ -	{ PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ -	{ PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ +	{ PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 compatible */ +	{ PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 compatible */ +	{ PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 compatible */ +	{ PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 compatible */ +	{ PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 compatible */ +	{ PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 compatible */  	{ PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */  	{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */  	{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ @@ -234,7 +234,7 @@ ath5k_pci_probe(struct pci_dev *pdev,  	mem = pci_iomap(pdev, 0, 0);  	if (!mem) { -		dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; +		dev_err(&pdev->dev, "cannot remap PCI memory region\n");  		ret = -EIO;  		goto err_reg;  	} @@ -297,7 +297,9 @@ ath5k_pci_remove(struct pci_dev *pdev)  #ifdef CONFIG_PM_SLEEP  static int ath5k_pci_suspend(struct device *dev)  { -	struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); +	struct pci_dev *pdev = to_pci_dev(dev); +	struct ieee80211_hw *hw = pci_get_drvdata(pdev); +	struct ath5k_softc *sc = hw->priv;  	ath5k_led_off(sc);  	return 0; @@ -306,7 +308,8 @@ static int ath5k_pci_suspend(struct device *dev)  static int ath5k_pci_resume(struct device *dev)  {  	struct pci_dev *pdev = to_pci_dev(dev); -	struct ath5k_softc *sc = pci_get_drvdata(pdev); +	struct ieee80211_hw *hw = pci_get_drvdata(pdev); +	struct ath5k_softc *sc = hw->priv;  	/*  	 * Suspend/Resume resets the PCI configuration space, so we have to diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 712a9ac4000..618ee54d5fe 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -32,7 +32,7 @@  #include "base.h"  /* - * AR5212+ can use higher rates for ack transmition + * AR5212+ can use higher rates for ack transmission   * based on current tx rate instead of the base rate.   * It does this to better utilize channel usage.   * This is a mapping between G rates (that cover both @@ -534,9 +534,9 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)  	local_irq_restore(flags); -	WARN_ON( i == ATH5K_MAX_TSF_READ ); +	WARN_ON(i == ATH5K_MAX_TSF_READ); -	return (((u64)tsf_upper1 << 32) | tsf_lower); +	return ((u64)tsf_upper1 << 32) | tsf_lower;  }  /** @@ -643,14 +643,14 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)  	/* Flush any pending BMISS interrupts on ISR by  	 * performing a clear-on-write operation on PISR  	 * register for the BMISS bit (writing a bit on -	 * ISR togles a reset for that bit and leaves -	 * the rest bits intact) */ +	 * ISR toggles a reset for that bit and leaves +	 * the remaining bits intact) */  	if (ah->ah_version == AR5K_AR5210)  		ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR);  	else  		ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR); -	/* TODO: Set enchanced sleep registers on AR5212 +	/* TODO: Set enhanced sleep registers on AR5212  	 * based on vif->bss_conf params, until then  	 * disable power save reporting.*/  	AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV); @@ -738,7 +738,7 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)  	dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3;  	/* NOTE: SWBA is different. Having a wrong window there does not -	 * stop us from sending data and this condition is catched thru +	 * stop us from sending data and this condition is caught by  	 * other means (SWBA interrupt) */  	if (ath5k_check_timer_win(nbtt, atim, 1, intval) && @@ -896,7 +896,7 @@ void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode,  	/* Set RSSI/BRSSI thresholds  	 *  	 * Note: If we decide to set this value -	 * dynamicaly, have in mind that when AR5K_RSSI_THR +	 * dynamically, have in mind that when AR5K_RSSI_THR  	 * register is read it might return 0x40 if we haven't  	 * wrote anything to it plus BMISS RSSI threshold is zeroed.  	 * So doing a save/restore procedure here isn't the right diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 55441913344..dd2b417729b 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -105,6 +105,7 @@ bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,  	if ((ah->ah_radio == AR5K_RF5112) ||  	(ah->ah_radio == AR5K_RF5413) || +	(ah->ah_radio == AR5K_RF2413) ||  	(ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))  		refclk_freq = 40;  	else @@ -173,7 +174,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah,  		data = ath5k_hw_bitswap(val, num_bits);  	for (bits_shifted = 0, bits_left = num_bits; bits_left > 0; -	position = 0, entry++) { +	     position = 0, entry++) {  		last_bit = (position + bits_left > 8) ? 8 :  					position + bits_left; @@ -363,7 +364,7 @@ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)  	return 0;  } -/* Schedule a gain probe check on the next transmited packet. +/* Schedule a gain probe check on the next transmitted packet.   * That means our next packet is going to be sent with lower   * tx power and a Peak to Average Power Detector (PAPD) will try   * to measure the gain. @@ -472,7 +473,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah)  		level[0] = 0;  		level[1] = (step == 63) ? 50 : step + 4;  		level[2] = (step != 63) ? 64 : level[0]; -		level[3] = level[2] + 50 ; +		level[3] = level[2] + 50;  		ah->ah_gain.g_high = level[3] -  			(step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5); @@ -549,7 +550,7 @@ static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah)  		for (ah->ah_gain.g_target = ah->ah_gain.g_current;  				ah->ah_gain.g_target <= ah->ah_gain.g_low && -				ah->ah_gain.g_step_idx < go->go_steps_count-1; +				ah->ah_gain.g_step_idx < go->go_steps_count - 1;  				g_step = &go->go_step[ah->ah_gain.g_step_idx])  			ah->ah_gain.g_target -= 2 *  			    (go->go_step[++ah->ah_gain.g_step_idx].gos_gain - @@ -614,13 +615,13 @@ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah)  			ath5k_hw_rf_gainf_corr(ah);  			ah->ah_gain.g_current =  				ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ? -				(ah->ah_gain.g_current-ah->ah_gain.g_f_corr) : +				(ah->ah_gain.g_current - ah->ah_gain.g_f_corr) :  				0;  		}  		/* Check if measurement is ok and if we need  		 * to adjust gain, schedule a gain adjustment, -		 * else switch back to the acive state */ +		 * else switch back to the active state */  		if (ath5k_hw_rf_check_gainf_readback(ah) &&  		AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&  		ath5k_hw_rf_gainf_adjust(ah)) { @@ -807,7 +808,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,  		 * use b_OB and b_DB parameters stored  		 * in eeprom on ee->ee_ob[ee_mode][0]  		 * -		 * For all other chips we use OB/DB for 2Ghz +		 * For all other chips we use OB/DB for 2GHz  		 * stored in the b/g modal section just like  		 * 802.11a on ee->ee_ob[ee_mode][1] */  		if ((ah->ah_radio == AR5K_RF5111) || @@ -970,17 +971,20 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,  			}  			/* Lower synth voltage on Rev 2 */ -			ath5k_hw_rfb_op(ah, rf_regs, 2, -					AR5K_RF_HIGH_VC_CP, true); +			if (ah->ah_radio == AR5K_RF5112 && +			    (ah->ah_radio_5ghz_revision & AR5K_SREV_REV) > 0) { +				ath5k_hw_rfb_op(ah, rf_regs, 2, +						AR5K_RF_HIGH_VC_CP, true); -			ath5k_hw_rfb_op(ah, rf_regs, 2, -					AR5K_RF_MID_VC_CP, true); +				ath5k_hw_rfb_op(ah, rf_regs, 2, +						AR5K_RF_MID_VC_CP, true); -			ath5k_hw_rfb_op(ah, rf_regs, 2, -					AR5K_RF_LOW_VC_CP, true); +				ath5k_hw_rfb_op(ah, rf_regs, 2, +						AR5K_RF_LOW_VC_CP, true); -			ath5k_hw_rfb_op(ah, rf_regs, 2, -					AR5K_RF_PUSH_UP, true); +				ath5k_hw_rfb_op(ah, rf_regs, 2, +						AR5K_RF_PUSH_UP, true); +			}  			/* Decrease power consumption on 5213+ BaseBand */  			if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { @@ -1259,7 +1263,7 @@ static int ath5k_hw_channel(struct ath5k_hw *ah,  {  	int ret;  	/* -	 * Check bounds supported by the PHY (we don't care about regultory +	 * Check bounds supported by the PHY (we don't care about regulatory  	 * restrictions at this point). Note: hw_value already has the band  	 * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok()  	 * of the band by that */ @@ -1331,7 +1335,7 @@ void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)  static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor)  {  	struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist; -	hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1); +	hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX - 1);  	hist->nfval[hist->index] = noise_floor;  } @@ -1344,10 +1348,10 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)  	memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort));  	for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) {  		for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) { -			if (sort[j] > sort[j-1]) { +			if (sort[j] > sort[j - 1]) {  				tmp = sort[j]; -				sort[j] = sort[j-1]; -				sort[j-1] = tmp; +				sort[j] = sort[j - 1]; +				sort[j - 1] = tmp;  			}  		}  	} @@ -1355,7 +1359,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)  		ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,  			"cal %d:%d\n", i, sort[i]);  	} -	return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2]; +	return sort[(ATH5K_NF_CAL_HIST_MAX - 1) / 2];  }  /* @@ -1604,11 +1608,13 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,  	int ret;  	if (ah->ah_radio == AR5K_RF5110) -		ret = ath5k_hw_rf5110_calibrate(ah, channel); -	else { -		ret = ath5k_hw_rf511x_iq_calibrate(ah); +		return ath5k_hw_rf5110_calibrate(ah, channel); + +	ret = ath5k_hw_rf511x_iq_calibrate(ah); + +	if ((ah->ah_radio == AR5K_RF5111 || ah->ah_radio == AR5K_RF5112) && +	    (channel->hw_value & CHANNEL_OFDM))  		ath5k_hw_request_rfgain_probe(ah); -	}  	return ret;  } @@ -1815,7 +1821,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,  	} else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) &  	AR5K_PHY_IQ_SPUR_FILT_EN) { -		/* Clean up spur mitigation settings and disable fliter */ +		/* Clean up spur mitigation settings and disable filter */  		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL,  					AR5K_PHY_BIN_MASK_CTL_RATE, 0);  		AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ, @@ -2080,7 +2086,7 @@ ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right,  	 * always 1 instead of 1.25, 1.75 etc). We scale up by 100  	 * to have some accuracy both for 0.5 and 0.25 steps.  	 */ -	ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left)); +	ratio = ((100 * y_right - 100 * y_left) / (x_right - x_left));  	/* Now scale down to be in range */  	result = y_left + (ratio * (target - x_left) / 100); @@ -2159,7 +2165,7 @@ ath5k_create_power_curve(s16 pmin, s16 pmax,  			u8 *vpd_table, u8 type)  {  	u8 idx[2] = { 0, 1 }; -	s16 pwr_i = 2*pmin; +	s16 pwr_i = 2 * pmin;  	int i;  	if (num_points < 2) @@ -2437,7 +2443,7 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,  	}  	if (edge_pwr) -		ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr); +		ah->ah_txpower.txp_max_pwr = 4 * min(edge_pwr, max_chan_pwr);  } @@ -2456,7 +2462,7 @@ static void  ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,  							s16 *table_max)  { -	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table; +	u8	*pcdac_out = ah->ah_txpower.txp_pd_table;  	u8	*pcdac_tmp = ah->ah_txpower.tmpL[0];  	u8	pcdac_0, pcdac_n, pcdac_i, pwr_idx, i;  	s16	min_pwr, max_pwr; @@ -2475,8 +2481,8 @@ ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min,  	/* Copy values from pcdac_tmp */  	pwr_idx = min_pwr; -	for (i = 0 ; pwr_idx <= max_pwr && -	pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) { +	for (i = 0; pwr_idx <= max_pwr && +		    pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) {  		pcdac_out[pcdac_i++] = pcdac_tmp[i];  		pwr_idx++;  	} @@ -2502,7 +2508,7 @@ static void  ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,  						s16 *table_max, u8 pdcurves)  { -	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table; +	u8	*pcdac_out = ah->ah_txpower.txp_pd_table;  	u8	*pcdac_low_pwr;  	u8	*pcdac_high_pwr;  	u8	*pcdac_tmp; @@ -2510,8 +2516,8 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,  	s16	max_pwr_idx;  	s16	min_pwr_idx;  	s16	mid_pwr_idx = 0; -	/* Edge flag turs on the 7nth bit on the PCDAC -	 * to delcare the higher power curve (force values +	/* Edge flag turns on the 7nth bit on the PCDAC +	 * to declare the higher power curve (force values  	 * to be greater than 64). If we only have one curve  	 * we don't need to set this, if we have 2 curves and  	 * fill the table backwards this can also be used to @@ -2552,7 +2558,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,  	}  	/* This is used when setting tx power*/ -	ah->ah_txpower.txp_min_idx = min_pwr_idx/2; +	ah->ah_txpower.txp_min_idx = min_pwr_idx / 2;  	/* Fill Power to PCDAC table backwards */  	pwr = max_pwr_idx; @@ -2561,14 +2567,14 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,  		 * edge flag and set pcdac_tmp to lower  		 * power curve.*/  		if (edge_flag == 0x40 && -		(2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) { +		(2 * pwr <= (table_max[1] - table_min[0]) || pwr == 0)) {  			edge_flag = 0x00;  			pcdac_tmp = pcdac_low_pwr; -			pwr = mid_pwr_idx/2; +			pwr = mid_pwr_idx / 2;  		}  		/* Don't go below 1, extrapolate below if we have -		 * already swithced to the lower power curve -or +		 * already switched to the lower power curve -or  		 * we only have one curve and edge_flag is zero  		 * anyway */  		if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) { @@ -2596,7 +2602,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min,  static void  ath5k_write_pcdac_table(struct ath5k_hw *ah)  { -	u8 	*pcdac_out = ah->ah_txpower.txp_pd_table; +	u8	*pcdac_out = ah->ah_txpower.txp_pd_table;  	int	i;  	/* @@ -2604,8 +2610,8 @@ ath5k_write_pcdac_table(struct ath5k_hw *ah)  	 */  	for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {  		ath5k_hw_reg_write(ah, -			(((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) | -			(((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16), +			(((pcdac_out[2 * i + 0] << 8 | 0xff) & 0xffff) << 0) | +			(((pcdac_out[2 * i + 1] << 8 | 0xff) & 0xffff) << 16),  			AR5K_PHY_PCDAC_TXPOWER(i));  	}  } @@ -2789,10 +2795,10 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)  	 */  	for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {  		ath5k_hw_reg_write(ah, -			((pdadc_out[4*i + 0] & 0xff) << 0) | -			((pdadc_out[4*i + 1] & 0xff) << 8) | -			((pdadc_out[4*i + 2] & 0xff) << 16) | -			((pdadc_out[4*i + 3] & 0xff) << 24), +			((pdadc_out[4 * i + 0] & 0xff) << 0) | +			((pdadc_out[4 * i + 1] & 0xff) << 8) | +			((pdadc_out[4 * i + 2] & 0xff) << 16) | +			((pdadc_out[4 * i + 3] & 0xff) << 24),  			AR5K_PHY_PDADC_TXPOWER(i));  	}  } @@ -2805,7 +2811,7 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)  /*   * This is the main function that uses all of the above   * to set PCDAC/PDADC table on hw for the current channel. - * This table is used for tx power calibration on the basband, + * This table is used for tx power calibration on the baseband,   * without it we get weird tx power levels and in some cases   * distorted spectral mask   */ diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index d12b827033c..f5c1000045d 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -72,7 +72,7 @@  #define	AR5K_CFG_SWRD		0x00000004	/* Byte-swap RX descriptor */  #define	AR5K_CFG_SWRB		0x00000008	/* Byte-swap RX buffer */  #define	AR5K_CFG_SWRG		0x00000010	/* Byte-swap Register access */ -#define AR5K_CFG_IBSS		0x00000020 	/* 0-BSS, 1-IBSS [5211+] */ +#define AR5K_CFG_IBSS		0x00000020	/* 0-BSS, 1-IBSS [5211+] */  #define AR5K_CFG_PHY_OK		0x00000100	/* [5211+] */  #define AR5K_CFG_EEBS		0x00000200	/* EEPROM is busy */  #define	AR5K_CFG_CLKGD		0x00000400	/* Clock gated (Disable dynamic clock) */ @@ -170,7 +170,7 @@  #define AR5K_TXCFG_SDMAMR_S		0  #define AR5K_TXCFG_B_MODE		0x00000008	/* Set b mode for 5111 (enable 2111) */  #define AR5K_TXCFG_TXFSTP		0x00000008	/* TX DMA full Stop [5210] */ -#define AR5K_TXCFG_TXFULL		0x000003f0	/* TX Triger level mask */ +#define AR5K_TXCFG_TXFULL		0x000003f0	/* TX Trigger level mask */  #define AR5K_TXCFG_TXFULL_S		4  #define AR5K_TXCFG_TXFULL_0B		0x00000000  #define AR5K_TXCFG_TXFULL_64B		0x00000010 @@ -283,16 +283,16 @@   */  #define AR5K_ISR		0x001c			/* Register Address [5210] */  #define AR5K_PISR		0x0080			/* Register Address [5211+] */ -#define AR5K_ISR_RXOK		0x00000001	/* Frame successfuly received */ +#define AR5K_ISR_RXOK		0x00000001	/* Frame successfully received */  #define AR5K_ISR_RXDESC		0x00000002	/* RX descriptor request */  #define AR5K_ISR_RXERR		0x00000004	/* Receive error */  #define AR5K_ISR_RXNOFRM	0x00000008	/* No frame received (receive timeout) */  #define AR5K_ISR_RXEOL		0x00000010	/* Empty RX descriptor */  #define AR5K_ISR_RXORN		0x00000020	/* Receive FIFO overrun */ -#define AR5K_ISR_TXOK		0x00000040	/* Frame successfuly transmited */ +#define AR5K_ISR_TXOK		0x00000040	/* Frame successfully transmitted */  #define AR5K_ISR_TXDESC		0x00000080	/* TX descriptor request */  #define AR5K_ISR_TXERR		0x00000100	/* Transmit error */ -#define AR5K_ISR_TXNOFRM	0x00000200	/* No frame transmited (transmit timeout) */ +#define AR5K_ISR_TXNOFRM	0x00000200	/* No frame transmitted (transmit timeout) */  #define AR5K_ISR_TXEOL		0x00000400	/* Empty TX descriptor */  #define AR5K_ISR_TXURN		0x00000800	/* Transmit FIFO underrun */  #define AR5K_ISR_MIB		0x00001000	/* Update MIB counters */ @@ -303,7 +303,7 @@  #define AR5K_ISR_BRSSI		0x00020000	/* Beacon rssi below threshold (?) */  #define AR5K_ISR_BMISS		0x00040000	/* Beacon missed */  #define AR5K_ISR_HIUERR		0x00080000	/* Host Interface Unit error [5211+] */ -#define AR5K_ISR_BNR		0x00100000 	/* Beacon not ready [5211+] */ +#define AR5K_ISR_BNR		0x00100000	/* Beacon not ready [5211+] */  #define AR5K_ISR_MCABT		0x00100000	/* Master Cycle Abort [5210] */  #define AR5K_ISR_RXCHIRP	0x00200000	/* CHIRP Received [5212+] */  #define AR5K_ISR_SSERR		0x00200000	/* Signaled System Error [5210] */ @@ -377,16 +377,16 @@   */  #define	AR5K_IMR		0x0020			/* Register Address [5210] */  #define AR5K_PIMR		0x00a0			/* Register Address [5211+] */ -#define AR5K_IMR_RXOK		0x00000001	/* Frame successfuly received*/ +#define AR5K_IMR_RXOK		0x00000001	/* Frame successfully received*/  #define AR5K_IMR_RXDESC		0x00000002	/* RX descriptor request*/  #define AR5K_IMR_RXERR		0x00000004	/* Receive error*/  #define AR5K_IMR_RXNOFRM	0x00000008	/* No frame received (receive timeout)*/  #define AR5K_IMR_RXEOL		0x00000010	/* Empty RX descriptor*/  #define AR5K_IMR_RXORN		0x00000020	/* Receive FIFO overrun*/ -#define AR5K_IMR_TXOK		0x00000040	/* Frame successfuly transmited*/ +#define AR5K_IMR_TXOK		0x00000040	/* Frame successfully transmitted*/  #define AR5K_IMR_TXDESC		0x00000080	/* TX descriptor request*/  #define AR5K_IMR_TXERR		0x00000100	/* Transmit error*/ -#define AR5K_IMR_TXNOFRM	0x00000200	/* No frame transmited (transmit timeout)*/ +#define AR5K_IMR_TXNOFRM	0x00000200	/* No frame transmitted (transmit timeout)*/  #define AR5K_IMR_TXEOL		0x00000400	/* Empty TX descriptor*/  #define AR5K_IMR_TXURN		0x00000800	/* Transmit FIFO underrun*/  #define AR5K_IMR_MIB		0x00001000	/* Update MIB counters*/ @@ -397,7 +397,7 @@  #define AR5K_IMR_BRSSI		0x00020000	/* Beacon rssi below threshold (?) */  #define AR5K_IMR_BMISS		0x00040000	/* Beacon missed*/  #define AR5K_IMR_HIUERR		0x00080000	/* Host Interface Unit error [5211+] */ -#define AR5K_IMR_BNR		0x00100000 	/* Beacon not ready [5211+] */ +#define AR5K_IMR_BNR		0x00100000	/* Beacon not ready [5211+] */  #define AR5K_IMR_MCABT		0x00100000	/* Master Cycle Abort [5210] */  #define AR5K_IMR_RXCHIRP	0x00200000	/* CHIRP Received [5212+]*/  #define AR5K_IMR_SSERR		0x00200000	/* Signaled System Error [5210] */ @@ -601,7 +601,7 @@   * QCU misc registers   */  #define AR5K_QCU_MISC_BASE		0x09c0			/* Register Address -Queue0 MISC */ -#define	AR5K_QCU_MISC_FRSHED_M		0x0000000f	/* Frame sheduling mask */ +#define	AR5K_QCU_MISC_FRSHED_M		0x0000000f	/* Frame scheduling mask */  #define	AR5K_QCU_MISC_FRSHED_ASAP		0	/* ASAP */  #define	AR5K_QCU_MISC_FRSHED_CBR		1	/* Constant Bit Rate */  #define	AR5K_QCU_MISC_FRSHED_DBA_GT		2	/* DMA Beacon alert gated */ @@ -653,13 +653,13 @@   * registers [5211+]   *   * These registers control the various characteristics of each queue - * for 802.11e (WME) combatibility so they go together with + * for 802.11e (WME) compatibility so they go together with   * QCU registers in pairs. For each queue we have a QCU mask register,   * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),   * a retry limit register (0x1080 - 0x10ac), a channel time register   * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and   * a sequence number register (0x1140 - 0x116c). It seems that "global" - * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k). + * registers here affect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).   * We use the same macros here for easier register access.   *   */ @@ -779,7 +779,7 @@   * and it's used for generating pseudo-random   * number sequences.   * - * (If i understand corectly, random numbers are + * (If i understand correctly, random numbers are   * used for idle sensing -multiplied with cwmin/max etc-)   */  #define AR5K_DCU_GBL_IFS_MISC			0x10f0			/* Register Address */ @@ -1007,7 +1007,7 @@  #define	AR5K_PCIE_WAEN	0x407c  /* - * PCI-E Serializer/Desirializer + * PCI-E Serializer/Deserializer   * registers   */  #define	AR5K_PCIE_SERDES	0x4080 @@ -1227,7 +1227,7 @@  					AR5K_USEC_5210 : AR5K_USEC_5211)  #define AR5K_USEC_1			0x0000007f	/* clock cycles for 1us */  #define AR5K_USEC_1_S			0 -#define AR5K_USEC_32			0x00003f80	/* clock cycles for 1us while on 32Mhz clock */ +#define AR5K_USEC_32			0x00003f80	/* clock cycles for 1us while on 32MHz clock */  #define AR5K_USEC_32_S			7  #define AR5K_USEC_TX_LATENCY_5211	0x007fc000  #define AR5K_USEC_TX_LATENCY_5211_S	14 @@ -1328,16 +1328,16 @@  #define AR5K_RX_FILTER_5211	0x803c			/* Register Address [5211+] */  #define AR5K_RX_FILTER		(ah->ah_version == AR5K_AR5210 ? \  				AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211) -#define	AR5K_RX_FILTER_UCAST 	0x00000001	/* Don't filter unicast frames */ -#define	AR5K_RX_FILTER_MCAST 	0x00000002	/* Don't filter multicast frames */ -#define	AR5K_RX_FILTER_BCAST 	0x00000004	/* Don't filter broadcast frames */ -#define	AR5K_RX_FILTER_CONTROL 	0x00000008	/* Don't filter control frames */ -#define	AR5K_RX_FILTER_BEACON 	0x00000010	/* Don't filter beacon frames */ -#define	AR5K_RX_FILTER_PROM 	0x00000020	/* Set promiscuous mode */ -#define	AR5K_RX_FILTER_XRPOLL 	0x00000040	/* Don't filter XR poll frame [5212+] */ +#define	AR5K_RX_FILTER_UCAST	0x00000001	/* Don't filter unicast frames */ +#define	AR5K_RX_FILTER_MCAST	0x00000002	/* Don't filter multicast frames */ +#define	AR5K_RX_FILTER_BCAST	0x00000004	/* Don't filter broadcast frames */ +#define	AR5K_RX_FILTER_CONTROL	0x00000008	/* Don't filter control frames */ +#define	AR5K_RX_FILTER_BEACON	0x00000010	/* Don't filter beacon frames */ +#define	AR5K_RX_FILTER_PROM	0x00000020	/* Set promiscuous mode */ +#define	AR5K_RX_FILTER_XRPOLL	0x00000040	/* Don't filter XR poll frame [5212+] */  #define	AR5K_RX_FILTER_PROBEREQ 0x00000080	/* Don't filter probe requests [5212+] */  #define	AR5K_RX_FILTER_PHYERR_5212	0x00000100	/* Don't filter phy errors [5212+] */ -#define	AR5K_RX_FILTER_RADARERR_5212 	0x00000200	/* Don't filter phy radar errors [5212+] */ +#define	AR5K_RX_FILTER_RADARERR_5212	0x00000200	/* Don't filter phy radar errors [5212+] */  #define AR5K_RX_FILTER_PHYERR_5211	0x00000040	/* [5211] */  #define AR5K_RX_FILTER_RADARERR_5211	0x00000080	/* [5211] */  #define AR5K_RX_FILTER_PHYERR  \ @@ -1461,7 +1461,7 @@   * ADDAC test register [5211+]   */  #define AR5K_ADDAC_TEST			0x8054			/* Register Address */ -#define AR5K_ADDAC_TEST_TXCONT 		0x00000001	/* Test continuous tx */ +#define AR5K_ADDAC_TEST_TXCONT		0x00000001	/* Test continuous tx */  #define AR5K_ADDAC_TEST_TST_MODE	0x00000002	/* Test mode */  #define AR5K_ADDAC_TEST_LOOP_EN		0x00000004	/* Enable loop */  #define AR5K_ADDAC_TEST_LOOP_LEN	0x00000008	/* Loop length (field) */ @@ -1632,7 +1632,7 @@  #define AR5K_SLEEP0_NEXT_DTIM		0x0007ffff	/* Mask for next DTIM (?) */  #define AR5K_SLEEP0_NEXT_DTIM_S		0  #define AR5K_SLEEP0_ASSUME_DTIM		0x00080000	/* Assume DTIM */ -#define AR5K_SLEEP0_ENH_SLEEP_EN	0x00100000	/* Enable enchanced sleep control */ +#define AR5K_SLEEP0_ENH_SLEEP_EN	0x00100000	/* Enable enhanced sleep control */  #define AR5K_SLEEP0_CABTO		0xff000000	/* Mask for CAB Time Out */  #define AR5K_SLEEP0_CABTO_S		24 @@ -1657,7 +1657,7 @@  /*   * TX power control (TPC) register   * - * XXX: PCDAC steps (0.5dbm) or DBM ? + * XXX: PCDAC steps (0.5dBm) or dBm ?   *   */  #define AR5K_TXPC			0x80e8			/* Register Address */ @@ -1673,7 +1673,7 @@  /*   * Profile count registers   * - * These registers can be cleared and freezed with ATH5K_MIBC, but they do not + * These registers can be cleared and frozen with ATH5K_MIBC, but they do not   * generate a MIB interrupt.   * Instead of overflowing, they shift by one bit to the right. All registers   * shift together, i.e. when one reaches the max, all shift at the same time by @@ -1838,7 +1838,7 @@  #define AR5K_PHY_TST2_TRIG_SEL		0x00000007	/* Trigger select (?)*/  #define AR5K_PHY_TST2_TRIG		0x00000010	/* Trigger (?) */  #define AR5K_PHY_TST2_CBUS_MODE		0x00000060	/* Cardbus mode (?) */ -#define AR5K_PHY_TST2_CLK32		0x00000400	/* CLK_OUT is CLK32 (32Khz external) */ +#define AR5K_PHY_TST2_CLK32		0x00000400	/* CLK_OUT is CLK32 (32kHz external) */  #define AR5K_PHY_TST2_CHANCOR_DUMP_EN	0x00000800	/* Enable Chancor dump (?) */  #define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP	0x00001000	/* Even Chancor dump (?) */  #define AR5K_PHY_TST2_RFSILENT_EN	0x00002000	/* Enable RFSILENT */ @@ -2002,7 +2002,7 @@  #define	AR5K_PHY_AGCCTL_OFDM_DIV_DIS	0x00000008	/* Disable antenna diversity on OFDM modes */  #define	AR5K_PHY_AGCCTL_NF_EN		0x00008000	/* Enable nf calibration to happen (?) */  #define	AR5K_PHY_AGCTL_FLTR_CAL		0x00010000	/* Allow filter calibration (?) */ -#define	AR5K_PHY_AGCCTL_NF_NOUPDATE	0x00020000	/* Don't update nf automaticaly */ +#define	AR5K_PHY_AGCCTL_NF_NOUPDATE	0x00020000	/* Don't update nf automatically */  /*   * PHY noise floor status register (CCA = Clear Channel Assessment) @@ -2038,7 +2038,7 @@  #define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S	24  /* Low thresholds */ -#define AR5K_PHY_WEAK_OFDM_LOW_THR 		0x986c +#define AR5K_PHY_WEAK_OFDM_LOW_THR		0x986c  #define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN	0x00000001  #define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT	0x00003f00  #define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S	8 @@ -2089,7 +2089,7 @@   *   * It's obvious from the code that 0x989c is the buffer register but   * for the other special registers that we write to after sending each - * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers + * packet, i have no idea. So I'll name them BUFFER_CONTROL_X registers   * for now. It's interesting that they are also used for some other operations.   */ @@ -2259,12 +2259,13 @@  #define	AR5K_PHY_FRAME_CTL_ILLLEN_ERR	0x08000000	/* Illegal length */  #define	AR5K_PHY_FRAME_CTL_SERVICE_ERR	0x20000000  #define	AR5K_PHY_FRAME_CTL_TXURN_ERR	0x40000000	/* TX underrun */ -#define AR5K_PHY_FRAME_CTL_INI		AR5K_PHY_FRAME_CTL_SERVICE_ERR | \ -			AR5K_PHY_FRAME_CTL_TXURN_ERR | \ -			AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \ -			AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \ -			AR5K_PHY_FRAME_CTL_PARITY_ERR | \ -			AR5K_PHY_FRAME_CTL_TIMING_ERR +#define AR5K_PHY_FRAME_CTL_INI	\ +			(AR5K_PHY_FRAME_CTL_SERVICE_ERR | \ +			 AR5K_PHY_FRAME_CTL_TXURN_ERR | \ +			 AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \ +			 AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \ +			 AR5K_PHY_FRAME_CTL_PARITY_ERR | \ +			 AR5K_PHY_FRAME_CTL_TIMING_ERR)  /*   * PHY Tx Power adjustment register [5212A+] @@ -2281,22 +2282,22 @@  #define	AR5K_PHY_RADAR			0x9954  #define	AR5K_PHY_RADAR_ENABLE		0x00000001  #define	AR5K_PHY_RADAR_DISABLE		0x00000000 -#define AR5K_PHY_RADAR_INBANDTHR    	0x0000003e	/* Inband threshold +#define AR5K_PHY_RADAR_INBANDTHR	0x0000003e	/* Inband threshold  							5-bits, units unknown {0..31}  							(? MHz ?) */  #define AR5K_PHY_RADAR_INBANDTHR_S	1 -#define AR5K_PHY_RADAR_PRSSI_THR    	0x00000fc0	/* Pulse RSSI/SNR threshold +#define AR5K_PHY_RADAR_PRSSI_THR	0x00000fc0	/* Pulse RSSI/SNR threshold  							6-bits, dBm range {0..63}  							in dBm units. */  #define AR5K_PHY_RADAR_PRSSI_THR_S	6 -#define AR5K_PHY_RADAR_PHEIGHT_THR   	0x0003f000	/* Pulse height threshold +#define AR5K_PHY_RADAR_PHEIGHT_THR	0x0003f000	/* Pulse height threshold  							6-bits, dBm range {0..63}  							in dBm units. */  #define AR5K_PHY_RADAR_PHEIGHT_THR_S	12 -#define AR5K_PHY_RADAR_RSSI_THR    	0x00fc0000	/* Radar RSSI/SNR threshold. +#define AR5K_PHY_RADAR_RSSI_THR		0x00fc0000	/* Radar RSSI/SNR threshold.  							6-bits, dBm range {0..63}  							in dBm units. */  #define AR5K_PHY_RADAR_RSSI_THR_S	18 @@ -2339,7 +2340,7 @@  #define AR5K_PHY_RESTART_DIV_GC_S	18  /* - * RF Bus access request register (for synth-oly channel switching) + * RF Bus access request register (for synth-only channel switching)   */  #define AR5K_PHY_RFBUS_REQ		0x997C  #define AR5K_PHY_RFBUS_REQ_REQUEST	0x00000001 @@ -2381,7 +2382,7 @@   */  #define	AR5K_BB_GAIN_BASE		0x9b00	/* BaseBand Amplifier Gain table base address */  #define AR5K_BB_GAIN(_n)		(AR5K_BB_GAIN_BASE + ((_n) << 2)) -#define	AR5K_RF_GAIN_BASE		0x9a00	/* RF Amplrifier Gain table base address */ +#define	AR5K_RF_GAIN_BASE		0x9a00	/* RF Amplifier Gain table base address */  #define AR5K_RF_GAIN(_n)		(AR5K_RF_GAIN_BASE + ((_n) << 2))  /* diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 126a4eab35f..9f9c2ad3ca6 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -25,7 +25,7 @@  #include <asm/unaligned.h> -#include <linux/pci.h> 		/* To determine if a card is pci-e */ +#include <linux/pci.h>		/* To determine if a card is pci-e */  #include <linux/log2.h>  #include <linux/platform_device.h>  #include "ath5k.h" @@ -142,10 +142,11 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)  	/* Set 32MHz USEC counter */  	if ((ah->ah_radio == AR5K_RF5112) || -		(ah->ah_radio == AR5K_RF5413) || -		(ah->ah_radio == AR5K_RF2316) || -		(ah->ah_radio == AR5K_RF2317)) -	/* Remain on 40MHz clock ? */ +	    (ah->ah_radio == AR5K_RF2413) || +	    (ah->ah_radio == AR5K_RF5413) || +	    (ah->ah_radio == AR5K_RF2316) || +	    (ah->ah_radio == AR5K_RF2317)) +		/* Remain on 40MHz clock ? */  		sclock = 40 - 1;  	else  		sclock = 32 - 1; @@ -213,7 +214,7 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)  	usec_reg = (usec | sclock | txlat | rxlat);  	ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC); -	/* On 5112 set tx frane to tx data start delay */ +	/* On 5112 set tx frame to tx data start delay */  	if (ah->ah_radio == AR5K_RF5112) {  		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2,  					AR5K_PHY_RF_CTL2_TXF2TXD_START, @@ -233,7 +234,7 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)  static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)  {  	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; -	u32 scal, spending; +	u32 scal, spending, sclock;  	/* Only set 32KHz settings if we have an external  	 * 32KHz crystal present */ @@ -317,6 +318,15 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)  		/* Set up tsf increment on each cycle */  		AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); + +		if ((ah->ah_radio == AR5K_RF5112) || +			(ah->ah_radio == AR5K_RF5413) || +			(ah->ah_radio == AR5K_RF2316) || +			(ah->ah_radio == AR5K_RF2317)) +			sclock = 40 - 1; +		else +			sclock = 32 - 1; +		AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, sclock);  	}  } @@ -375,19 +385,19 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)  static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)  {  	u32 mask = flags ? flags : ~0U; -	volatile u32 *reg; +	u32 __iomem *reg;  	u32 regval;  	u32 val = 0;  	/* ah->ah_mac_srev is not available at this point yet */  	if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) { -		reg = (u32 *) AR5K_AR2315_RESET; +		reg = (u32 __iomem *) AR5K_AR2315_RESET;  		if (mask & AR5K_RESET_CTL_PCU)  			val |= AR5K_AR2315_RESET_WMAC;  		if (mask & AR5K_RESET_CTL_BASEBAND)  			val |= AR5K_AR2315_RESET_BB_WARM;  	} else { -		reg = (u32 *) AR5K_AR5312_RESET; +		reg = (u32 __iomem *) AR5K_AR5312_RESET;  		if (to_platform_device(ah->ah_sc->dev)->id == 0) {  			if (mask & AR5K_RESET_CTL_PCU)  				val |= AR5K_AR5312_RESET_WMAC0; @@ -539,7 +549,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)  	 *  	 * Note: putting PCI core on warm reset on PCI-E cards  	 * results card to hang and always return 0xffff... so -	 * we ingore that flag for PCI-E cards. On PCI cards +	 * we ignore that flag for PCI-E cards. On PCI cards  	 * this flag gets cleared after 64 PCI clocks.  	 */  	bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI; @@ -596,7 +606,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)  	 *  	 * Note: putting PCI core on warm reset on PCI-E cards  	 * results card to hang and always return 0xffff... so -	 * we ingore that flag for PCI-E cards. On PCI cards +	 * we ignore that flag for PCI-E cards. On PCI cards  	 * this flag gets cleared after 64 PCI clocks.  	 */  	bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI; @@ -627,7 +637,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)  		return ret;  	} -	/* ...reset configuration regiter on Wisoc ... +	/* ...reset configuration register on Wisoc ...  	 * ...clear reset control register and pull device out of  	 * warm reset on others */  	if (ath5k_get_bus_type(ah) == ATH_AHB) @@ -704,7 +714,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)  		/*XXX: Can bwmode be used with dynamic mode ?  		 * (I don't think it supports 44MHz) */ -		/* On 2425 initvals TURBO_SHORT is not pressent */ +		/* On 2425 initvals TURBO_SHORT is not present */  		if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) {  			turbo = AR5K_PHY_TURBO_MODE |  				(ah->ah_radio == AR5K_RF2425) ? 0 : @@ -1277,11 +1287,16 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,  	ath5k_hw_dma_init(ah); -	/* Enable 32KHz clock function for AR5212+ chips +	/* +	 * Enable 32KHz clock function for AR5212+ chips  	 * Set clocks to 32KHz operation and use an  	 * external 32KHz crystal when sleeping if one -	 * exists */ -	if (ah->ah_version == AR5K_AR5212 && +	 * exists. +	 * Disabled by default because it is also disabled in +	 * other drivers and it is known to cause stability +	 * issues on some devices +	 */ +	if (ah->ah_use_32khz_clock && ah->ah_version == AR5K_AR5212 &&  	    op_mode != NL80211_IFTYPE_AP)  		ath5k_hw_set_sleep_clock(ah, true); diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h index 16b67e84906..5d11c23b429 100644 --- a/drivers/net/wireless/ath/ath5k/rfbuffer.h +++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h @@ -254,7 +254,7 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = {  /* RFX112 (Derby 1) */ -/* BANK 6 				len  pos col */ +/* BANK 6				len  pos col */  #define	AR5K_RF5112_OB_2GHZ		{ 3, 269, 0 }  #define	AR5K_RF5112_DB_2GHZ		{ 3, 272, 0 } @@ -495,7 +495,7 @@ static const struct ath5k_ini_rfbuffer rfb_5112a[] = {  /* BANK 2				len  pos col */  #define AR5K_RF2413_RF_TURBO		{ 1, 1,   2 } -/* BANK 6 				len  pos col */ +/* BANK 6				len  pos col */  #define	AR5K_RF2413_OB_2GHZ		{ 3, 168, 0 }  #define	AR5K_RF2413_DB_2GHZ		{ 3, 165, 0 } diff --git a/drivers/net/wireless/ath/ath5k/rfgain.h b/drivers/net/wireless/ath/ath5k/rfgain.h index 1354d8c392c..ebfae052d89 100644 --- a/drivers/net/wireless/ath/ath5k/rfgain.h +++ b/drivers/net/wireless/ath/ath5k/rfgain.h @@ -30,7 +30,7 @@ struct ath5k_ini_rfgain {  /* Initial RF Gain settings for RF5111 */  static const struct ath5k_ini_rfgain rfgain_5111[] = { -	/*			      5Ghz	2Ghz	*/ +	/*			      5GHz	2GHz	*/  	{ AR5K_RF_GAIN(0),	{ 0x000001a9, 0x00000000 } },  	{ AR5K_RF_GAIN(1),	{ 0x000001e9, 0x00000040 } },  	{ AR5K_RF_GAIN(2),	{ 0x00000029, 0x00000080 } }, @@ -99,7 +99,7 @@ static const struct ath5k_ini_rfgain rfgain_5111[] = {  /* Initial RF Gain settings for RF5112 */  static const struct ath5k_ini_rfgain rfgain_5112[] = { -	/*			      5Ghz	2Ghz	*/ +	/*			      5GHz	2GHz	*/  	{ AR5K_RF_GAIN(0),	{ 0x00000007, 0x00000007 } },  	{ AR5K_RF_GAIN(1),	{ 0x00000047, 0x00000047 } },  	{ AR5K_RF_GAIN(2),	{ 0x00000087, 0x00000087 } }, @@ -305,7 +305,7 @@ static const struct ath5k_ini_rfgain rfgain_2316[] = {  /* Initial RF Gain settings for RF5413 */  static const struct ath5k_ini_rfgain rfgain_5413[] = { -	/*			      5Ghz	2Ghz	*/ +	/*			      5GHz	2GHz	*/  	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },  	{ AR5K_RF_GAIN(1),	{ 0x00000040, 0x00000040 } },  	{ AR5K_RF_GAIN(2),	{ 0x00000080, 0x00000080 } }, @@ -452,7 +452,7 @@ static const struct ath5k_ini_rfgain rfgain_2425[] = {  /* Check if our current measurement is inside our   * current variable attenuation window */ -#define AR5K_GAIN_CHECK_ADJUST(_g) 		\ +#define AR5K_GAIN_CHECK_ADJUST(_g)		\  	((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)  struct ath5k_gain_opt_step { diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c index 929c68cdf8a..d8ad0e45e1c 100644 --- a/drivers/net/wireless/ath/ath5k/sysfs.c +++ b/drivers/net/wireless/ath/ath5k/sysfs.c @@ -10,18 +10,22 @@ static ssize_t ath5k_attr_show_##name(struct device *dev,		\  			struct device_attribute *attr,			\  			char *buf)					\  {									\ -	struct ath5k_softc *sc = dev_get_drvdata(dev);			\ -	return snprintf(buf, PAGE_SIZE, "%d\n", get); 			\ +	struct ieee80211_hw *hw = dev_get_drvdata(dev);			\ +	struct ath5k_softc *sc = hw->priv;				\ +	return snprintf(buf, PAGE_SIZE, "%d\n", get);			\  }									\  									\  static ssize_t ath5k_attr_store_##name(struct device *dev,		\  			struct device_attribute *attr,			\  			const char *buf, size_t count)			\  {									\ -	struct ath5k_softc *sc = dev_get_drvdata(dev);			\ -	int val;							\ +	struct ieee80211_hw *hw = dev_get_drvdata(dev);			\ +	struct ath5k_softc *sc = hw->priv;				\ +	int val, ret;							\  									\ -	val = (int)simple_strtoul(buf, NULL, 10);			\ +	ret = kstrtoint(buf, 10, &val);					\ +	if (ret < 0)							\ +		return ret;						\  	set(sc->ah, val);						\  	return count;							\  }									\ @@ -33,8 +37,9 @@ static ssize_t ath5k_attr_show_##name(struct device *dev,		\  			struct device_attribute *attr,			\  			char *buf)					\  {									\ -	struct ath5k_softc *sc = dev_get_drvdata(dev);			\ -	return snprintf(buf, PAGE_SIZE, "%d\n", get); 			\ +	struct ieee80211_hw *hw = dev_get_drvdata(dev);			\ +	struct ath5k_softc *sc = hw->priv;				\ +	return snprintf(buf, PAGE_SIZE, "%d\n", get);			\  }									\  static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL) diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h index 2de68adb624..235e0768ce1 100644 --- a/drivers/net/wireless/ath/ath5k/trace.h +++ b/drivers/net/wireless/ath/ath5k/trace.h @@ -12,9 +12,6 @@ static inline void trace_ ## name(proto) {}  struct sk_buff; -#define PRIV_ENTRY  __field(struct ath5k_softc *, priv) -#define PRIV_ASSIGN __entry->priv = priv -  #undef TRACE_SYSTEM  #define TRACE_SYSTEM ath5k @@ -22,12 +19,12 @@ TRACE_EVENT(ath5k_rx,  	TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb),  	TP_ARGS(priv, skb),  	TP_STRUCT__entry( -		PRIV_ENTRY +		__field(struct ath5k_softc *, priv)  		__field(unsigned long, skbaddr)  		__dynamic_array(u8, frame, skb->len)  	),  	TP_fast_assign( -		PRIV_ASSIGN; +		__entry->priv = priv;  		__entry->skbaddr = (unsigned long) skb;  		memcpy(__get_dynamic_array(frame), skb->data, skb->len);  	), @@ -43,14 +40,14 @@ TRACE_EVENT(ath5k_tx,  	TP_ARGS(priv, skb, q),  	TP_STRUCT__entry( -		PRIV_ENTRY +		__field(struct ath5k_softc *, priv)  		__field(unsigned long, skbaddr)  		__field(u8, qnum)  		__dynamic_array(u8, frame, skb->len)  	),  	TP_fast_assign( -		PRIV_ASSIGN; +		__entry->priv = priv;  		__entry->skbaddr = (unsigned long) skb;  		__entry->qnum = (u8) q->qnum;  		memcpy(__get_dynamic_array(frame), skb->data, skb->len); @@ -69,7 +66,7 @@ TRACE_EVENT(ath5k_tx_complete,  	TP_ARGS(priv, skb, q, ts),  	TP_STRUCT__entry( -		PRIV_ENTRY +		__field(struct ath5k_softc *, priv)  		__field(unsigned long, skbaddr)  		__field(u8, qnum)  		__field(u8, ts_status) @@ -78,7 +75,7 @@ TRACE_EVENT(ath5k_tx_complete,  	),  	TP_fast_assign( -		PRIV_ASSIGN; +		__entry->priv = priv;  		__entry->skbaddr = (unsigned long) skb;  		__entry->qnum = (u8) q->qnum;  		__entry->ts_status = ts->ts_status; diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 5b49cd03bfd..0b36fcf8a28 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -27,6 +27,10 @@ static const struct platform_device_id ath9k_platform_id_table[] = {  		.driver_data = AR5416_AR9100_DEVID,  	},  	{ +		.name = "ar933x_wmac", +		.driver_data = AR9300_DEVID_AR9330, +	}, +	{  		.name = "ar934x_wmac",  		.driver_data = AR9300_DEVID_AR9340,  	}, diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 441bb33f17a..fac2c6da6ca 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -627,6 +627,11 @@ static void ar5008_hw_init_bb(struct ath_hw *ah,  	else  		synthDelay /= 10; +	if (IS_CHAN_HALF_RATE(chan)) +		synthDelay *= 2; +	else if (IS_CHAN_QUARTER_RATE(chan)) +		synthDelay *= 4; +  	REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);  	udelay(synthDelay + BASE_ACTIVATE_DELAY); diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index f344cc2b3d5..9ff7c30573b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -499,45 +499,6 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah)  	}  } -/* - * 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_update_async_fifo(struct ath_hw *ah) -{ -	if (AR_SREV_9287_13_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_13_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)  { diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 077e8a6983f..45b262fe2c2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -28,11 +28,6 @@ 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; @@ -437,7 +432,6 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *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; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 2fe0a34cbab..3cbbb033fce 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c @@ -111,7 +111,9 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)  		switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {  		case 0: -			if ((freq % 20) == 0) +			if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) +				aModeRefSel = 0; +			else if ((freq % 20) == 0)  				aModeRefSel = 3;  			else if ((freq % 10) == 0)  				aModeRefSel = 2; @@ -129,8 +131,9 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)  			channelSel = CHANSEL_5G(freq);  			/* RefDivA setting */ -			REG_RMW_FIELD(ah, AR_AN_SYNTH9, -				      AR_AN_SYNTH9_REFDIVA, refDivA); +			ath9k_hw_analog_shift_rmw(ah, AR_AN_SYNTH9, +				      AR_AN_SYNTH9_REFDIVA, +				      AR_AN_SYNTH9_REFDIVA_S, refDivA);  		} @@ -447,26 +450,27 @@ static void ar9002_olc_init(struct ath_hw *ah)  static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,  					 struct ath9k_channel *chan)  { +	int ref_div = 5; +	int pll_div = 0x2c;  	u32 pll; -	pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); +	if (chan && IS_CHAN_5GHZ(chan) && !IS_CHAN_A_FAST_CLOCK(ah, chan)) { +		if (AR_SREV_9280_20(ah)) { +			ref_div = 10; +			pll_div = 0x50; +		} else { +			pll_div = 0x28; +		} +	} + +	pll = SM(ref_div, AR_RTC_9160_PLL_REFDIV); +	pll |= SM(pll_div, AR_RTC_9160_PLL_DIV);  	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;  } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index e8ac70da5ac..2339728a730 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -653,8 +653,8 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {  	{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},  	{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},  	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, -	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, -	{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, +	{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, +	{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},  	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},  	{0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},  	{0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, @@ -761,7 +761,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {  	{0x0000a3ec, 0x20202020},  	{0x0000a3f0, 0x00000000},  	{0x0000a3f4, 0x00000246}, -	{0x0000a3f8, 0x0cdbd380}, +	{0x0000a3f8, 0x0c9bd380},  	{0x0000a3fc, 0x000f0f01},  	{0x0000a400, 0x8fa91f01},  	{0x0000a404, 0x00000000}, @@ -780,7 +780,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {  	{0x0000a43c, 0x00100000},  	{0x0000a440, 0x00000000},  	{0x0000a444, 0x00000000}, -	{0x0000a448, 0x06000080}, +	{0x0000a448, 0x05000080},  	{0x0000a44c, 0x00000001},  	{0x0000a450, 0x00010000},  	{0x0000a458, 0x00000000}, @@ -1500,8 +1500,6 @@ static const u32 ar9300_2p2_mac_core[][2] = {  	{0x0000816c, 0x00000000},  	{0x000081c0, 0x00000000},  	{0x000081c4, 0x33332210}, -	{0x000081c8, 0x00000000}, -	{0x000081cc, 0x00000000},  	{0x000081ec, 0x00000000},  	{0x000081f0, 0x00000000},  	{0x000081f4, 0x00000000}, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index ff8150e46f0..1d09f22fee4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -1461,7 +1461,7 @@ static const struct ar9300_eeprom ar9300_h112 = {  		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },  		{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, -		{ { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, +		{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },  		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },  		{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, @@ -2616,7 +2616,7 @@ static const struct ar9300_eeprom ar9300_h116 = {  		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },  		 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, -		 { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, +		 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },  		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },  		 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, @@ -3324,6 +3324,8 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,  	read = ar9300_read_eeprom;  	if (AR_SREV_9485(ah))  		cptr = AR9300_BASE_ADDR_4K; +	else if (AR_SREV_9330(ah)) +		cptr = AR9300_BASE_ADDR_512;  	else  		cptr = AR9300_BASE_ADDR;  	ath_dbg(common, ATH_DBG_EEPROM, @@ -3442,7 +3444,7 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)  {  	int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz); -	if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) +	if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))  		REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);  	else {  		REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); @@ -3523,7 +3525,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)  		}  	} -	if (AR_SREV_9485(ah)) { +	if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {  		value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1);  		/*  		 * main_lnaconf, alt_lnaconf, main_tb, alt_tb @@ -3710,7 +3712,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)  		ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);  	if (internal_regulator) { -		if (AR_SREV_9485(ah)) { +		if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {  			int reg_pmu_set;  			reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM; @@ -3718,9 +3720,24 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)  			if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))  				return; -			reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) | -				      (2 << 14) | (6 << 17) | (1 << 20) | -				      (3 << 24) | (1 << 28); +			if (AR_SREV_9330(ah)) { +				if (ah->is_clk_25mhz) { +					reg_pmu_set = (3 << 1) | (8 << 4) | +						      (3 << 8) | (1 << 14) | +						      (6 << 17) | (1 << 20) | +						      (3 << 24); +				} else { +					reg_pmu_set = (4 << 1)  | (7 << 4) | +						      (3 << 8)  | (1 << 14) | +						      (6 << 17) | (1 << 20) | +						      (3 << 24); +				} +			} else { +				reg_pmu_set = (5 << 1) | (7 << 4) | +					      (1 << 8) | (2 << 14) | +					      (6 << 17) | (1 << 20) | +					      (3 << 24) | (1 << 28); +			}  			REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);  			if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set)) @@ -3751,7 +3768,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)  					   AR_RTC_REG_CONTROL1_SWREG_PROGRAM);  		}  	} else { -		if (AR_SREV_9485(ah)) { +		if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {  			REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);  			while (REG_READ_FIELD(ah, AR_PHY_PMU2,  					      AR_PHY_PMU2_PGM)) @@ -3795,9 +3812,9 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,  	ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));  	ar9003_hw_drive_strength_apply(ah);  	ar9003_hw_atten_apply(ah, chan); -	if (!AR_SREV_9340(ah)) +	if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))  		ar9003_hw_internal_regulator_apply(ah); -	if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) +	if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))  		ar9003_hw_apply_tuning_caps(ah);  } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 392bf0f8ff1..8efdec247c0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -19,6 +19,8 @@  #include "ar9003_2p2_initvals.h"  #include "ar9485_initvals.h"  #include "ar9340_initvals.h" +#include "ar9330_1p1_initvals.h" +#include "ar9330_1p2_initvals.h"  /* General hardware code for the AR9003 hadware family */ @@ -29,7 +31,113 @@   */  static void ar9003_hw_init_mode_regs(struct ath_hw *ah)  { -	if (AR_SREV_9340(ah)) { +	if (AR_SREV_9330_11(ah)) { +		/* mac */ +		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], +				ar9331_1p1_mac_core, +				ARRAY_SIZE(ar9331_1p1_mac_core), 2); +		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], +				ar9331_1p1_mac_postamble, +				ARRAY_SIZE(ar9331_1p1_mac_postamble), 5); + +		/* bb */ +		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], +				ar9331_1p1_baseband_core, +				ARRAY_SIZE(ar9331_1p1_baseband_core), 2); +		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], +				ar9331_1p1_baseband_postamble, +				ARRAY_SIZE(ar9331_1p1_baseband_postamble), 5); + +		/* radio */ +		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], +				ar9331_1p1_radio_core, +				ARRAY_SIZE(ar9331_1p1_radio_core), 2); +		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0); + +		/* soc */ +		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], +				ar9331_1p1_soc_preamble, +				ARRAY_SIZE(ar9331_1p1_soc_preamble), 2); +		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], +				ar9331_1p1_soc_postamble, +				ARRAY_SIZE(ar9331_1p1_soc_postamble), 2); + +		/* rx/tx gain */ +		INIT_INI_ARRAY(&ah->iniModesRxGain, +				ar9331_common_rx_gain_1p1, +				ARRAY_SIZE(ar9331_common_rx_gain_1p1), 2); +		INIT_INI_ARRAY(&ah->iniModesTxGain, +			ar9331_modes_lowest_ob_db_tx_gain_1p1, +			ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1), +			5); + +		/* additional clock settings */ +		if (ah->is_clk_25mhz) +			INIT_INI_ARRAY(&ah->iniModesAdditional, +					ar9331_1p1_xtal_25M, +					ARRAY_SIZE(ar9331_1p1_xtal_25M), 2); +		else +			INIT_INI_ARRAY(&ah->iniModesAdditional, +					ar9331_1p1_xtal_40M, +					ARRAY_SIZE(ar9331_1p1_xtal_40M), 2); +	} else if (AR_SREV_9330_12(ah)) { +		/* mac */ +		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], +				ar9331_1p2_mac_core, +				ARRAY_SIZE(ar9331_1p2_mac_core), 2); +		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], +				ar9331_1p2_mac_postamble, +				ARRAY_SIZE(ar9331_1p2_mac_postamble), 5); + +		/* bb */ +		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], +				ar9331_1p2_baseband_core, +				ARRAY_SIZE(ar9331_1p2_baseband_core), 2); +		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], +				ar9331_1p2_baseband_postamble, +				ARRAY_SIZE(ar9331_1p2_baseband_postamble), 5); + +		/* radio */ +		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], +				ar9331_1p2_radio_core, +				ARRAY_SIZE(ar9331_1p2_radio_core), 2); +		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0); + +		/* soc */ +		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], +				ar9331_1p2_soc_preamble, +				ARRAY_SIZE(ar9331_1p2_soc_preamble), 2); +		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], +				ar9331_1p2_soc_postamble, +				ARRAY_SIZE(ar9331_1p2_soc_postamble), 2); + +		/* rx/tx gain */ +		INIT_INI_ARRAY(&ah->iniModesRxGain, +				ar9331_common_rx_gain_1p2, +				ARRAY_SIZE(ar9331_common_rx_gain_1p2), 2); +		INIT_INI_ARRAY(&ah->iniModesTxGain, +			ar9331_modes_lowest_ob_db_tx_gain_1p2, +			ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2), +			5); + +		/* additional clock settings */ +		if (ah->is_clk_25mhz) +			INIT_INI_ARRAY(&ah->iniModesAdditional, +					ar9331_1p2_xtal_25M, +					ARRAY_SIZE(ar9331_1p2_xtal_25M), 2); +		else +			INIT_INI_ARRAY(&ah->iniModesAdditional, +					ar9331_1p2_xtal_40M, +					ARRAY_SIZE(ar9331_1p2_xtal_40M), 2); +	} else if (AR_SREV_9340(ah)) {  		/* mac */  		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);  		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], @@ -220,7 +328,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)  	switch (ar9003_hw_get_tx_gain_idx(ah)) {  	case 0:  	default: -		if (AR_SREV_9340(ah)) +		if (AR_SREV_9330_12(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9331_modes_lowest_ob_db_tx_gain_1p2, +				ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2), +				5); +		else if (AR_SREV_9330_11(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9331_modes_lowest_ob_db_tx_gain_1p1, +				ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1), +				5); +		else if (AR_SREV_9340(ah))  			INIT_INI_ARRAY(&ah->iniModesTxGain,  					ar9340Modes_lowest_ob_db_tx_gain_table_1p0,  				       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), @@ -237,7 +355,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)  				       5);  		break;  	case 1: -		if (AR_SREV_9340(ah)) +		if (AR_SREV_9330_12(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9331_modes_high_ob_db_tx_gain_1p2, +				ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2), +				5); +		else if (AR_SREV_9330_11(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9331_modes_high_ob_db_tx_gain_1p1, +				ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1), +				5); +		else if (AR_SREV_9340(ah))  			INIT_INI_ARRAY(&ah->iniModesTxGain,  					ar9340Modes_lowest_ob_db_tx_gain_table_1p0,  				       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), @@ -254,7 +382,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)  				       5);  		break;  	case 2: -		if (AR_SREV_9340(ah)) +		if (AR_SREV_9330_12(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9331_modes_low_ob_db_tx_gain_1p2, +				ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2), +				5); +		else if (AR_SREV_9330_11(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9331_modes_low_ob_db_tx_gain_1p1, +				ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1), +				5); +		else if (AR_SREV_9340(ah))  			INIT_INI_ARRAY(&ah->iniModesTxGain,  					ar9340Modes_lowest_ob_db_tx_gain_table_1p0,  				       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), @@ -271,7 +409,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)  				       5);  		break;  	case 3: -		if (AR_SREV_9340(ah)) +		if (AR_SREV_9330_12(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9331_modes_high_power_tx_gain_1p2, +				ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2), +				5); +		else if (AR_SREV_9330_11(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9331_modes_high_power_tx_gain_1p1, +				ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1), +				5); +		else if (AR_SREV_9340(ah))  			INIT_INI_ARRAY(&ah->iniModesTxGain,  					ar9340Modes_lowest_ob_db_tx_gain_table_1p0,  				       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), @@ -295,7 +443,17 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)  	switch (ar9003_hw_get_rx_gain_idx(ah)) {  	case 0:  	default: -		if (AR_SREV_9340(ah)) +		if (AR_SREV_9330_12(ah)) +			INIT_INI_ARRAY(&ah->iniModesRxGain, +					ar9331_common_rx_gain_1p2, +					ARRAY_SIZE(ar9331_common_rx_gain_1p2), +					2); +		else if (AR_SREV_9330_11(ah)) +			INIT_INI_ARRAY(&ah->iniModesRxGain, +					ar9331_common_rx_gain_1p1, +					ARRAY_SIZE(ar9331_common_rx_gain_1p1), +					2); +		else if (AR_SREV_9340(ah))  			INIT_INI_ARRAY(&ah->iniModesRxGain,  				       ar9340Common_rx_gain_table_1p0,  				       ARRAY_SIZE(ar9340Common_rx_gain_table_1p0), @@ -312,7 +470,17 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)  				       2);  		break;  	case 1: -		if (AR_SREV_9340(ah)) +		if (AR_SREV_9330_12(ah)) +			INIT_INI_ARRAY(&ah->iniModesRxGain, +				ar9331_common_wo_xlna_rx_gain_1p2, +				ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2), +				2); +		else if (AR_SREV_9330_11(ah)) +			INIT_INI_ARRAY(&ah->iniModesRxGain, +				ar9331_common_wo_xlna_rx_gain_1p1, +				ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1), +				2); +		else if (AR_SREV_9340(ah))  			INIT_INI_ARRAY(&ah->iniModesRxGain,  				       ar9340Common_wo_xlna_rx_gain_table_1p0,  				       ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0), diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 10d71f7d3fc..8ff0b88a29b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -43,13 +43,6 @@ static void ar9003_hw_set_desc_link(void *ds, u32 ds_link)  	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; @@ -236,6 +229,7 @@ static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,  static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,  				 struct ath_tx_status *ts)  { +	struct ar9003_txc *txc = (struct ar9003_txc *) ds;  	struct ar9003_txs *ads;  	u32 status; @@ -245,7 +239,11 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,  	if ((status & AR_TxDone) == 0)  		return -EINPROGRESS; -	ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; +	ts->qid = MS(ads->ds_info, AR_TxQcuNum); +	if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid)) +		ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; +	else +		return -ENOENT;  	if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||  	    (MS(ads->ds_info, AR_TxRxDesc) != 1)) { @@ -261,7 +259,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,  	ts->ts_seqnum = MS(status, AR_SeqNum);  	ts->tid = MS(status, AR_TxTid); -	ts->qid = MS(ads->ds_info, AR_TxQcuNum);  	ts->desc_id = MS(ads->status1, AR_TxDescId);  	ts->ts_tstamp = ads->status4;  	ts->ts_status = 0; @@ -498,7 +495,6 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *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; @@ -629,8 +625,7 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,  			rxs->rs_status |= ATH9K_RXERR_DECRYPT;  		else if (rxsp->status11 & AR_MichaelErr)  			rxs->rs_status |= ATH9K_RXERR_MIC; - -		if (rxsp->status11 & AR_KeyMiss) +		else if (rxsp->status11 & AR_KeyMiss)  			rxs->rs_status |= ATH9K_RXERR_DECRYPT;  	} diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index e4d6a87ec53..f80d1d63398 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -21,6 +21,36 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val)  {  	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);  	struct ath9k_channel *chan = ah->curchan; +	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + +	/* +	 * 3 bits for modalHeader5G.papdRateMaskHt20 +	 * is used for sub-band disabling of PAPRD. +	 * 5G band is divided into 3 sub-bands -- upper, +	 * middle, lower. +	 * if bit 30 of modalHeader5G.papdRateMaskHt20 is set +	 * -- disable PAPRD for upper band 5GHz +	 * if bit 29 of modalHeader5G.papdRateMaskHt20 is set +	 * -- disable PAPRD for middle band 5GHz +	 * if bit 28 of modalHeader5G.papdRateMaskHt20 is set +	 * -- disable PAPRD for lower band 5GHz +	 */ + +	if (IS_CHAN_5GHZ(chan)) { +		if (chan->channel >= UPPER_5G_SUB_BAND_START) { +			if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20) +								  & BIT(30)) +				val = false; +		} else if (chan->channel >= MID_5G_SUB_BAND_START) { +			if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20) +								  & BIT(29)) +				val = false; +		} else { +			if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20) +								  & BIT(28)) +				val = false; +		} +	}  	if (val) {  		ah->paprd_table_write_done = true; @@ -46,11 +76,10 @@ EXPORT_SYMBOL(ar9003_paprd_enable);  static int ar9003_get_training_power_2g(struct ath_hw *ah)  { -	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; -	struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G; +	struct ath9k_channel *chan = ah->curchan;  	unsigned int power, scale, delta; -	scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1); +	scale = ar9003_get_paprd_scale_factor(ah, chan);  	power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,  			       AR_PHY_POWERTX_RATE5_POWERTXHT20_0); @@ -67,20 +96,10 @@ static int ar9003_get_training_power_2g(struct ath_hw *ah)  static int ar9003_get_training_power_5g(struct ath_hw *ah)  {  	struct ath_common *common = ath9k_hw_common(ah); -	struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; -	struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G;  	struct ath9k_channel *chan = ah->curchan;  	unsigned int power, scale, delta; -	if (chan->channel >= 5700) -		scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), -			   AR9300_PAPRD_SCALE_1); -	else if (chan->channel >= 5400) -		scale = MS(le32_to_cpu(hdr->papdRateMaskHt40), -			   AR9300_PAPRD_SCALE_2); -	else -		scale = MS(le32_to_cpu(hdr->papdRateMaskHt40), -			   AR9300_PAPRD_SCALE_1); +	scale = ar9003_get_paprd_scale_factor(ah, chan);  	if (IS_CHAN_HT40(chan))  		power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8, @@ -94,7 +113,23 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)  	if (delta > scale)  		return -1; -	power += 2 * get_streams(common->tx_chainmask); +	switch (get_streams(common->tx_chainmask)) { +	case 1: +		delta = 6; +		break; +	case 2: +		delta = 4; +		break; +	case 3: +		delta = 2; +		break; +	default: +		delta = 0; +		ath_dbg(common, ATH_DBG_CALIBRATE, +		"Invalid tx-chainmask: %u\n", common->tx_chainmask); +	} + +	power += delta;  	return power;  } @@ -119,15 +154,16 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)  	else  		training_power = ar9003_get_training_power_5g(ah); +	ath_dbg(common, ATH_DBG_CALIBRATE, +		"Training power: %d, Target power: %d\n", +		training_power, ah->paprd_target_power); +  	if (training_power < 0) {  		ath_dbg(common, ATH_DBG_CALIBRATE,  			"PAPRD target power delta out of range");  		return -ERANGE;  	}  	ah->paprd_training_power = training_power; -	ath_dbg(common, ATH_DBG_CALIBRATE, -		"Training power: %d, Target power: %d\n", -		ah->paprd_training_power, ah->paprd_target_power);  	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,  		      ah->paprd_ratemask); @@ -230,7 +266,7 @@ static void ar9003_paprd_get_gain_table(struct ath_hw *ah)  	memset(entry, 0, sizeof(ah->paprd_gain_table_entries));  	memset(index, 0, sizeof(ah->paprd_gain_table_index)); -	for (i = 0; i < 32; i++) { +	for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {  		entry[i] = REG_READ(ah, reg);  		index[i] = (entry[i] >> 24) & 0xff;  		reg += 4; @@ -240,13 +276,13 @@ static void ar9003_paprd_get_gain_table(struct ath_hw *ah)  static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,  					    int target_power)  { -	int olpc_gain_delta = 0; +	int olpc_gain_delta = 0, cl_gain_mod;  	int alpha_therm, alpha_volt;  	int therm_cal_value, volt_cal_value;  	int therm_value, volt_value;  	int thermal_gain_corr, voltage_gain_corr;  	int desired_scale, desired_gain = 0; -	u32 reg; +	u32 reg_olpc  = 0, reg_cl_gain  = 0;  	REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,  		    AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); @@ -265,15 +301,29 @@ static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,  	volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,  				    AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE); -	if (chain == 0) -		reg = AR_PHY_TPC_11_B0; -	else if (chain == 1) -		reg = AR_PHY_TPC_11_B1; -	else -		reg = AR_PHY_TPC_11_B2; +	switch (chain) { +	case 0: +		reg_olpc = AR_PHY_TPC_11_B0; +		reg_cl_gain = AR_PHY_CL_TAB_0; +		break; +	case 1: +		reg_olpc = AR_PHY_TPC_11_B1; +		reg_cl_gain = AR_PHY_CL_TAB_1; +		break; +	case 2: +		reg_olpc = AR_PHY_TPC_11_B2; +		reg_cl_gain = AR_PHY_CL_TAB_2; +		break; +	default: +		ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, +		"Invalid chainmask: %d\n", chain); +		break; +	} -	olpc_gain_delta = REG_READ_FIELD(ah, reg, +	olpc_gain_delta = REG_READ_FIELD(ah, reg_olpc,  					 AR_PHY_TPC_11_OLPC_GAIN_DELTA); +	cl_gain_mod = REG_READ_FIELD(ah, reg_cl_gain, +					 AR_PHY_CL_TAB_CL_GAIN_MOD);  	if (olpc_gain_delta >= 128)  		olpc_gain_delta = olpc_gain_delta - 256; @@ -283,7 +333,7 @@ static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,  	voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +  			     (128 / 2)) / 128;  	desired_gain = target_power - olpc_gain_delta - thermal_gain_corr - -	    voltage_gain_corr + desired_scale; +	    voltage_gain_corr + desired_scale + cl_gain_mod;  	return desired_gain;  } @@ -721,7 +771,7 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)  	desired_gain = ar9003_get_desired_gain(ah, chain, train_power);  	gain_index = 0; -	for (i = 0; i < 32; i++) { +	for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {  		if (ah->paprd_gain_table_index[i] >= desired_gain)  			break;  		gain_index++; @@ -795,7 +845,26 @@ EXPORT_SYMBOL(ar9003_paprd_init_table);  bool ar9003_paprd_is_done(struct ath_hw *ah)  { -	return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1, +	int paprd_done, agc2_pwr; +	paprd_done = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,  				AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); + +	if (paprd_done == 0x1) { +		agc2_pwr = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1, +				AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR); + +		ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, +			"AGC2_PWR = 0x%x training done = 0x%x\n", +			agc2_pwr, paprd_done); +	/* +	 * agc2_pwr range should not be less than 'IDEAL_AGC2_PWR_CHANGE' +	 * when the training is completely done, otherwise retraining is +	 * done to make sure the value is in ideal range +	 */ +		if (agc2_pwr <= PAPRD_IDEAL_AGC2_PWR_RANGE) +			paprd_done = 0; +	} + +	return !!paprd_done;  }  EXPORT_SYMBOL(ar9003_paprd_is_done); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 892c48b1543..1baca8e4715 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -75,7 +75,19 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)  	freq = centers.synth_center;  	if (freq < 4800) {     /* 2 GHz, fractional mode */ -		if (AR_SREV_9485(ah)) { +		if (AR_SREV_9330(ah)) { +			u32 chan_frac; +			u32 div; + +			if (ah->is_clk_25mhz) +				div = 75; +			else +				div = 120; + +			channelSel = (freq * 4) / div; +			chan_frac = (((freq * 4) % div) * 0x20000) / div; +			channelSel = (channelSel << 17) | chan_frac; +		} else if (AR_SREV_9485(ah)) {  			u32 chan_frac;  			/* @@ -104,7 +116,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)  			u32 chan_frac;  			channelSel = (freq * 2) / 75; -			chan_frac = ((freq % 75) * 0x20000) / 75; +			chan_frac = (((freq * 2) % 75) * 0x20000) / 75;  			channelSel = (channelSel << 17) | chan_frac;  		} else {  			channelSel = CHANSEL_5G(freq); @@ -168,7 +180,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,  	 * is out-of-band and can be ignored.  	 */ -	if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) { +	if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {  		spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,  							 IS_CHAN_2GHZ(chan));  		if (spur_fbin_ptr[0] == 0) /* No spur */ @@ -193,7 +205,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,  	for (i = 0; i < max_spur_cnts; i++) {  		negative = 0; -		if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) +		if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))  			cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],  					IS_CHAN_2GHZ(chan)) - synth_freq;  		else @@ -659,6 +671,9 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,  		REG_WRITE_ARRAY(&ah->iniModesAdditional,  				modesIndex, regWrites); +	if (AR_SREV_9300(ah)) +		REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites); +  	if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)  		REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites); @@ -1074,7 +1089,10 @@ static 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_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ; +	if (AR_SREV_9330(ah)) +		ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9330_2GHZ; +	else +		ah->nf_2g.nominal = AR_PHY_CCA_NOM_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;  	ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ; @@ -1196,8 +1214,17 @@ static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah,  				 AR_PHY_9485_ANT_DIV_ALT_LNACONF_S;  	antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >>  				  AR_PHY_9485_ANT_FAST_DIV_BIAS_S; -	antconf->lna1_lna2_delta = -9; -	antconf->div_group = 2; + +	if (AR_SREV_9330_11(ah)) { +		antconf->lna1_lna2_delta = -9; +		antconf->div_group = 1; +	} else if (AR_SREV_9485(ah)) { +		antconf->lna1_lna2_delta = -9; +		antconf->div_group = 2; +	} else { +		antconf->lna1_lna2_delta = -3; +		antconf->div_group = 0; +	}  }  static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 443090d278e..6de3f0bc18e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -332,6 +332,8 @@  #define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -95  #define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -100 +#define AR_PHY_CCA_NOM_VAL_9330_2GHZ          -118 +  /*   * AGC Field Definitions   */ @@ -623,11 +625,11 @@  #define AR_PHY_65NM_CH2_RXTX1       0x16900  #define AR_PHY_65NM_CH2_RXTX2       0x16904 -#define AR_CH0_TOP2 (AR_SREV_9485(ah) ? 0x00016284 : 0x0001628c) +#define AR_CH0_TOP2		(AR_SREV_9300(ah) ? 0x1628c : 0x16284)  #define AR_CH0_TOP2_XPABIASLVL		0xf000  #define AR_CH0_TOP2_XPABIASLVL_S	12 -#define AR_CH0_XTAL		(AR_SREV_9485(ah) ? 0x16290 : 0x16294) +#define AR_CH0_XTAL		(AR_SREV_9300(ah) ? 0x16294 : 0x16290)  #define AR_CH0_XTAL_CAPINDAC	0x7f000000  #define AR_CH0_XTAL_CAPINDAC_S	24  #define AR_CH0_XTAL_CAPOUTDAC	0x00fe0000 @@ -1119,6 +1121,9 @@  #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5	0x3F00  #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S	8 +#define AR_PHY_CL_TAB_CL_GAIN_MOD		0x1f +#define AR_PHY_CL_TAB_CL_GAIN_MOD_S		0 +  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/ar9330_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h new file mode 100644 index 00000000000..f11d9b2677f --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h @@ -0,0 +1,1147 @@ +/* + * Copyright (c) 2011 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_9330_1P1_H +#define INITVALS_9330_1P1_H + +static const u32 ar9331_1p1_baseband_postamble[][5] = { +	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, +	{0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e}, +	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, +	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, +	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, +	{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, +	{0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044}, +	{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4}, +	{0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, +	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, +	{0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e}, +	{0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, +	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, +	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, +	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221}, +	{0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, +	{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, +	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, +	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, +	{0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0}, +	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, +	{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, +	{0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff}, +	{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, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501}, +	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, +	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, +	{0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, +	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981}, +	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, +	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, +	{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +}; + +static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p1[][5] = { +	/*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, +	{0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52}, +	{0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84}, +	{0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000}, +	{0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000}, +	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0}, +	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, +	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, +	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, +	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, +	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, +	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00}, +	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02}, +	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04}, +	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20}, +	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22}, +	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24}, +	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43}, +	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42}, +	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44}, +	{0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64}, +	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66}, +	{0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200}, +	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202}, +	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400}, +	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402}, +	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404}, +	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603}, +	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02}, +	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04}, +	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20}, +	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20}, +	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22}, +	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24}, +	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640}, +	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660}, +	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861}, +	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81}, +	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83}, +	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84}, +	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3}, +	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9}, +	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb}, +	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec}, +	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802}, +	{0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802}, +	{0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03}, +	{0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db}, +	{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000}, +}; + +static const u32 ar9331_modes_high_ob_db_tx_gain_1p1[][5] = { +	/*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, +	{0x0000a2dc, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52}, +	{0x0000a2e0, 0xffb31c84, 0xffb31c84, 0xffb31c84, 0xffb31c84}, +	{0x0000a2e4, 0xff43e000, 0xff43e000, 0xff43e000, 0xff43e000}, +	{0x0000a2e8, 0xfffc0000, 0xfffc0000, 0xfffc0000, 0xfffc0000}, +	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7}, +	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, +	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, +	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, +	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, +	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, +	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00}, +	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02}, +	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04}, +	{0x0000a52c, 0x41023e85, 0x41023e85, 0x3d001620, 0x3d001620}, +	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x3f001621, 0x3f001621}, +	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x42001640, 0x42001640}, +	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x44001641, 0x44001641}, +	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x46001642, 0x46001642}, +	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49001644, 0x49001644}, +	{0x0000a544, 0x6502feca, 0x6502feca, 0x4c001a81, 0x4c001a81}, +	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4f001a83, 0x4f001a83}, +	{0x0000a54c, 0x7203feca, 0x7203feca, 0x52001c84, 0x52001c84}, +	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001ce3, 0x55001ce3}, +	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x59001ce5, 0x59001ce5}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5d001ce9, 0x5d001ce9}, +	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x64001eec, 0x64001eec}, +	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x64001eec, 0x64001eec}, +	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x64001eec, 0x64001eec}, +	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec}, +	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec}, +	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec}, +	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec}, +	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec}, +	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec}, +	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200}, +	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202}, +	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400}, +	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402}, +	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404}, +	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603}, +	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02}, +	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04}, +	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20}, +	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20}, +	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22}, +	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24}, +	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640}, +	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660}, +	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861}, +	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81}, +	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83}, +	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84}, +	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3}, +	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9}, +	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb}, +	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec}, +	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802}, +	{0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802}, +	{0x0000a624, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03}, +	{0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a62c, 0x04015005, 0x04015005, 0x04015005, 0x04015005}, +	{0x0000a630, 0x04015005, 0x04015005, 0x04015005, 0x04015005}, +	{0x0000a634, 0x04015005, 0x04015005, 0x04015005, 0x04015005}, +	{0x0000a638, 0x04015005, 0x04015005, 0x04015005, 0x04015005}, +	{0x0000a63c, 0x04015005, 0x04015005, 0x04015005, 0x04015005}, +}; + +static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = { +	/*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, +	{0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52}, +	{0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84}, +	{0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000}, +	{0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000}, +	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0}, +	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, +	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, +	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, +	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, +	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, +	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00}, +	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02}, +	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04}, +	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20}, +	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22}, +	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24}, +	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43}, +	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42}, +	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44}, +	{0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64}, +	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66}, +	{0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200}, +	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202}, +	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400}, +	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402}, +	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404}, +	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603}, +	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02}, +	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04}, +	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20}, +	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20}, +	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22}, +	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24}, +	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640}, +	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660}, +	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861}, +	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81}, +	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83}, +	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84}, +	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3}, +	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9}, +	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb}, +	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec}, +	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802}, +	{0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802}, +	{0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03}, +	{0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db}, +	{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000}, +}; + +static const u32 ar9331_1p1_baseband_core_txfir_coeff_japan_2484[][2] = { +	/* Addr      allmodes  */ +	{0x0000a398, 0x00000000}, +	{0x0000a39c, 0x6f7f0301}, +	{0x0000a3a0, 0xca9228ee}, +}; + +static const u32 ar9331_1p1_xtal_25M[][2] = { +	/* Addr      allmodes  */ +	{0x00007038, 0x000002f8}, +	{0x00008244, 0x0010f3d7}, +	{0x0000824c, 0x0001e7ae}, +	{0x0001609c, 0x0f508f29}, +}; + +static const u32 ar9331_1p1_radio_core[][2] = { +	/* Addr      allmodes  */ +	{0x00016000, 0x36db6db6}, +	{0x00016004, 0x6db6db40}, +	{0x00016008, 0x73800000}, +	{0x0001600c, 0x00000000}, +	{0x00016040, 0x7f80fff8}, +	{0x00016044, 0x03db62db}, +	{0x00016048, 0x6c924268}, +	{0x0001604c, 0x000f0278}, +	{0x00016050, 0x4db6db8c}, +	{0x00016054, 0x6db60000}, +	{0x00016080, 0x00080000}, +	{0x00016084, 0x0e48048c}, +	{0x00016088, 0x14214514}, +	{0x0001608c, 0x119f081c}, +	{0x00016090, 0x24926490}, +	{0x00016098, 0xd411eb84}, +	{0x000160a0, 0xc2108ffe}, +	{0x000160a4, 0x812fc370}, +	{0x000160a8, 0x423c8000}, +	{0x000160ac, 0x24651800}, +	{0x000160b0, 0x03284f3e}, +	{0x000160b4, 0x92480040}, +	{0x000160c0, 0x006db6db}, +	{0x000160c4, 0x0186db60}, +	{0x000160c8, 0x6db6db6c}, +	{0x000160cc, 0x6de6c300}, +	{0x000160d0, 0x14500820}, +	{0x00016100, 0x04cb0001}, +	{0x00016104, 0xfff80015}, +	{0x00016108, 0x00080010}, +	{0x0001610c, 0x00170000}, +	{0x00016140, 0x10804000}, +	{0x00016144, 0x01884080}, +	{0x00016148, 0x000080c0}, +	{0x00016280, 0x01000015}, +	{0x00016284, 0x14d20000}, +	{0x00016288, 0x00318000}, +	{0x0001628c, 0x50000000}, +	{0x00016290, 0x4b96210f}, +	{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}, +}; + +static const u32 ar9331_1p1_soc_postamble[][5] = { +	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022}, +}; + +static const u32 ar9331_common_wo_xlna_rx_gain_1p1[][2] = { +	/* Addr      allmodes  */ +	{0x0000a000, 0x00060005}, +	{0x0000a004, 0x00810080}, +	{0x0000a008, 0x00830082}, +	{0x0000a00c, 0x00850084}, +	{0x0000a010, 0x01820181}, +	{0x0000a014, 0x01840183}, +	{0x0000a018, 0x01880185}, +	{0x0000a01c, 0x018a0189}, +	{0x0000a020, 0x02850284}, +	{0x0000a024, 0x02890288}, +	{0x0000a028, 0x028b028a}, +	{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, 0x24242428}, +	{0x0000a098, 0x171e1e1e}, +	{0x0000a09c, 0x02020b0b}, +	{0x0000a0a0, 0x02020202}, +	{0x0000a0a4, 0x00000000}, +	{0x0000a0a8, 0x00000000}, +	{0x0000a0ac, 0x00000000}, +	{0x0000a0b0, 0x00000000}, +	{0x0000a0b4, 0x00000000}, +	{0x0000a0b8, 0x00000000}, +	{0x0000a0bc, 0x00000000}, +	{0x0000a0c0, 0x22072208}, +	{0x0000a0c4, 0x22052206}, +	{0x0000a0c8, 0x22032204}, +	{0x0000a0cc, 0x22012202}, +	{0x0000a0d0, 0x221f2200}, +	{0x0000a0d4, 0x221d221e}, +	{0x0000a0d8, 0x33023303}, +	{0x0000a0dc, 0x33003301}, +	{0x0000a0e0, 0x331e331f}, +	{0x0000a0e4, 0x4402331d}, +	{0x0000a0e8, 0x44004401}, +	{0x0000a0ec, 0x441e441f}, +	{0x0000a0f0, 0x55025503}, +	{0x0000a0f4, 0x55005501}, +	{0x0000a0f8, 0x551e551f}, +	{0x0000a0fc, 0x6602551d}, +	{0x0000a100, 0x66006601}, +	{0x0000a104, 0x661e661f}, +	{0x0000a108, 0x7703661d}, +	{0x0000a10c, 0x77017702}, +	{0x0000a110, 0x00007700}, +	{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, 0x111f1100}, +	{0x0000a148, 0x111d111e}, +	{0x0000a14c, 0x111b111c}, +	{0x0000a150, 0x22032204}, +	{0x0000a154, 0x22012202}, +	{0x0000a158, 0x221f2200}, +	{0x0000a15c, 0x221d221e}, +	{0x0000a160, 0x33013302}, +	{0x0000a164, 0x331f3300}, +	{0x0000a168, 0x4402331e}, +	{0x0000a16c, 0x44004401}, +	{0x0000a170, 0x441e441f}, +	{0x0000a174, 0x55015502}, +	{0x0000a178, 0x551f5500}, +	{0x0000a17c, 0x6602551e}, +	{0x0000a180, 0x66006601}, +	{0x0000a184, 0x661e661f}, +	{0x0000a188, 0x7703661d}, +	{0x0000a18c, 0x77017702}, +	{0x0000a190, 0x00007700}, +	{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}, +}; + +static const u32 ar9331_1p1_baseband_core[][2] = { +	/* Addr      allmodes  */ +	{0x00009800, 0xafe68e30}, +	{0x00009804, 0xfd14e000}, +	{0x00009808, 0x9c0a8f6b}, +	{0x0000980c, 0x04800000}, +	{0x00009814, 0x9280c00a}, +	{0x00009818, 0x00000000}, +	{0x0000981c, 0x00020028}, +	{0x00009834, 0x5f3ca3de}, +	{0x00009838, 0x0108ecff}, +	{0x0000983c, 0x14750600}, +	{0x00009880, 0x201fff00}, +	{0x00009884, 0x00001042}, +	{0x000098a4, 0x00200400}, +	{0x000098b0, 0x32840bbe}, +	{0x000098d0, 0x004b6a8e}, +	{0x000098d4, 0x00000820}, +	{0x000098dc, 0x00000000}, +	{0x000098f0, 0x00000000}, +	{0x000098f4, 0x00000000}, +	{0x00009c04, 0x00000000}, +	{0x00009c08, 0x03200000}, +	{0x00009c0c, 0x00000000}, +	{0x00009c10, 0x00000000}, +	{0x00009c14, 0x00046384}, +	{0x00009c18, 0x05b6b440}, +	{0x00009c1c, 0x00b6b440}, +	{0x00009d00, 0xc080a333}, +	{0x00009d04, 0x40206c10}, +	{0x00009d08, 0x009c4060}, +	{0x00009d0c, 0x1883800a}, +	{0x00009d10, 0x01834061}, +	{0x00009d14, 0x00c00400}, +	{0x00009d18, 0x00000000}, +	{0x00009e08, 0x0038233c}, +	{0x00009e24, 0x9927b515}, +	{0x00009e28, 0x12ef0200}, +	{0x00009e30, 0x06336f77}, +	{0x00009e34, 0x6af6532f}, +	{0x00009e38, 0x0cc80c00}, +	{0x00009e40, 0x0d261820}, +	{0x00009e4c, 0x00001004}, +	{0x00009e50, 0x00ff03f1}, +	{0x00009fc0, 0x803e4788}, +	{0x00009fc4, 0x0001efb5}, +	{0x00009fcc, 0x40000014}, +	{0x0000a20c, 0x00000000}, +	{0x0000a220, 0x00000000}, +	{0x0000a224, 0x00000000}, +	{0x0000a228, 0x10002310}, +	{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, 0x00000006}, +	{0x0000a3f8, 0x0cdbd380}, +	{0x0000a3fc, 0x000f0f01}, +	{0x0000a400, 0x8fa91f01}, +	{0x0000a404, 0x00000000}, +	{0x0000a408, 0x0e79e5c6}, +	{0x0000a40c, 0x00820820}, +	{0x0000a414, 0x1ce739ce}, +	{0x0000a418, 0x2d001dce}, +	{0x0000a41c, 0x1ce739ce}, +	{0x0000a420, 0x000001ce}, +	{0x0000a424, 0x1ce739ce}, +	{0x0000a428, 0x000001ce}, +	{0x0000a42c, 0x1ce739ce}, +	{0x0000a430, 0x1ce739ce}, +	{0x0000a434, 0x00000000}, +	{0x0000a438, 0x00001801}, +	{0x0000a43c, 0x00000000}, +	{0x0000a440, 0x00000000}, +	{0x0000a444, 0x00000000}, +	{0x0000a448, 0x04000000}, +	{0x0000a44c, 0x00000001}, +	{0x0000a450, 0x00010000}, +	{0x0000a458, 0x00000000}, +	{0x0000a640, 0x00000000}, +	{0x0000a644, 0x3fad9d74}, +	{0x0000a648, 0x0048060a}, +	{0x0000a64c, 0x00003c37}, +	{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}, +}; + +static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = { +	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, +	{0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52}, +	{0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84}, +	{0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000}, +	{0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000}, +	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0}, +	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, +	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, +	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, +	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, +	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, +	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00}, +	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02}, +	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04}, +	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20}, +	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22}, +	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24}, +	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43}, +	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42}, +	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44}, +	{0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64}, +	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66}, +	{0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6}, +	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200}, +	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202}, +	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400}, +	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402}, +	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404}, +	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603}, +	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02}, +	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04}, +	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20}, +	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20}, +	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22}, +	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24}, +	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640}, +	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660}, +	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861}, +	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81}, +	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83}, +	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84}, +	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3}, +	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9}, +	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb}, +	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec}, +	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802}, +	{0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802}, +	{0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03}, +	{0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04}, +	{0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db}, +	{0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000}, +}; + +static const u32 ar9331_1p1_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 ar9331_1p1_soc_preamble[][2] = { +	/* Addr      allmodes  */ +	{0x00007020, 0x00000000}, +	{0x00007034, 0x00000002}, +	{0x00007038, 0x000002f8}, +}; + +static const u32 ar9331_1p1_xtal_40M[][2] = { +	/* Addr      allmodes  */ +	{0x00007038, 0x000004c2}, +	{0x00008244, 0x0010f400}, +	{0x0000824c, 0x0001e800}, +	{0x0001609c, 0x0b283f31}, +}; + +static const u32 ar9331_1p1_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}, +	{0x00008248, 0x00000800}, +	{0x00008250, 0x00000000}, +	{0x00008254, 0x00000000}, +	{0x00008258, 0x00000000}, +	{0x0000825c, 0x40000000}, +	{0x00008260, 0x00080922}, +	{0x00008264, 0x9d400010}, +	{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 ar9331_common_rx_gain_1p1[][2] = { +	/* Addr      allmodes  */ +	{0x0000a000, 0x00010000}, +	{0x0000a004, 0x00030002}, +	{0x0000a008, 0x00050004}, +	{0x0000a00c, 0x00810080}, +	{0x0000a010, 0x00830082}, +	{0x0000a014, 0x01810180}, +	{0x0000a018, 0x01830182}, +	{0x0000a01c, 0x01850184}, +	{0x0000a020, 0x01890188}, +	{0x0000a024, 0x018b018a}, +	{0x0000a028, 0x018d018c}, +	{0x0000a02c, 0x01910190}, +	{0x0000a030, 0x01930192}, +	{0x0000a034, 0x01950194}, +	{0x0000a038, 0x038a0196}, +	{0x0000a03c, 0x038c038b}, +	{0x0000a040, 0x0390038d}, +	{0x0000a044, 0x03920391}, +	{0x0000a048, 0x03940393}, +	{0x0000a04c, 0x03960395}, +	{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, 0x22222229}, +	{0x0000a084, 0x1d1d1d1d}, +	{0x0000a088, 0x1d1d1d1d}, +	{0x0000a08c, 0x1d1d1d1d}, +	{0x0000a090, 0x171d1d1d}, +	{0x0000a094, 0x11111717}, +	{0x0000a098, 0x00030311}, +	{0x0000a09c, 0x00000000}, +	{0x0000a0a0, 0x00000000}, +	{0x0000a0a4, 0x00000000}, +	{0x0000a0a8, 0x00000000}, +	{0x0000a0ac, 0x00000000}, +	{0x0000a0b0, 0x00000000}, +	{0x0000a0b4, 0x00000000}, +	{0x0000a0b8, 0x00000000}, +	{0x0000a0bc, 0x00000000}, +	{0x0000a0c0, 0x001f0000}, +	{0x0000a0c4, 0x01000101}, +	{0x0000a0c8, 0x011e011f}, +	{0x0000a0cc, 0x011c011d}, +	{0x0000a0d0, 0x02030204}, +	{0x0000a0d4, 0x02010202}, +	{0x0000a0d8, 0x021f0200}, +	{0x0000a0dc, 0x0302021e}, +	{0x0000a0e0, 0x03000301}, +	{0x0000a0e4, 0x031e031f}, +	{0x0000a0e8, 0x0402031d}, +	{0x0000a0ec, 0x04000401}, +	{0x0000a0f0, 0x041e041f}, +	{0x0000a0f4, 0x0502041d}, +	{0x0000a0f8, 0x05000501}, +	{0x0000a0fc, 0x051e051f}, +	{0x0000a100, 0x06010602}, +	{0x0000a104, 0x061f0600}, +	{0x0000a108, 0x061d061e}, +	{0x0000a10c, 0x07020703}, +	{0x0000a110, 0x07000701}, +	{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, 0x01000101}, +	{0x0000a148, 0x011e011f}, +	{0x0000a14c, 0x011c011d}, +	{0x0000a150, 0x02030204}, +	{0x0000a154, 0x02010202}, +	{0x0000a158, 0x021f0200}, +	{0x0000a15c, 0x0302021e}, +	{0x0000a160, 0x03000301}, +	{0x0000a164, 0x031e031f}, +	{0x0000a168, 0x0402031d}, +	{0x0000a16c, 0x04000401}, +	{0x0000a170, 0x041e041f}, +	{0x0000a174, 0x0502041d}, +	{0x0000a178, 0x05000501}, +	{0x0000a17c, 0x051e051f}, +	{0x0000a180, 0x06010602}, +	{0x0000a184, 0x061f0600}, +	{0x0000a188, 0x061d061e}, +	{0x0000a18c, 0x07020703}, +	{0x0000a190, 0x07000701}, +	{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}, +}; + +static const u32 ar9331_common_tx_gain_offset1_1[][1] = { +	{0}, +	{3}, +	{0}, +	{0}, +}; + +static const u32 ar9331_1p1_chansel_xtal_25M[] = { +	0x0101479e, +	0x0101d027, +	0x010258af, +	0x0102e138, +	0x010369c0, +	0x0103f249, +	0x01047ad1, +	0x0105035a, +	0x01058be2, +	0x0106146b, +	0x01069cf3, +	0x0107257c, +	0x0107ae04, +	0x0108f5b2, +}; + +static const u32 ar9331_1p1_chansel_xtal_40M[] = { +	0x00a0ccbe, +	0x00a12213, +	0x00a17769, +	0x00a1ccbe, +	0x00a22213, +	0x00a27769, +	0x00a2ccbe, +	0x00a32213, +	0x00a37769, +	0x00a3ccbe, +	0x00a42213, +	0x00a47769, +	0x00a4ccbe, +	0x00a5998b, +}; + +#endif /* INITVALS_9330_1P1_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h new file mode 100644 index 00000000000..0e6ca0834b3 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h @@ -0,0 +1,1080 @@ +/* + * Copyright (c) 2011 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_9330_1P2_H +#define INITVALS_9330_1P2_H + +static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p2[][5] = { +	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7}, +	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, +	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, +	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, +	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, +	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, +	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00}, +	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02}, +	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04}, +	{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620}, +	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621}, +	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640}, +	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641}, +	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642}, +	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644}, +	{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81}, +	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83}, +	{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84}, +	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3}, +	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9}, +	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec}, +	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec}, +	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200}, +	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202}, +	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400}, +	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402}, +	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404}, +	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603}, +	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02}, +	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04}, +	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20}, +	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20}, +	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22}, +	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24}, +	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640}, +	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660}, +	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861}, +	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81}, +	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83}, +	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84}, +	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3}, +	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9}, +	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb}, +	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec}, +	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802}, +	{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802}, +	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03}, +	{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +}; + +static const u32 ar9331_1p2_baseband_postamble[][5] = { +	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, +	{0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e}, +	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, +	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, +	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, +	{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, +	{0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044}, +	{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4}, +	{0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, +	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, +	{0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e}, +	{0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, +	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, +	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, +	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221}, +	{0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, +	{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, +	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, +	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, +	{0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0}, +	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, +	{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, +	{0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff}, +	{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, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501}, +	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, +	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, +	{0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, +	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981}, +	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, +	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, +	{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +}; + +static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = { +	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7}, +	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, +	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, +	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, +	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, +	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, +	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00}, +	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02}, +	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04}, +	{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620}, +	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621}, +	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640}, +	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641}, +	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642}, +	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644}, +	{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81}, +	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83}, +	{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84}, +	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3}, +	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9}, +	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec}, +	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec}, +	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200}, +	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202}, +	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400}, +	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402}, +	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404}, +	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603}, +	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02}, +	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04}, +	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20}, +	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20}, +	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22}, +	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24}, +	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640}, +	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660}, +	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861}, +	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81}, +	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83}, +	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84}, +	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3}, +	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9}, +	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb}, +	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec}, +	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802}, +	{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802}, +	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03}, +	{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +}; + +static const u32 ar9331_modes_low_ob_db_tx_gain_1p2[][5] = { +	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7}, +	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, +	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, +	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, +	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, +	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, +	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00}, +	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02}, +	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04}, +	{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620}, +	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621}, +	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640}, +	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641}, +	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642}, +	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644}, +	{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81}, +	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83}, +	{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84}, +	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3}, +	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9}, +	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec}, +	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec}, +	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200}, +	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202}, +	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400}, +	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402}, +	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404}, +	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603}, +	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02}, +	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04}, +	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20}, +	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20}, +	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22}, +	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24}, +	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640}, +	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660}, +	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861}, +	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81}, +	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83}, +	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84}, +	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3}, +	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9}, +	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb}, +	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec}, +	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802}, +	{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802}, +	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03}, +	{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +}; + +static const u32 ar9331_1p2_baseband_core_txfir_coeff_japan_2484[][2] = { +	/* Addr      allmodes  */ +	{0x0000a398, 0x00000000}, +	{0x0000a39c, 0x6f7f0301}, +	{0x0000a3a0, 0xca9228ee}, +}; + +static const u32 ar9331_1p2_xtal_25M[][2] = { +	/* Addr      allmodes  */ +	{0x00007038, 0x000002f8}, +	{0x00008244, 0x0010f3d7}, +	{0x0000824c, 0x0001e7ae}, +	{0x0001609c, 0x0f508f29}, +}; + +static const u32 ar9331_1p2_radio_core[][2] = { +	/* Addr      allmodes  */ +	{0x00016000, 0x36db6db6}, +	{0x00016004, 0x6db6db40}, +	{0x00016008, 0x73800000}, +	{0x0001600c, 0x00000000}, +	{0x00016040, 0x7f80fff8}, +	{0x00016044, 0x03d6d2db}, +	{0x00016048, 0x6c924268}, +	{0x0001604c, 0x000f0278}, +	{0x00016050, 0x4db6db8c}, +	{0x00016054, 0x6db60000}, +	{0x00016080, 0x00080000}, +	{0x00016084, 0x0e48048c}, +	{0x00016088, 0x14214514}, +	{0x0001608c, 0x119f081c}, +	{0x00016090, 0x24926490}, +	{0x00016098, 0xd411eb84}, +	{0x000160a0, 0xc2108ffe}, +	{0x000160a4, 0x812fc370}, +	{0x000160a8, 0x423c8000}, +	{0x000160ac, 0x24651800}, +	{0x000160b0, 0x03284f3e}, +	{0x000160b4, 0x92480040}, +	{0x000160c0, 0x006db6db}, +	{0x000160c4, 0x0186db60}, +	{0x000160c8, 0x6db6db6c}, +	{0x000160cc, 0x6de6c300}, +	{0x000160d0, 0x14500820}, +	{0x00016100, 0x04cb0001}, +	{0x00016104, 0xfff80015}, +	{0x00016108, 0x00080010}, +	{0x0001610c, 0x00170000}, +	{0x00016140, 0x10804000}, +	{0x00016144, 0x01884080}, +	{0x00016148, 0x000080c0}, +	{0x00016280, 0x01000015}, +	{0x00016284, 0x14d20000}, +	{0x00016288, 0x00318000}, +	{0x0001628c, 0x50000000}, +	{0x00016290, 0x4b96210f}, +	{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}, +}; + +static const u32 ar9331_1p2_soc_postamble[][5] = { +	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022}, +}; + +static const u32 ar9331_common_wo_xlna_rx_gain_1p2[][2] = { +	/* Addr      allmodes  */ +	{0x0000a000, 0x00060005}, +	{0x0000a004, 0x00810080}, +	{0x0000a008, 0x00830082}, +	{0x0000a00c, 0x00850084}, +	{0x0000a010, 0x01820181}, +	{0x0000a014, 0x01840183}, +	{0x0000a018, 0x01880185}, +	{0x0000a01c, 0x018a0189}, +	{0x0000a020, 0x02850284}, +	{0x0000a024, 0x02890288}, +	{0x0000a028, 0x028b028a}, +	{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, 0x24242428}, +	{0x0000a098, 0x171e1e1e}, +	{0x0000a09c, 0x02020b0b}, +	{0x0000a0a0, 0x02020202}, +	{0x0000a0a4, 0x00000000}, +	{0x0000a0a8, 0x00000000}, +	{0x0000a0ac, 0x00000000}, +	{0x0000a0b0, 0x00000000}, +	{0x0000a0b4, 0x00000000}, +	{0x0000a0b8, 0x00000000}, +	{0x0000a0bc, 0x00000000}, +	{0x0000a0c0, 0x22072208}, +	{0x0000a0c4, 0x22052206}, +	{0x0000a0c8, 0x22032204}, +	{0x0000a0cc, 0x22012202}, +	{0x0000a0d0, 0x221f2200}, +	{0x0000a0d4, 0x221d221e}, +	{0x0000a0d8, 0x33023303}, +	{0x0000a0dc, 0x33003301}, +	{0x0000a0e0, 0x331e331f}, +	{0x0000a0e4, 0x4402331d}, +	{0x0000a0e8, 0x44004401}, +	{0x0000a0ec, 0x441e441f}, +	{0x0000a0f0, 0x55025503}, +	{0x0000a0f4, 0x55005501}, +	{0x0000a0f8, 0x551e551f}, +	{0x0000a0fc, 0x6602551d}, +	{0x0000a100, 0x66006601}, +	{0x0000a104, 0x661e661f}, +	{0x0000a108, 0x7703661d}, +	{0x0000a10c, 0x77017702}, +	{0x0000a110, 0x00007700}, +	{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, 0x111f1100}, +	{0x0000a148, 0x111d111e}, +	{0x0000a14c, 0x111b111c}, +	{0x0000a150, 0x22032204}, +	{0x0000a154, 0x22012202}, +	{0x0000a158, 0x221f2200}, +	{0x0000a15c, 0x221d221e}, +	{0x0000a160, 0x33013302}, +	{0x0000a164, 0x331f3300}, +	{0x0000a168, 0x4402331e}, +	{0x0000a16c, 0x44004401}, +	{0x0000a170, 0x441e441f}, +	{0x0000a174, 0x55015502}, +	{0x0000a178, 0x551f5500}, +	{0x0000a17c, 0x6602551e}, +	{0x0000a180, 0x66006601}, +	{0x0000a184, 0x661e661f}, +	{0x0000a188, 0x7703661d}, +	{0x0000a18c, 0x77017702}, +	{0x0000a190, 0x00007700}, +	{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}, +}; + +static const u32 ar9331_1p2_baseband_core[][2] = { +	/* Addr      allmodes  */ +	{0x00009800, 0xafe68e30}, +	{0x00009804, 0xfd14e000}, +	{0x00009808, 0x9c0a8f6b}, +	{0x0000980c, 0x04800000}, +	{0x00009814, 0x9280c00a}, +	{0x00009818, 0x00000000}, +	{0x0000981c, 0x00020028}, +	{0x00009834, 0x5f3ca3de}, +	{0x00009838, 0x0108ecff}, +	{0x0000983c, 0x14750600}, +	{0x00009880, 0x201fff00}, +	{0x00009884, 0x00001042}, +	{0x000098a4, 0x00200400}, +	{0x000098b0, 0x32840bbe}, +	{0x000098d0, 0x004b6a8e}, +	{0x000098d4, 0x00000820}, +	{0x000098dc, 0x00000000}, +	{0x000098f0, 0x00000000}, +	{0x000098f4, 0x00000000}, +	{0x00009c04, 0x00000000}, +	{0x00009c08, 0x03200000}, +	{0x00009c0c, 0x00000000}, +	{0x00009c10, 0x00000000}, +	{0x00009c14, 0x00046384}, +	{0x00009c18, 0x05b6b440}, +	{0x00009c1c, 0x00b6b440}, +	{0x00009d00, 0xc080a333}, +	{0x00009d04, 0x40206c10}, +	{0x00009d08, 0x009c4060}, +	{0x00009d0c, 0x1883800a}, +	{0x00009d10, 0x01834061}, +	{0x00009d14, 0x00c00400}, +	{0x00009d18, 0x00000000}, +	{0x00009e08, 0x0038233c}, +	{0x00009e24, 0x9927b515}, +	{0x00009e28, 0x12ef0200}, +	{0x00009e30, 0x06336f77}, +	{0x00009e34, 0x6af6532f}, +	{0x00009e38, 0x0cc80c00}, +	{0x00009e40, 0x0d261820}, +	{0x00009e4c, 0x00001004}, +	{0x00009e50, 0x00ff03f1}, +	{0x00009fc0, 0x803e4788}, +	{0x00009fc4, 0x0001efb5}, +	{0x00009fcc, 0x40000014}, +	{0x0000a20c, 0x00000000}, +	{0x0000a220, 0x00000000}, +	{0x0000a224, 0x00000000}, +	{0x0000a228, 0x10002310}, +	{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, 0x00000006}, +	{0x0000a3f8, 0x0cdbd380}, +	{0x0000a3fc, 0x000f0f01}, +	{0x0000a400, 0x8fa91f01}, +	{0x0000a404, 0x00000000}, +	{0x0000a408, 0x0e79e5c6}, +	{0x0000a40c, 0x00820820}, +	{0x0000a414, 0x1ce739ce}, +	{0x0000a418, 0x2d001dce}, +	{0x0000a41c, 0x1ce739ce}, +	{0x0000a420, 0x000001ce}, +	{0x0000a424, 0x1ce739ce}, +	{0x0000a428, 0x000001ce}, +	{0x0000a42c, 0x1ce739ce}, +	{0x0000a430, 0x1ce739ce}, +	{0x0000a434, 0x00000000}, +	{0x0000a438, 0x00001801}, +	{0x0000a43c, 0x00000000}, +	{0x0000a440, 0x00000000}, +	{0x0000a444, 0x00000000}, +	{0x0000a448, 0x04000000}, +	{0x0000a44c, 0x00000001}, +	{0x0000a450, 0x00010000}, +	{0x0000a458, 0x00000000}, +	{0x0000a640, 0x00000000}, +	{0x0000a644, 0x3fad9d74}, +	{0x0000a648, 0x0048060a}, +	{0x0000a64c, 0x00003c37}, +	{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}, +}; + +static const u32 ar9331_modes_high_power_tx_gain_1p2[][5] = { +	/*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */ +	{0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7}, +	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, +	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, +	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, +	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, +	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, +	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00}, +	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02}, +	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04}, +	{0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620}, +	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621}, +	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640}, +	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641}, +	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642}, +	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644}, +	{0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81}, +	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83}, +	{0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84}, +	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3}, +	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5}, +	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9}, +	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec}, +	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec}, +	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec}, +	{0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, +	{0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, +	{0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, +	{0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200}, +	{0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202}, +	{0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400}, +	{0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402}, +	{0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404}, +	{0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603}, +	{0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02}, +	{0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04}, +	{0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20}, +	{0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20}, +	{0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22}, +	{0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24}, +	{0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640}, +	{0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660}, +	{0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861}, +	{0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81}, +	{0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83}, +	{0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84}, +	{0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3}, +	{0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9}, +	{0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb}, +	{0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec}, +	{0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802}, +	{0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802}, +	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03}, +	{0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +	{0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004}, +}; + +static const u32 ar9331_1p2_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 ar9331_1p2_soc_preamble[][2] = { +	/* Addr      allmodes  */ +	{0x00007020, 0x00000000}, +	{0x00007034, 0x00000002}, +	{0x00007038, 0x000002f8}, +}; + +static const u32 ar9331_1p2_xtal_40M[][2] = { +	/* Addr      allmodes  */ +	{0x00007038, 0x000004c2}, +	{0x00008244, 0x0010f400}, +	{0x0000824c, 0x0001e800}, +	{0x0001609c, 0x0b283f31}, +}; + +static const u32 ar9331_1p2_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}, +	{0x00008248, 0x00000800}, +	{0x00008250, 0x00000000}, +	{0x00008254, 0x00000000}, +	{0x00008258, 0x00000000}, +	{0x0000825c, 0x40000000}, +	{0x00008260, 0x00080922}, +	{0x00008264, 0x9d400010}, +	{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 ar9331_common_rx_gain_1p2[][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, 0x111f1100}, +	{0x0000a0c8, 0x111d111e}, +	{0x0000a0cc, 0x111b111c}, +	{0x0000a0d0, 0x22032204}, +	{0x0000a0d4, 0x22012202}, +	{0x0000a0d8, 0x221f2200}, +	{0x0000a0dc, 0x221d221e}, +	{0x0000a0e0, 0x33013302}, +	{0x0000a0e4, 0x331f3300}, +	{0x0000a0e8, 0x4402331e}, +	{0x0000a0ec, 0x44004401}, +	{0x0000a0f0, 0x441e441f}, +	{0x0000a0f4, 0x55015502}, +	{0x0000a0f8, 0x551f5500}, +	{0x0000a0fc, 0x6602551e}, +	{0x0000a100, 0x66006601}, +	{0x0000a104, 0x661e661f}, +	{0x0000a108, 0x7703661d}, +	{0x0000a10c, 0x77017702}, +	{0x0000a110, 0x00007700}, +	{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, 0x111f1100}, +	{0x0000a148, 0x111d111e}, +	{0x0000a14c, 0x111b111c}, +	{0x0000a150, 0x22032204}, +	{0x0000a154, 0x22012202}, +	{0x0000a158, 0x221f2200}, +	{0x0000a15c, 0x221d221e}, +	{0x0000a160, 0x33013302}, +	{0x0000a164, 0x331f3300}, +	{0x0000a168, 0x4402331e}, +	{0x0000a16c, 0x44004401}, +	{0x0000a170, 0x441e441f}, +	{0x0000a174, 0x55015502}, +	{0x0000a178, 0x551f5500}, +	{0x0000a17c, 0x6602551e}, +	{0x0000a180, 0x66006601}, +	{0x0000a184, 0x661e661f}, +	{0x0000a188, 0x7703661d}, +	{0x0000a18c, 0x77017702}, +	{0x0000a190, 0x00007700}, +	{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}, +}; + +#endif /* INITVALS_9330_1P2_H */ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f75068b4b31..46393f90f16 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -19,6 +19,7 @@  #include <linux/etherdevice.h>  #include <linux/device.h> +#include <linux/interrupt.h>  #include <linux/leds.h>  #include <linux/completion.h> @@ -54,8 +55,6 @@ struct ath_node;  		(_l) &= ((_sz) - 1);		\  	} while (0) -#define A_MAX(a, b) ((a) > (b) ? (a) : (b)) -  #define TSF_TO_TU(_h,_l) \  	((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) @@ -102,6 +101,11 @@ enum buffer_type {  #define ATH_TXSTATUS_RING_SIZE 64 +#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_descdma {  	void *dd_desc;  	dma_addr_t dd_desc_paddr; @@ -179,7 +183,7 @@ enum ATH_AGGR_STATUS {  struct ath_txq {  	int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */  	u32 axq_qnum; /* ath9k hardware queue number */ -	u32 *axq_link; +	void *axq_link;  	struct list_head axq_q;  	spinlock_t axq_lock;  	u32 axq_depth; @@ -188,7 +192,6 @@ struct ath_txq {  	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;  	int pending_frames; @@ -428,6 +431,7 @@ void ath_hw_check(struct work_struct *work);  void ath_hw_pll_work(struct work_struct *work);  void ath_paprd_calibrate(struct work_struct *work);  void ath_ani_calibrate(unsigned long data); +void ath_start_ani(struct ath_common *common);  /**********/  /* BTCOEX */ @@ -579,7 +583,7 @@ struct ath9k_vif_iter_data {  	int naps;      /* number of AP vifs */  	int nmeshes;   /* number of mesh vifs */  	int nstations; /* number of station vifs */ -	int nwds;      /* number of nwd vifs */ +	int nwds;      /* number of WDS vifs */  	int nadhocs;   /* number of adhoc vifs */  	int nothers;   /* number of vifs not specified above. */  }; @@ -669,12 +673,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,  		    const struct ath_bus_ops *bus_ops);  void ath9k_deinit_device(struct ath_softc *sc);  void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); -int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, -		    struct ath9k_channel *hchan); -void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);  void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); -bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);  bool ath9k_uses_beacons(int type);  #ifdef CONFIG_ATH9K_PCI diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index d4d8ceced89..0d13ff74a68 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -14,6 +14,7 @@   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   */ +#include <linux/dma-mapping.h>  #include "ath9k.h"  #define FUDGE 2 @@ -360,6 +361,7 @@ void ath_beacon_tasklet(unsigned long data)  	struct ath_common *common = ath9k_hw_common(ah);  	struct ath_buf *bf = NULL;  	struct ieee80211_vif *vif; +	struct ath_tx_status ts;  	int slot;  	u32 bfaddr, bc = 0; @@ -384,7 +386,9 @@ void ath_beacon_tasklet(unsigned long data)  			ath_dbg(common, ATH_DBG_BSTUCK,  				"beacon is officially stuck\n");  			sc->sc_flags |= SC_OP_TSF_RESET; +			spin_lock(&sc->sc_pcu_lock);  			ath_reset(sc, true); +			spin_unlock(&sc->sc_pcu_lock);  		}  		return; @@ -464,6 +468,11 @@ void ath_beacon_tasklet(unsigned long data)  		ath9k_hw_txstart(ah, sc->beacon.beaconq);  		sc->beacon.ast_be_xmit += bc;     /* XXX per-vif? */ +		if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { +			spin_lock_bh(&sc->sc_pcu_lock); +			ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts); +			spin_unlock_bh(&sc->sc_pcu_lock); +		}  	}  } @@ -496,7 +505,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,  	u32 nexttbtt, intval;  	/* NB: the beacon interval is kept internally in TU's */ -	intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); +	intval = TU_TO_USEC(conf->beacon_interval);  	intval /= ATH_BCBUF;    /* for staggered beacons */  	nexttbtt = intval; @@ -543,7 +552,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,  	}  	memset(&bs, 0, sizeof(bs)); -	intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; +	intval = conf->beacon_interval;  	/*  	 * Setup dtim and cfp parameters according to @@ -652,22 +661,13 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,  {  	struct ath_hw *ah = sc->sc_ah;  	struct ath_common *common = ath9k_hw_common(ah); -	u32 tsf, delta, intval, nexttbtt; +	u32 tsf, intval, nexttbtt;  	ath9k_reset_beacon_status(sc); -	tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE); -	intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); - -	if (!sc->beacon.bc_tstamp) -		nexttbtt = tsf + intval; -	else { -		if (tsf > sc->beacon.bc_tstamp) -			delta = (tsf - sc->beacon.bc_tstamp); -		else -			delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp)); -		nexttbtt = tsf + intval - (delta % intval); -	} +	intval = TU_TO_USEC(conf->beacon_interval); +	tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval); +	nexttbtt = tsf + intval;  	ath_dbg(common, ATH_DBG_BEACON,  		"IBSS nexttbtt %u intval %u (%u)\n", diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index d55ffd7d4bd..22d3a26e684 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -176,6 +176,56 @@ static const struct file_operations fops_rx_chainmask = {  	.llseek = default_llseek,  }; +static ssize_t read_file_disable_ani(struct file *file, char __user *user_buf, +			     size_t count, loff_t *ppos) +{ +	struct ath_softc *sc = file->private_data; +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	char buf[32]; +	unsigned int len; + +	len = sprintf(buf, "%d\n", common->disable_ani); +	return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_disable_ani(struct file *file, +				      const char __user *user_buf, +				      size_t count, loff_t *ppos) +{ +	struct ath_softc *sc = file->private_data; +	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	unsigned long disable_ani; +	char buf[32]; +	ssize_t len; + +	len = min(count, sizeof(buf) - 1); +	if (copy_from_user(buf, user_buf, len)) +		return -EFAULT; + +	buf[len] = '\0'; +	if (strict_strtoul(buf, 0, &disable_ani)) +		return -EINVAL; + +	common->disable_ani = !!disable_ani; + +	if (disable_ani) { +		sc->sc_flags &= ~SC_OP_ANI_RUN; +		del_timer_sync(&common->ani.timer); +	} else { +		sc->sc_flags |= SC_OP_ANI_RUN; +		ath_start_ani(common); +	} + +	return count; +} + +static const struct file_operations fops_disable_ani = { +	.read = read_file_disable_ani, +	.write = write_file_disable_ani, +	.open = ath9k_debugfs_open, +	.owner = THIS_MODULE, +	.llseek = default_llseek, +};  static ssize_t read_file_dma(struct file *file, char __user *user_buf,  			     size_t count, loff_t *ppos) @@ -550,6 +600,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,  	PR("MPDUs Queued:    ", queued);  	PR("MPDUs Completed: ", completed); +	PR("MPDUs XRetried:  ", xretries);  	PR("Aggregates:      ", a_aggr);  	PR("AMPDUs Queued HW:", a_queued_hw);  	PR("AMPDUs Queued SW:", a_queued_sw); @@ -587,7 +638,6 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,  	PRQLE("axq_q empty:       ", axq_q);  	PRQLE("axq_acq empty:     ", axq_acq); -	PRQLE("txq_fifo_pending:  ", txq_fifo_pending);  	for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {  		snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);  		PRQLE(tmp, txq_fifo[i]); @@ -807,7 +857,10 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,  		else  			TX_STAT_INC(qnum, a_completed);  	} else { -		TX_STAT_INC(qnum, completed); +		if (bf_isxretried(bf)) +			TX_STAT_INC(qnum, xretries); +		else +			TX_STAT_INC(qnum, completed);  	}  	if (ts->ts_status & ATH9K_TXERR_FIFO) @@ -1160,6 +1213,8 @@ int ath9k_init_debug(struct ath_hw *ah)  			    sc->debug.debugfs_phy, sc, &fops_rx_chainmask);  	debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR,  			    sc->debug.debugfs_phy, sc, &fops_tx_chainmask); +	debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR, +			    sc->debug.debugfs_phy, sc, &fops_disable_ani);  	debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,  			    sc, &fops_regidx);  	debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 8ce6ad80f4e..4a04510e111 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -116,6 +116,7 @@ struct ath_tx_stats {  	u32 tx_bytes_all;  	u32 queued;  	u32 completed; +	u32 xretries;  	u32 a_aggr;  	u32 a_queued_hw;  	u32 a_queued_sw; diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 260f1f37a60..8028fe90f66 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -49,6 +49,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {  	  .driver_info = AR9280_USB },  /* Netgear WNDA3200 */  	{ USB_DEVICE(0x083A, 0xA704),  	  .driver_info = AR9280_USB },  /* SMC Networks */ +	{ USB_DEVICE(0x0411, 0x017f), +	  .driver_info = AR9280_USB },  /* Sony UWA-BR100 */  	{ USB_DEVICE(0x0cf3, 0x20ff),  	  .driver_info = STORAGE_DEVICE }, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index aa6a7311870..57fe22b2424 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -79,7 +79,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,  	memset(&bs, 0, sizeof(bs)); -	intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; +	intval = bss_conf->beacon_interval;  	bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval);  	/* @@ -194,7 +194,7 @@ static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,  	u8 cmd_rsp;  	u64 tsf; -	intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; +	intval = bss_conf->beacon_interval;  	intval /= ATH9K_HTC_MAX_BCN_VIF;  	nexttbtt = intval; @@ -250,7 +250,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,  	u8 cmd_rsp;  	u64 tsf; -	intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; +	intval = bss_conf->beacon_interval;  	nexttbtt = intval;  	/* @@ -427,7 +427,7 @@ static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv,  	u16 intval;  	int slot; -	intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD; +	intval = priv->cur_beacon_conf.beacon_interval;  	tsf = be64_to_cpu(swba->tsf);  	tsftu = TSF_TO_TU(tsf >> 32, tsf); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 61e6d395071..3bea7ea86f0 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -754,6 +754,7 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,  		IEEE80211_HW_RX_INCLUDES_FCS |  		IEEE80211_HW_SUPPORTS_PS |  		IEEE80211_HW_PS_NULLFUNC_STACK | +		IEEE80211_HW_REPORTS_TX_ACK_STATUS |  		IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;  	hw->wiphy->interface_modes = diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7b779689543..7212acb2bd6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1294,11 +1294,16 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,  	u32 rfilt;  	mutex_lock(&priv->mutex); -	ath9k_htc_ps_wakeup(priv); -  	changed_flags &= SUPPORTED_FILTERS;  	*total_flags &= SUPPORTED_FILTERS; +	if (priv->op_flags & OP_INVALID) { +		ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_ANY, +			"Unable to configure filter on invalid state\n"); +		return; +	} +	ath9k_htc_ps_wakeup(priv); +  	priv->rxfilter = *total_flags;  	rfilt = ath9k_htc_calcrxfilter(priv);  	ath9k_hw_setrxfilter(priv->ah, rfilt); diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 2f3e07263fc..cb29e887538 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -39,11 +39,6 @@ static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds,  	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, diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1be7c8bbef8..2a5f908d803 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -87,7 +87,10 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)  	struct ath_common *common = ath9k_hw_common(ah);  	unsigned int clockrate; -	if (!ah->curchan) /* should really check for CCK instead */ +	/* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */ +	if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) +		clockrate = 117; +	else if (!ah->curchan) /* should really check for CCK instead */  		clockrate = ATH9K_CLOCK_RATE_CCK;  	else if (conf->channel->band == IEEE80211_BAND_2GHZ)  		clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; @@ -99,6 +102,13 @@ static void ath9k_hw_set_clockrate(struct ath_hw *ah)  	if (conf_is_ht40(conf))  		clockrate *= 2; +	if (ah->curchan) { +		if (IS_CHAN_HALF_RATE(ah->curchan)) +			clockrate /= 2; +		if (IS_CHAN_QUARTER_RATE(ah->curchan)) +			clockrate /= 4; +	} +  	common->clockrate = clockrate;  } @@ -251,6 +261,15 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)  	case AR5416_AR9100_DEVID:  		ah->hw_version.macVersion = AR_SREV_VERSION_9100;  		break; +	case AR9300_DEVID_AR9330: +		ah->hw_version.macVersion = AR_SREV_VERSION_9330; +		if (ah->get_mac_revision) { +			ah->hw_version.macRev = ah->get_mac_revision(); +		} else { +			val = REG_READ(ah, AR_SREV); +			ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); +		} +		return;  	case AR9300_DEVID_AR9340:  		ah->hw_version.macVersion = AR_SREV_VERSION_9340;  		val = REG_READ(ah, AR_SREV); @@ -551,6 +570,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)  	case AR_SREV_VERSION_9287:  	case AR_SREV_VERSION_9271:  	case AR_SREV_VERSION_9300: +	case AR_SREV_VERSION_9330:  	case AR_SREV_VERSION_9485:  	case AR_SREV_VERSION_9340:  		break; @@ -561,7 +581,8 @@ static int __ath9k_hw_init(struct ath_hw *ah)  		return -EOPNOTSUPP;  	} -	if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah)) +	if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) || +	    AR_SREV_9330(ah))  		ah->is_pciexpress = false;  	ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); @@ -604,7 +625,10 @@ static int __ath9k_hw_init(struct ath_hw *ah)  	else  		ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); -	ah->bb_watchdog_timeout_ms = 25; +	if (AR_SREV_9330(ah)) +		ah->bb_watchdog_timeout_ms = 85; +	else +		ah->bb_watchdog_timeout_ms = 25;  	common->state = ATH_HW_INITIALIZED; @@ -630,6 +654,7 @@ int ath9k_hw_init(struct ath_hw *ah)  	case AR2427_DEVID_PCIE:  	case AR9300_DEVID_PCIE:  	case AR9300_DEVID_AR9485_PCIE: +	case AR9300_DEVID_AR9330:  	case AR9300_DEVID_AR9340:  		break;  	default: @@ -722,6 +747,39 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,  		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,  			      AR_CH0_BB_DPLL2_PLL_PWD, 0x0);  		udelay(1000); +	} else if (AR_SREV_9330(ah)) { +		u32 ddr_dpll2, pll_control2, kd; + +		if (ah->is_clk_25mhz) { +			ddr_dpll2 = 0x18e82f01; +			pll_control2 = 0xe04a3d; +			kd = 0x1d; +		} else { +			ddr_dpll2 = 0x19e82f01; +			pll_control2 = 0x886666; +			kd = 0x3d; +		} + +		/* program DDR PLL ki and kd value */ +		REG_WRITE(ah, AR_CH0_DDR_DPLL2, ddr_dpll2); + +		/* program DDR PLL phase_shift */ +		REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3, +			      AR_CH0_DPLL3_PHASE_SHIFT, 0x1); + +		REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); +		udelay(1000); + +		/* program refdiv, nint, frac to RTC register */ +		REG_WRITE(ah, AR_RTC_PLL_CONTROL2, pll_control2); + +		/* program BB PLL kd and ki value */ +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KD, kd); +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KI, 0x06); + +		/* program BB PLL phase_shift */ +		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, +			      AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);  	} else if (AR_SREV_9340(ah)) {  		u32 regval, pll2_divint, pll2_divfrac, refdiv; @@ -763,7 +821,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,  	REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); -	if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) +	if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))  		udelay(1000);  	/* Switch the core clock for ar9271 to 117Mhz */ @@ -847,6 +905,13 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,  	}  } +static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us) +{ +	u32 val = ath9k_hw_mac_to_clks(ah, us - 2); +	val = min(val, (u32) 0xFFFF); +	REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val); +} +  static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)  {  	u32 val = ath9k_hw_mac_to_clks(ah, us); @@ -884,25 +949,60 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu)  void ath9k_hw_init_global_settings(struct ath_hw *ah)  { -	struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; +	struct ath_common *common = ath9k_hw_common(ah); +	struct ieee80211_conf *conf = &common->hw->conf; +	const struct ath9k_channel *chan = ah->curchan;  	int acktimeout;  	int slottime;  	int sifstime; +	int rx_lat = 0, tx_lat = 0, eifs = 0; +	u32 reg;  	ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",  		ah->misc_mode); +	if (!chan) +		return; +  	if (ah->misc_mode != 0)  		REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode); -	if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ) -		sifstime = 16; -	else -		sifstime = 10; +	rx_lat = 37; +	tx_lat = 54; + +	if (IS_CHAN_HALF_RATE(chan)) { +		eifs = 175; +		rx_lat *= 2; +		tx_lat *= 2; +		if (IS_CHAN_A_FAST_CLOCK(ah, chan)) +		    tx_lat += 11; + +		slottime = 13; +		sifstime = 32; +	} else if (IS_CHAN_QUARTER_RATE(chan)) { +		eifs = 340; +		rx_lat *= 4; +		tx_lat *= 4; +		if (IS_CHAN_A_FAST_CLOCK(ah, chan)) +		    tx_lat += 22; + +		slottime = 21; +		sifstime = 64; +	} else { +		eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS); +		reg = REG_READ(ah, AR_USEC); +		rx_lat = MS(reg, AR_USEC_RX_LAT); +		tx_lat = MS(reg, AR_USEC_TX_LAT); + +		slottime = ah->slottime; +		if (IS_CHAN_5GHZ(chan)) +			sifstime = 16; +		else +			sifstime = 10; +	}  	/* As defined by IEEE 802.11-2007 17.3.8.6 */ -	slottime = ah->slottime + 3 * ah->coverage_class; -	acktimeout = slottime + sifstime; +	acktimeout = slottime + sifstime + 3 * ah->coverage_class;  	/*  	 * Workaround for early ACK timeouts, add an offset to match the @@ -914,11 +1014,20 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)  	if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)  		acktimeout += 64 - sifstime - ah->slottime; -	ath9k_hw_setslottime(ah, ah->slottime); +	ath9k_hw_set_sifs_time(ah, sifstime); +	ath9k_hw_setslottime(ah, slottime);  	ath9k_hw_set_ack_timeout(ah, acktimeout);  	ath9k_hw_set_cts_timeout(ah, acktimeout);  	if (ah->globaltxtimeout != (u32) -1)  		ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); + +	REG_WRITE(ah, AR_D_GBL_IFS_EIFS, ath9k_hw_mac_to_clks(ah, eifs)); +	REG_RMW(ah, AR_USEC, +		(common->clockrate - 1) | +		SM(rx_lat, AR_USEC_RX_LAT) | +		SM(tx_lat, AR_USEC_TX_LAT), +		AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC); +  }  EXPORT_SYMBOL(ath9k_hw_init_global_settings); @@ -1114,6 +1223,41 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)  			rst_flags |= AR_RTC_RC_MAC_COLD;  	} +	if (AR_SREV_9330(ah)) { +		int npend = 0; +		int i; + +		/* AR9330 WAR: +		 * call external reset function to reset WMAC if: +		 * - doing a cold reset +		 * - we have pending frames in the TX queues +		 */ + +		for (i = 0; i < AR_NUM_QCU; i++) { +			npend = ath9k_hw_numtxpending(ah, i); +			if (npend) +				break; +		} + +		if (ah->external_reset && +		    (npend || type == ATH9K_RESET_COLD)) { +			int reset_err = 0; + +			ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, +				"reset MAC via external reset\n"); + +			reset_err = ah->external_reset(); +			if (reset_err) { +				ath_err(ath9k_hw_common(ah), +					"External reset failed, err=%d\n", +					reset_err); +				return false; +			} + +			REG_WRITE(ah, AR_RTC_RESET, 1); +		} +	} +  	REG_WRITE(ah, AR_RTC_RC, rst_flags);  	REGWRITE_BUFFER_FLUSH(ah); @@ -1487,9 +1631,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  	ath9k_hw_init_global_settings(ah); -	if (!AR_SREV_9300_20_OR_LATER(ah)) { -		ar9002_hw_update_async_fifo(ah); -		ar9002_hw_enable_wep_aggregation(ah); +	if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) { +		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); +		REG_SET_BIT(ah, AR_PCU_MISC_MODE2, +			    AR_PCU_MISC_MODE2_ENABLE_AGGWEP);  	}  	REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); @@ -1545,7 +1693,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  				REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);  		}  #ifdef __BIG_ENDIAN -		else if (AR_SREV_9340(ah)) +		else if (AR_SREV_9330(ah) || AR_SREV_9340(ah))  			REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);  		else  			REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); @@ -1785,16 +1933,16 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,  	REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt));  	REG_WRITE(ah, AR_BEACON_PERIOD, -		  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); +		  TU_TO_USEC(bs->bs_intval));  	REG_WRITE(ah, AR_DMA_BEACON_PERIOD, -		  TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); +		  TU_TO_USEC(bs->bs_intval));  	REGWRITE_BUFFER_FLUSH(ah);  	REG_RMW_FIELD(ah, AR_RSSI_THR,  		      AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); -	beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD; +	beaconintval = bs->bs_intval;  	if (bs->bs_sleepduration > beaconintval)  		beaconintval = bs->bs_sleepduration; @@ -1983,7 +2131,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)  	if (AR_SREV_9300_20_OR_LATER(ah)) {  		pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK; -		if (!AR_SREV_9485(ah)) +		if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah))  			pCap->hw_caps |= ATH9K_HW_CAP_LDPC;  		pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; @@ -1996,10 +2144,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)  			pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;  	} 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))) +		if (AR_SREV_9280_20(ah))  			pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;  	} @@ -2025,7 +2170,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)  	} -	if (AR_SREV_9485(ah)) { +	if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {  		ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);  		/*  		 * enable the diversity-combining algorithm only when @@ -2574,6 +2719,7 @@ static struct {  	{ AR_SREV_VERSION_9287,         "9287" },  	{ AR_SREV_VERSION_9271,         "9271" },  	{ AR_SREV_VERSION_9300,         "9300" }, +	{ AR_SREV_VERSION_9330,         "9330" },  	{ AR_SREV_VERSION_9485,         "9485" },  }; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 4b157c53d1a..6acd0f975ae 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -45,6 +45,7 @@  #define AR9300_DEVID_PCIE	0x0030  #define AR9300_DEVID_AR9340	0x0031  #define AR9300_DEVID_AR9485_PCIE 0x0032 +#define AR9300_DEVID_AR9330	0x0035  #define AR5416_AR9100_DEVID	0x000b @@ -142,6 +143,8 @@  #define AR_KEYTABLE_SIZE            128  #define POWER_UP_TIME               10000  #define SPUR_RSSI_THRESH            40 +#define UPPER_5G_SUB_BAND_START		5700 +#define MID_5G_SUB_BAND_START		5400  #define CAB_TIMEOUT_VAL             10  #define BEACON_TIMEOUT_VAL          10 @@ -157,8 +160,9 @@  #define ATH9K_HW_RX_HP_QDEPTH	16  #define ATH9K_HW_RX_LP_QDEPTH	128 -#define PAPRD_GAIN_TABLE_ENTRIES    32 -#define PAPRD_TABLE_SZ              24 +#define PAPRD_GAIN_TABLE_ENTRIES	32 +#define PAPRD_TABLE_SZ			24 +#define PAPRD_IDEAL_AGC2_PWR_RANGE	0xe0  enum ath_hw_txq_subtype {  	ATH_TXQ_AC_BE = 0, @@ -403,7 +407,6 @@ struct ath9k_beacon_state {  	u32 bs_nexttbtt;  	u32 bs_nextdtim;  	u32 bs_intval; -#define ATH9K_BEACON_PERIOD       0x0000ffff  #define ATH9K_TSFOOR_THRESHOLD    0x00004240 /* 16k us */  	u32 bs_dtimperiod;  	u16 bs_cfpperiod; @@ -603,7 +606,6 @@ struct ath_hw_ops {  				     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, @@ -862,6 +864,8 @@ struct ath_hw {  	u32 ent_mode;  	bool is_clk_25mhz; +	int (*get_mac_revision)(void); +	int (*external_reset)(void);  };  struct ath_bus_ops { @@ -981,8 +985,6 @@ void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,  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_update_async_fifo(struct ath_hw *ah); -void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);  /*   * Code specific to AR9003, we stuff these here to avoid callbacks diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 45c585a337e..b855fe1adc3 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -14,6 +14,7 @@   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   */ +#include <linux/dma-mapping.h>  #include <linux/slab.h>  #include <linux/ath9k_platform.h> @@ -245,7 +246,7 @@ static void setup_ht_cap(struct ath_softc *sc,  	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;  	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; -	if (AR_SREV_9485(ah)) +	if (AR_SREV_9330(ah) || AR_SREV_9485(ah))  		max_streams = 1;  	else if (AR_SREV_9300_20_OR_LATER(ah))  		max_streams = 3; @@ -298,10 +299,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  		      struct list_head *head, const char *name,  		      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);  	u8 *ds;  	struct ath_buf *bf; @@ -396,9 +393,6 @@ fail2:  fail:  	memset(dd, 0, sizeof(*dd));  	return error; -#undef ATH_DESC_4KB_BOUND_CHECK -#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED -#undef DS2PHYS  }  void ath9k_init_crypto(struct ath_softc *sc) @@ -519,7 +513,6 @@ static void ath9k_init_misc(struct ath_softc *sc)  {  	struct ath_common *common = ath9k_hw_common(sc->sc_ah);  	int i = 0; -  	setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);  	sc->config.txpowlimit = ATH_TXPOWER_MAX; @@ -575,6 +568,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,  		sc->sc_ah->gpio_val = pdata->gpio_val;  		sc->sc_ah->led_pin = pdata->led_pin;  		ah->is_clk_25mhz = pdata->is_clk_25mhz; +		ah->get_mac_revision = pdata->get_mac_revision; +		ah->external_reset = pdata->external_reset;  	}  	common = ath9k_hw_common(ah); @@ -585,6 +580,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,  	common->priv = sc;  	common->debug_mask = ath9k_debug;  	common->btcoex_enabled = ath9k_btcoex_enable == 1; +	common->disable_ani = false;  	spin_lock_init(&common->cc_lock);  	spin_lock_init(&sc->sc_serial_rw); diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index c2091f1f409..b6b523a897e 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -645,8 +645,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,  			rs->rs_status |= ATH9K_RXERR_DECRYPT;  		else if (ads.ds_rxstatus8 & AR_MichaelErr)  			rs->rs_status |= ATH9K_RXERR_MIC; - -		if (ads.ds_rxstatus8 & AR_KeyMiss) +		else if (ads.ds_rxstatus8 & AR_KeyMiss)  			rs->rs_status |= ATH9K_RXERR_DECRYPT;  	} diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2ca351fe6d3..9098aaad97a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -62,14 +62,12 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)  	if (txq->axq_depth || !list_empty(&txq->axq_acq))  		pending = true; -	else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) -		pending = !list_empty(&txq->txq_fifo_pending);  	spin_unlock_bh(&txq->axq_lock);  	return pending;  } -bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) +static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)  {  	unsigned long flags;  	bool ret; @@ -136,7 +134,7 @@ void ath9k_ps_restore(struct ath_softc *sc)  	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);  } -static void ath_start_ani(struct ath_common *common) +void ath_start_ani(struct ath_common *common)  {  	struct ath_hw *ah = common->ah;  	unsigned long timestamp = jiffies_to_msecs(jiffies); @@ -219,7 +217,7 @@ static int ath_update_survey_stats(struct ath_softc *sc)   * by reseting the chip.  To accomplish this we must first cleanup any pending   * DMA, then restart stuff.  */ -int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, +static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,  		    struct ath9k_channel *hchan)  {  	struct ath_hw *ah = sc->sc_ah; @@ -302,7 +300,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,  			ath_set_beacon(sc);  		ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);  		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); -		ath_start_ani(common); +		if (!common->disable_ani) +			ath_start_ani(common);  	}   ps_restore: @@ -361,7 +360,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int  	txctl.paprd = BIT(chain);  	if (ath_tx_start(hw, skb, &txctl) != 0) { -		ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n"); +		ath_dbg(common, ATH_DBG_CALIBRATE, "PAPRD TX failed\n");  		dev_kfree_skb_any(skb);  		return false;  	} @@ -370,7 +369,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int  			msecs_to_jiffies(ATH_PAPRD_TIMEOUT));  	if (!time_left) -		ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE, +		ath_dbg(common, ATH_DBG_CALIBRATE,  			"Timeout waiting for paprd training on TX chain %d\n",  			chain); @@ -394,12 +393,14 @@ void ath_paprd_calibrate(struct work_struct *work)  	if (!caldata)  		return; +	ath9k_ps_wakeup(sc); +  	if (ar9003_paprd_init_table(ah) < 0) -		return; +		goto fail_paprd;  	skb = alloc_skb(len, GFP_KERNEL);  	if (!skb) -		return; +		goto fail_paprd;  	skb_put(skb, len);  	memset(skb->data, 0, len); @@ -411,7 +412,6 @@ void ath_paprd_calibrate(struct work_struct *work)  	memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);  	memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); -	ath9k_ps_wakeup(sc);  	for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {  		if (!(common->tx_chainmask & BIT(chain)))  			continue; @@ -431,11 +431,18 @@ void ath_paprd_calibrate(struct work_struct *work)  		if (!ath_paprd_send_frame(sc, skb, chain))  			goto fail_paprd; -		if (!ar9003_paprd_is_done(ah)) +		if (!ar9003_paprd_is_done(ah)) { +			ath_dbg(common, ATH_DBG_CALIBRATE, +				"PAPRD not yet done on chain %d\n", chain);  			break; +		} -		if (ar9003_paprd_create_curve(ah, caldata, chain) != 0) +		if (ar9003_paprd_create_curve(ah, caldata, chain)) { +			ath_dbg(common, ATH_DBG_CALIBRATE, +				"PAPRD create curve failed on chain %d\n", +								   chain);  			break; +		}  		chain_ok = 1;  	} @@ -515,24 +522,19 @@ void ath_ani_calibrate(unsigned long data)  		common->ani.checkani_timer = timestamp;  	} -	/* Skip all processing if there's nothing to do. */ -	if (longcal || shortcal || aniflag) { -		/* Call ANI routine if necessary */ -		if (aniflag) { -			spin_lock_irqsave(&common->cc_lock, flags); -			ath9k_hw_ani_monitor(ah, ah->curchan); -			ath_update_survey_stats(sc); -			spin_unlock_irqrestore(&common->cc_lock, flags); -		} +	/* Call ANI routine if necessary */ +	if (aniflag) { +		spin_lock_irqsave(&common->cc_lock, flags); +		ath9k_hw_ani_monitor(ah, ah->curchan); +		ath_update_survey_stats(sc); +		spin_unlock_irqrestore(&common->cc_lock, flags); +	} -		/* Perform calibration if necessary */ -		if (longcal || shortcal) { -			common->ani.caldone = -				ath9k_hw_calibrate(ah, -						   ah->curchan, -						   common->rx_chainmask, -						   longcal); -		} +	/* Perform calibration if necessary */ +	if (longcal || shortcal) { +		common->ani.caldone = +			ath9k_hw_calibrate(ah, ah->curchan, +						common->rx_chainmask, longcal);  	}  	ath9k_ps_restore(sc); @@ -615,8 +617,11 @@ void ath_hw_check(struct work_struct *work)  	ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "  		"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);  	if (busy >= 99) { -		if (++sc->hw_busy_count >= 3) +		if (++sc->hw_busy_count >= 3) { +			spin_lock_bh(&sc->sc_pcu_lock);  			ath_reset(sc, true); +			spin_unlock_bh(&sc->sc_pcu_lock); +		}  	} else if (busy >= 0)  		sc->hw_busy_count = 0; @@ -635,7 +640,9 @@ static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)  			/* Rx is hung for more than 500ms. Reset it */  			ath_dbg(common, ATH_DBG_RESET,  				"Possible RX hang, resetting"); +			spin_lock_bh(&sc->sc_pcu_lock);  			ath_reset(sc, true); +			spin_unlock_bh(&sc->sc_pcu_lock);  			count = 0;  		}  	} else @@ -672,7 +679,9 @@ void ath9k_tasklet(unsigned long data)  	if ((status & ATH9K_INT_FATAL) ||  	    (status & ATH9K_INT_BB_WATCHDOG)) { +		spin_lock(&sc->sc_pcu_lock);  		ath_reset(sc, true); +		spin_unlock(&sc->sc_pcu_lock);  		return;  	} @@ -868,7 +877,7 @@ chip_reset:  #undef SCHED_INTR  } -void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) +static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)  {  	struct ath_hw *ah = sc->sc_ah;  	struct ath_common *common = ath9k_hw_common(ah); @@ -974,10 +983,10 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)  	sc->hw_busy_count = 0;  	/* Stop ANI */ +  	del_timer_sync(&common->ani.timer);  	ath9k_ps_wakeup(sc); -	spin_lock_bh(&sc->sc_pcu_lock);  	ieee80211_stop_queues(hw); @@ -1020,10 +1029,11 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)  	}  	ieee80211_wake_queues(hw); -	spin_unlock_bh(&sc->sc_pcu_lock);  	/* Start ANI */ -	ath_start_ani(common); +	if (!common->disable_ani) +		ath_start_ani(common); +  	ath9k_ps_restore(sc);  	return r; @@ -1261,7 +1271,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)  	/* disable HAL and put h/w to sleep */  	ath9k_hw_disable(ah); -	ath9k_hw_configpcipowersave(ah, 1, 1);  	spin_unlock_bh(&sc->sc_pcu_lock); @@ -1412,10 +1421,14 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,  	ath9k_hw_set_interrupts(ah, ah->imask);  	/* Set up ANI */ -	if ((iter_data.naps + iter_data.nadhocs) > 0) { +	if (iter_data.naps > 0) {  		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; -		sc->sc_flags |= SC_OP_ANI_RUN; -		ath_start_ani(common); + +		if (!common->disable_ani) { +			sc->sc_flags |= SC_OP_ANI_RUN; +			ath_start_ani(common); +		} +  	} else {  		sc->sc_flags &= ~SC_OP_ANI_RUN;  		del_timer_sync(&common->ani.timer); @@ -1952,50 +1965,38 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)  	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;  	struct ath_vif *avp = (void *)vif->drv_priv; -	switch (sc->sc_ah->opmode) { -	case NL80211_IFTYPE_ADHOC: -		/* There can be only one vif available */ +	/* +	 * Skip iteration if primary station vif's bss info +	 * was not changed +	 */ +	if (sc->sc_flags & SC_OP_PRIM_STA_VIF) +		return; + +	if (bss_conf->assoc) { +		sc->sc_flags |= SC_OP_PRIM_STA_VIF; +		avp->primary_sta_vif = true;  		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);  		common->curaid = bss_conf->aid;  		ath9k_hw_write_associd(sc->sc_ah); -		/* configure beacon */ -		if (bss_conf->enable_beacon) -			ath_beacon_config(sc, vif); -		break; -	case NL80211_IFTYPE_STATION: -		/* -		 * Skip iteration if primary station vif's bss info -		 * was not changed -		 */ -		if (sc->sc_flags & SC_OP_PRIM_STA_VIF) -			break; - -		if (bss_conf->assoc) { -			sc->sc_flags |= SC_OP_PRIM_STA_VIF; -			avp->primary_sta_vif = true; -			memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); -			common->curaid = bss_conf->aid; -			ath9k_hw_write_associd(sc->sc_ah); -			ath_dbg(common, ATH_DBG_CONFIG, +		ath_dbg(common, ATH_DBG_CONFIG,  				"Bss Info ASSOC %d, bssid: %pM\n",  				bss_conf->aid, common->curbssid); -			ath_beacon_config(sc, vif); -			/* -			 * Request a re-configuration of Beacon related timers -			 * on the receipt of the first Beacon frame (i.e., -			 * after time sync with the AP). -			 */ -			sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; -			/* Reset rssi stats */ -			sc->last_rssi = ATH_RSSI_DUMMY_MARKER; -			sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; +		ath_beacon_config(sc, vif); +		/* +		 * Request a re-configuration of Beacon related timers +		 * on the receipt of the first Beacon frame (i.e., +		 * after time sync with the AP). +		 */ +		sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; +		/* Reset rssi stats */ +		sc->last_rssi = ATH_RSSI_DUMMY_MARKER; +		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; +		if (!common->disable_ani) {  			sc->sc_flags |= SC_OP_ANI_RUN;  			ath_start_ani(common);  		} -		break; -	default: -		break; +  	}  } @@ -2005,6 +2006,9 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)  	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;  	struct ath_vif *avp = (void *)vif->drv_priv; +	if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) +		return; +  	/* Reconfigure bss info */  	if (avp->primary_sta_vif && !bss_conf->assoc) {  		ath_dbg(common, ATH_DBG_CONFIG, @@ -2023,8 +2027,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)  	 * None of station vifs are associated.  	 * Clear bssid & aid  	 */ -	if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && -	    !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) { +	if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) {  		ath9k_hw_write_associd(sc->sc_ah);  		/* Stop ANI */  		sc->sc_flags &= ~SC_OP_ANI_RUN; @@ -2054,6 +2057,26 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,  			common->curbssid, common->curaid);  	} +	if (changed & BSS_CHANGED_IBSS) { +		/* There can be only one vif available */ +		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); +		common->curaid = bss_conf->aid; +		ath9k_hw_write_associd(sc->sc_ah); + +		if (bss_conf->ibss_joined) { +			sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; + +			if (!common->disable_ani) { +				sc->sc_flags |= SC_OP_ANI_RUN; +				ath_start_ani(common); +			} + +		} else { +			sc->sc_flags &= ~SC_OP_ANI_RUN; +			del_timer_sync(&common->ani.timer); +		} +	} +  	/* Enable transmission of beacons (AP, IBSS, MESH) */  	if ((changed & BSS_CHANGED_BEACON) ||  	    ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) { @@ -2308,9 +2331,9 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)  	ath9k_ps_wakeup(sc);  	spin_lock_bh(&sc->sc_pcu_lock);  	drain_txq = ath_drain_all_txq(sc, false); -	spin_unlock_bh(&sc->sc_pcu_lock);  	if (!drain_txq)  		ath_reset(sc, false); +	spin_unlock_bh(&sc->sc_pcu_lock);  	ath9k_ps_restore(sc);  	ieee80211_wake_queues(hw); @@ -2334,7 +2357,7 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)  	return false;  } -int ath9k_tx_last_beacon(struct ieee80211_hw *hw) +static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)  {  	struct ath_softc *sc = hw->priv;  	struct ath_hw *ah = sc->sc_ah; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index b8cbfc70721..3bad0b2cf9a 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -278,6 +278,12 @@ static int ath_pci_suspend(struct device *device)  	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); +	/* The device has to be moved to FULLSLEEP forcibly. +	 * Otherwise the chip never moved to full sleep, +	 * when no interface is up. +	 */ +	ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); +  	return 0;  } diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index ba7f36ab0a7..c04a6c3cac7 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -379,7 +379,30 @@ static const struct ath_rate_table ar5416_11g_ratetable = {  };  static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, -				struct ieee80211_tx_rate *rate); +				struct ieee80211_tx_rate *rate) +{ +	int rix = 0, i = 0; +	static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 }; + +	if (!(rate->flags & IEEE80211_TX_RC_MCS)) +		return rate->idx; + +	while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) { +		rix++; i++; +	} + +	rix += rate->idx + rate_table->mcs_start; + +	if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && +	    (rate->flags & IEEE80211_TX_RC_SHORT_GI)) +		rix = rate_table->info[rix].ht_index; +	else if (rate->flags & IEEE80211_TX_RC_SHORT_GI) +		rix = rate_table->info[rix].sgi_index; +	else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) +		rix = rate_table->info[rix].cw40index; + +	return rix; +}  static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,  				   struct ath_rate_priv *ath_rc_priv) @@ -533,7 +556,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,  					[valid_rate_count] = j;  				ath_rc_priv->valid_phy_ratecnt[phy] += 1;  				ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); -				hi = A_MAX(hi, j); +				hi = max(hi, j);  			}  		}  	} @@ -569,7 +592,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,  				[ath_rc_priv->valid_phy_ratecnt[phy]] = j;  			ath_rc_priv->valid_phy_ratecnt[phy] += 1;  			ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); -			hi = A_MAX(hi, j); +			hi = max(hi, j);  		}  	} @@ -1080,31 +1103,6 @@ static void ath_rc_update_ht(struct ath_softc *sc,  } -static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, -				struct ieee80211_tx_rate *rate) -{ -	int rix = 0, i = 0; -	static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 }; - -	if (!(rate->flags & IEEE80211_TX_RC_MCS)) -		return rate->idx; - -	while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) { -		rix++; i++; -	} - -	rix += rate->idx + rate_table->mcs_start; - -	if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && -	    (rate->flags & IEEE80211_TX_RC_SHORT_GI)) -		rix = rate_table->info[rix].ht_index; -	else if (rate->flags & IEEE80211_TX_RC_SHORT_GI) -		rix = rate_table->info[rix].sgi_index; -	else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) -		rix = rate_table->info[rix].cw40index; - -	return rix; -}  static void ath_rc_tx_status(struct ath_softc *sc,  			     struct ath_rate_priv *ath_rc_priv, @@ -1228,7 +1226,7 @@ static void ath_rc_init(struct ath_softc *sc,  						       ht_mcs,  						       ath_rc_priv->ht_cap);  		} -		hi = A_MAX(hi, hthi); +		hi = max(hi, hthi);  	}  	ath_rc_priv->rate_table_size = hi + 1; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 07e35e59c9e..70dc8ecdad4 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -14,6 +14,7 @@   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   */ +#include <linux/dma-mapping.h>  #include "ath9k.h"  #include "ar9003_mac.h" @@ -39,6 +40,7 @@ static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio,  			result = true;  		break;  	case 1: +	case 2:  		if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) &&  			(curr_alt_set == ATH_ANT_DIV_COMB_LNA1) &&  				(alt_rssi_avg >= (main_rssi_avg - 5))) || @@ -1075,39 +1077,39 @@ static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,  		antcomb->rssi_lna1 = main_rssi_avg;  	switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { -	case (0x10): /* LNA2 A-B */ +	case 0x10: /* LNA2 A-B */  		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;  		antcomb->first_quick_scan_conf =  			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;  		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;  		break; -	case (0x20): /* LNA1 A-B */ +	case 0x20: /* LNA1 A-B */  		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;  		antcomb->first_quick_scan_conf =  			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;  		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;  		break; -	case (0x21): /* LNA1 LNA2 */ +	case 0x21: /* LNA1 LNA2 */  		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;  		antcomb->first_quick_scan_conf =  			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;  		antcomb->second_quick_scan_conf =  			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;  		break; -	case (0x12): /* LNA2 LNA1 */ +	case 0x12: /* LNA2 LNA1 */  		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;  		antcomb->first_quick_scan_conf =  			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;  		antcomb->second_quick_scan_conf =  			ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;  		break; -	case (0x13): /* LNA2 A+B */ +	case 0x13: /* LNA2 A+B */  		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;  		antcomb->first_quick_scan_conf =  			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;  		antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;  		break; -	case (0x23): /* LNA1 A+B */ +	case 0x23: /* LNA1 A+B */  		antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;  		antcomb->first_quick_scan_conf =  			ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; @@ -1324,65 +1326,148 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,  		/* Adjust the fast_div_bias based on main and alt lna conf */  		switch ((ant_conf->main_lna_conf << 4) |  				ant_conf->alt_lna_conf) { -		case (0x01): /* A-B LNA2 */ +		case 0x01: /* A-B LNA2 */  			ant_conf->fast_div_bias = 0x3b;  			break; -		case (0x02): /* A-B LNA1 */ +		case 0x02: /* A-B LNA1 */  			ant_conf->fast_div_bias = 0x3d;  			break; -		case (0x03): /* A-B A+B */ +		case 0x03: /* A-B A+B */  			ant_conf->fast_div_bias = 0x1;  			break; -		case (0x10): /* LNA2 A-B */ +		case 0x10: /* LNA2 A-B */  			ant_conf->fast_div_bias = 0x7;  			break; -		case (0x12): /* LNA2 LNA1 */ +		case 0x12: /* LNA2 LNA1 */  			ant_conf->fast_div_bias = 0x2;  			break; -		case (0x13): /* LNA2 A+B */ +		case 0x13: /* LNA2 A+B */  			ant_conf->fast_div_bias = 0x7;  			break; -		case (0x20): /* LNA1 A-B */ +		case 0x20: /* LNA1 A-B */  			ant_conf->fast_div_bias = 0x6;  			break; -		case (0x21): /* LNA1 LNA2 */ +		case 0x21: /* LNA1 LNA2 */  			ant_conf->fast_div_bias = 0x0;  			break; -		case (0x23): /* LNA1 A+B */ +		case 0x23: /* LNA1 A+B */  			ant_conf->fast_div_bias = 0x6;  			break; -		case (0x30): /* A+B A-B */ +		case 0x30: /* A+B A-B */  			ant_conf->fast_div_bias = 0x1;  			break; -		case (0x31): /* A+B LNA2 */ +		case 0x31: /* A+B LNA2 */  			ant_conf->fast_div_bias = 0x3b;  			break; -		case (0x32): /* A+B LNA1 */ +		case 0x32: /* A+B LNA1 */  			ant_conf->fast_div_bias = 0x3d;  			break;  		default:  			break;  		} +	} else if (ant_conf->div_group == 1) { +		/* Adjust the fast_div_bias based on main and alt_lna_conf */ +		switch ((ant_conf->main_lna_conf << 4) | +			ant_conf->alt_lna_conf) { +		case 0x01: /* A-B LNA2 */ +			ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x02: /* A-B LNA1 */ +			ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x03: /* A-B A+B */ +			ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x10: /* LNA2 A-B */ +			if (!(antcomb->scan) && +			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) +				ant_conf->fast_div_bias = 0x3f; +			else +				ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x12: /* LNA2 LNA1 */ +			ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x13: /* LNA2 A+B */ +			if (!(antcomb->scan) && +			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) +				ant_conf->fast_div_bias = 0x3f; +			else +				ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x20: /* LNA1 A-B */ +			if (!(antcomb->scan) && +			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) +				ant_conf->fast_div_bias = 0x3f; +			else +				ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x21: /* LNA1 LNA2 */ +			ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x23: /* LNA1 A+B */ +			if (!(antcomb->scan) && +			    (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) +				ant_conf->fast_div_bias = 0x3f; +			else +				ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x30: /* A+B A-B */ +			ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x31: /* A+B LNA2 */ +			ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		case 0x32: /* A+B LNA1 */ +			ant_conf->fast_div_bias = 0x1; +			ant_conf->main_gaintb = 0; +			ant_conf->alt_gaintb = 0; +			break; +		default: +			break; +		}  	} else if (ant_conf->div_group == 2) {  		/* Adjust the fast_div_bias based on main and alt_lna_conf */  		switch ((ant_conf->main_lna_conf << 4) |  				ant_conf->alt_lna_conf) { -		case (0x01): /* A-B LNA2 */ +		case 0x01: /* A-B LNA2 */  			ant_conf->fast_div_bias = 0x1;  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x02): /* A-B LNA1 */ +		case 0x02: /* A-B LNA1 */  			ant_conf->fast_div_bias = 0x1;  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x03): /* A-B A+B */ +		case 0x03: /* A-B A+B */  			ant_conf->fast_div_bias = 0x1;  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x10): /* LNA2 A-B */ +		case 0x10: /* LNA2 A-B */  			if (!(antcomb->scan) &&  				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))  				ant_conf->fast_div_bias = 0x1; @@ -1391,12 +1476,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x12): /* LNA2 LNA1 */ +		case 0x12: /* LNA2 LNA1 */  			ant_conf->fast_div_bias = 0x1;  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x13): /* LNA2 A+B */ +		case 0x13: /* LNA2 A+B */  			if (!(antcomb->scan) &&  				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))  				ant_conf->fast_div_bias = 0x1; @@ -1405,7 +1490,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x20): /* LNA1 A-B */ +		case 0x20: /* LNA1 A-B */  			if (!(antcomb->scan) &&  				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))  				ant_conf->fast_div_bias = 0x1; @@ -1414,12 +1499,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x21): /* LNA1 LNA2 */ +		case 0x21: /* LNA1 LNA2 */  			ant_conf->fast_div_bias = 0x1;  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x23): /* LNA1 A+B */ +		case 0x23: /* LNA1 A+B */  			if (!(antcomb->scan) &&  				(alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))  				ant_conf->fast_div_bias = 0x1; @@ -1428,17 +1513,17 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x30): /* A+B A-B */ +		case 0x30: /* A+B A-B */  			ant_conf->fast_div_bias = 0x1;  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x31): /* A+B LNA2 */ +		case 0x31: /* A+B LNA2 */  			ant_conf->fast_div_bias = 0x1;  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0;  			break; -		case (0x32): /* A+B LNA1 */ +		case 0x32: /* A+B LNA1 */  			ant_conf->fast_div_bias = 0x1;  			ant_conf->main_gaintb = 0;  			ant_conf->alt_gaintb = 0; @@ -1446,9 +1531,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,  		default:  			break;  		} -  	} -  }  /* Antenna diversity and combining */ diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index c18ee9921fb..759b72cca3c 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -600,7 +600,6 @@  #define AR_D_GBL_IFS_SIFS         0x1030  #define AR_D_GBL_IFS_SIFS_M       0x0000FFFF -#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB  #define AR_D_GBL_IFS_SIFS_RESV0   0xFFFFFFFF  #define AR_D_TXBLK_BASE            0x1038 @@ -616,12 +615,10 @@  #define AR_D_GBL_IFS_SLOT         0x1070  #define AR_D_GBL_IFS_SLOT_M       0x0000FFFF  #define AR_D_GBL_IFS_SLOT_RESV0   0xFFFF0000 -#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR   0x00000420  #define AR_D_GBL_IFS_EIFS         0x10b0  #define AR_D_GBL_IFS_EIFS_M       0x0000FFFF  #define AR_D_GBL_IFS_EIFS_RESV0   0xFFFF0000 -#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR   0x0000A5EB  #define AR_D_GBL_IFS_MISC        0x10f0  #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL        0x00000007 @@ -788,6 +785,10 @@  #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_VERSION_9330		0x200 +#define AR_SREV_REVISION_9330_10	0 +#define AR_SREV_REVISION_9330_11	1 +#define AR_SREV_REVISION_9330_12	2  #define AR_SREV_VERSION_9485		0x240  #define AR_SREV_REVISION_9485_10	0  #define AR_SREV_REVISION_9485_11        1 @@ -862,6 +863,18 @@  #define AR_SREV_9300_20_OR_LATER(_ah) \  	((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300) +#define AR_SREV_9330(_ah) \ +	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330)) +#define AR_SREV_9330_10(_ah) \ +	(AR_SREV_9330((_ah)) && \ +	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_10)) +#define AR_SREV_9330_11(_ah) \ +	(AR_SREV_9330((_ah)) && \ +	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_11)) +#define AR_SREV_9330_12(_ah) \ +	(AR_SREV_9330((_ah)) && \ +	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12)) +  #define AR_SREV_9485(_ah) \  	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))  #define AR_SREV_9485_10(_ah) \ @@ -1461,7 +1474,6 @@ enum {  #define AR_TIME_OUT_ACK_S    0  #define AR_TIME_OUT_CTS      0x3FFF0000  #define AR_TIME_OUT_CTS_S    16 -#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR    0x16001D56  #define AR_RSSI_THR          0x8018  #define AR_RSSI_THR_MASK     0x000000FF @@ -1477,7 +1489,6 @@ enum {  #define AR_USEC_TX_LAT_S     14  #define AR_USEC_RX_LAT       0x1F800000  #define AR_USEC_RX_LAT_S     23 -#define AR_USEC_ASYNC_FIFO_DUR    0x12e00074  #define AR_RESET_TSF        0x8020  #define AR_RESET_TSF_ONCE   0x01000000 diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 3779b8977d4..6eb58b16ab0 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -14,6 +14,7 @@   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   */ +#include <linux/dma-mapping.h>  #include "ath9k.h"  #include "ar9003_mac.h" @@ -53,7 +54,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,  				struct ath_txq *txq, struct list_head *bf_q,  				struct ath_tx_status *ts, int txok, int sendbar);  static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, -			     struct list_head *head); +			     struct list_head *head, bool internal);  static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);  static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,  			     struct ath_tx_status *ts, int nframes, int nbad, @@ -377,8 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  			bf_next = bf->bf_next;  			bf->bf_state.bf_type |= BUF_XRETRY; -			if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) || -			    !bf->bf_stale || bf_next != NULL) +			if (!bf->bf_stale || bf_next != NULL)  				list_move_tail(&bf->list, &bf_head);  			ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false); @@ -463,20 +463,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  			}  		} -		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. -			 */ -			if (!bf_last->bf_stale) -				list_move_tail(&bf->list, &bf_head); -			else -				INIT_LIST_HEAD(&bf_head); -		} else { -			BUG_ON(list_empty(bf_q)); +		/* +		 * Make sure the last desc is reclaimed if it +		 * not a holding desc. +		 */ +		if (!bf_last->bf_stale || bf_next != NULL)  			list_move_tail(&bf->list, &bf_head); -		} +		else +			INIT_LIST_HEAD(&bf_head);  		if (!txpending || (tid->state & AGGR_CLEANUP)) {  			/* @@ -572,11 +566,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  	rcu_read_unlock(); -	if (needreset) { -		spin_unlock_bh(&sc->sc_pcu_lock); +	if (needreset)  		ath_reset(sc, false); -		spin_lock_bh(&sc->sc_pcu_lock); -	}  }  static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, @@ -671,7 +662,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,  	 * TODO - this could be improved to be dependent on the rate.  	 *      The hardware can keep up at lower rates, but not higher rates  	 */ -	if (fi->keyix != ATH9K_TXKEYIX_INVALID) +	if ((fi->keyix != ATH9K_TXKEYIX_INVALID) && +	    !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))  		ndelim += ATH_AGGR_ENCRYPTDELIM;  	/* @@ -837,7 +829,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,  			bf->bf_state.bf_type &= ~BUF_AGGR;  			ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);  			ath_buf_set_rate(sc, bf, fi->framelen); -			ath_tx_txqaddbuf(sc, txq, &bf_q); +			ath_tx_txqaddbuf(sc, txq, &bf_q, false);  			continue;  		} @@ -849,7 +841,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,  		/* anchor last desc of aggregate */  		ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); -		ath_tx_txqaddbuf(sc, txq, &bf_q); +		ath_tx_txqaddbuf(sc, txq, &bf_q, false);  		TX_STAT_INC(txq->axq_qnum, a_aggr);  	} while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH && @@ -1085,7 +1077,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)  		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[axq_qnum];  } @@ -1155,13 +1146,8 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf)      return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);  } -/* - * Drain a given TX queue (could be Beacon or Data) - * - * This assumes output has been stopped and - * we do not need to block ath_tx_tasklet. - */ -void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) +static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq, +			       struct list_head *list, bool retry_tx)  {  	struct ath_buf *bf, *lastbf;  	struct list_head bf_head; @@ -1170,93 +1156,63 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)  	memset(&ts, 0, sizeof(ts));  	INIT_LIST_HEAD(&bf_head); -	for (;;) { -		spin_lock_bh(&txq->axq_lock); +	while (!list_empty(list)) { +		bf = list_first_entry(list, 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); -				ath_tx_return_buffer(sc, bf); -				continue; -			} +			ath_tx_return_buffer(sc, bf); +			continue;  		}  		lastbf = bf->bf_lastbf; - -		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); -		} +		list_cut_position(&bf_head, list, &lastbf->list);  		txq->axq_depth--;  		if (bf_is_ampdu_not_probing(bf))  			txq->axq_ampdu_depth--; -		spin_unlock_bh(&txq->axq_lock); +		spin_unlock_bh(&txq->axq_lock);  		if (bf_isampdu(bf))  			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,  					     retry_tx);  		else  			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); +		spin_lock_bh(&txq->axq_lock);  	} +} +/* + * Drain a given TX queue (could be Beacon or Data) + * + * This assumes output has been stopped and + * we do not need to block ath_tx_tasklet. + */ +void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) +{  	spin_lock_bh(&txq->axq_lock); -	txq->axq_tx_inprogress = false; -	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); +		int idx = txq->txq_tailidx; -			if (bf_isampdu(bf)) -				ath_tx_complete_aggr(sc, txq, bf, &bf_head, -						     &ts, 0, retry_tx); -			else -				ath_tx_complete_buf(sc, bf, txq, &bf_head, -						    &ts, 0, 0); -			spin_lock_bh(&txq->axq_lock); +		while (!list_empty(&txq->txq_fifo[idx])) { +			ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx], +					   retry_tx); + +			INCR(idx, ATH_TXFIFO_DEPTH);  		} -		spin_unlock_bh(&txq->axq_lock); +		txq->txq_tailidx = idx;  	} +	txq->axq_link = NULL; +	txq->axq_tx_inprogress = false; +	ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx); +  	/* flush any pending frames if aggregation is enabled */ -	if (sc->sc_flags & SC_OP_TXAGGR) { -		if (!retry_tx) { -			spin_lock_bh(&txq->axq_lock); -			ath_txq_drain_pending_buffers(sc, txq); -			spin_unlock_bh(&txq->axq_lock); -		} -	} +	if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx) +		ath_txq_drain_pending_buffers(sc, txq); + +	spin_unlock_bh(&txq->axq_lock);  }  bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) @@ -1370,11 +1326,13 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)   * assume the descriptors are already chained together by caller.   */  static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, -			     struct list_head *head) +			     struct list_head *head, bool internal)  {  	struct ath_hw *ah = sc->sc_ah;  	struct ath_common *common = ath9k_hw_common(ah); -	struct ath_buf *bf; +	struct ath_buf *bf, *bf_last; +	bool puttxbuf = false; +	bool edma;  	/*  	 * Insert the frame on the outbound list and @@ -1384,51 +1342,49 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,  	if (list_empty(head))  		return; +	edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);  	bf = list_first_entry(head, struct ath_buf, list); +	bf_last = list_entry(head->prev, struct ath_buf, list);  	ath_dbg(common, ATH_DBG_QUEUE,  		"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); -	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_dbg(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]); +	if (edma && list_empty(&txq->txq_fifo[txq->txq_headidx])) { +		list_splice_tail_init(head, &txq->txq_fifo[txq->txq_headidx]);  		INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH); -		TX_STAT_INC(txq->axq_qnum, puttxbuf); -		ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); -		ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", -			txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); +		puttxbuf = true;  	} else {  		list_splice_tail_init(head, &txq->axq_q); -		if (txq->axq_link == NULL) { -			TX_STAT_INC(txq->axq_qnum, puttxbuf); -			ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); -			ath_dbg(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; +		if (txq->axq_link) { +			ath9k_hw_set_desc_link(ah, txq->axq_link, bf->bf_daddr);  			ath_dbg(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); +		} else if (!edma) +			puttxbuf = true; + +		txq->axq_link = bf_last->bf_desc; +	} + +	if (puttxbuf) { +		TX_STAT_INC(txq->axq_qnum, puttxbuf); +		ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); +		ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", +			txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); +	} + +	if (!edma) {  		TX_STAT_INC(txq->axq_qnum, txstart);  		ath9k_hw_txstart(ah, txq->axq_qnum);  	} -	txq->axq_depth++; -	if (bf_is_ampdu_not_probing(bf)) -		txq->axq_ampdu_depth++; + +	if (!internal) { +		txq->axq_depth++; +		if (bf_is_ampdu_not_probing(bf)) +			txq->axq_ampdu_depth++; +	}  }  static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, @@ -1470,7 +1426,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,  	TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);  	bf->bf_lastbf = bf;  	ath_buf_set_rate(sc, bf, fi->framelen); -	ath_tx_txqaddbuf(sc, txctl->txq, &bf_head); +	ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);  }  static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, @@ -1490,7 +1446,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,  	bf->bf_lastbf = bf;  	fi = get_frame_info(bf->bf_mpdu);  	ath_buf_set_rate(sc, bf, fi->framelen); -	ath_tx_txqaddbuf(sc, txq, bf_head); +	ath_tx_txqaddbuf(sc, txq, bf_head, false);  	TX_STAT_INC(txq->axq_qnum, queued);  } @@ -2077,6 +2033,38 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,  	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;  } +static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, +				  struct ath_tx_status *ts, struct ath_buf *bf, +				  struct list_head *bf_head) +{ +	int txok; + +	txq->axq_depth--; +	txok = !(ts->ts_status & ATH9K_TXERR_MASK); +	txq->axq_tx_inprogress = false; +	if (bf_is_ampdu_not_probing(bf)) +		txq->axq_ampdu_depth--; + +	spin_unlock_bh(&txq->axq_lock); + +	if (!bf_isampdu(bf)) { +		/* +		 * This frame is sent out as a single frame. +		 * Use hardware retry status for this frame. +		 */ +		if (ts->ts_status & ATH9K_TXERR_XRETRY) +			bf->bf_state.bf_type |= BUF_XRETRY; +		ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true); +		ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0); +	} else +		ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true); + +	spin_lock_bh(&txq->axq_lock); + +	if (sc->sc_flags & SC_OP_TXAGGR) +		ath_txq_schedule(sc, txq); +} +  static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)  {  	struct ath_hw *ah = sc->sc_ah; @@ -2085,20 +2073,18 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)  	struct list_head bf_head;  	struct ath_desc *ds;  	struct ath_tx_status ts; -	int txok;  	int status;  	ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",  		txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),  		txq->axq_link); +	spin_lock_bh(&txq->axq_lock);  	for (;;) { -		spin_lock_bh(&txq->axq_lock);  		if (list_empty(&txq->axq_q)) {  			txq->axq_link = NULL;  			if (sc->sc_flags & SC_OP_TXAGGR)  				ath_txq_schedule(sc, txq); -			spin_unlock_bh(&txq->axq_lock);  			break;  		}  		bf = list_first_entry(&txq->axq_q, struct ath_buf, list); @@ -2114,13 +2100,11 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)  		bf_held = NULL;  		if (bf->bf_stale) {  			bf_held = bf; -			if (list_is_last(&bf_held->list, &txq->axq_q)) { -				spin_unlock_bh(&txq->axq_lock); +			if (list_is_last(&bf_held->list, &txq->axq_q))  				break; -			} else { -				bf = list_entry(bf_held->list.next, -						struct ath_buf, list); -			} + +			bf = list_entry(bf_held->list.next, struct ath_buf, +					list);  		}  		lastbf = bf->bf_lastbf; @@ -2128,10 +2112,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)  		memset(&ts, 0, sizeof(ts));  		status = ath9k_hw_txprocdesc(ah, ds, &ts); -		if (status == -EINPROGRESS) { -			spin_unlock_bh(&txq->axq_lock); +		if (status == -EINPROGRESS)  			break; -		} +  		TX_STAT_INC(txq->axq_qnum, txprocdesc);  		/* @@ -2145,42 +2128,14 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)  			list_cut_position(&bf_head,  				&txq->axq_q, lastbf->list.prev); -		txq->axq_depth--; -		txok = !(ts.ts_status & ATH9K_TXERR_MASK); -		txq->axq_tx_inprogress = false; -		if (bf_held) +		if (bf_held) {  			list_del(&bf_held->list); - -		if (bf_is_ampdu_not_probing(bf)) -			txq->axq_ampdu_depth--; - -		spin_unlock_bh(&txq->axq_lock); - -		if (bf_held)  			ath_tx_return_buffer(sc, bf_held); - -		if (!bf_isampdu(bf)) { -			/* -			 * This frame is sent out as a single frame. -			 * Use hardware retry status for this frame. -			 */ -			if (ts.ts_status & ATH9K_TXERR_XRETRY) -				bf->bf_state.bf_type |= BUF_XRETRY; -			ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true);  		} -		if (bf_isampdu(bf)) -			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok, -					     true); -		else -			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); - -		spin_lock_bh(&txq->axq_lock); - -		if (sc->sc_flags & SC_OP_TXAGGR) -			ath_txq_schedule(sc, txq); -		spin_unlock_bh(&txq->axq_lock); +		ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);  	} +	spin_unlock_bh(&txq->axq_lock);  }  static void ath_tx_complete_poll_work(struct work_struct *work) @@ -2213,7 +2168,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work)  	if (needreset) {  		ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,  			"tx hung, resetting the chip\n"); +		spin_lock_bh(&sc->sc_pcu_lock);  		ath_reset(sc, true); +		spin_unlock_bh(&sc->sc_pcu_lock);  	}  	ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, @@ -2237,17 +2194,16 @@ void ath_tx_tasklet(struct ath_softc *sc)  void ath_tx_edma_tasklet(struct ath_softc *sc)  { -	struct ath_tx_status txs; +	struct ath_tx_status ts;  	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); +		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);  		if (status == -EINPROGRESS)  			break;  		if (status == -EIO) { @@ -2257,12 +2213,13 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)  		}  		/* Skip beacon completions */ -		if (txs.qid == sc->beacon.beaconq) +		if (ts.qid == sc->beacon.beaconq)  			continue; -		txq = &sc->tx.txq[txs.qid]; +		txq = &sc->tx.txq[ts.qid];  		spin_lock_bh(&txq->axq_lock); +  		if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {  			spin_unlock_bh(&txq->axq_lock);  			return; @@ -2275,41 +2232,21 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)  		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; -		if (bf_is_ampdu_not_probing(bf)) -			txq->axq_ampdu_depth--; -		spin_unlock_bh(&txq->axq_lock); -		txok = !(txs.ts_status & ATH9K_TXERR_MASK); - -		if (!bf_isampdu(bf)) { -			if (txs.ts_status & ATH9K_TXERR_XRETRY) -				bf->bf_state.bf_type |= BUF_XRETRY; -			ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true); -		} - -		if (bf_isampdu(bf)) -			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, -					     txok, true); -		else -			ath_tx_complete_buf(sc, bf, txq, &bf_head, -					    &txs, txok, 0); +		if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) { +			INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); -		spin_lock_bh(&txq->axq_lock); +			if (!list_empty(&txq->axq_q)) { +				struct list_head bf_q; -		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); +				INIT_LIST_HEAD(&bf_q); +				txq->axq_link = NULL; +				list_splice_tail_init(&txq->axq_q, &bf_q); +				ath_tx_txqaddbuf(sc, txq, &bf_q, true); +			} +		} +		ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);  		spin_unlock_bh(&txq->axq_lock);  	}  } diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 4da01a9f568..f9a4655ea0b 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -67,6 +67,8 @@  #define PAYLOAD_MAX	(CARL9170_MAX_CMD_LEN / 4 - 1) +static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 }; +  enum carl9170_rf_init_mode {  	CARL9170_RFI_NONE,  	CARL9170_RFI_WARM, @@ -440,7 +442,6 @@ struct ar9170 {  enum carl9170_ps_off_override_reasons {  	PS_OFF_VIF	= BIT(0),  	PS_OFF_BCN	= BIT(1), -	PS_OFF_5GHZ	= BIT(2),  };  struct carl9170_ba_stats { diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index 221957c5d37..39ddea5794f 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c @@ -237,7 +237,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)  		ar->disable_offload = true;  	} -	if (SUPP(CARL9170FW_PSM)) +	if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM))  		ar->hw->flags |= IEEE80211_HW_SUPPORTS_PS;  	if (!SUPP(CARL9170FW_USB_INIT_FIRMWARE)) { diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index 30449d21b76..0a6dec529b5 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -4,7 +4,7 @@   * Firmware command interface definitions   *   * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> - * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> + * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.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 @@ -54,6 +54,7 @@ enum carl9170_cmd_oids {  	CARL9170_CMD_BCN_CTRL		= 0x05,  	CARL9170_CMD_READ_TSF		= 0x06,  	CARL9170_CMD_RX_FILTER		= 0x07, +	CARL9170_CMD_WOL		= 0x08,  	/* CAM */  	CARL9170_CMD_EKEY		= 0x10, @@ -180,6 +181,21 @@ struct carl9170_bcn_ctrl_cmd {  #define CARL9170_BCN_CTRL_DRAIN	0  #define CARL9170_BCN_CTRL_CAB_TRIGGER	1 +struct carl9170_wol_cmd { +	__le32		flags; +	u8		mac[6]; +	u8		bssid[6]; +	__le32		null_interval; +	__le32		free_for_use2; +	__le32		mask; +	u8		pattern[32]; +} __packed; + +#define CARL9170_WOL_CMD_SIZE		60 + +#define CARL9170_WOL_DISCONNECT		1 +#define CARL9170_WOL_MAGIC_PKT		2 +  struct carl9170_cmd_head {  	union {  		struct { @@ -203,6 +219,7 @@ struct carl9170_cmd {  		struct carl9170_write_reg	wreg;  		struct carl9170_rf_init		rf_init;  		struct carl9170_psm		psm; +		struct carl9170_wol_cmd		wol;  		struct carl9170_bcn_ctrl_cmd	bcn_ctrl;  		struct carl9170_rx_filter_cmd	rx_filter;  		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN]; diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h index 921066822dd..7ba62bb7705 100644 --- a/drivers/net/wireless/ath/carl9170/fwdesc.h +++ b/drivers/net/wireless/ath/carl9170/fwdesc.h @@ -3,7 +3,7 @@   *   * Firmware descriptor format   * - * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> + * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.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 @@ -72,6 +72,9 @@ enum carl9170fw_feature_list {  	/* Wake up on WLAN */  	CARL9170FW_WOL, +	/* Firmware supports PSM in the 5GHZ Band */ +	CARL9170FW_FIXED_5GHZ_PSM, +  	/* KEEP LAST */  	__CARL9170FW_FEATURE_NUM  }; @@ -82,6 +85,7 @@ enum carl9170fw_feature_list {  #define DBG_MAGIC	"DBG\0"  #define CHK_MAGIC	"CHK\0"  #define TXSQ_MAGIC	"TXSQ" +#define WOL_MAGIC	"WOL\0"  #define LAST_MAGIC	"LAST"  #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31) @@ -104,7 +108,7 @@ struct carl9170fw_desc_head {  	(sizeof(struct carl9170fw_desc_head))  #define CARL9170FW_OTUS_DESC_MIN_VER		6 -#define CARL9170FW_OTUS_DESC_CUR_VER		6 +#define CARL9170FW_OTUS_DESC_CUR_VER		7  struct carl9170fw_otus_desc {  	struct carl9170fw_desc_head head;  	__le32 feature_set; @@ -186,6 +190,16 @@ struct carl9170fw_txsq_desc {  #define CARL9170FW_TXSQ_DESC_SIZE			\  	(sizeof(struct carl9170fw_txsq_desc)) +#define CARL9170FW_WOL_DESC_MIN_VER			1 +#define CARL9170FW_WOL_DESC_CUR_VER			1 +struct carl9170fw_wol_desc { +	struct carl9170fw_desc_head head; + +	__le32 supported_triggers;	/* CARL9170_WOL_ */ +} __packed; +#define CARL9170FW_WOL_DESC_SIZE			\ +	(sizeof(struct carl9170fw_wol_desc)) +  #define CARL9170FW_LAST_DESC_MIN_VER			1  #define CARL9170FW_LAST_DESC_CUR_VER			2  struct carl9170fw_last_desc { diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h index 4e30762dd90..261f8935107 100644 --- a/drivers/net/wireless/ath/carl9170/hw.h +++ b/drivers/net/wireless/ath/carl9170/hw.h @@ -4,7 +4,7 @@   * Register map, hardware-specific definitions   *   * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> - * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> + * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.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 @@ -357,7 +357,18 @@  #define AR9170_MAC_REG_DMA_WLAN_STATUS		(AR9170_MAC_REG_BASE + 0xd38)  #define	AR9170_MAC_REG_DMA_STATUS		(AR9170_MAC_REG_BASE + 0xd3c) +#define AR9170_MAC_REG_DMA_TXQ_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd40) +#define	AR9170_MAC_REG_DMA_TXQ0_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd40) +#define	AR9170_MAC_REG_DMA_TXQ1_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd44) +#define	AR9170_MAC_REG_DMA_TXQ2_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd48) +#define	AR9170_MAC_REG_DMA_TXQ3_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd4c) +#define	AR9170_MAC_REG_DMA_TXQ4_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd50) +#define	AR9170_MAC_REG_DMA_TXQ0Q1_LEN		(AR9170_MAC_REG_BASE + 0xd54) +#define	AR9170_MAC_REG_DMA_TXQ2Q3_LEN		(AR9170_MAC_REG_BASE + 0xd58) +#define	AR9170_MAC_REG_DMA_TXQ4_LEN		(AR9170_MAC_REG_BASE + 0xd5c) +#define AR9170_MAC_REG_DMA_TXQX_LAST_ADDR	(AR9170_MAC_REG_BASE + 0xd74) +#define AR9170_MAC_REG_DMA_TXQX_FAIL_ADDR	(AR9170_MAC_REG_BASE + 0xd78)  #define	AR9170_MAC_REG_TXRX_MPI			(AR9170_MAC_REG_BASE + 0xd7c)  #define		AR9170_MAC_TXRX_MPI_TX_MPI_MASK		0x0000000f  #define		AR9170_MAC_TXRX_MPI_TX_TO_MASK		0x0000fff0 diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 54d093c2ab4..a61cf6781d5 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -345,11 +345,11 @@ static int carl9170_op_start(struct ieee80211_hw *hw)  	carl9170_zap_queues(ar);  	/* reset QoS defaults */ -	CARL9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023,  0); /* BEST EFFORT */ -	CARL9170_FILL_QUEUE(ar->edcf[1], 2, 7,    15, 94); /* VIDEO */ -	CARL9170_FILL_QUEUE(ar->edcf[2], 2, 3,     7, 47); /* VOICE */ -	CARL9170_FILL_QUEUE(ar->edcf[3], 7, 15, 1023,  0); /* BACKGROUND */ -	CARL9170_FILL_QUEUE(ar->edcf[4], 2, 3,     7,  0); /* SPECIAL */ +	CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_VO], 2, 3,     7, 47); +	CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_VI], 2, 7,    15, 94); +	CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_BE], 3, 15, 1023,  0); +	CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_BK], 7, 15, 1023,  0); +	CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_SPECIAL], 2, 3, 7, 0);  	ar->current_factor = ar->current_density = -1;  	/* "The first key is unique." */ @@ -1484,6 +1484,13 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw,  	}  } +static bool carl9170_tx_frames_pending(struct ieee80211_hw *hw) +{ +	struct ar9170 *ar = hw->priv; + +	return !!atomic_read(&ar->tx_total_queued); +} +  static const struct ieee80211_ops carl9170_ops = {  	.start			= carl9170_op_start,  	.stop			= carl9170_op_stop, @@ -1504,6 +1511,7 @@ static const struct ieee80211_ops carl9170_ops = {  	.get_survey		= carl9170_op_get_survey,  	.get_stats		= carl9170_op_get_stats,  	.ampdu_action		= carl9170_op_ampdu_action, +	.tx_frames_pending	= carl9170_tx_frames_pending,  };  void *carl9170_alloc(size_t priv_size) @@ -1577,6 +1585,7 @@ void *carl9170_alloc(size_t priv_size)  		     IEEE80211_HW_REPORTS_TX_ACK_STATUS |  		     IEEE80211_HW_SUPPORTS_PS |  		     IEEE80211_HW_PS_NULLFUNC_STACK | +		     IEEE80211_HW_NEED_DTIM_PERIOD |  		     IEEE80211_HW_SIGNAL_DBM;  	if (!modparam_noht) { diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index b6ae0e179c8..da1ab962ee4 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -1783,12 +1783,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,  		}  	} -	/* FIXME: PSM does not work in 5GHz Band */ -	if (channel->band == IEEE80211_BAND_5GHZ) -		ar->ps.off_override |= PS_OFF_5GHZ; -	else -		ar->ps.off_override &= ~PS_OFF_5GHZ; -  	ar->channel = channel;  	ar->ht_settings = new_ht;  	return 0; diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index ec21ea9fd8d..dc99030ea8b 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -472,7 +472,7 @@ static struct sk_buff *carl9170_rx_copy_data(u8 *buf, int len)  		u8 *qc = ieee80211_get_qos_ctl(hdr);  		reserved += NET_IP_ALIGN; -		if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) +		if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)  			reserved += NET_IP_ALIGN;  	} diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index 2fb53d06751..333b69ef2ae 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c @@ -112,6 +112,8 @@ static struct usb_device_id carl9170_usb_ids[] = {  	{ USB_DEVICE(0x04bb, 0x093f) },  	/* NEC WL300NU-G */  	{ USB_DEVICE(0x0409, 0x0249) }, +	/* NEC WL300NU-AG */ +	{ USB_DEVICE(0x0409, 0x02b4) },  	/* AVM FRITZ!WLAN USB Stick N */  	{ USB_DEVICE(0x057c, 0x8401) },  	/* AVM FRITZ!WLAN USB Stick N 2.4 */ diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h index 15095c03516..64703778cfe 100644 --- a/drivers/net/wireless/ath/carl9170/version.h +++ b/drivers/net/wireless/ath/carl9170/version.h @@ -1,7 +1,7 @@  #ifndef __CARL9170_SHARED_VERSION_H  #define __CARL9170_SHARED_VERSION_H  #define CARL9170FW_VERSION_YEAR 11 -#define CARL9170FW_VERSION_MONTH 1 -#define CARL9170FW_VERSION_DAY 22 -#define CARL9170FW_VERSION_GIT "1.9.2" +#define CARL9170FW_VERSION_MONTH 6 +#define CARL9170FW_VERSION_DAY 30 +#define CARL9170FW_VERSION_GIT "1.9.4"  #endif /* __CARL9170_SHARED_VERSION_H */ diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h index 9e1324b67e0..ea17995b32f 100644 --- a/drivers/net/wireless/ath/carl9170/wlan.h +++ b/drivers/net/wireless/ath/carl9170/wlan.h @@ -4,7 +4,7 @@   * RX/TX meta descriptor format   *   * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> - * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com> + * Copyright 2009-2011 Christian Lamparter <chunkeey@googlemail.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 @@ -278,7 +278,7 @@ struct ar9170_tx_frame {  struct carl9170_tx_superframe {  	struct carl9170_tx_superdesc s;  	struct ar9170_tx_frame f; -} __packed; +} __packed __aligned(4);  #endif /* __CARL9170FW__ */ @@ -328,7 +328,7 @@ struct _carl9170_tx_superframe {  	struct _carl9170_tx_superdesc s;  	struct _ar9170_tx_hwdesc f;  	u8 frame_data[0]; -} __packed; +} __packed __aligned(4);  #define	CARL9170_TX_SUPERDESC_LEN		24  #define	AR9170_TX_HWDESC_LEN			8 @@ -404,16 +404,6 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)  	       (t->DAidx & 0xc0) >> 6;  } -enum ar9170_txq { -	AR9170_TXQ_BE, - -	AR9170_TXQ_VI, -	AR9170_TXQ_VO, -	AR9170_TXQ_BK, - -	__AR9170_NUM_TXQ, -}; -  /*   * This is an workaround for several undocumented bugs.   * Don't mess with the QoS/AC <-> HW Queue map, if you don't @@ -431,7 +421,14 @@ enum ar9170_txq {   * result, this makes the device pretty much useless   * for any serious 802.11n setup.   */ -static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 }; +enum ar9170_txq { +	AR9170_TXQ_BK = 0,	/* TXQ0 */ +	AR9170_TXQ_BE,		/* TXQ1	*/ +	AR9170_TXQ_VI,		/* TXQ2	*/ +	AR9170_TXQ_VO,		/* TXQ3 */ + +	__AR9170_NUM_TXQ, +};  #define	AR9170_TXQ_DEPTH			32 diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 39a11e8af4f..7e45ca2e78e 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -40,6 +40,7 @@  ******************************************************************************/  #include <linux/init.h> +#include <linux/interrupt.h>  #include <linux/kernel.h>  #include <linux/ptrace.h> diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 480595f0441..d2293dcc117 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -26,6 +26,16 @@ config B43  	  This driver can be built as a module (recommended) that will be called "b43".  	  If unsure, say M. +config B43_BCMA +	bool "Support for BCMA bus" +	depends on B43 && BCMA && BROKEN +	default y + +config B43_SSB +	bool +	depends on B43 && SSB +	default y +  # Auto-select SSB PCI-HOST support, if possible  config B43_PCI_AUTOSELECT  	bool @@ -80,6 +90,12 @@ config B43_SDIO  #Data transfers to the device via PIO. We want it as a fallback even  # if we can do DMA. +config B43_BCMA_PIO +	bool +	depends on B43_BCMA +	select BCMA_BLOCKIO +	default y +  config B43_PIO  	bool  	depends on B43 @@ -107,6 +123,22 @@ config B43_PHY_LP  	  and embedded devices. It supports 802.11a/g  	  (802.11a support is optional, and currently disabled). +config B43_PHY_HT +	bool "Support for HT-PHY devices (BROKEN)" +	depends on B43 && BROKEN +	---help--- +	  Support for the HT-PHY. + +	  Say N, this is BROKEN and crashes driver. + +config B43_PHY_LCN +	bool "Support for LCN-PHY devices (BROKEN)" +	depends on B43 && BROKEN +	---help--- +	  Support for the LCN-PHY. + +	  Say N, this is BROKEN and crashes driver. +  # This config option automatically enables b43 LEDS support,  # if it's possible.  config B43_LEDS diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index cef334a8c66..4648bbf76ab 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -1,4 +1,5 @@  b43-y				+= main.o +b43-y				+= bus.o  b43-y				+= tables.o  b43-$(CONFIG_B43_PHY_N)		+= tables_nphy.o  b43-$(CONFIG_B43_PHY_N)		+= radio_2055.o @@ -9,6 +10,10 @@ b43-y				+= phy_a.o  b43-$(CONFIG_B43_PHY_N)		+= phy_n.o  b43-$(CONFIG_B43_PHY_LP)	+= phy_lp.o  b43-$(CONFIG_B43_PHY_LP)	+= tables_lpphy.o +b43-$(CONFIG_B43_PHY_HT)	+= phy_ht.o +b43-$(CONFIG_B43_PHY_HT)	+= tables_phy_ht.o +b43-$(CONFIG_B43_PHY_HT)	+= radio_2059.o +b43-$(CONFIG_B43_PHY_LCN)	+= phy_lcn.o tables_phy_lcn.o  b43-y				+= sysfs.o  b43-y				+= xmit.o  b43-y				+= lo.o diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 25a78cfb7d1..08a28270bbb 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -5,12 +5,14 @@  #include <linux/spinlock.h>  #include <linux/interrupt.h>  #include <linux/hw_random.h> +#include <linux/bcma/bcma.h>  #include <linux/ssb/ssb.h>  #include <net/mac80211.h>  #include "debugfs.h"  #include "leds.h"  #include "rfkill.h" +#include "bus.h"  #include "lo.h"  #include "phy_common.h" @@ -90,6 +92,8 @@  #define B43_MMIO_PIO11_BASE4		0x300  #define B43_MMIO_PIO11_BASE5		0x340 +#define B43_MMIO_RADIO24_CONTROL	0x3D8	/* core rev >= 24 only */ +#define B43_MMIO_RADIO24_DATA		0x3DA	/* core rev >= 24 only */  #define B43_MMIO_PHY_VER		0x3E0  #define B43_MMIO_PHY_RADIO		0x3E2  #define B43_MMIO_PHY0			0x3E6 @@ -361,6 +365,10 @@ enum {  #define B43_PHYTYPE_G			0x02  #define B43_PHYTYPE_N			0x04  #define B43_PHYTYPE_LP			0x05 +#define B43_PHYTYPE_SSLPN		0x06 +#define B43_PHYTYPE_HT			0x07 +#define B43_PHYTYPE_LCN			0x08 +#define B43_PHYTYPE_LCNXN		0x09  /* PHYRegisters */  #define B43_PHY_ILT_A_CTRL		0x0072 @@ -414,6 +422,17 @@ enum {  #define B43_MACCMD_CCA			0x00000008	/* Clear channel assessment */  #define B43_MACCMD_BGNOISE		0x00000010	/* Background noise */ +/* BCMA 802.11 core specific IO Control (BCMA_IOCTL) flags */ +#define B43_BCMA_IOCTL_PHY_CLKEN	0x00000004	/* PHY Clock Enable */ +#define B43_BCMA_IOCTL_PHY_RESET	0x00000008	/* PHY Reset */ +#define B43_BCMA_IOCTL_MACPHYCLKEN	0x00000010	/* MAC PHY Clock Control Enable */ +#define B43_BCMA_IOCTL_PLLREFSEL	0x00000020	/* PLL Frequency Reference Select */ +#define B43_BCMA_IOCTL_PHY_BW		0x000000C0	/* PHY band width and clock speed mask (N-PHY+ only?) */ +#define  B43_BCMA_IOCTL_PHY_BW_10MHZ	0x00000000	/* 10 MHz bandwidth, 40 MHz PHY */ +#define  B43_BCMA_IOCTL_PHY_BW_20MHZ	0x00000040	/* 20 MHz bandwidth, 80 MHz PHY */ +#define  B43_BCMA_IOCTL_PHY_BW_40MHZ	0x00000080	/* 40 MHz bandwidth, 160 MHz PHY */ +#define B43_BCMA_IOCTL_GMODE		0x00002000	/* G Mode Enable */ +  /* 802.11 core specific TM State Low (SSB_TMSLOW) flags */  #define B43_TMSLOW_GMODE		0x20000000	/* G Mode Enable */  #define B43_TMSLOW_PHY_BANDWIDTH	0x00C00000	/* PHY band width and clock speed mask (N-PHY only) */ @@ -707,7 +726,7 @@ enum {  /* Data structure for one wireless device (802.11 core) */  struct b43_wldev { -	struct ssb_device *sdev; +	struct b43_bus_dev *dev;  	struct b43_wl *wl;  	/* The device initialization status. @@ -879,36 +898,59 @@ static inline enum ieee80211_band b43_current_band(struct b43_wl *wl)  	return wl->hw->conf.channel->band;  } +static inline int b43_bus_may_powerdown(struct b43_wldev *wldev) +{ +	return wldev->dev->bus_may_powerdown(wldev->dev); +} +static inline int b43_bus_powerup(struct b43_wldev *wldev, bool dynamic_pctl) +{ +	return wldev->dev->bus_powerup(wldev->dev, dynamic_pctl); +} +static inline int b43_device_is_enabled(struct b43_wldev *wldev) +{ +	return wldev->dev->device_is_enabled(wldev->dev); +} +static inline void b43_device_enable(struct b43_wldev *wldev, +				     u32 core_specific_flags) +{ +	wldev->dev->device_enable(wldev->dev, core_specific_flags); +} +static inline void b43_device_disable(struct b43_wldev *wldev, +				      u32 core_specific_flags) +{ +	wldev->dev->device_disable(wldev->dev, core_specific_flags); +} +  static inline u16 b43_read16(struct b43_wldev *dev, u16 offset)  { -	return ssb_read16(dev->sdev, offset); +	return dev->dev->read16(dev->dev, offset);  }  static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value)  { -	ssb_write16(dev->sdev, offset, value); +	dev->dev->write16(dev->dev, offset, value);  }  static inline u32 b43_read32(struct b43_wldev *dev, u16 offset)  { -	return ssb_read32(dev->sdev, offset); +	return dev->dev->read32(dev->dev, offset);  }  static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value)  { -	ssb_write32(dev->sdev, offset, value); +	dev->dev->write32(dev->dev, offset, value);  }  static inline void b43_block_read(struct b43_wldev *dev, void *buffer,  				 size_t count, u16 offset, u8 reg_width)  { -	ssb_block_read(dev->sdev, buffer, count, offset, reg_width); +	dev->dev->block_read(dev->dev, buffer, count, offset, reg_width);  }  static inline void b43_block_write(struct b43_wldev *dev, const void *buffer,  				   size_t count, u16 offset, u8 reg_width)  { -	ssb_block_write(dev->sdev, buffer, count, offset, reg_width); +	dev->dev->block_write(dev->dev, buffer, count, offset, reg_width);  }  static inline bool b43_using_pio_transfers(struct b43_wldev *dev) diff --git a/drivers/net/wireless/b43/bus.c b/drivers/net/wireless/b43/bus.c new file mode 100644 index 00000000000..a5e61a9fb53 --- /dev/null +++ b/drivers/net/wireless/b43/bus.c @@ -0,0 +1,256 @@ +/* + +  Broadcom B43 wireless driver +  Bus abstraction layer + +  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. + +  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; see the file COPYING.  If not, write to +  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, +  Boston, MA 02110-1301, USA. + +*/ + +#include "b43.h" +#include "bus.h" + +/* BCMA */ +#ifdef CONFIG_B43_BCMA +static int b43_bus_bcma_bus_may_powerdown(struct b43_bus_dev *dev) +{ +	return 0; /* bcma_bus_may_powerdown(dev->bdev->bus); */ +} +static int b43_bus_bcma_bus_powerup(struct b43_bus_dev *dev, +					  bool dynamic_pctl) +{ +	return 0; /* bcma_bus_powerup(dev->sdev->bus, dynamic_pctl); */ +} +static int b43_bus_bcma_device_is_enabled(struct b43_bus_dev *dev) +{ +	return bcma_core_is_enabled(dev->bdev); +} +static void b43_bus_bcma_device_enable(struct b43_bus_dev *dev, +					     u32 core_specific_flags) +{ +	bcma_core_enable(dev->bdev, core_specific_flags); +} +static void b43_bus_bcma_device_disable(struct b43_bus_dev *dev, +					      u32 core_specific_flags) +{ +	bcma_core_disable(dev->bdev, core_specific_flags); +} +static u16 b43_bus_bcma_read16(struct b43_bus_dev *dev, u16 offset) +{ +	return bcma_read16(dev->bdev, offset); +} +static u32 b43_bus_bcma_read32(struct b43_bus_dev *dev, u16 offset) +{ +	return bcma_read32(dev->bdev, offset); +} +static +void b43_bus_bcma_write16(struct b43_bus_dev *dev, u16 offset, u16 value) +{ +	bcma_write16(dev->bdev, offset, value); +} +static +void b43_bus_bcma_write32(struct b43_bus_dev *dev, u16 offset, u32 value) +{ +	bcma_write32(dev->bdev, offset, value); +} +static +void b43_bus_bcma_block_read(struct b43_bus_dev *dev, void *buffer, +			     size_t count, u16 offset, u8 reg_width) +{ +	bcma_block_read(dev->bdev, buffer, count, offset, reg_width); +} +static +void b43_bus_bcma_block_write(struct b43_bus_dev *dev, const void *buffer, +			      size_t count, u16 offset, u8 reg_width) +{ +	bcma_block_write(dev->bdev, buffer, count, offset, reg_width); +} + +struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core) +{ +	struct b43_bus_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL); +	if (!dev) +		return NULL; + +	dev->bus_type = B43_BUS_BCMA; +	dev->bdev = core; + +	dev->bus_may_powerdown = b43_bus_bcma_bus_may_powerdown; +	dev->bus_powerup = b43_bus_bcma_bus_powerup; +	dev->device_is_enabled = b43_bus_bcma_device_is_enabled; +	dev->device_enable = b43_bus_bcma_device_enable; +	dev->device_disable = b43_bus_bcma_device_disable; + +	dev->read16 = b43_bus_bcma_read16; +	dev->read32 = b43_bus_bcma_read32; +	dev->write16 = b43_bus_bcma_write16; +	dev->write32 = b43_bus_bcma_write32; +	dev->block_read = b43_bus_bcma_block_read; +	dev->block_write = b43_bus_bcma_block_write; + +	dev->dev = &core->dev; +	dev->dma_dev = core->dma_dev; +	dev->irq = core->irq; + +	/* +	dev->board_vendor = core->bus->boardinfo.vendor; +	dev->board_type = core->bus->boardinfo.type; +	dev->board_rev = core->bus->boardinfo.rev; +	*/ + +	dev->chip_id = core->bus->chipinfo.id; +	dev->chip_rev = core->bus->chipinfo.rev; +	dev->chip_pkg = core->bus->chipinfo.pkg; + +	dev->bus_sprom = &core->bus->sprom; + +	dev->core_id = core->id.id; +	dev->core_rev = core->id.rev; + +	return dev; +} +#endif /* CONFIG_B43_BCMA */ + +/* SSB */ +#ifdef CONFIG_B43_SSB +static inline int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev) +{ +	return ssb_bus_may_powerdown(dev->sdev->bus); +} +static inline int b43_bus_ssb_bus_powerup(struct b43_bus_dev *dev, +					  bool dynamic_pctl) +{ +	return ssb_bus_powerup(dev->sdev->bus, dynamic_pctl); +} +static inline int b43_bus_ssb_device_is_enabled(struct b43_bus_dev *dev) +{ +	return ssb_device_is_enabled(dev->sdev); +} +static inline void b43_bus_ssb_device_enable(struct b43_bus_dev *dev, +					     u32 core_specific_flags) +{ +	ssb_device_enable(dev->sdev, core_specific_flags); +} +static inline void b43_bus_ssb_device_disable(struct b43_bus_dev *dev, +					      u32 core_specific_flags) +{ +	ssb_device_disable(dev->sdev, core_specific_flags); +} + +static inline u16 b43_bus_ssb_read16(struct b43_bus_dev *dev, u16 offset) +{ +	return ssb_read16(dev->sdev, offset); +} +static inline u32 b43_bus_ssb_read32(struct b43_bus_dev *dev, u16 offset) +{ +	return ssb_read32(dev->sdev, offset); +} +static inline +void b43_bus_ssb_write16(struct b43_bus_dev *dev, u16 offset, u16 value) +{ +	ssb_write16(dev->sdev, offset, value); +} +static inline +void b43_bus_ssb_write32(struct b43_bus_dev *dev, u16 offset, u32 value) +{ +	ssb_write32(dev->sdev, offset, value); +} +static inline +void b43_bus_ssb_block_read(struct b43_bus_dev *dev, void *buffer, +			    size_t count, u16 offset, u8 reg_width) +{ +	ssb_block_read(dev->sdev, buffer, count, offset, reg_width); +} +static inline +void b43_bus_ssb_block_write(struct b43_bus_dev *dev, const void *buffer, +			     size_t count, u16 offset, u8 reg_width) +{ +	ssb_block_write(dev->sdev, buffer, count, offset, reg_width); +} + +struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev) +{ +	struct b43_bus_dev *dev; + +	dev = kzalloc(sizeof(*dev), GFP_KERNEL); +	if (!dev) +		return NULL; + +	dev->bus_type = B43_BUS_SSB; +	dev->sdev = sdev; + +	dev->bus_may_powerdown = b43_bus_ssb_bus_may_powerdown; +	dev->bus_powerup = b43_bus_ssb_bus_powerup; +	dev->device_is_enabled = b43_bus_ssb_device_is_enabled; +	dev->device_enable = b43_bus_ssb_device_enable; +	dev->device_disable = b43_bus_ssb_device_disable; + +	dev->read16 = b43_bus_ssb_read16; +	dev->read32 = b43_bus_ssb_read32; +	dev->write16 = b43_bus_ssb_write16; +	dev->write32 = b43_bus_ssb_write32; +	dev->block_read = b43_bus_ssb_block_read; +	dev->block_write = b43_bus_ssb_block_write; + +	dev->dev = sdev->dev; +	dev->dma_dev = sdev->dma_dev; +	dev->irq = sdev->irq; + +	dev->board_vendor = sdev->bus->boardinfo.vendor; +	dev->board_type = sdev->bus->boardinfo.type; +	dev->board_rev = sdev->bus->boardinfo.rev; + +	dev->chip_id = sdev->bus->chip_id; +	dev->chip_rev = sdev->bus->chip_rev; +	dev->chip_pkg = sdev->bus->chip_package; + +	dev->bus_sprom = &sdev->bus->sprom; + +	dev->core_id = sdev->id.coreid; +	dev->core_rev = sdev->id.revision; + +	return dev; +} +#endif /* CONFIG_B43_SSB */ + +void *b43_bus_get_wldev(struct b43_bus_dev *dev) +{ +	switch (dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		return bcma_get_drvdata(dev->bdev); +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		return ssb_get_drvdata(dev->sdev); +#endif +	} +	return NULL; +} + +void b43_bus_set_wldev(struct b43_bus_dev *dev, void *wldev) +{ +	switch (dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		bcma_set_drvdata(dev->bdev, wldev); +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		ssb_set_drvdata(dev->sdev, wldev); +#endif +	} +} diff --git a/drivers/net/wireless/b43/bus.h b/drivers/net/wireless/b43/bus.h new file mode 100644 index 00000000000..184c9565927 --- /dev/null +++ b/drivers/net/wireless/b43/bus.h @@ -0,0 +1,70 @@ +#ifndef B43_BUS_H_ +#define B43_BUS_H_ + +enum b43_bus_type { +#ifdef CONFIG_B43_BCMA +	B43_BUS_BCMA, +#endif +	B43_BUS_SSB, +}; + +struct b43_bus_dev { +	enum b43_bus_type bus_type; +	union { +		struct bcma_device *bdev; +		struct ssb_device *sdev; +	}; + +	int (*bus_may_powerdown)(struct b43_bus_dev *dev); +	int (*bus_powerup)(struct b43_bus_dev *dev, bool dynamic_pctl); +	int (*device_is_enabled)(struct b43_bus_dev *dev); +	void (*device_enable)(struct b43_bus_dev *dev, +			      u32 core_specific_flags); +	void (*device_disable)(struct b43_bus_dev *dev, +			       u32 core_specific_flags); + +	u16 (*read16)(struct b43_bus_dev *dev, u16 offset); +	u32 (*read32)(struct b43_bus_dev *dev, u16 offset); +	void (*write16)(struct b43_bus_dev *dev, u16 offset, u16 value); +	void (*write32)(struct b43_bus_dev *dev, u16 offset, u32 value); +	void (*block_read)(struct b43_bus_dev *dev, void *buffer, +			   size_t count, u16 offset, u8 reg_width); +	void (*block_write)(struct b43_bus_dev *dev, const void *buffer, +			    size_t count, u16 offset, u8 reg_width); + +	struct device *dev; +	struct device *dma_dev; +	unsigned int irq; + +	u16 board_vendor; +	u16 board_type; +	u16 board_rev; + +	u16 chip_id; +	u8 chip_rev; +	u8 chip_pkg; + +	struct ssb_sprom *bus_sprom; + +	u16 core_id; +	u8 core_rev; +}; + +static inline bool b43_bus_host_is_pcmcia(struct b43_bus_dev *dev) +{ +	return (dev->bus_type == B43_BUS_SSB && +		dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA); +} +static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev) +{ +	return (dev->bus_type == B43_BUS_SSB && +		dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO); +} + +struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core); +struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev); + +void *b43_bus_get_wldev(struct b43_bus_dev *dev); +void b43_bus_set_wldev(struct b43_bus_dev *dev, void *data); + +#endif /* B43_BUS_H_ */ diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 47d44bcff37..ce572aebeff 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -333,10 +333,10 @@ static inline  	dma_addr_t dmaaddr;  	if (tx) { -		dmaaddr = dma_map_single(ring->dev->sdev->dma_dev, +		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,  					 buf, len, DMA_TO_DEVICE);  	} else { -		dmaaddr = dma_map_single(ring->dev->sdev->dma_dev, +		dmaaddr = dma_map_single(ring->dev->dev->dma_dev,  					 buf, len, DMA_FROM_DEVICE);  	} @@ -348,10 +348,10 @@ static inline  			  dma_addr_t addr, size_t len, int tx)  {  	if (tx) { -		dma_unmap_single(ring->dev->sdev->dma_dev, +		dma_unmap_single(ring->dev->dev->dma_dev,  				 addr, len, DMA_TO_DEVICE);  	} else { -		dma_unmap_single(ring->dev->sdev->dma_dev, +		dma_unmap_single(ring->dev->dev->dma_dev,  				 addr, len, DMA_FROM_DEVICE);  	}  } @@ -361,7 +361,7 @@ static inline  				 dma_addr_t addr, size_t len)  {  	B43_WARN_ON(ring->tx); -	dma_sync_single_for_cpu(ring->dev->sdev->dma_dev, +	dma_sync_single_for_cpu(ring->dev->dev->dma_dev,  				    addr, len, DMA_FROM_DEVICE);  } @@ -370,7 +370,7 @@ static inline  				    dma_addr_t addr, size_t len)  {  	B43_WARN_ON(ring->tx); -	dma_sync_single_for_device(ring->dev->sdev->dma_dev, +	dma_sync_single_for_device(ring->dev->dev->dma_dev,  				   addr, len, DMA_FROM_DEVICE);  } @@ -401,7 +401,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring)  	 */  	if (ring->type == B43_DMA_64BIT)  		flags |= GFP_DMA; -	ring->descbase = dma_alloc_coherent(ring->dev->sdev->dma_dev, +	ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,  					    B43_DMA_RINGMEMSIZE,  					    &(ring->dmabase), flags);  	if (!ring->descbase) { @@ -415,7 +415,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring)  static void free_ringmemory(struct b43_dmaring *ring)  { -	dma_free_coherent(ring->dev->sdev->dma_dev, B43_DMA_RINGMEMSIZE, +	dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,  			  ring->descbase, ring->dmabase);  } @@ -523,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,  				  dma_addr_t addr,  				  size_t buffersize, bool dma_to_device)  { -	if (unlikely(dma_mapping_error(ring->dev->sdev->dma_dev, addr))) +	if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))  		return 1;  	switch (ring->type) { @@ -757,14 +757,14 @@ static void dmacontroller_cleanup(struct b43_dmaring *ring)  static void free_all_descbuffers(struct b43_dmaring *ring)  { -	struct b43_dmadesc_generic *desc;  	struct b43_dmadesc_meta *meta;  	int i;  	if (!ring->used_slots)  		return;  	for (i = 0; i < ring->nr_slots; i++) { -		desc = ring->ops->idx2desc(ring, i, &meta); +		/* get meta - ignore returned value */ +		ring->ops->idx2desc(ring, i, &meta);  		if (!meta->skb || b43_dma_ptr_is_poisoned(meta->skb)) {  			B43_WARN_ON(!ring->tx); @@ -869,7 +869,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,  			goto err_kfree_meta;  		/* test for ability to dma to txhdr_cache */ -		dma_test = dma_map_single(dev->sdev->dma_dev, +		dma_test = dma_map_single(dev->dev->dma_dev,  					  ring->txhdr_cache,  					  b43_txhdr_size(dev),  					  DMA_TO_DEVICE); @@ -884,7 +884,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,  			if (!ring->txhdr_cache)  				goto err_kfree_meta; -			dma_test = dma_map_single(dev->sdev->dma_dev, +			dma_test = dma_map_single(dev->dev->dma_dev,  						  ring->txhdr_cache,  						  b43_txhdr_size(dev),  						  DMA_TO_DEVICE); @@ -898,7 +898,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,  			}  		} -		dma_unmap_single(dev->sdev->dma_dev, +		dma_unmap_single(dev->dev->dma_dev,  				 dma_test, b43_txhdr_size(dev),  				 DMA_TO_DEVICE);  	} @@ -1013,9 +1013,9 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)  	/* Try to set the DMA mask. If it fails, try falling back to a  	 * lower mask, as we can always also support a lower one. */  	while (1) { -		err = dma_set_mask(dev->sdev->dma_dev, mask); +		err = dma_set_mask(dev->dev->dma_dev, mask);  		if (!err) { -			err = dma_set_coherent_mask(dev->sdev->dma_dev, mask); +			err = dma_set_coherent_mask(dev->dev->dma_dev, mask);  			if (!err)  				break;  		} @@ -1055,7 +1055,14 @@ int b43_dma_init(struct b43_wldev *dev)  	err = b43_dma_set_mask(dev, dmamask);  	if (err)  		return err; -	dma->translation = ssb_dma_translation(dev->sdev); + +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		dma->translation = ssb_dma_translation(dev->dev->sdev); +		break; +#endif +	}  	err = -ENOMEM;  	/* setup TX DMA channels. */ @@ -1085,7 +1092,7 @@ int b43_dma_init(struct b43_wldev *dev)  		goto err_destroy_mcast;  	/* No support for the TX status DMA ring. */ -	B43_WARN_ON(dev->sdev->id.revision < 5); +	B43_WARN_ON(dev->dev->core_rev < 5);  	b43dbg(dev->wl, "%u-bit DMA initialized\n",  	       (unsigned int)type); @@ -1388,7 +1395,6 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,  {  	const struct b43_dma_ops *ops;  	struct b43_dmaring *ring; -	struct b43_dmadesc_generic *desc;  	struct b43_dmadesc_meta *meta;  	int slot, firstused;  	bool frame_succeed; @@ -1416,7 +1422,8 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,  	ops = ring->ops;  	while (1) {  		B43_WARN_ON(slot < 0 || slot >= ring->nr_slots); -		desc = ops->idx2desc(ring, slot, &meta); +		/* get meta - ignore returned value */ +		ops->idx2desc(ring, slot, &meta);  		if (b43_dma_ptr_is_poisoned(meta->skb)) {  			b43dbg(dev->wl, "Poisoned TX slot %d (first=%d) " @@ -1600,6 +1607,7 @@ void b43_dma_rx(struct b43_dmaring *ring)  		dma_rx(ring, &slot);  		update_max_used_slots(ring, ++used_slots);  	} +	wmb();  	ops->set_current_rxslot(ring, slot);  	ring->current_slot = slot;  } diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c index 0cafafe368a..b56ed41fc1b 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c @@ -138,7 +138,7 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,  	led->led_dev.default_trigger = default_trigger;  	led->led_dev.brightness_set = b43_led_brightness_set; -	err = led_classdev_register(dev->sdev->dev, &led->led_dev); +	err = led_classdev_register(dev->dev->dev, &led->led_dev);  	if (err) {  		b43warn(dev->wl, "LEDs: Failed to register %s\n", name);  		led->wl = NULL; @@ -215,13 +215,12 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,  				  enum b43_led_behaviour *behaviour,  				  bool *activelow)  { -	struct ssb_bus *bus = dev->sdev->bus;  	u8 sprom[4]; -	sprom[0] = bus->sprom.gpio0; -	sprom[1] = bus->sprom.gpio1; -	sprom[2] = bus->sprom.gpio2; -	sprom[3] = bus->sprom.gpio3; +	sprom[0] = dev->dev->bus_sprom->gpio0; +	sprom[1] = dev->dev->bus_sprom->gpio1; +	sprom[2] = dev->dev->bus_sprom->gpio2; +	sprom[3] = dev->dev->bus_sprom->gpio3;  	if (sprom[led_index] == 0xFF) {  		/* There is no LED information in the SPROM @@ -231,12 +230,12 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,  		case 0:  			*behaviour = B43_LED_ACTIVITY;  			*activelow = 1; -			if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) +			if (dev->dev->board_vendor == PCI_VENDOR_ID_COMPAQ)  				*behaviour = B43_LED_RADIO_ALL;  			break;  		case 1:  			*behaviour = B43_LED_RADIO_B; -			if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) +			if (dev->dev->board_vendor == PCI_VENDOR_ID_ASUSTEK)  				*behaviour = B43_LED_ASSOC;  			break;  		case 2: diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c index 2ef7d4b3854..a3dc8bb8ca9 100644 --- a/drivers/net/wireless/b43/lo.c +++ b/drivers/net/wireless/b43/lo.c @@ -98,7 +98,7 @@ static u16 lo_measure_feedthrough(struct b43_wldev *dev,  		rfover |= pga;  		rfover |= lna;  		rfover |= trsw_rx; -		if ((dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) +		if ((dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA)  		    && phy->rev > 6)  			rfover |= B43_PHY_RFOVERVAL_EXTLNA; @@ -301,14 +301,12 @@ static void lo_measure_gain_values(struct b43_wldev *dev,  		max_rx_gain = 0;  	if (has_loopback_gain(phy)) { -		int trsw_rx = 0;  		int trsw_rx_gain;  		if (use_trsw_rx) {  			trsw_rx_gain = gphy->trsw_rx_gain / 2;  			if (max_rx_gain >= trsw_rx_gain) {  				trsw_rx_gain = max_rx_gain - trsw_rx_gain; -				trsw_rx = 0x20;  			}  		} else  			trsw_rx_gain = max_rx_gain; @@ -387,7 +385,7 @@ struct lo_g_saved_values {  static void lo_measure_setup(struct b43_wldev *dev,  			     struct lo_g_saved_values *sav)  { -	struct ssb_sprom *sprom = &dev->sdev->bus->sprom; +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	struct b43_phy *phy = &dev->phy;  	struct b43_phy_g *gphy = phy->g;  	struct b43_txpower_lo_control *lo = gphy->lo_control; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index eb415968698..092dd931886 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -113,6 +113,17 @@ static int b43_modparam_pio = B43_PIO_DEFAULT;  module_param_named(pio, b43_modparam_pio, int, 0644);  MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); +#ifdef CONFIG_B43_BCMA +static const struct bcma_device_id b43_bcma_tbl[] = { +	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS), +	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS), +	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS), +	BCMA_CORETABLE_END +}; +MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl); +#endif + +#ifdef CONFIG_B43_SSB  static const struct ssb_device_id b43_ssb_tbl[] = {  	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),  	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6), @@ -126,8 +137,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = {  	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),  	SSB_DEVTABLE_END  }; -  MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl); +#endif  /* Channel and ratetables are shared for all devices.   * They can't be const, because ieee80211 puts some precalculated @@ -548,7 +559,7 @@ void b43_tsf_read(struct b43_wldev *dev, u64 *tsf)  {  	u32 low, high; -	B43_WARN_ON(dev->sdev->id.revision < 3); +	B43_WARN_ON(dev->dev->core_rev < 3);  	/* The hardware guarantees us an atomic read, if we  	 * read the low register first. */ @@ -586,7 +597,7 @@ static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf)  {  	u32 low, high; -	B43_WARN_ON(dev->sdev->id.revision < 3); +	B43_WARN_ON(dev->dev->core_rev < 3);  	low = tsf;  	high = (tsf >> 32); @@ -714,7 +725,7 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)  		b43_ram_write(dev, i * 4, buffer[i]);  	b43_write16(dev, 0x0568, 0x0000); -	if (dev->sdev->id.revision < 11) +	if (dev->dev->core_rev < 11)  		b43_write16(dev, 0x07C0, 0x0000);  	else  		b43_write16(dev, 0x07C0, 0x0100); @@ -1132,7 +1143,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)  	b43_write32(dev, B43_MMIO_MACCTL, macctl);  	/* Commit write */  	b43_read32(dev, B43_MMIO_MACCTL); -	if (awake && dev->sdev->id.revision >= 5) { +	if (awake && dev->dev->core_rev >= 5) {  		/* Wait for the microcode to wake up. */  		for (i = 0; i < 100; i++) {  			ucstat = b43_shm_read16(dev, B43_SHM_SHARED, @@ -1144,35 +1155,65 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)  	}  } -static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, u32 flags) +#ifdef CONFIG_B43_BCMA +static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode) +{ +	u32 flags = 0; + +	if (gmode) +		flags = B43_BCMA_IOCTL_GMODE; +	flags |= B43_BCMA_IOCTL_PHY_CLKEN; +	flags |= B43_BCMA_IOCTL_PHY_BW_20MHZ; /* Make 20 MHz def */ +	b43_device_enable(dev, flags); + +	/* TODO: reset PHY */ +} +#endif + +static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)  { +	struct ssb_device *sdev = dev->dev->sdev;  	u32 tmslow; +	u32 flags = 0; +	if (gmode) +		flags |= B43_TMSLOW_GMODE;  	flags |= B43_TMSLOW_PHYCLKEN;  	flags |= B43_TMSLOW_PHYRESET;  	if (dev->phy.type == B43_PHYTYPE_N)  		flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */ -	ssb_device_enable(dev->sdev, flags); +	b43_device_enable(dev, flags);  	msleep(2);		/* Wait for the PLL to turn on. */  	/* Now take the PHY out of Reset again */ -	tmslow = ssb_read32(dev->sdev, SSB_TMSLOW); +	tmslow = ssb_read32(sdev, SSB_TMSLOW);  	tmslow |= SSB_TMSLOW_FGC;  	tmslow &= ~B43_TMSLOW_PHYRESET; -	ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); -	ssb_read32(dev->sdev, SSB_TMSLOW);	/* flush */ +	ssb_write32(sdev, SSB_TMSLOW, tmslow); +	ssb_read32(sdev, SSB_TMSLOW);	/* flush */  	msleep(1);  	tmslow &= ~SSB_TMSLOW_FGC; -	ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); -	ssb_read32(dev->sdev, SSB_TMSLOW);	/* flush */ +	ssb_write32(sdev, SSB_TMSLOW, tmslow); +	ssb_read32(sdev, SSB_TMSLOW);	/* flush */  	msleep(1);  } -void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) +void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode)  {  	u32 macctl; -	b43_ssb_wireless_core_reset(dev, flags); +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		b43_bcma_wireless_core_reset(dev, gmode); +		break; +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		b43_ssb_wireless_core_reset(dev, gmode); +		break; +#endif +	}  	/* Turn Analog ON, but only if we already know the PHY-type.  	 * This protects against very early setup where we don't know the @@ -1183,7 +1224,7 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)  	macctl = b43_read32(dev, B43_MMIO_MACCTL);  	macctl &= ~B43_MACCTL_GMODE; -	if (flags & B43_TMSLOW_GMODE) +	if (gmode)  		macctl |= B43_MACCTL_GMODE;  	macctl |= B43_MACCTL_IHR_ENABLED;  	b43_write32(dev, B43_MMIO_MACCTL, macctl); @@ -1221,7 +1262,7 @@ static void drain_txstatus_queue(struct b43_wldev *dev)  {  	u32 dummy; -	if (dev->sdev->id.revision < 5) +	if (dev->dev->core_rev < 5)  		return;  	/* Read all entries from the microcode TXstatus FIFO  	 * and throw them away. @@ -1427,9 +1468,9 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,  	/* Get the mask of available antennas. */  	if (dev->phy.gmode) -		antenna_mask = dev->sdev->bus->sprom.ant_available_bg; +		antenna_mask = dev->dev->bus_sprom->ant_available_bg;  	else -		antenna_mask = dev->sdev->bus->sprom.ant_available_a; +		antenna_mask = dev->dev->bus_sprom->ant_available_a;  	if (!(antenna_mask & (1 << (antenna_nr - 1)))) {  		/* This antenna is not available. Fall back to default. */ @@ -1644,7 +1685,7 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)  	mutex_lock(&wl->mutex);  	dev = wl->current_dev;  	if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { -		if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { +		if (b43_bus_host_is_sdio(dev->dev)) {  			/* wl->mutex is enough. */  			b43_do_beacon_update_trigger_work(dev);  			mmiowb(); @@ -1689,7 +1730,7 @@ static void b43_update_templates(struct b43_wl *wl)  static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)  {  	b43_time_lock(dev); -	if (dev->sdev->id.revision >= 3) { +	if (dev->dev->core_rev >= 3) {  		b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16));  		b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10));  	} else { @@ -1923,7 +1964,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)  		return IRQ_NONE;  	reason &= dev->irq_mask;  	if (!reason) -		return IRQ_HANDLED; +		return IRQ_NONE;  	dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)  	    & 0x0001DC00; @@ -2063,7 +2104,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx,  		B43_WARN_ON(1);  		return -ENOSYS;  	} -	err = request_firmware(&blob, ctx->fwname, ctx->dev->sdev->dev); +	err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);  	if (err == -ENOENT) {  		snprintf(ctx->errors[ctx->req_type],  			 sizeof(ctx->errors[ctx->req_type]), @@ -2113,26 +2154,48 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)  {  	struct b43_wldev *dev = ctx->dev;  	struct b43_firmware *fw = &ctx->dev->fw; -	const u8 rev = ctx->dev->sdev->id.revision; +	const u8 rev = ctx->dev->dev->core_rev;  	const char *filename;  	u32 tmshigh;  	int err; +	/* Files for HT and LCN were found by trying one by one */ +  	/* Get microcode */ -	if ((rev >= 5) && (rev <= 10)) +	if ((rev >= 5) && (rev <= 10)) {  		filename = "ucode5"; -	else if ((rev >= 11) && (rev <= 12)) +	} else if ((rev >= 11) && (rev <= 12)) {  		filename = "ucode11"; -	else if (rev == 13) +	} else if (rev == 13) {  		filename = "ucode13"; -	else if (rev == 14) +	} else if (rev == 14) {  		filename = "ucode14"; -	else if (rev == 15) +	} else if (rev == 15) {  		filename = "ucode15"; -	else if ((rev >= 16) && (rev <= 20)) -		filename = "ucode16_mimo"; -	else -		goto err_no_ucode; +	} else { +		switch (dev->phy.type) { +		case B43_PHYTYPE_N: +			if (rev >= 16) +				filename = "ucode16_mimo"; +			else +				goto err_no_ucode; +			break; +		case B43_PHYTYPE_HT: +			if (rev == 29) +				filename = "ucode29_mimo"; +			else +				goto err_no_ucode; +			break; +		case B43_PHYTYPE_LCN: +			if (rev == 24) +				filename = "ucode24_mimo"; +			else +				goto err_no_ucode; +			break; +		default: +			goto err_no_ucode; +		} +	}  	err = b43_do_request_fw(ctx, filename, &fw->ucode);  	if (err)  		goto err_load; @@ -2157,7 +2220,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)  	switch (dev->phy.type) {  	case B43_PHYTYPE_A:  		if ((rev >= 5) && (rev <= 10)) { -			tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); +			tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);  			if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)  				filename = "a0g1initvals5";  			else @@ -2191,6 +2254,18 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)  		else  			goto err_no_initvals;  		break; +	case B43_PHYTYPE_HT: +		if (rev == 29) +			filename = "ht0initvals29"; +		else +			goto err_no_initvals; +		break; +	case B43_PHYTYPE_LCN: +		if (rev == 24) +			filename = "lcn0initvals24"; +		else +			goto err_no_initvals; +		break;  	default:  		goto err_no_initvals;  	} @@ -2202,7 +2277,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)  	switch (dev->phy.type) {  	case B43_PHYTYPE_A:  		if ((rev >= 5) && (rev <= 10)) { -			tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); +			tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH);  			if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)  				filename = "a0g1bsinitvals5";  			else @@ -2238,6 +2313,18 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)  		else  			goto err_no_initvals;  		break; +	case B43_PHYTYPE_HT: +		if (rev == 29) +			filename = "ht0bsinitvals29"; +		else +			goto err_no_initvals; +		break; +	case B43_PHYTYPE_LCN: +		if (rev == 24) +			filename = "lcn0bsinitvals24"; +		else +			goto err_no_initvals; +		break;  	default:  		goto err_no_initvals;  	} @@ -2448,7 +2535,7 @@ static int b43_upload_microcode(struct b43_wldev *dev)  	snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",  			dev->fw.rev, dev->fw.patch); -	wiphy->hw_version = dev->sdev->id.coreid; +	wiphy->hw_version = dev->dev->core_id;  	if (b43_is_old_txhdr_format(dev)) {  		/* We're over the deadline, but we keep support for old fw @@ -2566,7 +2653,7 @@ out:   */  static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_bus *bus = dev->dev->sdev->bus;  #ifdef CONFIG_SSB_DRIVER_PCICORE  	return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev); @@ -2588,7 +2675,7 @@ static int b43_gpio_init(struct b43_wldev *dev)  	mask = 0x0000001F;  	set = 0x0000000F; -	if (dev->sdev->bus->chip_id == 0x4301) { +	if (dev->dev->chip_id == 0x4301) {  		mask |= 0x0060;  		set |= 0x0060;  	} @@ -2599,21 +2686,34 @@ static int b43_gpio_init(struct b43_wldev *dev)  		mask |= 0x0180;  		set |= 0x0180;  	} -	if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) { +	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL) {  		b43_write16(dev, B43_MMIO_GPIO_MASK,  			    b43_read16(dev, B43_MMIO_GPIO_MASK)  			    | 0x0200);  		mask |= 0x0200;  		set |= 0x0200;  	} -	if (dev->sdev->id.revision >= 2) +	if (dev->dev->core_rev >= 2)  		mask |= 0x0010;	/* FIXME: This is redundant. */ -	gpiodev = b43_ssb_gpio_dev(dev); -	if (gpiodev) -		ssb_write32(gpiodev, B43_GPIO_CONTROL, -			    (ssb_read32(gpiodev, B43_GPIO_CONTROL) -			     & mask) | set); +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL, +				(bcma_cc_read32(&dev->dev->bdev->bus->drv_cc, +					BCMA_CC_GPIOCTL) & mask) | set); +		break; +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		gpiodev = b43_ssb_gpio_dev(dev); +		if (gpiodev) +			ssb_write32(gpiodev, B43_GPIO_CONTROL, +				    (ssb_read32(gpiodev, B43_GPIO_CONTROL) +				    & mask) | set); +		break; +#endif +	}  	return 0;  } @@ -2623,9 +2723,21 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)  {  	struct ssb_device *gpiodev; -	gpiodev = b43_ssb_gpio_dev(dev); -	if (gpiodev) -		ssb_write32(gpiodev, B43_GPIO_CONTROL, 0); +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		bcma_cc_write32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_GPIOCTL, +				0); +		break; +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		gpiodev = b43_ssb_gpio_dev(dev); +		if (gpiodev) +			ssb_write32(gpiodev, B43_GPIO_CONTROL, 0); +		break; +#endif +	}  }  /* http://bcm-specs.sipsolutions.net/EnableMac */ @@ -2697,12 +2809,30 @@ out:  /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */  void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)  { -	u32 tmslow = ssb_read32(dev->sdev, SSB_TMSLOW); -	if (on) -		tmslow |= B43_TMSLOW_MACPHYCLKEN; -	else -		tmslow &= ~B43_TMSLOW_MACPHYCLKEN; -	ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); +	u32 tmp; + +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		tmp = bcma_read32(dev->dev->bdev, BCMA_IOCTL); +		if (on) +			tmp |= B43_BCMA_IOCTL_MACPHYCLKEN; +		else +			tmp &= ~B43_BCMA_IOCTL_MACPHYCLKEN; +		bcma_write32(dev->dev->bdev, BCMA_IOCTL, tmp); +		break; +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); +		if (on) +			tmp |= B43_TMSLOW_MACPHYCLKEN; +		else +			tmp &= ~B43_TMSLOW_MACPHYCLKEN; +		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); +		break; +#endif +	}  }  static void b43_adjust_opmode(struct b43_wldev *dev) @@ -2741,15 +2871,15 @@ static void b43_adjust_opmode(struct b43_wldev *dev)  	/* Workaround: On old hardware the HW-MAC-address-filter  	 * doesn't work properly, so always run promisc in filter  	 * it in software. */ -	if (dev->sdev->id.revision <= 4) +	if (dev->dev->core_rev <= 4)  		ctl |= B43_MACCTL_PROMISC;  	b43_write32(dev, B43_MMIO_MACCTL, ctl);  	cfp_pretbtt = 2;  	if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) { -		if (dev->sdev->bus->chip_id == 0x4306 && -		    dev->sdev->bus->chip_rev == 3) +		if (dev->dev->chip_id == 0x4306 && +		    dev->dev->chip_rev == 3)  			cfp_pretbtt = 100;  		else  			cfp_pretbtt = 50; @@ -2907,7 +3037,7 @@ static int b43_chip_init(struct b43_wldev *dev)  		b43_write16(dev, 0x005E, value16);  	}  	b43_write32(dev, 0x0100, 0x01000000); -	if (dev->sdev->id.revision < 5) +	if (dev->dev->core_rev < 5)  		b43_write32(dev, 0x010C, 0x01000000);  	b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) @@ -2922,7 +3052,7 @@ static int b43_chip_init(struct b43_wldev *dev)  	/* Initially set the wireless operation mode. */  	b43_adjust_opmode(dev); -	if (dev->sdev->id.revision < 3) { +	if (dev->dev->core_rev < 3) {  		b43_write16(dev, 0x060E, 0x0000);  		b43_write16(dev, 0x0610, 0x8000);  		b43_write16(dev, 0x0604, 0x0000); @@ -2941,8 +3071,20 @@ static int b43_chip_init(struct b43_wldev *dev)  	b43_mac_phy_clock_set(dev, true); -	b43_write16(dev, B43_MMIO_POWERUP_DELAY, -		    dev->sdev->bus->chipco.fast_pwrup_delay); +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		/* FIXME: 0xE74 is quite common, but should be read from CC */ +		b43_write16(dev, B43_MMIO_POWERUP_DELAY, 0xE74); +		break; +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		b43_write16(dev, B43_MMIO_POWERUP_DELAY, +			    dev->dev->sdev->bus->chipco.fast_pwrup_delay); +		break; +#endif +	}  	err = 0;  	b43dbg(dev->wl, "Chip initialized\n"); @@ -3105,7 +3247,7 @@ static int b43_validate_chipaccess(struct b43_wldev *dev)  	b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0);  	b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4); -	if ((dev->sdev->id.revision >= 3) && (dev->sdev->id.revision <= 10)) { +	if ((dev->dev->core_rev >= 3) && (dev->dev->core_rev <= 10)) {  		/* The 32bit register shadows the two 16bit registers  		 * with update sideeffects. Validate this. */  		b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA); @@ -3458,21 +3600,33 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)  static void b43_put_phy_into_reset(struct b43_wldev *dev)  { -	struct ssb_device *sdev = dev->sdev; -	u32 tmslow; +	u32 tmp; -	tmslow = ssb_read32(sdev, SSB_TMSLOW); -	tmslow &= ~B43_TMSLOW_GMODE; -	tmslow |= B43_TMSLOW_PHYRESET; -	tmslow |= SSB_TMSLOW_FGC; -	ssb_write32(sdev, SSB_TMSLOW, tmslow); -	msleep(1); +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		b43err(dev->wl, +		       "Putting PHY into reset not supported on BCMA\n"); +		break; +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); +		tmp &= ~B43_TMSLOW_GMODE; +		tmp |= B43_TMSLOW_PHYRESET; +		tmp |= SSB_TMSLOW_FGC; +		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); +		msleep(1); -	tmslow = ssb_read32(sdev, SSB_TMSLOW); -	tmslow &= ~SSB_TMSLOW_FGC; -	tmslow |= B43_TMSLOW_PHYRESET; -	ssb_write32(sdev, SSB_TMSLOW, tmslow); -	msleep(1); +		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); +		tmp &= ~SSB_TMSLOW_FGC; +		tmp |= B43_TMSLOW_PHYRESET; +		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); +		msleep(1); + +		break; +#endif +	}  }  static const char *band_to_string(enum ieee80211_band band) @@ -3954,7 +4108,7 @@ redo:  	/* Disable interrupts on the device. */  	b43_set_status(dev, B43_STAT_INITIALIZED); -	if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { +	if (b43_bus_host_is_sdio(dev->dev)) {  		/* wl->mutex is locked. That is enough. */  		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);  		b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	/* Flush */ @@ -3967,11 +4121,11 @@ redo:  	/* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */  	orig_dev = dev;  	mutex_unlock(&wl->mutex); -	if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { +	if (b43_bus_host_is_sdio(dev->dev)) {  		b43_sdio_free_irq(dev);  	} else { -		synchronize_irq(dev->sdev->irq); -		free_irq(dev->sdev->irq, dev); +		synchronize_irq(dev->dev->irq); +		free_irq(dev->dev->irq, dev);  	}  	mutex_lock(&wl->mutex);  	dev = wl->current_dev; @@ -4004,19 +4158,19 @@ static int b43_wireless_core_start(struct b43_wldev *dev)  	B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED);  	drain_txstatus_queue(dev); -	if (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) { +	if (b43_bus_host_is_sdio(dev->dev)) {  		err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler);  		if (err) {  			b43err(dev->wl, "Cannot request SDIO IRQ\n");  			goto out;  		}  	} else { -		err = request_threaded_irq(dev->sdev->irq, b43_interrupt_handler, +		err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler,  					   b43_interrupt_thread_handler,  					   IRQF_SHARED, KBUILD_MODNAME, dev);  		if (err) {  			b43err(dev->wl, "Cannot request IRQ-%d\n", -			       dev->sdev->irq); +			       dev->dev->irq);  			goto out;  		}  	} @@ -4083,9 +4237,21 @@ static int b43_phy_versioning(struct b43_wldev *dev)  			unsupported = 1;  		break;  #endif +#ifdef CONFIG_B43_PHY_HT +	case B43_PHYTYPE_HT: +		if (phy_rev > 1) +			unsupported = 1; +		break; +#endif +#ifdef CONFIG_B43_PHY_LCN +	case B43_PHYTYPE_LCN: +		if (phy_rev > 1) +			unsupported = 1; +		break; +#endif  	default:  		unsupported = 1; -	}; +	}  	if (unsupported) {  		b43err(dev->wl, "FOUND UNSUPPORTED PHY "  		       "(Analog %u, Type %u, Revision %u)\n", @@ -4096,22 +4262,42 @@ static int b43_phy_versioning(struct b43_wldev *dev)  	       analog_type, phy_type, phy_rev);  	/* Get RADIO versioning */ -	if (dev->sdev->bus->chip_id == 0x4317) { -		if (dev->sdev->bus->chip_rev == 0) -			tmp = 0x3205017F; -		else if (dev->sdev->bus->chip_rev == 1) -			tmp = 0x4205017F; -		else -			tmp = 0x5205017F; +	if (dev->dev->core_rev >= 24) { +		u16 radio24[3]; + +		for (tmp = 0; tmp < 3; tmp++) { +			b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp); +			radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); +		} + +		/* Broadcom uses "id" for our "ver" and has separated "ver" */ +		/* radio_ver = (radio24[0] & 0xF0) >> 4; */ + +		radio_manuf = 0x17F; +		radio_ver = (radio24[2] << 8) | radio24[1]; +		radio_rev = (radio24[0] & 0xF);  	} else { -		b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID); -		tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); -		b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID); -		tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16; +		if (dev->dev->chip_id == 0x4317) { +			if (dev->dev->chip_rev == 0) +				tmp = 0x3205017F; +			else if (dev->dev->chip_rev == 1) +				tmp = 0x4205017F; +			else +				tmp = 0x5205017F; +		} else { +			b43_write16(dev, B43_MMIO_RADIO_CONTROL, +				    B43_RADIOCTL_ID); +			tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); +			b43_write16(dev, B43_MMIO_RADIO_CONTROL, +				    B43_RADIOCTL_ID); +			tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) +				<< 16; +		} +		radio_manuf = (tmp & 0x00000FFF); +		radio_ver = (tmp & 0x0FFFF000) >> 12; +		radio_rev = (tmp & 0xF0000000) >> 28;  	} -	radio_manuf = (tmp & 0x00000FFF); -	radio_ver = (tmp & 0x0FFFF000) >> 12; -	radio_rev = (tmp & 0xF0000000) >> 28; +  	if (radio_manuf != 0x17F /* Broadcom */)  		unsupported = 1;  	switch (phy_type) { @@ -4139,6 +4325,14 @@ static int b43_phy_versioning(struct b43_wldev *dev)  		if (radio_ver != 0x2062 && radio_ver != 0x2063)  			unsupported = 1;  		break; +	case B43_PHYTYPE_HT: +		if (radio_ver != 0x2059) +			unsupported = 1; +		break; +	case B43_PHYTYPE_LCN: +		if (radio_ver != 0x2064) +			unsupported = 1; +		break;  	default:  		B43_WARN_ON(1);  	} @@ -4204,7 +4398,7 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)  static void b43_bluetooth_coext_enable(struct b43_wldev *dev)  { -	struct ssb_sprom *sprom = &dev->sdev->bus->sprom; +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	u64 hf;  	if (!modparam_btcoex) @@ -4231,16 +4425,21 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev)  static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_bus *bus;  	u32 tmp; +	if (dev->dev->bus_type != B43_BUS_SSB) +		return; + +	bus = dev->dev->sdev->bus; +  	if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) ||  	    (bus->chip_id == 0x4312)) { -		tmp = ssb_read32(dev->sdev, SSB_IMCFGLO); +		tmp = ssb_read32(dev->dev->sdev, SSB_IMCFGLO);  		tmp &= ~SSB_IMCFGLO_REQTO;  		tmp &= ~SSB_IMCFGLO_SERTO;  		tmp |= 0x3; -		ssb_write32(dev->sdev, SSB_IMCFGLO, tmp); +		ssb_write32(dev->dev->sdev, SSB_IMCFGLO, tmp);  		ssb_commit_settings(bus);  	}  } @@ -4310,36 +4509,45 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)  		dev->wl->current_beacon = NULL;  	} -	ssb_device_disable(dev->sdev, 0); -	ssb_bus_may_powerdown(dev->sdev->bus); +	b43_device_disable(dev, 0); +	b43_bus_may_powerdown(dev);  }  /* Initialize a wireless core */  static int b43_wireless_core_init(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; -	struct ssb_sprom *sprom = &bus->sprom; +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	struct b43_phy *phy = &dev->phy;  	int err;  	u64 hf; -	u32 tmp;  	B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); -	err = ssb_bus_powerup(bus, 0); +	err = b43_bus_powerup(dev, 0);  	if (err)  		goto out; -	if (!ssb_device_is_enabled(dev->sdev)) { -		tmp = phy->gmode ? B43_TMSLOW_GMODE : 0; -		b43_wireless_core_reset(dev, tmp); -	} +	if (!b43_device_is_enabled(dev)) +		b43_wireless_core_reset(dev, phy->gmode);  	/* Reset all data structures. */  	setup_struct_wldev_for_init(dev);  	phy->ops->prepare_structs(dev);  	/* Enable IRQ routing to this device. */ -	ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->sdev); +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci, +				      dev->dev->bdev, true); +		break; +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		ssb_pcicore_dev_irqvecs_enable(&dev->dev->sdev->bus->pcicore, +					       dev->dev->sdev); +		break; +#endif +	}  	b43_imcfglo_timeouts_workaround(dev);  	b43_bluetooth_coext_disable(dev); @@ -4352,7 +4560,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)  	if (err)  		goto err_busdown;  	b43_shm_write16(dev, B43_SHM_SHARED, -			B43_SHM_SH_WLCOREREV, dev->sdev->id.revision); +			B43_SHM_SH_WLCOREREV, dev->dev->core_rev);  	hf = b43_hf_read(dev);  	if (phy->type == B43_PHYTYPE_G) {  		hf |= B43_HF_SYMW; @@ -4370,8 +4578,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev)  	if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)  		hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */  #ifdef CONFIG_SSB_DRIVER_PCICORE -	if ((bus->bustype == SSB_BUSTYPE_PCI) && -	    (bus->pcicore.dev->id.revision <= 10)) +	if (dev->dev->bus_type == B43_BUS_SSB && +	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && +	    dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)  		hf |= B43_HF_PCISCW; /* PCI slow clock workaround. */  #endif  	hf &= ~B43_HF_SKCFPUP; @@ -4399,8 +4608,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)  	/* Maximum Contention Window */  	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); -	if ((dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA) || -	    (dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO) || +	if (b43_bus_host_is_pcmcia(dev->dev) || +	    b43_bus_host_is_sdio(dev->dev) ||  	    dev->use_pio) {  		dev->__using_pio_transfers = 1;  		err = b43_pio_init(dev); @@ -4414,7 +4623,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)  	b43_set_synth_pu_delay(dev, 1);  	b43_bluetooth_coext_enable(dev); -	ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)); +	b43_bus_powerup(dev, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW));  	b43_upload_card_macaddress(dev);  	b43_security_init(dev); @@ -4431,7 +4640,7 @@ out:  err_chip_exit:  	b43_chip_exit(dev);  err_busdown: -	ssb_bus_may_powerdown(bus); +	b43_bus_may_powerdown(dev);  	B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT);  	return err;  } @@ -4737,11 +4946,9 @@ static void b43_wireless_core_detach(struct b43_wldev *dev)  static int b43_wireless_core_attach(struct b43_wldev *dev)  {  	struct b43_wl *wl = dev->wl; -	struct ssb_bus *bus = dev->sdev->bus; -	struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL; +	struct pci_dev *pdev = NULL;  	int err;  	bool have_2ghz_phy = 0, have_5ghz_phy = 0; -	u32 tmp;  	/* Do NOT do any device initialization here.  	 * Do it in wireless_core_init() instead. @@ -4750,25 +4957,42 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)  	 * that in core_init(), too.  	 */ -	err = ssb_bus_powerup(bus, 0); +#ifdef CONFIG_B43_SSB +	if (dev->dev->bus_type == B43_BUS_SSB && +	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) +		pdev = dev->dev->sdev->bus->host_pci; +#endif + +	err = b43_bus_powerup(dev, 0);  	if (err) {  		b43err(wl, "Bus powerup failed\n");  		goto out;  	} -	/* Get the PHY type. */ -	if (dev->sdev->id.revision >= 5) { -		u32 tmshigh; -		tmshigh = ssb_read32(dev->sdev, SSB_TMSHIGH); -		have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY); -		have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY); -	} else -		B43_WARN_ON(1); +	/* Get the PHY type. */ +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		/* FIXME */ +		have_2ghz_phy = 1; +		have_5ghz_phy = 0; +		break; +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		if (dev->dev->core_rev >= 5) { +			u32 tmshigh = ssb_read32(dev->dev->sdev, SSB_TMSHIGH); +			have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY); +			have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY); +		} else +			B43_WARN_ON(1); +		break; +#endif +	}  	dev->phy.gmode = have_2ghz_phy;  	dev->phy.radio_on = 1; -	tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; -	b43_wireless_core_reset(dev, tmp); +	b43_wireless_core_reset(dev, dev->phy.gmode);  	err = b43_phy_versioning(dev);  	if (err) @@ -4790,6 +5014,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)  #endif  		case B43_PHYTYPE_G:  		case B43_PHYTYPE_N: +		case B43_PHYTYPE_HT: +		case B43_PHYTYPE_LCN:  			have_2ghz_phy = 1;  			break;  		default: @@ -4816,8 +5042,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)  		goto err_powerdown;  	dev->phy.gmode = have_2ghz_phy; -	tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; -	b43_wireless_core_reset(dev, tmp); +	b43_wireless_core_reset(dev, dev->phy.gmode);  	err = b43_validate_chipaccess(dev);  	if (err) @@ -4832,8 +5057,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)  	INIT_WORK(&dev->restart_work, b43_chip_reset);  	dev->phy.ops->switch_analog(dev, 0); -	ssb_device_disable(dev->sdev, 0); -	ssb_bus_may_powerdown(bus); +	b43_device_disable(dev, 0); +	b43_bus_may_powerdown(dev);  out:  	return err; @@ -4841,11 +5066,11 @@ out:  err_phy_free:  	b43_phy_free(dev);  err_powerdown: -	ssb_bus_may_powerdown(bus); +	b43_bus_may_powerdown(dev);  	return err;  } -static void b43_one_core_detach(struct ssb_device *dev) +static void b43_one_core_detach(struct b43_bus_dev *dev)  {  	struct b43_wldev *wldev;  	struct b43_wl *wl; @@ -4853,17 +5078,17 @@ static void b43_one_core_detach(struct ssb_device *dev)  	/* Do not cancel ieee80211-workqueue based work here.  	 * See comment in b43_remove(). */ -	wldev = ssb_get_drvdata(dev); +	wldev = b43_bus_get_wldev(dev);  	wl = wldev->wl;  	b43_debugfs_remove_device(wldev);  	b43_wireless_core_detach(wldev);  	list_del(&wldev->list);  	wl->nr_devs--; -	ssb_set_drvdata(dev, NULL); +	b43_bus_set_wldev(dev, NULL);  	kfree(wldev);  } -static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) +static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)  {  	struct b43_wldev *wldev;  	int err = -ENOMEM; @@ -4873,7 +5098,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)  		goto out;  	wldev->use_pio = b43_modparam_pio; -	wldev->sdev = dev; +	wldev->dev = dev;  	wldev->wl = wl;  	b43_set_status(wldev, B43_STAT_UNINIT);  	wldev->bad_frames_preempt = modparam_bad_frames_preempt; @@ -4885,7 +5110,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)  	list_add(&wldev->list, &wl->devlist);  	wl->nr_devs++; -	ssb_set_drvdata(dev, wldev); +	b43_bus_set_wldev(dev, wldev);  	b43_debugfs_add_device(wldev);        out: @@ -4926,17 +5151,17 @@ static void b43_sprom_fixup(struct ssb_bus *bus)  	}  } -static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl) +static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)  {  	struct ieee80211_hw *hw = wl->hw; -	ssb_set_devtypedata(dev, NULL); +	ssb_set_devtypedata(dev->sdev, NULL);  	ieee80211_free_hw(hw);  } -static struct b43_wl *b43_wireless_init(struct ssb_device *dev) +static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)  { -	struct ssb_sprom *sprom = &dev->bus->sprom; +	struct ssb_sprom *sprom = dev->bus_sprom;  	struct ieee80211_hw *hw;  	struct b43_wl *wl; @@ -4978,28 +5203,62 @@ static struct b43_wl *b43_wireless_init(struct ssb_device *dev)  	skb_queue_head_init(&wl->tx_queue);  	b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n", -		dev->bus->chip_id, dev->id.revision); +		dev->chip_id, dev->core_rev);  	return wl;  } -static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id) +#ifdef CONFIG_B43_BCMA +static int b43_bcma_probe(struct bcma_device *core) +{ +	struct b43_bus_dev *dev; + +	dev = b43_bus_dev_bcma_init(core); +	if (!dev) +		return -ENODEV; + +	b43err(NULL, "BCMA is not supported yet!"); +	kfree(dev); +	return -EOPNOTSUPP; +} + +static void b43_bcma_remove(struct bcma_device *core) +{ +	/* TODO */ +} + +static struct bcma_driver b43_bcma_driver = { +	.name		= KBUILD_MODNAME, +	.id_table	= b43_bcma_tbl, +	.probe		= b43_bcma_probe, +	.remove		= b43_bcma_remove, +}; +#endif + +#ifdef CONFIG_B43_SSB +static +int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)  { +	struct b43_bus_dev *dev;  	struct b43_wl *wl;  	int err;  	int first = 0; -	wl = ssb_get_devtypedata(dev); +	dev = b43_bus_dev_ssb_init(sdev); +	if (!dev) +		return -ENOMEM; + +	wl = ssb_get_devtypedata(sdev);  	if (!wl) {  		/* Probing the first core. Must setup common struct b43_wl */  		first = 1; -		b43_sprom_fixup(dev->bus); +		b43_sprom_fixup(sdev->bus);  		wl = b43_wireless_init(dev);  		if (IS_ERR(wl)) {  			err = PTR_ERR(wl);  			goto out;  		} -		ssb_set_devtypedata(dev, wl); -		B43_WARN_ON(ssb_get_devtypedata(dev) != wl); +		ssb_set_devtypedata(sdev, wl); +		B43_WARN_ON(ssb_get_devtypedata(sdev) != wl);  	}  	err = b43_one_core_attach(dev, wl);  	if (err) @@ -5023,10 +5282,10 @@ static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id)  	return err;  } -static void b43_ssb_remove(struct ssb_device *dev) +static void b43_ssb_remove(struct ssb_device *sdev)  { -	struct b43_wl *wl = ssb_get_devtypedata(dev); -	struct b43_wldev *wldev = ssb_get_drvdata(dev); +	struct b43_wl *wl = ssb_get_devtypedata(sdev); +	struct b43_wldev *wldev = ssb_get_drvdata(sdev);  	/* We must cancel any work here before unregistering from ieee80211,  	 * as the ieee80211 unreg will destroy the workqueue. */ @@ -5042,17 +5301,25 @@ static void b43_ssb_remove(struct ssb_device *dev)  		ieee80211_unregister_hw(wl->hw);  	} -	b43_one_core_detach(dev); +	b43_one_core_detach(wldev->dev);  	if (list_empty(&wl->devlist)) {  		b43_leds_unregister(wl);  		/* Last core on the chip unregistered.  		 * We can destroy common struct b43_wl.  		 */ -		b43_wireless_exit(dev, wl); +		b43_wireless_exit(wldev->dev, wl);  	}  } +static struct ssb_driver b43_ssb_driver = { +	.name		= KBUILD_MODNAME, +	.id_table	= b43_ssb_tbl, +	.probe		= b43_ssb_probe, +	.remove		= b43_ssb_remove, +}; +#endif /* CONFIG_B43_SSB */ +  /* Perform a hardware reset. This can be called from any context. */  void b43_controller_restart(struct b43_wldev *dev, const char *reason)  { @@ -5063,13 +5330,6 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)  	ieee80211_queue_work(dev->wl->hw, &dev->restart_work);  } -static struct ssb_driver b43_ssb_driver = { -	.name		= KBUILD_MODNAME, -	.id_table	= b43_ssb_tbl, -	.probe		= b43_ssb_probe, -	.remove		= b43_ssb_remove, -}; -  static void b43_print_driverinfo(void)  {  	const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", @@ -5108,14 +5368,27 @@ static int __init b43_init(void)  	err = b43_sdio_init();  	if (err)  		goto err_pcmcia_exit; -	err = ssb_driver_register(&b43_ssb_driver); +#ifdef CONFIG_B43_BCMA +	err = bcma_driver_register(&b43_bcma_driver);  	if (err)  		goto err_sdio_exit; +#endif +#ifdef CONFIG_B43_SSB +	err = ssb_driver_register(&b43_ssb_driver); +	if (err) +		goto err_bcma_driver_exit; +#endif  	b43_print_driverinfo();  	return err; +#ifdef CONFIG_B43_SSB +err_bcma_driver_exit: +#endif +#ifdef CONFIG_B43_BCMA +	bcma_driver_unregister(&b43_bcma_driver);  err_sdio_exit: +#endif  	b43_sdio_exit();  err_pcmcia_exit:  	b43_pcmcia_exit(); @@ -5126,7 +5399,12 @@ err_dfs_exit:  static void __exit b43_exit(void)  { +#ifdef CONFIG_B43_SSB  	ssb_driver_unregister(&b43_ssb_driver); +#endif +#ifdef CONFIG_B43_BCMA +	bcma_driver_unregister(&b43_bcma_driver); +#endif  	b43_sdio_exit();  	b43_pcmcia_exit();  	b43_debugfs_exit(); diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index a0d327f1318..e4ebce9be59 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -121,7 +121,7 @@ void b43_hf_write(struct b43_wldev *dev, u64 value);  void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on); -void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags); +void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode);  void b43_controller_restart(struct b43_wldev *dev, const char *reason); diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c index b01c8ced57c..73ace5552ba 100644 --- a/drivers/net/wireless/b43/phy_a.c +++ b/drivers/net/wireless/b43/phy_a.c @@ -265,7 +265,6 @@ static void hardware_pctl_init_aphy(struct b43_wldev *dev)  void b43_phy_inita(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus;  	struct b43_phy *phy = &dev->phy;  	/* This lowlevel A-PHY init is also called from G-PHY init. @@ -296,9 +295,9 @@ void b43_phy_inita(struct b43_wldev *dev)  		b43_radio_init2060(dev); -		if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && -		    ((bus->boardinfo.type == SSB_BOARD_BU4306) || -		     (bus->boardinfo.type == SSB_BOARD_BU4309))) { +		if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) && +		    ((dev->dev->board_type == SSB_BOARD_BU4306) || +		     (dev->dev->board_type == SSB_BOARD_BU4309))) {  			; //TODO: A PHY LO  		} @@ -311,7 +310,7 @@ void b43_phy_inita(struct b43_wldev *dev)  	}  	if ((phy->type == B43_PHYTYPE_G) && -	    (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) { +	    (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)) {  		b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF);  	}  } @@ -323,17 +322,17 @@ static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev)  	struct b43_phy_a *aphy = phy->a;  	s16 pab0, pab1, pab2; -	pab0 = (s16) (dev->sdev->bus->sprom.pa1b0); -	pab1 = (s16) (dev->sdev->bus->sprom.pa1b1); -	pab2 = (s16) (dev->sdev->bus->sprom.pa1b2); +	pab0 = (s16) (dev->dev->bus_sprom->pa1b0); +	pab1 = (s16) (dev->dev->bus_sprom->pa1b1); +	pab2 = (s16) (dev->dev->bus_sprom->pa1b2);  	if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&  	    pab0 != -1 && pab1 != -1 && pab2 != -1) {  		/* The pabX values are set in SPROM. Use them. */ -		if ((s8) dev->sdev->bus->sprom.itssi_a != 0 && -		    (s8) dev->sdev->bus->sprom.itssi_a != -1) +		if ((s8) dev->dev->bus_sprom->itssi_a != 0 && +		    (s8) dev->dev->bus_sprom->itssi_a != -1)  			aphy->tgt_idle_tssi = -			    (s8) (dev->sdev->bus->sprom.itssi_a); +			    (s8) (dev->dev->bus_sprom->itssi_a);  		else  			aphy->tgt_idle_tssi = 62;  		aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0, diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index e46b2f4f092..101957512bc 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -31,6 +31,8 @@  #include "phy_a.h"  #include "phy_n.h"  #include "phy_lp.h" +#include "phy_ht.h" +#include "phy_lcn.h"  #include "b43.h"  #include "main.h" @@ -59,6 +61,16 @@ int b43_phy_allocate(struct b43_wldev *dev)  		phy->ops = &b43_phyops_lp;  #endif  		break; +	case B43_PHYTYPE_HT: +#ifdef CONFIG_B43_PHY_HT +		phy->ops = &b43_phyops_ht; +#endif +		break; +	case B43_PHYTYPE_LCN: +#ifdef CONFIG_B43_PHY_LCN +		phy->ops = &b43_phyops_lcn; +#endif +		break;  	}  	if (B43_WARN_ON(!phy->ops))  		return -ENODEV; @@ -168,7 +180,7 @@ void b43_phy_lock(struct b43_wldev *dev)  	B43_WARN_ON(dev->phy.phy_locked);  	dev->phy.phy_locked = 1;  #endif -	B43_WARN_ON(dev->sdev->id.revision < 3); +	B43_WARN_ON(dev->dev->core_rev < 3);  	if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))  		b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); @@ -180,7 +192,7 @@ void b43_phy_unlock(struct b43_wldev *dev)  	B43_WARN_ON(!dev->phy.phy_locked);  	dev->phy.phy_locked = 0;  #endif -	B43_WARN_ON(dev->sdev->id.revision < 3); +	B43_WARN_ON(dev->dev->core_rev < 3);  	if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP))  		b43_power_saving_ctl_bits(dev, 0); @@ -368,8 +380,8 @@ void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags)  	/* The next check will be needed in two seconds, or later. */  	phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2)); -	if ((dev->sdev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && -	    (dev->sdev->bus->boardinfo.type == SSB_BOARD_BU4306)) +	if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) && +	    (dev->dev->board_type == SSB_BOARD_BU4306))  		return; /* No software txpower adjustment needed */  	result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI)); diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index 2401bee8b08..aa77ba612a9 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -194,6 +194,8 @@ struct b43_phy_a;  struct b43_phy_g;  struct b43_phy_n;  struct b43_phy_lp; +struct b43_phy_ht; +struct b43_phy_lcn;  struct b43_phy {  	/* Hardware operation callbacks. */ @@ -216,6 +218,10 @@ struct b43_phy {  		struct b43_phy_n *n;  		/* LP-PHY specific information */  		struct b43_phy_lp *lp; +		/* HT-PHY specific information */ +		struct b43_phy_ht *ht; +		/* LCN-PHY specific information */ +		struct b43_phy_lcn *lcn;  	};  	/* Band support flags. */ diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index 1758a282f91..83532d19347 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c @@ -718,7 +718,7 @@ static void b43_calc_nrssi_threshold(struct b43_wldev *dev)  	B43_WARN_ON(phy->type != B43_PHYTYPE_G);  	if (!phy->gmode || -	    !(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { +	    !(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {  		tmp16 = b43_nrssi_hw_read(dev, 0x20);  		if (tmp16 >= 0x20)  			tmp16 -= 0x40; @@ -1114,7 +1114,7 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev,  {  	struct b43_phy *phy = &dev->phy;  	struct b43_phy_g *gphy = phy->g; -	struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	if (!phy->gmode)  		return 0; @@ -1491,7 +1491,6 @@ static u16 b43_radio_init2050(struct b43_wldev *dev)  static void b43_phy_initb5(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus;  	struct b43_phy *phy = &dev->phy;  	struct b43_phy_g *gphy = phy->g;  	u16 offset, value; @@ -1500,8 +1499,8 @@ static void b43_phy_initb5(struct b43_wldev *dev)  	if (phy->analog == 1) {  		b43_radio_set(dev, 0x007A, 0x0050);  	} -	if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) && -	    (bus->boardinfo.type != SSB_BOARD_BU4306)) { +	if ((dev->dev->board_vendor != SSB_BOARDVENDOR_BCM) && +	    (dev->dev->board_type != SSB_BOARD_BU4306)) {  		value = 0x2120;  		for (offset = 0x00A8; offset < 0x00C7; offset++) {  			b43_phy_write(dev, offset, value); @@ -1620,7 +1619,7 @@ static void b43_phy_initb6(struct b43_wldev *dev)  		b43_radio_write16(dev, 0x5A, 0x88);  		b43_radio_write16(dev, 0x5B, 0x6B);  		b43_radio_write16(dev, 0x5C, 0x0F); -		if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) { +		if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_ALTIQ) {  			b43_radio_write16(dev, 0x5D, 0xFA);  			b43_radio_write16(dev, 0x5E, 0xD8);  		} else { @@ -1787,7 +1786,7 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)  	b43_phy_set(dev, B43_PHY_RFOVER, 0x0100);  	b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF); -	if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) { +	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_EXTLNA) {  		if (phy->rev >= 7) {  			b43_phy_set(dev, B43_PHY_RFOVER, 0x0800);  			b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000); @@ -1922,7 +1921,6 @@ static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev)  /* Initialize B/G PHY power control */  static void b43_phy_init_pctl(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus;  	struct b43_phy *phy = &dev->phy;  	struct b43_phy_g *gphy = phy->g;  	struct b43_rfatt old_rfatt; @@ -1931,8 +1929,8 @@ static void b43_phy_init_pctl(struct b43_wldev *dev)  	B43_WARN_ON(phy->type != B43_PHYTYPE_G); -	if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && -	    (bus->boardinfo.type == SSB_BOARD_BU4306)) +	if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) && +	    (dev->dev->board_type == SSB_BOARD_BU4306))  		return;  	b43_phy_write(dev, 0x0028, 0x8018); @@ -2053,7 +2051,7 @@ static void b43_phy_initg(struct b43_wldev *dev)  	if (phy->rev >= 6) {  		b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12));  	} -	if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) +	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)  		b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);  	else  		b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F); @@ -2066,7 +2064,7 @@ static void b43_phy_initg(struct b43_wldev *dev)  		b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);  	} -	if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { +	if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI)) {  		/* The specs state to update the NRSSI LT with  		 * the value 0x7FFFFFFF here. I think that is some weird  		 * compiler optimization in the original driver. @@ -2088,8 +2086,8 @@ static void b43_phy_initg(struct b43_wldev *dev)  	/* FIXME: The spec says in the following if, the 0 should be replaced  	   'if OFDM may not be used in the current locale'  	   but OFDM is legal everywhere */ -	if ((dev->sdev->bus->chip_id == 0x4306 -	     && dev->sdev->bus->chip_package == 2) || 0) { +	if ((dev->dev->chip_id == 0x4306 +	     && dev->dev->chip_pkg == 2) || 0) {  		b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF);  		b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF);  	} @@ -2105,7 +2103,7 @@ void b43_gphy_channel_switch(struct b43_wldev *dev,  	b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));  	if (channel == 14) { -		if (dev->sdev->bus->sprom.country_code == +		if (dev->dev->bus_sprom->country_code ==  		    SSB_SPROM1CCODE_JAPAN)  			b43_hf_write(dev,  				     b43_hf_read(dev) & ~B43_HF_ACPR); @@ -2136,17 +2134,17 @@ static void default_baseband_attenuation(struct b43_wldev *dev,  static void default_radio_attenuation(struct b43_wldev *dev,  				      struct b43_rfatt *rf)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct b43_bus_dev *bdev = dev->dev;  	struct b43_phy *phy = &dev->phy;  	rf->with_padmix = 0; -	if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && -	    bus->boardinfo.type == SSB_BOARD_BCM4309G) { -		if (bus->boardinfo.rev < 0x43) { +	if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM && +	    dev->dev->board_type == SSB_BOARD_BCM4309G) { +		if (dev->dev->board_rev < 0x43) {  			rf->att = 2;  			return; -		} else if (bus->boardinfo.rev < 0x51) { +		} else if (dev->dev->board_rev < 0x51) {  			rf->att = 3;  			return;  		} @@ -2172,21 +2170,21 @@ static void default_radio_attenuation(struct b43_wldev *dev,  			return;  		case 1:  			if (phy->type == B43_PHYTYPE_G) { -				if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM -				    && bus->boardinfo.type == SSB_BOARD_BCM4309G -				    && bus->boardinfo.rev >= 30) +				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM +				    && bdev->board_type == SSB_BOARD_BCM4309G +				    && bdev->board_rev >= 30)  					rf->att = 3; -				else if (bus->boardinfo.vendor == +				else if (bdev->board_vendor ==  					 SSB_BOARDVENDOR_BCM -					 && bus->boardinfo.type == +					 && bdev->board_type ==  					 SSB_BOARD_BU4306)  					rf->att = 3;  				else  					rf->att = 1;  			} else { -				if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM -				    && bus->boardinfo.type == SSB_BOARD_BCM4309G -				    && bus->boardinfo.rev >= 30) +				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM +				    && bdev->board_type == SSB_BOARD_BCM4309G +				    && bdev->board_rev >= 30)  					rf->att = 7;  				else  					rf->att = 6; @@ -2194,16 +2192,16 @@ static void default_radio_attenuation(struct b43_wldev *dev,  			return;  		case 2:  			if (phy->type == B43_PHYTYPE_G) { -				if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM -				    && bus->boardinfo.type == SSB_BOARD_BCM4309G -				    && bus->boardinfo.rev >= 30) +				if (bdev->board_vendor == SSB_BOARDVENDOR_BCM +				    && bdev->board_type == SSB_BOARD_BCM4309G +				    && bdev->board_rev >= 30)  					rf->att = 3; -				else if (bus->boardinfo.vendor == +				else if (bdev->board_vendor ==  					 SSB_BOARDVENDOR_BCM -					 && bus->boardinfo.type == +					 && bdev->board_type ==  					 SSB_BOARD_BU4306)  					rf->att = 5; -				else if (bus->chip_id == 0x4320) +				else if (bdev->chip_id == 0x4320)  					rf->att = 4;  				else  					rf->att = 3; @@ -2384,11 +2382,11 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)  	struct b43_phy_g *gphy = phy->g;  	s16 pab0, pab1, pab2; -	pab0 = (s16) (dev->sdev->bus->sprom.pa0b0); -	pab1 = (s16) (dev->sdev->bus->sprom.pa0b1); -	pab2 = (s16) (dev->sdev->bus->sprom.pa0b2); +	pab0 = (s16) (dev->dev->bus_sprom->pa0b0); +	pab1 = (s16) (dev->dev->bus_sprom->pa0b1); +	pab2 = (s16) (dev->dev->bus_sprom->pa0b2); -	B43_WARN_ON((dev->sdev->bus->chip_id == 0x4301) && +	B43_WARN_ON((dev->dev->chip_id == 0x4301) &&  		    (phy->radio_ver != 0x2050)); /* Not supported anymore */  	gphy->dyn_tssi_tbl = 0; @@ -2396,10 +2394,10 @@ static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev)  	if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&  	    pab0 != -1 && pab1 != -1 && pab2 != -1) {  		/* The pabX values are set in SPROM. Use them. */ -		if ((s8) dev->sdev->bus->sprom.itssi_bg != 0 && -		    (s8) dev->sdev->bus->sprom.itssi_bg != -1) { +		if ((s8) dev->dev->bus_sprom->itssi_bg != 0 && +		    (s8) dev->dev->bus_sprom->itssi_bg != -1) {  			gphy->tgt_idle_tssi = -				(s8) (dev->sdev->bus->sprom.itssi_bg); +				(s8) (dev->dev->bus_sprom->itssi_bg);  		} else  			gphy->tgt_idle_tssi = 62;  		gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0, @@ -2537,7 +2535,7 @@ static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev)  		b43_wireless_core_reset(dev, 0);  		b43_phy_initg(dev);  		phy->gmode = 1; -		b43_wireless_core_reset(dev, B43_TMSLOW_GMODE); +		b43_wireless_core_reset(dev, 1);  	}  	return 0; @@ -2840,7 +2838,7 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)  				    B43_TXCTL_TXMIX;  				rfatt += 2;  				bbatt += 2; -			} else if (dev->sdev->bus->sprom. +			} else if (dev->dev->bus_sprom->  				   boardflags_lo &  				   B43_BFL_PACTRL) {  				bbatt += 4 * (rfatt - 2); @@ -2914,14 +2912,14 @@ static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,  	estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi);  	B43_WARN_ON(phy->type != B43_PHYTYPE_G); -	max_pwr = dev->sdev->bus->sprom.maxpwr_bg; -	if (dev->sdev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) +	max_pwr = dev->dev->bus_sprom->maxpwr_bg; +	if (dev->dev->bus_sprom->boardflags_lo & B43_BFL_PACTRL)  		max_pwr -= 3; /* minus 0.75 */  	if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) {  		b43warn(dev->wl,  			"Invalid max-TX-power value in SPROM.\n");  		max_pwr = INT_TO_Q52(20); /* fake it */ -		dev->sdev->bus->sprom.maxpwr_bg = max_pwr; +		dev->dev->bus_sprom->maxpwr_bg = max_pwr;  	}  	/* Get desired power (in Q5.2) */ @@ -3014,7 +3012,7 @@ static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)  {  	struct b43_phy *phy = &dev->phy; -	if (!(dev->sdev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) +	if (!(dev->dev->bus_sprom->boardflags_lo & B43_BFL_RSSI))  		return;  	b43_mac_suspend(dev); diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c new file mode 100644 index 00000000000..29821036bad --- /dev/null +++ b/drivers/net/wireless/b43/phy_ht.c @@ -0,0 +1,406 @@ +/* + +  Broadcom B43 wireless driver +  IEEE 802.11n HT-PHY support + +  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. + +  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; see the file COPYING.  If not, write to +  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, +  Boston, MA 02110-1301, USA. + +*/ + +#include <linux/slab.h> + +#include "b43.h" +#include "phy_ht.h" +#include "tables_phy_ht.h" +#include "radio_2059.h" +#include "main.h" + +/************************************************** + * Radio 2059. + **************************************************/ + +static void b43_radio_2059_channel_setup(struct b43_wldev *dev, +			const struct b43_phy_ht_channeltab_e_radio2059 *e) +{ +	u8 i; +	u16 routing; + +	b43_radio_write(dev, 0x16, e->radio_syn16); +	b43_radio_write(dev, 0x17, e->radio_syn17); +	b43_radio_write(dev, 0x22, e->radio_syn22); +	b43_radio_write(dev, 0x25, e->radio_syn25); +	b43_radio_write(dev, 0x27, e->radio_syn27); +	b43_radio_write(dev, 0x28, e->radio_syn28); +	b43_radio_write(dev, 0x29, e->radio_syn29); +	b43_radio_write(dev, 0x2c, e->radio_syn2c); +	b43_radio_write(dev, 0x2d, e->radio_syn2d); +	b43_radio_write(dev, 0x37, e->radio_syn37); +	b43_radio_write(dev, 0x41, e->radio_syn41); +	b43_radio_write(dev, 0x43, e->radio_syn43); +	b43_radio_write(dev, 0x47, e->radio_syn47); +	b43_radio_write(dev, 0x4a, e->radio_syn4a); +	b43_radio_write(dev, 0x58, e->radio_syn58); +	b43_radio_write(dev, 0x5a, e->radio_syn5a); +	b43_radio_write(dev, 0x6a, e->radio_syn6a); +	b43_radio_write(dev, 0x6d, e->radio_syn6d); +	b43_radio_write(dev, 0x6e, e->radio_syn6e); +	b43_radio_write(dev, 0x92, e->radio_syn92); +	b43_radio_write(dev, 0x98, e->radio_syn98); + +	for (i = 0; i < 2; i++) { +		routing = i ? R2059_RXRX1 : R2059_TXRX0; +		b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a); +		b43_radio_write(dev, routing | 0x58, e->radio_rxtx58); +		b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a); +		b43_radio_write(dev, routing | 0x6a, e->radio_rxtx6a); +		b43_radio_write(dev, routing | 0x6d, e->radio_rxtx6d); +		b43_radio_write(dev, routing | 0x6e, e->radio_rxtx6e); +		b43_radio_write(dev, routing | 0x92, e->radio_rxtx92); +		b43_radio_write(dev, routing | 0x98, e->radio_rxtx98); +	} + +	udelay(50); + +	/* Calibration */ +	b43_radio_mask(dev, 0x2b, ~0x1); +	b43_radio_mask(dev, 0x2e, ~0x4); +	b43_radio_set(dev, 0x2e, 0x4); +	b43_radio_set(dev, 0x2b, 0x1); + +	udelay(300); +} + +static void b43_radio_2059_init(struct b43_wldev *dev) +{ +	const u16 routing[] = { R2059_SYN, R2059_TXRX0, R2059_RXRX1 }; +	const u16 radio_values[3][2] = { +		{ 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 }, +	}; +	u16 i, j; + +	b43_radio_write(dev, R2059_ALL | 0x51, 0x0070); +	b43_radio_write(dev, R2059_ALL | 0x5a, 0x0003); + +	for (i = 0; i < ARRAY_SIZE(routing); i++) +		b43_radio_set(dev, routing[i] | 0x146, 0x3); + +	b43_radio_set(dev, 0x2e, 0x0078); +	b43_radio_set(dev, 0xc0, 0x0080); +	msleep(2); +	b43_radio_mask(dev, 0x2e, ~0x0078); +	b43_radio_mask(dev, 0xc0, ~0x0080); + +	if (1) { /* FIXME */ +		b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x1); +		udelay(10); +		b43_radio_set(dev, R2059_RXRX1 | 0x0BF, 0x1); +		b43_radio_maskset(dev, R2059_RXRX1 | 0x19B, 0x3, 0x2); + +		b43_radio_set(dev, R2059_RXRX1 | 0x4, 0x2); +		udelay(100); +		b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x2); + +		for (i = 0; i < 10000; i++) { +			if (b43_radio_read(dev, R2059_RXRX1 | 0x145) & 1) { +				i = 0; +				break; +			} +			udelay(100); +		} +		if (i) +			b43err(dev->wl, "radio 0x945 timeout\n"); + +		b43_radio_mask(dev, R2059_RXRX1 | 0x4, ~0x1); +		b43_radio_set(dev, 0xa, 0x60); + +		for (i = 0; i < 3; i++) { +			b43_radio_write(dev, 0x17F, radio_values[i][0]); +			b43_radio_write(dev, 0x13D, 0x6E); +			b43_radio_write(dev, 0x13E, radio_values[i][1]); +			b43_radio_write(dev, 0x13C, 0x55); + +			for (j = 0; j < 10000; j++) { +				if (b43_radio_read(dev, 0x140) & 2) { +					j = 0; +					break; +				} +				udelay(500); +			} +			if (j) +				b43err(dev->wl, "radio 0x140 timeout\n"); + +			b43_radio_write(dev, 0x13C, 0x15); +		} + +		b43_radio_mask(dev, 0x17F, ~0x1); +	} + +	b43_radio_mask(dev, 0x11, 0x0008); +} + +/************************************************** + * Channel switching ops. + **************************************************/ + +static void b43_phy_ht_channel_setup(struct b43_wldev *dev, +				const struct b43_phy_ht_channeltab_e_phy *e, +				struct ieee80211_channel *new_channel) +{ +	bool old_band_5ghz; +	u8 i; + +	old_band_5ghz = b43_phy_read(dev, B43_PHY_HT_BANDCTL) & 0; /* FIXME */ +	if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) { +		/* TODO */ +	} else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) { +		/* TODO */ +	} + +	b43_phy_write(dev, B43_PHY_HT_BW1, e->bw1); +	b43_phy_write(dev, B43_PHY_HT_BW2, e->bw2); +	b43_phy_write(dev, B43_PHY_HT_BW3, e->bw3); +	b43_phy_write(dev, B43_PHY_HT_BW4, e->bw4); +	b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5); +	b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6); + +	/* TODO: some ops on PHY regs 0x0B0 and 0xC0A */ + +	/* TODO: separated function? */ +	for (i = 0; i < 3; i++) { +		u16 mask; +		u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8)); + +		if (0) /* FIXME */ +			mask = 0x2 << (i * 4); +		else +			mask = 0; +		b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask); + +		b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16); +		b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)), +				tmp & 0xFF); +		b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)), +				tmp & 0xFF); +	} + +	b43_phy_write(dev, 0x017e, 0x3830); +} + +static int b43_phy_ht_set_channel(struct b43_wldev *dev, +				  struct ieee80211_channel *channel, +				  enum nl80211_channel_type channel_type) +{ +	struct b43_phy *phy = &dev->phy; + +	const struct b43_phy_ht_channeltab_e_radio2059 *chent_r2059 = NULL; + +	if (phy->radio_ver == 0x2059) { +		chent_r2059 = b43_phy_ht_get_channeltab_e_r2059(dev, +							channel->center_freq); +		if (!chent_r2059) +			return -ESRCH; +	} else { +		return -ESRCH; +	} + +	/* TODO: In case of N-PHY some bandwidth switching goes here */ + +	if (phy->radio_ver == 0x2059) { +		b43_radio_2059_channel_setup(dev, chent_r2059); +		b43_phy_ht_channel_setup(dev, &(chent_r2059->phy_regs), +					 channel); +	} else { +		return -ESRCH; +	} + +	return 0; +} + +/************************************************** + * Basic PHY ops. + **************************************************/ + +static int b43_phy_ht_op_allocate(struct b43_wldev *dev) +{ +	struct b43_phy_ht *phy_ht; + +	phy_ht = kzalloc(sizeof(*phy_ht), GFP_KERNEL); +	if (!phy_ht) +		return -ENOMEM; +	dev->phy.ht = phy_ht; + +	return 0; +} + +static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev) +{ +	struct b43_phy *phy = &dev->phy; +	struct b43_phy_ht *phy_ht = phy->ht; + +	memset(phy_ht, 0, sizeof(*phy_ht)); +} + +static int b43_phy_ht_op_init(struct b43_wldev *dev) +{ +	b43_phy_ht_tables_init(dev); + +	return 0; +} + +static void b43_phy_ht_op_free(struct b43_wldev *dev) +{ +	struct b43_phy *phy = &dev->phy; +	struct b43_phy_ht *phy_ht = phy->ht; + +	kfree(phy_ht); +	phy->ht = NULL; +} + +/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ +static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev, +					bool blocked) +{ +	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) +		b43err(dev->wl, "MAC not suspended\n"); + +	if (blocked) { +		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0); +	} else { +		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0); +		b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x1); +		b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0); +		b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x2); + +		if (dev->phy.radio_ver == 0x2059) +			b43_radio_2059_init(dev); +		else +			B43_WARN_ON(1); +	} +} + +static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on) +{ +	if (on) { +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00cd); +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x0000); +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00cd); +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x0000); +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00cd); +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x0000); +	} else { +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x07ff); +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00fd); +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x07ff); +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00fd); +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x07ff); +		b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00fd); +	} +} + +static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev, +					unsigned int new_channel) +{ +	struct ieee80211_channel *channel = dev->wl->hw->conf.channel; +	enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type; + +	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { +		if ((new_channel < 1) || (new_channel > 14)) +			return -EINVAL; +	} else { +		return -EINVAL; +	} + +	return b43_phy_ht_set_channel(dev, channel, channel_type); +} + +static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev) +{ +	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) +		return 1; +	return 36; +} + +/************************************************** + * R/W ops. + **************************************************/ + +static u16 b43_phy_ht_op_read(struct b43_wldev *dev, u16 reg) +{ +	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); +	return b43_read16(dev, B43_MMIO_PHY_DATA); +} + +static void b43_phy_ht_op_write(struct b43_wldev *dev, u16 reg, u16 value) +{ +	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); +	b43_write16(dev, B43_MMIO_PHY_DATA, value); +} + +static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, +				 u16 set) +{ +	b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); +	b43_write16(dev, B43_MMIO_PHY_DATA, +		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); +} + +static u16 b43_phy_ht_op_radio_read(struct b43_wldev *dev, u16 reg) +{ +	/* HT-PHY needs 0x200 for read access */ +	reg |= 0x200; + +	b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg); +	return b43_read16(dev, B43_MMIO_RADIO24_DATA); +} + +static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg, +				      u16 value) +{ +	b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg); +	b43_write16(dev, B43_MMIO_RADIO24_DATA, value); +} + +static enum b43_txpwr_result +b43_phy_ht_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi) +{ +	return B43_TXPWR_RES_DONE; +} + +static void b43_phy_ht_op_adjust_txpower(struct b43_wldev *dev) +{ +} + +/************************************************** + * PHY ops struct. + **************************************************/ + +const struct b43_phy_operations b43_phyops_ht = { +	.allocate		= b43_phy_ht_op_allocate, +	.free			= b43_phy_ht_op_free, +	.prepare_structs	= b43_phy_ht_op_prepare_structs, +	.init			= b43_phy_ht_op_init, +	.phy_read		= b43_phy_ht_op_read, +	.phy_write		= b43_phy_ht_op_write, +	.phy_maskset		= b43_phy_ht_op_maskset, +	.radio_read		= b43_phy_ht_op_radio_read, +	.radio_write		= b43_phy_ht_op_radio_write, +	.software_rfkill	= b43_phy_ht_op_software_rfkill, +	.switch_analog		= b43_phy_ht_op_switch_analog, +	.switch_channel		= b43_phy_ht_op_switch_channel, +	.get_default_chan	= b43_phy_ht_op_get_default_chan, +	.recalc_txpower		= b43_phy_ht_op_recalc_txpower, +	.adjust_txpower		= b43_phy_ht_op_adjust_txpower, +}; diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h new file mode 100644 index 00000000000..7ad7affc8df --- /dev/null +++ b/drivers/net/wireless/b43/phy_ht.h @@ -0,0 +1,46 @@ +#ifndef B43_PHY_HT_H_ +#define B43_PHY_HT_H_ + +#include "phy_common.h" + + +#define B43_PHY_HT_BANDCTL			0x009 /* Band control */ +#define B43_PHY_HT_TABLE_ADDR			0x072 /* Table address */ +#define B43_PHY_HT_TABLE_DATALO			0x073 /* Table data low */ +#define B43_PHY_HT_TABLE_DATAHI			0x074 /* Table data high */ +#define B43_PHY_HT_BW1				0x1CE +#define B43_PHY_HT_BW2				0x1CF +#define B43_PHY_HT_BW3				0x1D0 +#define B43_PHY_HT_BW4				0x1D1 +#define B43_PHY_HT_BW5				0x1D2 +#define B43_PHY_HT_BW6				0x1D3 + +#define B43_PHY_HT_RF_CTL1			B43_PHY_EXTG(0x010) + +#define B43_PHY_HT_AFE_CTL1			B43_PHY_EXTG(0x110) +#define B43_PHY_HT_AFE_CTL2			B43_PHY_EXTG(0x111) +#define B43_PHY_HT_AFE_CTL3			B43_PHY_EXTG(0x114) +#define B43_PHY_HT_AFE_CTL4			B43_PHY_EXTG(0x115) +#define B43_PHY_HT_AFE_CTL5			B43_PHY_EXTG(0x118) +#define B43_PHY_HT_AFE_CTL6			B43_PHY_EXTG(0x119) + + +/* Values for PHY registers used on channel switching */ +struct b43_phy_ht_channeltab_e_phy { +	u16 bw1; +	u16 bw2; +	u16 bw3; +	u16 bw4; +	u16 bw5; +	u16 bw6; +}; + + +struct b43_phy_ht { +}; + + +struct b43_phy_operations; +extern const struct b43_phy_operations b43_phyops_ht; + +#endif /* B43_PHY_HT_H_ */ diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c new file mode 100644 index 00000000000..9f7dbbd5ced --- /dev/null +++ b/drivers/net/wireless/b43/phy_lcn.c @@ -0,0 +1,52 @@ +/* + +  Broadcom B43 wireless driver +  IEEE 802.11n LCN-PHY support + +  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. + +  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; see the file COPYING.  If not, write to +  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, +  Boston, MA 02110-1301, USA. + +*/ + +#include <linux/slab.h> + +#include "b43.h" +#include "phy_lcn.h" +#include "tables_phy_lcn.h" +#include "main.h" + +/************************************************** + * PHY ops struct. + **************************************************/ + +const struct b43_phy_operations b43_phyops_lcn = { +	/* +	.allocate		= b43_phy_lcn_op_allocate, +	.free			= b43_phy_lcn_op_free, +	.prepare_structs	= b43_phy_lcn_op_prepare_structs, +	.init			= b43_phy_lcn_op_init, +	.phy_read		= b43_phy_lcn_op_read, +	.phy_write		= b43_phy_lcn_op_write, +	.phy_maskset		= b43_phy_lcn_op_maskset, +	.radio_read		= b43_phy_lcn_op_radio_read, +	.radio_write		= b43_phy_lcn_op_radio_write, +	.software_rfkill	= b43_phy_lcn_op_software_rfkill, +	.switch_analog		= b43_phy_lcn_op_switch_analog, +	.switch_channel		= b43_phy_lcn_op_switch_channel, +	.get_default_chan	= b43_phy_lcn_op_get_default_chan, +	.recalc_txpower		= b43_phy_lcn_op_recalc_txpower, +	.adjust_txpower		= b43_phy_lcn_op_adjust_txpower, +	*/ +}; diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h new file mode 100644 index 00000000000..c046c2a6cab --- /dev/null +++ b/drivers/net/wireless/b43/phy_lcn.h @@ -0,0 +1,14 @@ +#ifndef B43_PHY_LCN_H_ +#define B43_PHY_LCN_H_ + +#include "phy_common.h" + + +struct b43_phy_lcn { +}; + + +struct b43_phy_operations; +extern const struct b43_phy_operations b43_phyops_lcn; + +#endif /* B43_PHY_LCN_H_ */
\ No newline at end of file diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 012c8da2f94..daec1d9e4a1 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c @@ -85,39 +85,39 @@ static void b43_lpphy_op_free(struct b43_wldev *dev)  /* http://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */  static void lpphy_read_band_sprom(struct b43_wldev *dev)  { +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	struct b43_phy_lp *lpphy = dev->phy.lp; -	struct ssb_bus *bus = dev->sdev->bus;  	u16 cckpo, maxpwr;  	u32 ofdmpo;  	int i;  	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { -		lpphy->tx_isolation_med_band = bus->sprom.tri2g; -		lpphy->bx_arch = bus->sprom.bxa2g; -		lpphy->rx_pwr_offset = bus->sprom.rxpo2g; -		lpphy->rssi_vf = bus->sprom.rssismf2g; -		lpphy->rssi_vc = bus->sprom.rssismc2g; -		lpphy->rssi_gs = bus->sprom.rssisav2g; -		lpphy->txpa[0] = bus->sprom.pa0b0; -		lpphy->txpa[1] = bus->sprom.pa0b1; -		lpphy->txpa[2] = bus->sprom.pa0b2; -		maxpwr = bus->sprom.maxpwr_bg; +		lpphy->tx_isolation_med_band = sprom->tri2g; +		lpphy->bx_arch = sprom->bxa2g; +		lpphy->rx_pwr_offset = sprom->rxpo2g; +		lpphy->rssi_vf = sprom->rssismf2g; +		lpphy->rssi_vc = sprom->rssismc2g; +		lpphy->rssi_gs = sprom->rssisav2g; +		lpphy->txpa[0] = sprom->pa0b0; +		lpphy->txpa[1] = sprom->pa0b1; +		lpphy->txpa[2] = sprom->pa0b2; +		maxpwr = sprom->maxpwr_bg;  		lpphy->max_tx_pwr_med_band = maxpwr; -		cckpo = bus->sprom.cck2gpo; +		cckpo = sprom->cck2gpo;  		/*  		 * We don't read SPROM's opo as specs say. On rev8 SPROMs  		 * opo == ofdm2gpo and we don't know any SSB with LP-PHY  		 * and SPROM rev below 8.  		 */ -		B43_WARN_ON(bus->sprom.revision < 8); -		ofdmpo = bus->sprom.ofdm2gpo; +		B43_WARN_ON(sprom->revision < 8); +		ofdmpo = sprom->ofdm2gpo;  		if (cckpo) {  			for (i = 0; i < 4; i++) {  				lpphy->tx_max_rate[i] =  					maxpwr - (ofdmpo & 0xF) * 2;  				ofdmpo >>= 4;  			} -			ofdmpo = bus->sprom.ofdm2gpo; +			ofdmpo = sprom->ofdm2gpo;  			for (i = 4; i < 15; i++) {  				lpphy->tx_max_rate[i] =  					maxpwr - (ofdmpo & 0xF) * 2; @@ -131,39 +131,39 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev)  				lpphy->tx_max_rate[i] = maxpwr - ofdmpo;  		}  	} else { /* 5GHz */ -		lpphy->tx_isolation_low_band = bus->sprom.tri5gl; -		lpphy->tx_isolation_med_band = bus->sprom.tri5g; -		lpphy->tx_isolation_hi_band = bus->sprom.tri5gh; -		lpphy->bx_arch = bus->sprom.bxa5g; -		lpphy->rx_pwr_offset = bus->sprom.rxpo5g; -		lpphy->rssi_vf = bus->sprom.rssismf5g; -		lpphy->rssi_vc = bus->sprom.rssismc5g; -		lpphy->rssi_gs = bus->sprom.rssisav5g; -		lpphy->txpa[0] = bus->sprom.pa1b0; -		lpphy->txpa[1] = bus->sprom.pa1b1; -		lpphy->txpa[2] = bus->sprom.pa1b2; -		lpphy->txpal[0] = bus->sprom.pa1lob0; -		lpphy->txpal[1] = bus->sprom.pa1lob1; -		lpphy->txpal[2] = bus->sprom.pa1lob2; -		lpphy->txpah[0] = bus->sprom.pa1hib0; -		lpphy->txpah[1] = bus->sprom.pa1hib1; -		lpphy->txpah[2] = bus->sprom.pa1hib2; -		maxpwr = bus->sprom.maxpwr_al; -		ofdmpo = bus->sprom.ofdm5glpo; +		lpphy->tx_isolation_low_band = sprom->tri5gl; +		lpphy->tx_isolation_med_band = sprom->tri5g; +		lpphy->tx_isolation_hi_band = sprom->tri5gh; +		lpphy->bx_arch = sprom->bxa5g; +		lpphy->rx_pwr_offset = sprom->rxpo5g; +		lpphy->rssi_vf = sprom->rssismf5g; +		lpphy->rssi_vc = sprom->rssismc5g; +		lpphy->rssi_gs = sprom->rssisav5g; +		lpphy->txpa[0] = sprom->pa1b0; +		lpphy->txpa[1] = sprom->pa1b1; +		lpphy->txpa[2] = sprom->pa1b2; +		lpphy->txpal[0] = sprom->pa1lob0; +		lpphy->txpal[1] = sprom->pa1lob1; +		lpphy->txpal[2] = sprom->pa1lob2; +		lpphy->txpah[0] = sprom->pa1hib0; +		lpphy->txpah[1] = sprom->pa1hib1; +		lpphy->txpah[2] = sprom->pa1hib2; +		maxpwr = sprom->maxpwr_al; +		ofdmpo = sprom->ofdm5glpo;  		lpphy->max_tx_pwr_low_band = maxpwr;  		for (i = 4; i < 12; i++) {  			lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2;  			ofdmpo >>= 4;  		} -		maxpwr = bus->sprom.maxpwr_a; -		ofdmpo = bus->sprom.ofdm5gpo; +		maxpwr = sprom->maxpwr_a; +		ofdmpo = sprom->ofdm5gpo;  		lpphy->max_tx_pwr_med_band = maxpwr;  		for (i = 4; i < 12; i++) {  			lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2;  			ofdmpo >>= 4;  		} -		maxpwr = bus->sprom.maxpwr_ah; -		ofdmpo = bus->sprom.ofdm5ghpo; +		maxpwr = sprom->maxpwr_ah; +		ofdmpo = sprom->ofdm5ghpo;  		lpphy->max_tx_pwr_hi_band = maxpwr;  		for (i = 4; i < 12; i++) {  			lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2; @@ -214,7 +214,8 @@ static void lpphy_table_init(struct b43_wldev *dev)  static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_bus *bus = dev->dev->sdev->bus; +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	struct b43_phy_lp *lpphy = dev->phy.lp;  	u16 tmp, tmp2; @@ -242,9 +243,9 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)  	b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);  	b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB,  			0xFF00, lpphy->rx_pwr_offset); -	if ((bus->sprom.boardflags_lo & B43_BFL_FEM) && +	if ((sprom->boardflags_lo & B43_BFL_FEM) &&  	   ((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || -	   (bus->sprom.boardflags_hi & B43_BFH_PAREF))) { +	   (sprom->boardflags_hi & B43_BFH_PAREF))) {  		ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);  		ssb_pmu_set_ldo_paref(&bus->chipco, true);  		if (dev->phy.rev == 0) { @@ -260,7 +261,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)  	}  	tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000;  	b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp); -	if (bus->sprom.boardflags_hi & B43_BFH_RSSIINV) +	if (sprom->boardflags_hi & B43_BFH_RSSIINV)  		b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA);  	else  		b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA); @@ -268,7 +269,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)  	b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL,  			0xFFF9, (lpphy->bx_arch << 1));  	if (dev->phy.rev == 1 && -	   (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) { +	   (sprom->boardflags_hi & B43_BFH_FEM_BT)) {  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900);  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A); @@ -286,8 +287,8 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);  	} else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ || -		  (bus->boardinfo.type == 0x048A) || ((dev->phy.rev == 0) && -		  (bus->sprom.boardflags_lo & B43_BFL_FEM))) { +		  (dev->dev->board_type == 0x048A) || ((dev->phy.rev == 0) && +		  (sprom->boardflags_lo & B43_BFL_FEM))) {  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001); @@ -297,7 +298,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00);  	} else if (dev->phy.rev == 1 || -		  (bus->sprom.boardflags_lo & B43_BFL_FEM)) { +		  (sprom->boardflags_lo & B43_BFL_FEM)) {  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004);  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800);  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004); @@ -316,15 +317,15 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006);  		b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700);  	} -	if (dev->phy.rev == 1 && (bus->sprom.boardflags_hi & B43_BFH_PAREF)) { +	if (dev->phy.rev == 1 && (sprom->boardflags_hi & B43_BFH_PAREF)) {  		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1);  		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2);  		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3);  		b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4);  	} -	if ((bus->sprom.boardflags_hi & B43_BFH_FEM_BT) && -	    (bus->chip_id == 0x5354) && -	    (bus->chip_package == SSB_CHIPPACK_BCM4712S)) { +	if ((sprom->boardflags_hi & B43_BFH_FEM_BT) && +	    (dev->dev->chip_id == 0x5354) && +	    (dev->dev->chip_pkg == SSB_CHIPPACK_BCM4712S)) {  		b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);  		b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);  		b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF); @@ -412,7 +413,6 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)  static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus;  	struct b43_phy_lp *lpphy = dev->phy.lp;  	b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50); @@ -432,7 +432,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)  	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000);  	b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000);  	b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1); -	if (bus->boardinfo.rev >= 0x18) { +	if (dev->dev->board_rev >= 0x18) {  		b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC);  		b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14);  	} else { @@ -449,7 +449,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)  	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0);  	b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300);  	b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00); -	if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { +	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {  		b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);  		b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xA);  	} else { @@ -467,7 +467,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)  	b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);  	b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000); -	if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { +	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {  		b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);  		b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);  	} @@ -492,7 +492,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)  		      0x2000 | ((u16)lpphy->rssi_gs << 10) |  		      ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf); -	if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { +	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {  		b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C);  		b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800);  		b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400); @@ -519,7 +519,7 @@ struct b2062_freqdata {  static void lpphy_2062_init(struct b43_wldev *dev)  {  	struct b43_phy_lp *lpphy = dev->phy.lp; -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_bus *bus = dev->dev->sdev->bus;  	u32 crystalfreq, tmp, ref;  	unsigned int i;  	const struct b2062_freqdata *fd = NULL; @@ -697,7 +697,7 @@ static void lpphy_radio_init(struct b43_wldev *dev)  		lpphy_sync_stx(dev);  		b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);  		b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0); -		if (dev->sdev->bus->chip_id == 0x4325) { +		if (dev->dev->chip_id == 0x4325) {  			// TODO SSB PMU recalibration  		}  	} @@ -1289,7 +1289,7 @@ finish:  static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_bus *bus = dev->dev->sdev->bus;  	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;  	u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;  	int i; @@ -1840,7 +1840,6 @@ static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,  static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)  {  	struct b43_phy_lp *lpphy = dev->phy.lp; -	struct ssb_bus *bus = dev->sdev->bus;  	struct lpphy_tx_gains gains, oldgains;  	int old_txpctl, old_afe_ovr, old_rf, old_bbmult; @@ -1854,7 +1853,7 @@ static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)  	lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); -	if (bus->chip_id == 0x4325 && bus->chip_rev == 0) +	if (dev->dev->chip_id == 0x4325 && dev->dev->chip_rev == 0)  		lpphy_papd_cal(dev, gains, 0, 1, 30);  	else  		lpphy_papd_cal(dev, gains, 0, 1, 65); @@ -1870,7 +1869,6 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,  			    bool rx, bool pa, struct lpphy_tx_gains *gains)  {  	struct b43_phy_lp *lpphy = dev->phy.lp; -	struct ssb_bus *bus = dev->sdev->bus;  	const struct lpphy_rx_iq_comp *iqcomp = NULL;  	struct lpphy_tx_gains nogains, oldgains;  	u16 tmp; @@ -1879,7 +1877,7 @@ static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,  	memset(&nogains, 0, sizeof(nogains));  	memset(&oldgains, 0, sizeof(oldgains)); -	if (bus->chip_id == 0x5354) { +	if (dev->dev->chip_id == 0x5354) {  		for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {  			if (lpphy_5354_iq_table[i].chan == lpphy->channel) {  				iqcomp = &lpphy_5354_iq_table[i]; @@ -2408,11 +2406,9 @@ static const struct b206x_channel b2063_chantbl[] = {  static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; -  	b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF);  	udelay(20); -	if (bus->chip_id == 0x5354) { +	if (dev->dev->chip_id == 0x5354) {  		b43_radio_write(dev, B2062_N_COMM1, 4);  		b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4);  	} else { @@ -2432,7 +2428,7 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,  			    unsigned int channel)  {  	struct b43_phy_lp *lpphy = dev->phy.lp; -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_bus *bus = dev->dev->sdev->bus;  	const struct b206x_channel *chandata = NULL;  	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;  	u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; @@ -2522,7 +2518,7 @@ static void lpphy_b2063_vco_calib(struct b43_wldev *dev)  static int lpphy_b2063_tune(struct b43_wldev *dev,  			    unsigned int channel)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_bus *bus = dev->dev->sdev->bus;  	static const struct b206x_channel *chandata = NULL;  	u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; @@ -2670,6 +2666,11 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)  {  	int err; +	if (dev->dev->bus_type != B43_BUS_SSB) { +		b43err(dev->wl, "LP-PHY is supported only on SSB!\n"); +		return -EOPNOTSUPP; +	} +  	lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?  	lpphy_baseband_init(dev);  	lpphy_radio_init(dev); diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 05960ddde24..95c28f584ed 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -299,7 +299,7 @@ static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)  static void b43_nphy_tx_power_fix(struct b43_wldev *dev)  {  	struct b43_phy_n *nphy = dev->phy.n; -	struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	u8 txpi[2], bbmult, i;  	u16 tmp, radio_gain, dac_gain; @@ -423,16 +423,15 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev)  static void b43_radio_init2055_post(struct b43_wldev *dev)  {  	struct b43_phy_n *nphy = dev->phy.n; -	struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); -	struct ssb_boardinfo *binfo = &(dev->sdev->bus->boardinfo); +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	int i;  	u16 val;  	bool workaround = false;  	if (sprom->revision < 4) -		workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM && -				binfo->type == 0x46D && -				binfo->rev >= 0x41); +		workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM +			      && dev->dev->board_type == 0x46D +			      && dev->dev->board_rev >= 0x41);  	else  		workaround =  			!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS); @@ -604,17 +603,33 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)  /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */  static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)  { -	u32 tmslow; +	u32 tmp;  	if (dev->phy.type != B43_PHYTYPE_N)  		return; -	tmslow = ssb_read32(dev->sdev, SSB_TMSLOW); -	if (force) -		tmslow |= SSB_TMSLOW_FGC; -	else -		tmslow &= ~SSB_TMSLOW_FGC; -	ssb_write32(dev->sdev, SSB_TMSLOW, tmslow); +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		tmp = bcma_read32(dev->dev->bdev, BCMA_IOCTL); +		if (force) +			tmp |= BCMA_IOCTL_FGC; +		else +			tmp &= ~BCMA_IOCTL_FGC; +		bcma_write32(dev->dev->bdev, BCMA_IOCTL, tmp); +		break; +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); +		if (force) +			tmp |= SSB_TMSLOW_FGC; +		else +			tmp &= ~SSB_TMSLOW_FGC; +		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); +		break; +#endif +	}  }  /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ @@ -959,8 +974,21 @@ static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)  		b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);  		b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0); -		ssb_chipco_gpio_control(&dev->sdev->bus->chipco, 0xFC00, -					0xFC00); +		switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +		case B43_BUS_BCMA: +			bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc, +						 0xFC00, 0xFC00); +			break; +#endif +#ifdef CONFIG_B43_SSB +		case B43_BUS_SSB: +			ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco, +						0xFC00, 0xFC00); +			break; +#endif +		} +  		b43_write32(dev, B43_MMIO_MACCTL,  			b43_read32(dev, B43_MMIO_MACCTL) &  			~B43_MACCTL_GPOUTSMSK); @@ -983,7 +1011,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)  {  	u16 tmp; -	if (dev->sdev->id.revision == 16) +	if (dev->dev->core_rev == 16)  		b43_mac_suspend(dev);  	tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL); @@ -993,7 +1021,7 @@ static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)  	tmp |= (val & mask);  	b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp); -	if (dev->sdev->id.revision == 16) +	if (dev->dev->core_rev == 16)  		b43_mac_enable(dev);  	return tmp; @@ -1168,7 +1196,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)  static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)  {  	struct b43_phy_n *nphy = dev->phy.n; -	struct ssb_sprom *sprom = &(dev->sdev->bus->sprom); +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	/* PHY rev 0, 1, 2 */  	u8 i, j; @@ -1373,7 +1401,7 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)  /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */  static void b43_nphy_workarounds(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	struct b43_phy *phy = &dev->phy;  	struct b43_phy_n *nphy = phy->n; @@ -1443,9 +1471,9 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)  		/* N PHY WAR TX Chain Update with hw_phytxchain as argument */ -		if ((bus->sprom.boardflags2_lo & B43_BFL2_APLL_WAR && +		if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&  		    b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || -		    (bus->sprom.boardflags2_lo & B43_BFL2_GPLL_WAR && +		    (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&  		    b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))  			tmp32 = 0x00088888;  		else @@ -1503,8 +1531,8 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)  		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);  		b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); -		if (bus->sprom.boardflags2_lo & 0x100 && -		    bus->boardinfo.type == 0x8B) { +		if (sprom->boardflags2_lo & 0x100 && +		    dev->dev->board_type == 0x8B) {  			delays1[0] = 0x1;  			delays1[5] = 0x14;  		} @@ -3586,7 +3614,7 @@ static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)   */  int b43_phy_initn(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	struct b43_phy *phy = &dev->phy;  	struct b43_phy_n *nphy = phy->n;  	u8 tx_pwr_state; @@ -3599,9 +3627,22 @@ int b43_phy_initn(struct b43_wldev *dev)  	bool do_cal = false;  	if ((dev->phy.rev >= 3) && -	   (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && +	   (sprom->boardflags_lo & B43_BFL_EXTLNA) &&  	   (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) { -		chipco_set32(&dev->sdev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40); +		switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +		case B43_BUS_BCMA: +			bcma_cc_set32(&dev->dev->bdev->bus->drv_cc, +				      BCMA_CC_CHIPCTL, 0x40); +			break; +#endif +#ifdef CONFIG_B43_SSB +		case B43_BUS_SSB: +			chipco_set32(&dev->dev->sdev->bus->chipco, +				     SSB_CHIPCO_CHIPCTL, 0x40); +			break; +#endif +		}  	}  	nphy->deaf_count = 0;  	b43_nphy_tables_init(dev); @@ -3639,9 +3680,9 @@ int b43_phy_initn(struct b43_wldev *dev)  	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);  	b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); -	if (bus->sprom.boardflags2_lo & 0x100 || -	    (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && -	     bus->boardinfo.type == 0x8B)) +	if (sprom->boardflags2_lo & 0x100 || +	    (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE && +	     dev->dev->board_type == 0x8B))  		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);  	else  		b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8); @@ -4026,11 +4067,24 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,  /* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */  static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)  { -	u16 val = on ? 0 : 0x7FFF; +	u16 override = on ? 0x0 : 0x7FFF; +	u16 core = on ? 0xD : 0x00FD; -	if (dev->phy.rev >= 3) -		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, val); -	b43_phy_write(dev, B43_NPHY_AFECTL_OVER, val); +	if (dev->phy.rev >= 3) { +		if (on) { +			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core); +			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override); +			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core); +			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override); +		} else { +			b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override); +			b43_phy_write(dev, B43_NPHY_AFECTL_C1, core); +			b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override); +			b43_phy_write(dev, B43_NPHY_AFECTL_C2, core); +		} +	} else { +		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override); +	}  }  static int b43_nphy_op_switch_channel(struct b43_wldev *dev, diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 72ab94df756..44da620d9cc 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -111,7 +111,7 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,  		B43_MMIO_PIO11_BASE5,  	}; -	if (dev->sdev->id.revision >= 11) { +	if (dev->dev->core_rev >= 11) {  		B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11));  		return bases_rev11[index];  	} @@ -121,14 +121,14 @@ static u16 index_to_pioqueue_base(struct b43_wldev *dev,  static u16 pio_txqueue_offset(struct b43_wldev *dev)  { -	if (dev->sdev->id.revision >= 11) +	if (dev->dev->core_rev >= 11)  		return 0x18;  	return 0;  }  static u16 pio_rxqueue_offset(struct b43_wldev *dev)  { -	if (dev->sdev->id.revision >= 11) +	if (dev->dev->core_rev >= 11)  		return 0x38;  	return 8;  } @@ -144,7 +144,7 @@ static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev,  	if (!q)  		return NULL;  	q->dev = dev; -	q->rev = dev->sdev->id.revision; +	q->rev = dev->dev->core_rev;  	q->mmio_base = index_to_pioqueue_base(dev, index) +  		       pio_txqueue_offset(dev);  	q->index = index; @@ -178,7 +178,7 @@ static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev,  	if (!q)  		return NULL;  	q->dev = dev; -	q->rev = dev->sdev->id.revision; +	q->rev = dev->dev->core_rev;  	q->mmio_base = index_to_pioqueue_base(dev, index) +  		       pio_rxqueue_offset(dev); diff --git a/drivers/net/wireless/b43/radio_2055.h b/drivers/net/wireless/b43/radio_2055.h index d9bfa0f21b7..67f96122f8d 100644 --- a/drivers/net/wireless/b43/radio_2055.h +++ b/drivers/net/wireless/b43/radio_2055.h @@ -251,4 +251,9 @@ struct b43_nphy_channeltab_entry_rev2 {  void b2055_upload_inittab(struct b43_wldev *dev,  			  bool ghz5, bool ignore_uploadflag); +/* Get the NPHY Channel Switch Table entry for a channel. + * Returns NULL on failure to find an entry. */ +const struct b43_nphy_channeltab_entry_rev2 * +b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel); +  #endif /* B43_RADIO_2055_H_ */ diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h index d601f6e7e31..d52df6be705 100644 --- a/drivers/net/wireless/b43/radio_2056.h +++ b/drivers/net/wireless/b43/radio_2056.h @@ -1117,4 +1117,9 @@ struct b43_nphy_channeltab_entry_rev3 {  void b2056_upload_inittabs(struct b43_wldev *dev,  			   bool ghz5, bool ignore_uploadflag); +/* Get the NPHY Channel Switch Table entry for a channel. + * Returns NULL on failure to find an entry. */ +const struct b43_nphy_channeltab_entry_rev3 * +b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq); +  #endif /* B43_RADIO_2056_H_ */ diff --git a/drivers/net/wireless/b43/radio_2059.c b/drivers/net/wireless/b43/radio_2059.c new file mode 100644 index 00000000000..23dea4ba821 --- /dev/null +++ b/drivers/net/wireless/b43/radio_2059.c @@ -0,0 +1,165 @@ +/* + +  Broadcom B43 wireless driver +  IEEE 802.11n 2059 radio device data tables + +  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. + +  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; see the file COPYING.  If not, write to +  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, +  Boston, MA 02110-1301, USA. + +*/ + +#include "b43.h" +#include "radio_2059.h" + +#define RADIOREGS(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \ +		  r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \ +		  r20, r21, r22, r23, r24, r25, r26, r27, r28) \ +	.radio_syn16			= r00,	\ +	.radio_syn17			= r01,	\ +	.radio_syn22			= r02,	\ +	.radio_syn25			= r03,	\ +	.radio_syn27			= r04,	\ +	.radio_syn28			= r05,	\ +	.radio_syn29			= r06,	\ +	.radio_syn2c			= r07,	\ +	.radio_syn2d			= r08,	\ +	.radio_syn37			= r09,	\ +	.radio_syn41			= r10,	\ +	.radio_syn43			= r11,	\ +	.radio_syn47			= r12,	\ +	.radio_syn4a			= r13,	\ +	.radio_syn58			= r14,	\ +	.radio_syn5a			= r15,	\ +	.radio_syn6a			= r16,	\ +	.radio_syn6d			= r17,	\ +	.radio_syn6e			= r18,	\ +	.radio_syn92			= r19,	\ +	.radio_syn98			= r20,	\ +	.radio_rxtx4a			= r21,	\ +	.radio_rxtx58			= r22,	\ +	.radio_rxtx5a			= r23,	\ +	.radio_rxtx6a			= r24,	\ +	.radio_rxtx6d			= r25,	\ +	.radio_rxtx6e			= r26,	\ +	.radio_rxtx92			= r27,	\ +	.radio_rxtx98			= r28 + +#define PHYREGS(r0, r1, r2, r3, r4, r5)	\ +	.phy_regs.bw1	= r0,	\ +	.phy_regs.bw2	= r1,	\ +	.phy_regs.bw3	= r2,	\ +	.phy_regs.bw4	= r3,	\ +	.phy_regs.bw5	= r4,	\ +	.phy_regs.bw6	= r5 + +static const struct b43_phy_ht_channeltab_e_radio2059 b43_phy_ht_channeltab_radio2059[] = { +  {	.freq			= 2412, +	RADIOREGS(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, +		  0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443), +  }, +  {	.freq			= 2417, +	RADIOREGS(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, +		  0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441), +  }, +  {	.freq			= 2422, +	RADIOREGS(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, +		  0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f), +  }, +  {	.freq			= 2427, +	RADIOREGS(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, +		  0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d), +  }, +  {	.freq			= 2432, +	RADIOREGS(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, +		  0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a), +  }, +  {	.freq			= 2437, +	RADIOREGS(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, +		  0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438), +  }, +  {	.freq			= 2442, +	RADIOREGS(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, +		  0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436), +  }, +  {	.freq			= 2447, +	RADIOREGS(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, +		  0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434), +  }, +  {	.freq			= 2452, +	RADIOREGS(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, +		  0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431), +  }, +  {	.freq			= 2457, +	RADIOREGS(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, +		  0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f), +  }, +  {	.freq			= 2462, +	RADIOREGS(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, +		  0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d), +  }, +  {	.freq			= 2467, +	RADIOREGS(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, +		  0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b), +  }, +  {	.freq			= 2472, +	RADIOREGS(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, +		  0x09, 0x0f, 0x05, 0x00, 0x05, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x61, 0x03, +		  0x00, 0x00, 0x00, 0xf0, 0x00), +	PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429), +  }, +}; + +const struct b43_phy_ht_channeltab_e_radio2059 +*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq) +{ +	return NULL; +} diff --git a/drivers/net/wireless/b43/radio_2059.h b/drivers/net/wireless/b43/radio_2059.h new file mode 100644 index 00000000000..e4d69e55e9f --- /dev/null +++ b/drivers/net/wireless/b43/radio_2059.h @@ -0,0 +1,54 @@ +#ifndef B43_RADIO_2059_H_ +#define B43_RADIO_2059_H_ + +#include <linux/types.h> + +#include "phy_ht.h" + +#define R2059_SYN			0x000 +#define R2059_TXRX0			0x400 +#define R2059_RXRX1			0x800 +#define R2059_ALL			0xC00 + +/* Values for various registers uploaded on channel switching */ +struct b43_phy_ht_channeltab_e_radio2059 { +	/* The channel frequency in MHz */ +	u16 freq; +	/* Values for radio registers */ +	u8 radio_syn16; +	u8 radio_syn17; +	u8 radio_syn22; +	u8 radio_syn25; +	u8 radio_syn27; +	u8 radio_syn28; +	u8 radio_syn29; +	u8 radio_syn2c; +	u8 radio_syn2d; +	u8 radio_syn37; +	u8 radio_syn41; +	u8 radio_syn43; +	u8 radio_syn47; +	u8 radio_syn4a; +	u8 radio_syn58; +	u8 radio_syn5a; +	u8 radio_syn6a; +	u8 radio_syn6d; +	u8 radio_syn6e; +	u8 radio_syn92; +	u8 radio_syn98; +	u8 radio_rxtx4a; +	u8 radio_rxtx58; +	u8 radio_rxtx5a; +	u8 radio_rxtx6a; +	u8 radio_rxtx6d; +	u8 radio_rxtx6e; +	u8 radio_rxtx92; +	u8 radio_rxtx98; +	/* Values for PHY registers */ +	struct b43_phy_ht_channeltab_e_phy phy_regs; +}; + +const struct b43_phy_ht_channeltab_e_radio2059 +*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq); + +#endif /* B43_RADIO_2059_H_ */ diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index a617efe3828..59c3afe047a 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c @@ -37,17 +37,16 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)  {  	struct b43_wl *wl = hw_to_b43_wl(hw);  	struct b43_wldev *dev = wl->current_dev; -	struct ssb_bus *bus = dev->sdev->bus;  	bool enabled;  	bool brought_up = false;  	mutex_lock(&wl->mutex);  	if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) { -		if (ssb_bus_powerup(bus, 0)) { +		if (b43_bus_powerup(dev, 0)) {  			mutex_unlock(&wl->mutex);  			return;  		} -		ssb_device_enable(dev->sdev, 0); +		b43_device_enable(dev, 0);  		brought_up = true;  	} @@ -63,8 +62,8 @@ void b43_rfkill_poll(struct ieee80211_hw *hw)  	}  	if (brought_up) { -		ssb_device_disable(dev->sdev, 0); -		ssb_bus_may_powerdown(bus); +		b43_device_disable(dev, 0); +		b43_bus_may_powerdown(dev);  	}  	mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c index 808e25b7970..4fd6775b8c3 100644 --- a/drivers/net/wireless/b43/sdio.c +++ b/drivers/net/wireless/b43/sdio.c @@ -66,7 +66,7 @@ static void b43_sdio_interrupt_dispatcher(struct sdio_func *func)  int b43_sdio_request_irq(struct b43_wldev *dev,  			 void (*handler)(struct b43_wldev *dev))  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_bus *bus = dev->dev->sdev->bus;  	struct sdio_func *func = bus->host_sdio;  	struct b43_sdio *sdio = sdio_get_drvdata(func);  	int err; @@ -82,7 +82,7 @@ int b43_sdio_request_irq(struct b43_wldev *dev,  void b43_sdio_free_irq(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_bus *bus = dev->dev->sdev->bus;  	struct sdio_func *func = bus->host_sdio;  	struct b43_sdio *sdio = sdio_get_drvdata(func); @@ -93,8 +93,8 @@ void b43_sdio_free_irq(struct b43_wldev *dev)  	sdio->irq_handler = NULL;  } -static int b43_sdio_probe(struct sdio_func *func, -			  const struct sdio_device_id *id) +static int __devinit b43_sdio_probe(struct sdio_func *func, +				    const struct sdio_device_id *id)  {  	struct b43_sdio *sdio;  	struct sdio_func_tuple *tuple; @@ -171,7 +171,7 @@ out:  	return error;  } -static void b43_sdio_remove(struct sdio_func *func) +static void __devexit b43_sdio_remove(struct sdio_func *func)  {  	struct b43_sdio *sdio = sdio_get_drvdata(func); diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c index 57af619725c..f1ae4e05a32 100644 --- a/drivers/net/wireless/b43/sysfs.c +++ b/drivers/net/wireless/b43/sysfs.c @@ -140,7 +140,7 @@ static DEVICE_ATTR(interference, 0644,  int b43_sysfs_register(struct b43_wldev *wldev)  { -	struct device *dev = wldev->sdev->dev; +	struct device *dev = wldev->dev->dev;  	B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED); @@ -149,7 +149,7 @@ int b43_sysfs_register(struct b43_wldev *wldev)  void b43_sysfs_unregister(struct b43_wldev *wldev)  { -	struct device *dev = wldev->sdev->dev; +	struct device *dev = wldev->dev->dev;  	device_remove_file(dev, &dev_attr_interference);  } diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c index 59df3c64af6..6748c5a196e 100644 --- a/drivers/net/wireless/b43/tables_lpphy.c +++ b/drivers/net/wireless/b43/tables_lpphy.c @@ -2304,7 +2304,6 @@ void lpphy_rev0_1_table_init(struct b43_wldev *dev)  void lpphy_rev2plus_table_init(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus;  	int i;  	B43_WARN_ON(dev->phy.rev < 2); @@ -2341,7 +2340,7 @@ void lpphy_rev2plus_table_init(struct b43_wldev *dev)  	b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),  		ARRAY_SIZE(lpphy_papd_mult_table), lpphy_papd_mult_table); -	if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { +	if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {  		b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),  			ARRAY_SIZE(lpphy_a0_gain_idx_table), lpphy_a0_gain_idx_table);  		b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0), @@ -2416,12 +2415,12 @@ void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,  void lpphy_init_tx_gain_table(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	switch (dev->phy.rev) {  	case 0: -		if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) || -		    (bus->sprom.boardflags_lo & B43_BFL_HGPA)) +		if ((sprom->boardflags_hi & B43_BFH_NOPA) || +		    (sprom->boardflags_lo & B43_BFL_HGPA))  			lpphy_write_gain_table_bulk(dev, 0, 128,  					lpphy_rev0_nopa_tx_gain_table);  		else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) @@ -2432,8 +2431,8 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev)  					lpphy_rev0_5ghz_tx_gain_table);  		break;  	case 1: -		if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) || -		    (bus->sprom.boardflags_lo & B43_BFL_HGPA)) +		if ((sprom->boardflags_hi & B43_BFH_NOPA) || +		    (sprom->boardflags_lo & B43_BFL_HGPA))  			lpphy_write_gain_table_bulk(dev, 0, 128,  					lpphy_rev1_nopa_tx_gain_table);  		else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) @@ -2444,7 +2443,7 @@ void lpphy_init_tx_gain_table(struct b43_wldev *dev)  					lpphy_rev1_5ghz_tx_gain_table);  		break;  	default: -		if (bus->sprom.boardflags_hi & B43_BFH_NOPA) +		if (sprom->boardflags_hi & B43_BFH_NOPA)  			lpphy_write_gain_table_bulk(dev, 0, 128,  					lpphy_rev2_nopa_tx_gain_table);  		else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 18569367ce4..a81696bff0e 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -60,16 +60,8 @@ struct nphy_gain_ctl_workaround_entry {  struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(  	struct b43_wldev *dev, bool ghz5, bool ext_lna); -/* Get the NPHY Channel Switch Table entry for a channel. - * Returns NULL on failure to find an entry. */ -const struct b43_nphy_channeltab_entry_rev2 * -b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel); -const struct b43_nphy_channeltab_entry_rev3 * -b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq); -  /* The N-PHY tables. */ -  #define B43_NTAB_TYPEMASK		0xF0000000  #define B43_NTAB_8BIT			0x10000000  #define B43_NTAB_16BIT			0x20000000 diff --git a/drivers/net/wireless/b43/tables_phy_ht.c b/drivers/net/wireless/b43/tables_phy_ht.c new file mode 100644 index 00000000000..603938657b1 --- /dev/null +++ b/drivers/net/wireless/b43/tables_phy_ht.c @@ -0,0 +1,750 @@ +/* + +  Broadcom B43 wireless driver +  IEEE 802.11n HT-PHY data tables + +  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. + +  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; see the file COPYING.  If not, write to +  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, +  Boston, MA 02110-1301, USA. + +*/ + +#include "b43.h" +#include "tables_phy_ht.h" +#include "phy_common.h" +#include "phy_ht.h" + +static const u16 b43_httab_0x12[] = { +	0x0000, 0x0008, 0x000a, 0x0010, 0x0012, 0x0019, +	0x001a, 0x001c, 0x0080, 0x0088, 0x008a, 0x0090, +	0x0092, 0x0099, 0x009a, 0x009c, 0x0100, 0x0108, +	0x010a, 0x0110, 0x0112, 0x0119, 0x011a, 0x011c, +	0x0180, 0x0188, 0x018a, 0x0190, 0x0192, 0x0199, +	0x019a, 0x019c, 0x0000, 0x0098, 0x00a0, 0x00a8, +	0x009a, 0x00a2, 0x00aa, 0x0120, 0x0128, 0x0128, +	0x0130, 0x0138, 0x0138, 0x0140, 0x0122, 0x012a, +	0x012a, 0x0132, 0x013a, 0x013a, 0x0142, 0x01a8, +	0x01b0, 0x01b8, 0x01b0, 0x01b8, 0x01c0, 0x01c8, +	0x01c0, 0x01c8, 0x01d0, 0x01d0, 0x01d8, 0x01aa, +	0x01b2, 0x01ba, 0x01b2, 0x01ba, 0x01c2, 0x01ca, +	0x01c2, 0x01ca, 0x01d2, 0x01d2, 0x01da, 0x0001, +	0x0002, 0x0004, 0x0009, 0x000c, 0x0011, 0x0014, +	0x0018, 0x0020, 0x0021, 0x0022, 0x0024, 0x0081, +	0x0082, 0x0084, 0x0089, 0x008c, 0x0091, 0x0094, +	0x0098, 0x00a0, 0x00a1, 0x00a2, 0x00a4, 0x0007, +	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, +	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, +	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, +	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, +	0x0007, 0x0007, +}; + +static const u16 b43_httab_0x27[] = { +	0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a, +	0x001d, 0x0020, 0x0009, 0x000e, 0x0011, 0x0014, +	0x0017, 0x001a, 0x001d, 0x0020, 0x0009, 0x000e, +	0x0011, 0x0014, 0x0017, 0x001a, 0x001d, 0x0020, +	0x0009, 0x000e, 0x0011, 0x0014, 0x0017, 0x001a, +	0x001d, 0x0020, +}; + +static const u16 b43_httab_0x26[] = { +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, +}; + +static const u32 b43_httab_0x25[] = { +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +static const u32 b43_httab_0x2f[] = { +	0x00035700, 0x0002cc9a, 0x00026666, 0x0001581f, +	0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f, +	0x0001581f, 0x0001581f, 0x0001581f, 0x00035700, +	0x0002cc9a, 0x00026666, 0x0001581f, 0x0001581f, +	0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f, +	0x0001581f, 0x0001581f, +}; + +static const u16 b43_httab_0x1a[] = { +	0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052, +	0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e, +	0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a, +	0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046, +	0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040, +	0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a, +	0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033, +	0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b, +	0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f, +	0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e, +	0x000b, 0x0007, 0x0002, 0x00fd, +}; + +static const u16 b43_httab_0x1b[] = { +	0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052, +	0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e, +	0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a, +	0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046, +	0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040, +	0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a, +	0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033, +	0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b, +	0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f, +	0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e, +	0x000b, 0x0007, 0x0002, 0x00fd, +}; + +static const u16 b43_httab_0x1c[] = { +	0x0055, 0x0054, 0x0054, 0x0053, 0x0052, 0x0052, +	0x0051, 0x0051, 0x0050, 0x004f, 0x004f, 0x004e, +	0x004e, 0x004d, 0x004c, 0x004c, 0x004b, 0x004a, +	0x0049, 0x0049, 0x0048, 0x0047, 0x0046, 0x0046, +	0x0045, 0x0044, 0x0043, 0x0042, 0x0041, 0x0040, +	0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003a, +	0x0039, 0x0038, 0x0037, 0x0036, 0x0035, 0x0033, +	0x0032, 0x0031, 0x002f, 0x002e, 0x002c, 0x002b, +	0x0029, 0x0027, 0x0025, 0x0023, 0x0021, 0x001f, +	0x001d, 0x001a, 0x0018, 0x0015, 0x0012, 0x000e, +	0x000b, 0x0007, 0x0002, 0x00fd, +}; + +static const u32 b43_httab_0x1a_0xc0[] = { +	0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e, +	0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037, +	0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031, +	0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040, +	0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039, +	0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033, +	0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e, +	0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037, +	0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031, +	0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c, +	0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e, +	0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037, +	0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031, +	0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c, +	0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042, +	0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b, +	0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034, +	0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f, +	0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e, +	0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037, +	0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031, +	0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c, +	0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027, +	0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023, +	0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e, +	0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037, +	0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031, +	0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c, +	0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027, +	0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023, +	0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f, +	0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c, +}; + +static const u32 b43_httab_0x1a_0x140[] = { +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +static const u32 b43_httab_0x1b_0x140[] = { +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +static const u32 b43_httab_0x1c_0x140[] = { +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +static const u16 b43_httab_0x1a_0x1c0[] = { +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, +}; + +static const u16 b43_httab_0x1b_0x1c0[] = { +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, +}; + +static const u16 b43_httab_0x1c_0x1c0[] = { +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, +}; + +static const u16 b43_httab_0x1a_0x240[] = { +	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, +	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, +	0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, +	0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, +	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, +	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, +	0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e, +	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, +	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, +	0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc, +	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, +	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, +}; + +static const u16 b43_httab_0x1b_0x240[] = { +	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, +	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, +	0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, +	0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, +	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, +	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, +	0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e, +	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, +	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, +	0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc, +	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, +	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, +}; + +static const u16 b43_httab_0x1c_0x240[] = { +	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, +	0x0036, 0x0036, 0x0036, 0x0036, 0x0036, 0x0036, +	0x0036, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, +	0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, +	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, +	0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, +	0x001e, 0x001e, 0x001e, 0x001e, 0x000e, 0x000e, +	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, +	0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, +	0x000e, 0x000e, 0x000e, 0x000e, 0x01fc, 0x01fc, +	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, +	0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, 0x01fc, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, 0x01ee, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, 0x01d6, +	0x01d6, 0x01d6, +}; + +static const u32 b43_httab_0x1f[] = { +	0x00000000, 0x00000000, 0x00016023, 0x00006028, +	0x00034036, 0x0003402e, 0x0007203c, 0x0006e037, +	0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d, +	0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9, +	0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9, +	0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6, +	0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c, +	0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b, +	0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15, +	0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9, +	0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87, +	0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3, +	0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa, +	0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff, +	0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff, +	0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff, +}; + +static const u32 b43_httab_0x21[] = { +	0x00000000, 0x00000000, 0x00016023, 0x00006028, +	0x00034036, 0x0003402e, 0x0007203c, 0x0006e037, +	0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d, +	0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9, +	0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9, +	0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6, +	0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c, +	0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b, +	0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15, +	0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9, +	0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87, +	0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3, +	0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa, +	0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff, +	0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff, +	0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff, +}; + +static const u32 b43_httab_0x23[] = { +	0x00000000, 0x00000000, 0x00016023, 0x00006028, +	0x00034036, 0x0003402e, 0x0007203c, 0x0006e037, +	0x00070030, 0x0009401f, 0x0009a00f, 0x000b600d, +	0x000c8007, 0x000ce007, 0x00101fff, 0x00121ff9, +	0x0012e004, 0x0014dffc, 0x0016dff6, 0x0018dfe9, +	0x001b3fe5, 0x001c5fd0, 0x001ddfc2, 0x001f1fb6, +	0x00207fa4, 0x00219f8f, 0x0022ff7d, 0x00247f6c, +	0x0024df5b, 0x00267f4b, 0x0027df3b, 0x0029bf3b, +	0x002b5f2f, 0x002d3f2e, 0x002f5f2a, 0x002fff15, +	0x00315f0b, 0x0032defa, 0x0033beeb, 0x0034fed9, +	0x00353ec5, 0x00361eb0, 0x00363e9b, 0x0036be87, +	0x0036be70, 0x0038fe67, 0x0044beb2, 0x00513ef3, +	0x00595f11, 0x00669f3d, 0x0078dfdf, 0x00a143aa, +	0x01642fff, 0x0162afff, 0x01620fff, 0x0160cfff, +	0x015f0fff, 0x015dafff, 0x015bcfff, 0x015bcfff, +	0x015b4fff, 0x015acfff, 0x01590fff, 0x0156cfff, +}; + +static const u32 b43_httab_0x20[] = { +	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035, +	0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043, +	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054, +	0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a, +	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085, +	0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8, +	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3, +	0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a, +	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e, +	0x01720162, 0x015d0177, 0x0149018e, 0x013701a5, +	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212, +	0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b, +	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348, +	0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422, +	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533, +	0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c, +}; + +static const u32 b43_httab_0x22[] = { +	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035, +	0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043, +	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054, +	0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a, +	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085, +	0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8, +	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3, +	0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a, +	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e, +	0x01720162, 0x015d0177, 0x0149018e, 0x013701a5, +	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212, +	0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b, +	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348, +	0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422, +	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533, +	0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c, +}; + +static const u32 b43_httab_0x24[] = { +	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035, +	0x09220038, 0x08ab003b, 0x081f003f, 0x07a20043, +	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054, +	0x05bf0059, 0x0571005e, 0x051e0064, 0x04d3006a, +	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085, +	0x03a1008d, 0x036f0095, 0x033d009e, 0x030b00a8, +	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3, +	0x024900e0, 0x022900ed, 0x020a00fb, 0x01ec010a, +	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e, +	0x01720162, 0x015d0177, 0x0149018e, 0x013701a5, +	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212, +	0x00e90231, 0x00dc0253, 0x00d00276, 0x00c4029b, +	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348, +	0x0093037a, 0x008b03af, 0x008303e6, 0x007c0422, +	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533, +	0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c, +}; + +/************************************************** + * R/W ops. + **************************************************/ + +u32 b43_httab_read(struct b43_wldev *dev, u32 offset) +{ +	u32 type, value; + +	type = offset & B43_HTTAB_TYPEMASK; +	offset &= ~B43_HTTAB_TYPEMASK; +	B43_WARN_ON(offset > 0xFFFF); + +	switch (type) { +	case B43_HTTAB_8BIT: +		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); +		value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF; +		break; +	case B43_HTTAB_16BIT: +		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); +		value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO); +		break; +	case B43_HTTAB_32BIT: +		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); +		value = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI); +		value <<= 16; +		value |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO); +		break; +	default: +		B43_WARN_ON(1); +		value = 0; +	} + +	return value; +} + +void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset, +			 unsigned int nr_elements, void *_data) +{ +	u32 type; +	u8 *data = _data; +	unsigned int i; + +	type = offset & B43_HTTAB_TYPEMASK; +	offset &= ~B43_HTTAB_TYPEMASK; +	B43_WARN_ON(offset > 0xFFFF); + +	b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); + +	for (i = 0; i < nr_elements; i++) { +		switch (type) { +		case B43_HTTAB_8BIT: +			*data = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO) & 0xFF; +			data++; +			break; +		case B43_HTTAB_16BIT: +			*((u16 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO); +			data += 2; +			break; +		case B43_HTTAB_32BIT: +			*((u32 *)data) = b43_phy_read(dev, B43_PHY_HT_TABLE_DATAHI); +			*((u32 *)data) <<= 16; +			*((u32 *)data) |= b43_phy_read(dev, B43_PHY_HT_TABLE_DATALO); +			data += 4; +			break; +		default: +			B43_WARN_ON(1); +		} +	} +} + +void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value) +{ +	u32 type; + +	type = offset & B43_HTTAB_TYPEMASK; +	offset &= 0xFFFF; + +	switch (type) { +	case B43_HTTAB_8BIT: +		B43_WARN_ON(value & ~0xFF); +		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); +		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); +		break; +	case B43_HTTAB_16BIT: +		B43_WARN_ON(value & ~0xFFFF); +		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); +		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); +		break; +	case B43_HTTAB_32BIT: +		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); +		b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16); +		b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value & 0xFFFF); +		break; +	default: +		B43_WARN_ON(1); +	} + +	return; +} + +void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, +			  unsigned int nr_elements, const void *_data) +{ +	u32 type, value; +	const u8 *data = _data; +	unsigned int i; + +	type = offset & B43_HTTAB_TYPEMASK; +	offset &= ~B43_HTTAB_TYPEMASK; +	B43_WARN_ON(offset > 0xFFFF); + +	b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); + +	for (i = 0; i < nr_elements; i++) { +		switch (type) { +		case B43_HTTAB_8BIT: +			value = *data; +			data++; +			B43_WARN_ON(value & ~0xFF); +			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); +			break; +		case B43_HTTAB_16BIT: +			value = *((u16 *)data); +			data += 2; +			B43_WARN_ON(value & ~0xFFFF); +			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); +			break; +		case B43_HTTAB_32BIT: +			value = *((u32 *)data); +			data += 4; +			b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, value >> 16); +			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, +					value & 0xFFFF); +			break; +		default: +			B43_WARN_ON(1); +		} +	} +} + +/************************************************** + * Tables ops. + **************************************************/ + +#define httab_upload(dev, offset, data) do { \ +		b43_httab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \ +	} while (0) +void b43_phy_ht_tables_init(struct b43_wldev *dev) +{ +	httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12); +	httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27); +	httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26); +	httab_upload(dev, B43_HTTAB32(0x25, 0), b43_httab_0x25); +	httab_upload(dev, B43_HTTAB32(0x2f, 0), b43_httab_0x2f); +	httab_upload(dev, B43_HTTAB16(0x1a, 0), b43_httab_0x1a); +	httab_upload(dev, B43_HTTAB16(0x1b, 0), b43_httab_0x1b); +	httab_upload(dev, B43_HTTAB16(0x1c, 0), b43_httab_0x1c); +	httab_upload(dev, B43_HTTAB32(0x1a, 0x0c0), b43_httab_0x1a_0xc0); +	httab_upload(dev, B43_HTTAB32(0x1a, 0x140), b43_httab_0x1a_0x140); +	httab_upload(dev, B43_HTTAB32(0x1b, 0x140), b43_httab_0x1b_0x140); +	httab_upload(dev, B43_HTTAB32(0x1c, 0x140), b43_httab_0x1c_0x140); +	httab_upload(dev, B43_HTTAB16(0x1a, 0x1c0), b43_httab_0x1a_0x1c0); +	httab_upload(dev, B43_HTTAB16(0x1b, 0x1c0), b43_httab_0x1b_0x1c0); +	httab_upload(dev, B43_HTTAB16(0x1c, 0x1c0), b43_httab_0x1c_0x1c0); +	httab_upload(dev, B43_HTTAB16(0x1a, 0x240), b43_httab_0x1a_0x240); +	httab_upload(dev, B43_HTTAB16(0x1b, 0x240), b43_httab_0x1b_0x240); +	httab_upload(dev, B43_HTTAB16(0x1c, 0x240), b43_httab_0x1c_0x240); +	httab_upload(dev, B43_HTTAB32(0x1f, 0), b43_httab_0x1f); +	httab_upload(dev, B43_HTTAB32(0x21, 0), b43_httab_0x21); +	httab_upload(dev, B43_HTTAB32(0x23, 0), b43_httab_0x23); +	httab_upload(dev, B43_HTTAB32(0x20, 0), b43_httab_0x20); +	httab_upload(dev, B43_HTTAB32(0x22, 0), b43_httab_0x22); +	httab_upload(dev, B43_HTTAB32(0x24, 0), b43_httab_0x24); +} diff --git a/drivers/net/wireless/b43/tables_phy_ht.h b/drivers/net/wireless/b43/tables_phy_ht.h new file mode 100644 index 00000000000..ea3be382c89 --- /dev/null +++ b/drivers/net/wireless/b43/tables_phy_ht.h @@ -0,0 +1,22 @@ +#ifndef B43_TABLES_PHY_HT_H_ +#define B43_TABLES_PHY_HT_H_ + +/* The HT-PHY tables. */ +#define B43_HTTAB_TYPEMASK		0xF0000000 +#define B43_HTTAB_8BIT			0x10000000 +#define B43_HTTAB_16BIT			0x20000000 +#define B43_HTTAB_32BIT			0x30000000 +#define B43_HTTAB8(table, offset)	(((table) << 10) | (offset) | B43_HTTAB_8BIT) +#define B43_HTTAB16(table, offset)	(((table) << 10) | (offset) | B43_HTTAB_16BIT) +#define B43_HTTAB32(table, offset)	(((table) << 10) | (offset) | B43_HTTAB_32BIT) + +u32 b43_httab_read(struct b43_wldev *dev, u32 offset); +void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset, +			 unsigned int nr_elements, void *_data); +void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value); +void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, +			  unsigned int nr_elements, const void *_data); + +void b43_phy_ht_tables_init(struct b43_wldev *dev); + +#endif /* B43_TABLES_PHY_HT_H_ */ diff --git a/drivers/net/wireless/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c new file mode 100644 index 00000000000..40c1d0915dd --- /dev/null +++ b/drivers/net/wireless/b43/tables_phy_lcn.c @@ -0,0 +1,34 @@ +/* + +  Broadcom B43 wireless driver +  IEEE 802.11n LCN-PHY data tables + +  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. + +  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; see the file COPYING.  If not, write to +  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, +  Boston, MA 02110-1301, USA. + +*/ + +#include "b43.h" +#include "tables_phy_lcn.h" +#include "phy_common.h" +#include "phy_lcn.h" + +/************************************************** + * Tables ops. + **************************************************/ + +void b43_phy_lcn_tables_init(struct b43_wldev *dev) +{ +} diff --git a/drivers/net/wireless/b43/tables_phy_lcn.h b/drivers/net/wireless/b43/tables_phy_lcn.h new file mode 100644 index 00000000000..5e31b15b81e --- /dev/null +++ b/drivers/net/wireless/b43/tables_phy_lcn.h @@ -0,0 +1,6 @@ +#ifndef B43_TABLES_PHY_LCN_H_ +#define B43_TABLES_PHY_LCN_H_ + +void b43_phy_lcn_tables_init(struct b43_wldev *dev); + +#endif /* B43_TABLES_PHY_LCN_H_ */ diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c index 8f4db448ec3..5d00d0eaf2e 100644 --- a/drivers/net/wireless/b43/wa.c +++ b/drivers/net/wireless/b43/wa.c @@ -458,17 +458,15 @@ static void b43_wa_rssi_adc(struct b43_wldev *dev)  static void b43_wa_boards_a(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; - -	if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && -	    bus->boardinfo.type == SSB_BOARD_BU4306 && -	    bus->boardinfo.rev < 0x30) { +	if (dev->dev->board_vendor == SSB_BOARDVENDOR_BCM && +	    dev->dev->board_type == SSB_BOARD_BU4306 && +	    dev->dev->board_rev < 0x30) {  		b43_phy_write(dev, 0x0010, 0xE000);  		b43_phy_write(dev, 0x0013, 0x0140);  		b43_phy_write(dev, 0x0014, 0x0280);  	} else { -		if (bus->boardinfo.type == SSB_BOARD_MP4318 && -		    bus->boardinfo.rev < 0x20) { +		if (dev->dev->board_type == SSB_BOARD_MP4318 && +		    dev->dev->board_rev < 0x20) {  			b43_phy_write(dev, 0x0013, 0x0210);  			b43_phy_write(dev, 0x0014, 0x0840);  		} else { @@ -486,19 +484,19 @@ static void b43_wa_boards_a(struct b43_wldev *dev)  static void b43_wa_boards_g(struct b43_wldev *dev)  { -	struct ssb_bus *bus = dev->sdev->bus; +	struct ssb_sprom *sprom = dev->dev->bus_sprom;  	struct b43_phy *phy = &dev->phy; -	if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM || -	    bus->boardinfo.type != SSB_BOARD_BU4306 || -	    bus->boardinfo.rev != 0x17) { +	if (dev->dev->board_vendor != SSB_BOARDVENDOR_BCM || +	    dev->dev->board_type != SSB_BOARD_BU4306 || +	    dev->dev->board_rev != 0x17) {  		if (phy->rev < 2) {  			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 1, 0x0002);  			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 2, 0x0001);  		} else {  			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 1, 0x0002);  			b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001); -			if ((bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && +			if ((sprom->boardflags_lo & B43_BFL_EXTLNA) &&  			    (phy->rev >= 7)) {  				b43_phy_mask(dev, B43_PHY_EXTG(0x11), 0xF7FF);  				b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001); @@ -510,7 +508,7 @@ static void b43_wa_boards_g(struct b43_wldev *dev)  			}  		}  	} -	if (bus->sprom.boardflags_lo & B43_BFL_FEM) { +	if (sprom->boardflags_lo & B43_BFL_FEM) {  		b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120);  		b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480);  	} diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index c8f99aebe01..82bcf759513 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -323,8 +323,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,  			/* we give the phase1key and iv16 here, the key is stored in  			 * shm. With that the hardware can do phase 2 and encryption.  			 */ -			ieee80211_get_tkip_key(info->control.hw_key, skb_frag, -					IEEE80211_TKIP_P1_KEY, (u8*)phase1key); +			ieee80211_get_tkip_p1k(info->control.hw_key, skb_frag, phase1key);  			/* phase1key is in host endian. Copy to little-endian txhdr->iv. */  			for (i = 0; i < 5; i++) {  				txhdr->iv[i * 2 + 0] = phase1key[i]; @@ -547,7 +546,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,  			else  				tmp -= 3;  		} else { -			if (dev->sdev->bus->sprom. +			if (dev->dev->bus_sprom->  			    boardflags_lo & B43_BFL_RSSI) {  				if (in_rssi > 63)  					in_rssi = 63; diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index e03e01d0bc3..c33934ad6cd 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -817,14 +817,13 @@ static void dmacontroller_cleanup(struct b43legacy_dmaring *ring)  static void free_all_descbuffers(struct b43legacy_dmaring *ring)  { -	struct b43legacy_dmadesc_generic *desc;  	struct b43legacy_dmadesc_meta *meta;  	int i;  	if (!ring->used_slots)  		return;  	for (i = 0; i < ring->nr_slots; i++) { -		desc = ring->ops->idx2desc(ring, i, &meta); +		ring->ops->idx2desc(ring, i, &meta);  		if (!meta->skb) {  			B43legacy_WARN_ON(!ring->tx); @@ -1371,10 +1370,8 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,  		     struct sk_buff *skb)  {  	struct b43legacy_dmaring *ring; -	struct ieee80211_hdr *hdr;  	int err = 0;  	unsigned long flags; -	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);  	ring = priority_to_txring(dev, skb_get_queue_mapping(skb));  	spin_lock_irqsave(&ring->lock, flags); @@ -1401,8 +1398,6 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,  	/* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing  	 * into the skb data or cb now. */ -	hdr = NULL; -	info = NULL;  	err = dma_tx_fragment(ring, &skb);  	if (unlikely(err == -ENOKEY)) {  		/* Drop this packet, as we don't have the encryption key @@ -1435,7 +1430,6 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,  {  	const struct b43legacy_dma_ops *ops;  	struct b43legacy_dmaring *ring; -	struct b43legacy_dmadesc_generic *desc;  	struct b43legacy_dmadesc_meta *meta;  	int retry_limit;  	int slot; @@ -1450,7 +1444,7 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,  	ops = ring->ops;  	while (1) {  		B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); -		desc = ops->idx2desc(ring, slot, &meta); +		ops->idx2desc(ring, slot, &meta);  		if (meta->skb)  			unmap_descbuffer(ring, meta->dmaaddr, diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1ab8861dd43..d6db6c17da4 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1564,10 +1564,10 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)  	struct b43legacy_firmware *fw = &dev->fw;  	const u8 rev = dev->dev->id.revision;  	const char *filename; -	u32 tmshigh;  	int err; -	tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); +	/* do dummy read */ +	ssb_read32(dev->dev, SSB_TMSHIGH);  	if (!fw->ucode) {  		if (rev == 2)  			filename = "ucode2"; @@ -2634,11 +2634,9 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,  	unsigned long flags;  	unsigned int new_phymode = 0xFFFF;  	int antenna_tx; -	int antenna_rx;  	int err = 0;  	antenna_tx = B43legacy_ANTENNA_DEFAULT; -	antenna_rx = B43legacy_ANTENNA_DEFAULT;  	mutex_lock(&wl->mutex);  	dev = wl->current_dev; @@ -2775,14 +2773,12 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,  {  	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);  	struct b43legacy_wldev *dev; -	struct b43legacy_phy *phy;  	unsigned long flags;  	mutex_lock(&wl->mutex);  	B43legacy_WARN_ON(wl->vif != vif);  	dev = wl->current_dev; -	phy = &dev->phy;  	/* Disable IRQs while reconfiguring the device.  	 * This makes it possible to drop the spinlock throughout @@ -2974,7 +2970,7 @@ static int b43legacy_phy_versioning(struct b43legacy_wldev *dev)  		break;  	default:  		unsupported = 1; -	}; +	}  	if (unsupported) {  		b43legacyerr(dev->wl, "FOUND UNSUPPORTED PHY "  		       "(Analog %u, Type %u, Revision %u)\n", diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 3a95541708a..6c174f38ca3 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -321,11 +321,9 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,  		struct ieee80211_hdr *hdr;  		int rts_rate;  		int rts_rate_fb; -		int rts_rate_ofdm;  		int rts_rate_fb_ofdm;  		rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value; -		rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);  		rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);  		rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);  		if (rts_rate_fb_ofdm) diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index 88dc6a52bdf..7bb0b4b3f2c 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h @@ -1,6 +1,7 @@  #ifndef HOSTAP_WLAN_H  #define HOSTAP_WLAN_H +#include <linux/interrupt.h>  #include <linux/wireless.h>  #include <linux/netdevice.h>  #include <linux/mutex.h> diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 44307753587..3774dd03474 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -287,7 +287,7 @@ static const char *command_types[] = {  	"unused",		/* HOST_INTERRUPT_COALESCING */  	"undefined",  	"CARD_DISABLE_PHY_OFF", -	"MSDU_TX_RATES" "undefined", +	"MSDU_TX_RATES",  	"undefined",  	"SET_STATION_STAT_BITS",  	"CLEAR_STATIONS_STAT_BITS", diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h index 91795b5a93c..ecb561d7a7a 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.h +++ b/drivers/net/wireless/ipw2x00/ipw2200.h @@ -32,6 +32,7 @@  #include <linux/module.h>  #include <linux/moduleparam.h>  #include <linux/init.h> +#include <linux/interrupt.h>  #include <linux/mutex.h>  #include <linux/pci.h> diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index e5ad76cd77d..32a9966c3bf 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c @@ -442,7 +442,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,  		 * 802.11, but makes it easier to use different keys with  		 * stations that do not support WEP key mapping). */ -		if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) +		if (is_unicast_ether_addr(hdr->addr1) || local->bcrx_sta_key)  			(void)hostap_handle_sta_crypto(local, hdr, &crypt,  						       &sta);  #endif @@ -772,7 +772,7 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb,  #ifdef NOT_YET  	if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) { -		if (dst[0] & 0x01) { +		if (is_multicast_ether_addr(dst)) {  			/* copy multicast frame both to the higher layers and  			 * to the wireless media */  			ieee->ap->bridged_multicast++; diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c index d7bd6cf00a8..6623e505225 100644 --- a/drivers/net/wireless/ipw2x00/libipw_wx.c +++ b/drivers/net/wireless/ipw2x00/libipw_wx.c @@ -30,6 +30,7 @@  ******************************************************************************/ +#include <linux/hardirq.h>  #include <linux/kmod.h>  #include <linux/slab.h>  #include <linux/module.h> diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c index d096dc28204..dab67a12d73 100644 --- a/drivers/net/wireless/iwlegacy/iwl-3945.c +++ b/drivers/net/wireless/iwlegacy/iwl-3945.c @@ -408,7 +408,6 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv,  #ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS  	iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);  #endif -	iwl_legacy_recover_from_statistics(priv, pkt);  	memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));  } @@ -2640,7 +2639,6 @@ static struct iwl_lib_ops iwl3945_lib = {  	.txq_free_tfd = iwl3945_hw_txq_free_tfd,  	.txq_init = iwl3945_hw_tx_queue_init,  	.load_ucode = iwl3945_load_bsm, -	.dump_nic_event_log = iwl3945_dump_nic_event_log,  	.dump_nic_error_log = iwl3945_dump_nic_error_log,  	.apm_ops = {  		.init = iwl3945_apm_init, @@ -2698,9 +2696,7 @@ static struct iwl_base_params iwl3945_base_params = {  	.set_l0s = false,  	.use_bsm = true,  	.led_compensation = 64, -	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,  	.wd_timeout = IWL_DEF_WD_TIMEOUT, -	.max_event_log_size = 512,  };  static struct iwl_cfg iwl3945_bg_cfg = { diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c index a7a4739880d..2be6d9e3b01 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c @@ -694,47 +694,6 @@ void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,  	       sizeof(struct iwl_rx_phy_res));  } -static int iwl4965_get_single_channel_for_scan(struct iwl_priv *priv, -					   struct ieee80211_vif *vif, -					   enum ieee80211_band band, -					   struct iwl_scan_channel *scan_ch) -{ -	const struct ieee80211_supported_band *sband; -	u16 passive_dwell = 0; -	u16 active_dwell = 0; -	int 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_legacy_get_active_dwell_time(priv, band, 0); -	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif); - -	if (passive_dwell <= active_dwell) -		passive_dwell = active_dwell + 1; - -	channel = iwl_legacy_get_single_channel_number(priv, band); -	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 iwl4965_get_channels_for_scan(struct iwl_priv *priv,  				     struct ieee80211_vif *vif,  				     enum ieee80211_band band, @@ -858,16 +817,13 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)  	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;  	if (iwl_legacy_is_any_associated(priv)) { -		u16 interval = 0; +		u16 interval;  		u32 extra;  		u32 suspend_time = 100;  		u32 scan_suspend_time = 100;  		IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); -		if (priv->is_internal_short_scan) -			interval = 0; -		else -			interval = vif->bss_conf.beacon_int; +		interval = vif->bss_conf.beacon_int;  		scan->suspend_time = 0;  		scan->max_out_time = cpu_to_le32(200 * 1024); @@ -882,9 +838,7 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)  			       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) { +	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++) { @@ -981,38 +935,21 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)  	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_legacy_fill_probe_req(priv, + +	cmd_len = iwl_legacy_fill_probe_req(priv,  					(struct ieee80211_mgmt *)scan->data,  					vif->addr,  					priv->scan_request->ie,  					priv->scan_request->ie_len,  					IWL_MAX_SCAN_SIZE - sizeof(*scan)); -	} else { -		/* use bcast addr, will not be transmitted but must be valid */ -		cmd_len = iwl_legacy_fill_probe_req(priv, -					(struct ieee80211_mgmt *)scan->data, -					iwlegacy_bcast_addr, 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 = -			iwl4965_get_single_channel_for_scan(priv, vif, band, -				(void *)&scan->data[le16_to_cpu( -				scan->tx_cmd.len)]); -	} else { -		scan->channel_count = -			iwl4965_get_channels_for_scan(priv, vif, band, -				is_active, n_probes, -				(void *)&scan->data[le16_to_cpu( -				scan->tx_cmd.len)]); -	} +	scan->channel_count = iwl4965_get_channels_for_scan(priv, vif, band, +						is_active, n_probes, +						(void *)&scan->data[cmd_len]);  	if (scan->channel_count == 0) {  		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);  		return -EIO; diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c index 24d149909ba..9b65153bdd0 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c @@ -2275,6 +2275,9 @@ iwl4965_rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,  	if (rate_control_send_low(sta, priv_sta, txrc))  		return; +	if (!lq_sta) +		return; +  	rate_idx  = lq_sta->last_txrate_idx;  	if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c index b9fa2f6411a..2b144bbfc3c 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c @@ -151,81 +151,6 @@ static void iwl4965_accumulative_statistics(struct iwl_priv *priv,  #define REG_RECALIB_PERIOD (60) -/** - * iwl4965_good_plcp_health - checks for plcp error. - * - * When the plcp error is exceeding the thresholds, reset the radio - * to improve the throughput. - */ -bool iwl4965_good_plcp_health(struct iwl_priv *priv, -				struct iwl_rx_packet *pkt) -{ -	bool rc = true; -	int combined_plcp_delta; -	unsigned int plcp_msec; -	unsigned long plcp_received_jiffies; - -	if (priv->cfg->base_params->plcp_delta_threshold == -	    IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) { -		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n"); -		return rc; -	} - -	/* -	 * check for plcp_err and trigger radio reset if it exceeds -	 * the plcp error threshold plcp_delta. -	 */ -	plcp_received_jiffies = jiffies; -	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies - -					(long) priv->plcp_jiffies); -	priv->plcp_jiffies = plcp_received_jiffies; -	/* -	 * check to make sure plcp_msec is not 0 to prevent division -	 * by zero. -	 */ -	if (plcp_msec) { -		struct statistics_rx_phy *ofdm; -		struct statistics_rx_ht_phy *ofdm_ht; - -		ofdm = &pkt->u.stats.rx.ofdm; -		ofdm_ht = &pkt->u.stats.rx.ofdm_ht; -		combined_plcp_delta = -		    (le32_to_cpu(ofdm->plcp_err) - -		    le32_to_cpu(priv->_4965.statistics. -				rx.ofdm.plcp_err)) + -		    (le32_to_cpu(ofdm_ht->plcp_err) - -		    le32_to_cpu(priv->_4965.statistics. -				rx.ofdm_ht.plcp_err)); - -		if ((combined_plcp_delta > 0) && -		    ((combined_plcp_delta * 100) / plcp_msec) > -			priv->cfg->base_params->plcp_delta_threshold) { -			/* -			 * if plcp_err exceed the threshold, -			 * the following data is printed in csv format: -			 *    Text: plcp_err exceeded %d, -			 *    Received ofdm.plcp_err, -			 *    Current ofdm.plcp_err, -			 *    Received ofdm_ht.plcp_err, -			 *    Current ofdm_ht.plcp_err, -			 *    combined_plcp_delta, -			 *    plcp_msec -			 */ -			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " -				"%u, %u, %u, %u, %d, %u mSecs\n", -				priv->cfg->base_params->plcp_delta_threshold, -				le32_to_cpu(ofdm->plcp_err), -				le32_to_cpu(ofdm->plcp_err), -				le32_to_cpu(ofdm_ht->plcp_err), -				le32_to_cpu(ofdm_ht->plcp_err), -				combined_plcp_delta, plcp_msec); - -			rc = false; -		} -	} -	return rc; -} -  void iwl4965_rx_statistics(struct iwl_priv *priv,  			      struct iwl_rx_mem_buffer *rxb)  { @@ -248,8 +173,7 @@ void iwl4965_rx_statistics(struct iwl_priv *priv,  	iwl4965_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);  #endif -	iwl_legacy_recover_from_statistics(priv, pkt); - +	/* TODO: reading some of statistics is unneeded */  	memcpy(&priv->_4965.statistics, &pkt->u.stats,  		sizeof(priv->_4965.statistics)); diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c index 79ac081832f..ac4f64de136 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c @@ -240,8 +240,7 @@ static void iwl4965_tx_cmd_build_hwcrypto(struct iwl_priv *priv,  	case WLAN_CIPHER_SUITE_TKIP:  		tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; -		ieee80211_get_tkip_key(keyconf, skb_frag, -			IEEE80211_TKIP_P2_KEY, tx_cmd->key); +		ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);  		IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");  		break; diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c index facc94e74b0..bd4b000733f 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965.c @@ -496,7 +496,7 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel)  	    channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)  		return CALIB_CH_GROUP_4; -	return -1; +	return -EINVAL;  }  static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel) @@ -915,7 +915,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,  	if (txatten_grp < 0) {  		IWL_ERR(priv, "Can't find txatten group for channel %d.\n",  			  channel); -		return -EINVAL; +		return txatten_grp;  	}  	IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n", @@ -1185,8 +1185,6 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,  	ret = iwl_legacy_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,  				     sizeof(rxon_assoc), &rxon_assoc, NULL); -	if (ret) -		return ret;  	return ret;  } @@ -2071,7 +2069,6 @@ static struct iwl_lib_ops iwl4965_lib = {  	.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,  	.init_alive_start = iwl4965_init_alive_start,  	.load_ucode = iwl4965_load_bsm, -	.dump_nic_event_log = iwl4965_dump_nic_event_log,  	.dump_nic_error_log = iwl4965_dump_nic_error_log,  	.dump_fh = iwl4965_dump_fh,  	.set_channel_switch = iwl4965_hw_channel_switch, @@ -2102,7 +2099,6 @@ static struct iwl_lib_ops iwl4965_lib = {  		.tx_stats_read = iwl4965_ucode_tx_stats_read,  		.general_stats_read = iwl4965_ucode_general_stats_read,  	}, -	.check_plcp_health = iwl4965_good_plcp_health,  };  static const struct iwl_legacy_ops iwl4965_legacy_ops = { @@ -2152,10 +2148,8 @@ static struct iwl_base_params iwl4965_base_params = {  	.use_bsm = true,  	.led_compensation = 61,  	.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, -	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,  	.wd_timeout = IWL_DEF_WD_TIMEOUT,  	.temperature_kelvin = true, -	.max_event_log_size = 512,  	.ucode_tracing = true,  	.sensitivity_calib_by_driver = true,  	.chain_noise_calib_by_driver = true, diff --git a/drivers/net/wireless/iwlegacy/iwl-commands.h b/drivers/net/wireless/iwlegacy/iwl-commands.h index 17a1d504348..ee21210bea9 100644 --- a/drivers/net/wireless/iwlegacy/iwl-commands.h +++ b/drivers/net/wireless/iwlegacy/iwl-commands.h @@ -2297,14 +2297,7 @@ struct iwl_spectrum_notification {  #define IWL_POWER_VEC_SIZE 5  #define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK	cpu_to_le16(BIT(0)) -#define IWL_POWER_POWER_SAVE_ENA_MSK		cpu_to_le16(BIT(0)) -#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK	cpu_to_le16(BIT(1)) -#define IWL_POWER_SLEEP_OVER_DTIM_MSK		cpu_to_le16(BIT(2))  #define IWL_POWER_PCI_PM_MSK			cpu_to_le16(BIT(3)) -#define IWL_POWER_FAST_PD			cpu_to_le16(BIT(4)) -#define IWL_POWER_BEACON_FILTERING		cpu_to_le16(BIT(5)) -#define IWL_POWER_SHADOW_REG_ENA		cpu_to_le16(BIT(6)) -#define IWL_POWER_CT_KILL_SET			cpu_to_le16(BIT(7))  struct iwl3945_powertable_cmd {  	__le16 flags; diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index 3be76bd5499..35cd2537e7f 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c @@ -931,7 +931,6 @@ void iwl_legacy_irq_handle_error(struct iwl_priv *priv)  	priv->cfg->ops->lib->dump_nic_error_log(priv);  	if (priv->cfg->ops->lib->dump_fh)  		priv->cfg->ops->lib->dump_fh(priv, NULL, false); -	priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);  #ifdef CONFIG_IWLWIFI_LEGACY_DEBUG  	if (iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS)  		iwl_legacy_print_rx_config_cmd(priv, @@ -1707,41 +1706,14 @@ iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)  EXPORT_SYMBOL(iwl_legacy_update_stats);  #endif -static void _iwl_legacy_force_rf_reset(struct iwl_priv *priv) -{ -	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -		return; - -	if (!iwl_legacy_is_any_associated(priv)) { -		IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n"); -		return; -	} -	/* -	 * There is no easy and better way to force reset the radio, -	 * the only known method is switching channel which will force to -	 * reset and tune the radio. -	 * Use internal short scan (single channel) operation to should -	 * achieve this objective. -	 * Driver should reset the radio when number of consecutive missed -	 * beacon, or any other uCode error condition detected. -	 */ -	IWL_DEBUG_INFO(priv, "perform radio reset.\n"); -	iwl_legacy_internal_short_hw_scan(priv); -} - - -int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external) +int iwl_legacy_force_reset(struct iwl_priv *priv, bool external)  {  	struct iwl_force_reset *force_reset;  	if (test_bit(STATUS_EXIT_PENDING, &priv->status))  		return -EINVAL; -	if (mode >= IWL_MAX_FORCE_RESET) { -		IWL_DEBUG_INFO(priv, "invalid reset request.\n"); -		return -EINVAL; -	} -	force_reset = &priv->force_reset[mode]; +	force_reset = &priv->force_reset;  	force_reset->reset_request_count++;  	if (!external) {  		if (force_reset->last_force_reset_jiffies && @@ -1754,37 +1726,34 @@ int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)  	}  	force_reset->reset_success_count++;  	force_reset->last_force_reset_jiffies = jiffies; -	IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode); -	switch (mode) { -	case IWL_RF_RESET: -		_iwl_legacy_force_rf_reset(priv); -		break; -	case IWL_FW_RESET: -		/* -		 * if the request is from external(ex: debugfs), -		 * then always perform the request in regardless the module -		 * parameter setting -		 * if the request is from internal (uCode error or driver -		 * detect failure), then fw_restart module parameter -		 * need to be check before performing firmware reload -		 */ -		if (!external && !priv->cfg->mod_params->restart_fw) { -			IWL_DEBUG_INFO(priv, "Cancel firmware reload based on " -				       "module parameter setting\n"); -			break; -		} -		IWL_ERR(priv, "On demand firmware reload\n"); -		/* Set the FW error flag -- cleared on iwl_down */ -		set_bit(STATUS_FW_ERROR, &priv->status); -		wake_up_interruptible(&priv->wait_command_queue); -		/* -		 * Keep the restart process from trying to send host -		 * commands by clearing the INIT status bit -		 */ -		clear_bit(STATUS_READY, &priv->status); -		queue_work(priv->workqueue, &priv->restart); -		break; + +	/* +	 * if the request is from external(ex: debugfs), +	 * then always perform the request in regardless the module +	 * parameter setting +	 * if the request is from internal (uCode error or driver +	 * detect failure), then fw_restart module parameter +	 * need to be check before performing firmware reload +	 */ + +	if (!external && !priv->cfg->mod_params->restart_fw) { +		IWL_DEBUG_INFO(priv, "Cancel firmware reload based on " +			       "module parameter setting\n"); +		return 0;  	} + +	IWL_ERR(priv, "On demand firmware reload\n"); + +	/* Set the FW error flag -- cleared on iwl_down */ +	set_bit(STATUS_FW_ERROR, &priv->status); +	wake_up_interruptible(&priv->wait_command_queue); +	/* +	 * Keep the restart process from trying to send host +	 * commands by clearing the INIT status bit +	 */ +	clear_bit(STATUS_READY, &priv->status); +	queue_work(priv->workqueue, &priv->restart); +  	return 0;  } @@ -1879,7 +1848,7 @@ static int iwl_legacy_check_stuck_queue(struct iwl_priv *priv, int cnt)  	if (time_after(jiffies, timeout)) {  		IWL_ERR(priv, "Queue %d stuck for %u ms.\n",  				q->id, priv->cfg->base_params->wd_timeout); -		ret = iwl_legacy_force_reset(priv, IWL_FW_RESET, false); +		ret = iwl_legacy_force_reset(priv, false);  		return (ret == -EAGAIN) ? 0 : 1;  	} diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h index c5fbda0760d..84da79376ef 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.h +++ b/drivers/net/wireless/iwlegacy/iwl-core.h @@ -143,8 +143,7 @@ struct iwl_lib_ops {  	int (*is_valid_rtc_data_addr)(u32 addr);  	/* 1st ucode load */  	int (*load_ucode)(struct iwl_priv *priv); -	int (*dump_nic_event_log)(struct iwl_priv *priv, -				  bool full_log, char **buf, bool display); +  	void (*dump_nic_error_log)(struct iwl_priv *priv);  	int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);  	int (*set_channel_switch)(struct iwl_priv *priv, @@ -161,9 +160,6 @@ struct iwl_lib_ops {  	/* temperature */  	struct iwl_temp_ops temp_ops; -	/* check for plcp health */ -	bool (*check_plcp_health)(struct iwl_priv *priv, -					struct iwl_rx_packet *pkt);  	struct iwl_debugfs_ops debugfs_ops; @@ -207,11 +203,8 @@ struct iwl_mod_params {   *	to the deviation to achieve the desired led frequency.   *	The detail algorithm is described in iwl-led.c   * @chain_noise_num_beacons: number of beacons used to compute chain noise - * @plcp_delta_threshold: plcp error rate threshold used to trigger - *	radio tuning when there is a high receiving plcp error rate   * @wd_timeout: TX queues watchdog timeout   * @temperature_kelvin: temperature report by uCode in kelvin - * @max_event_log_size: size of event log buffer size for ucode event logging   * @ucode_tracing: support ucode continuous tracing   * @sensitivity_calib_by_driver: driver has the capability to perform   *	sensitivity calibration operation @@ -229,10 +222,8 @@ struct iwl_base_params {  	u16 led_compensation;  	int chain_noise_num_beacons; -	u8 plcp_delta_threshold;  	unsigned int wd_timeout;  	bool temperature_kelvin; -	u32 max_event_log_size;  	const bool ucode_tracing;  	const bool sensitivity_calib_by_driver;  	const bool chain_noise_calib_by_driver; @@ -441,7 +432,7 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,  		    struct ieee80211_vif *vif,  		    struct cfg80211_scan_request *req);  void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv); -int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external); +int iwl_legacy_force_reset(struct iwl_priv *priv, bool external);  u16 iwl_legacy_fill_probe_req(struct iwl_priv *priv,  			struct ieee80211_mgmt *frame,  		       const u8 *ta, const u8 *ie, int ie_len, int left); @@ -493,7 +484,7 @@ static inline u16 iwl_legacy_pcie_link_ctl(struct iwl_priv *priv)  {  	int pos;  	u16 pci_lnk_ctl; -	pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP); +	pos = pci_pcie_cap(priv->pci_dev);  	pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);  	return pci_lnk_ctl;  } @@ -521,8 +512,6 @@ extern const struct dev_pm_ops iwl_legacy_pm_ops;  *  Error Handling Debugging  ******************************************************/  void iwl4965_dump_nic_error_log(struct iwl_priv *priv); -int iwl4965_dump_nic_event_log(struct iwl_priv *priv, -			   bool full_log, char **buf, bool display);  #ifdef CONFIG_IWLWIFI_LEGACY_DEBUG  void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,  			     struct iwl_rxon_context *ctx); diff --git a/drivers/net/wireless/iwlegacy/iwl-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-debugfs.c index 2d32438b4cb..996996a7165 100644 --- a/drivers/net/wireless/iwlegacy/iwl-debugfs.c +++ b/drivers/net/wireless/iwlegacy/iwl-debugfs.c @@ -391,48 +391,6 @@ static ssize_t iwl_legacy_dbgfs_nvm_read(struct file *file,  	return ret;  } -static ssize_t iwl_legacy_dbgfs_log_event_read(struct file *file, -					 char __user *user_buf, -					 size_t count, loff_t *ppos) -{ -	struct iwl_priv *priv = file->private_data; -	char *buf; -	int pos = 0; -	ssize_t ret = -ENOMEM; - -	ret = pos = priv->cfg->ops->lib->dump_nic_event_log( -					priv, true, &buf, true); -	if (buf) { -		ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); -		kfree(buf); -	} -	return ret; -} - -static ssize_t iwl_legacy_dbgfs_log_event_write(struct file *file, -					const char __user *user_buf, -					size_t count, loff_t *ppos) -{ -	struct iwl_priv *priv = file->private_data; -	u32 event_log_flag; -	char buf[8]; -	int buf_size; - -	memset(buf, 0, sizeof(buf)); -	buf_size = min(count, sizeof(buf) -  1); -	if (copy_from_user(buf, user_buf, buf_size)) -		return -EFAULT; -	if (sscanf(buf, "%d", &event_log_flag) != 1) -		return -EFAULT; -	if (event_log_flag == 1) -		priv->cfg->ops->lib->dump_nic_event_log(priv, true, -							NULL, false); - -	return count; -} - - -  static ssize_t  iwl_legacy_dbgfs_channels_read(struct file *file, char __user *user_buf,  				       size_t count, loff_t *ppos) @@ -706,7 +664,6 @@ static ssize_t iwl_legacy_dbgfs_disable_ht40_read(struct file *file,  }  DEBUGFS_READ_WRITE_FILE_OPS(sram); -DEBUGFS_READ_WRITE_FILE_OPS(log_event);  DEBUGFS_READ_FILE_OPS(nvm);  DEBUGFS_READ_FILE_OPS(stations);  DEBUGFS_READ_FILE_OPS(channels); @@ -1098,56 +1055,6 @@ static ssize_t iwl_legacy_dbgfs_clear_ucode_statistics_write(struct file *file,  	return count;  } -static ssize_t iwl_legacy_dbgfs_ucode_tracing_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[128]; -	const size_t bufsz = sizeof(buf); - -	pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n", -			priv->event_log.ucode_trace ? "On" : "Off"); -	pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n", -			priv->event_log.non_wraps_count); -	pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n", -			priv->event_log.wraps_once_count); -	pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n", -			priv->event_log.wraps_more_count); - -	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_legacy_dbgfs_ucode_tracing_write(struct file *file, -					 const char __user *user_buf, -					 size_t count, loff_t *ppos) -{ -	struct iwl_priv *priv = file->private_data; -	char buf[8]; -	int buf_size; -	int trace; - -	memset(buf, 0, sizeof(buf)); -	buf_size = min(count, sizeof(buf) -  1); -	if (copy_from_user(buf, user_buf, buf_size)) -		return -EFAULT; -	if (sscanf(buf, "%d", &trace) != 1) -		return -EFAULT; - -	if (trace) { -		priv->event_log.ucode_trace = true; -		/* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */ -		mod_timer(&priv->ucode_trace, -			jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); -	} else { -		priv->event_log.ucode_trace = false; -		del_timer_sync(&priv->ucode_trace); -	} - -	return count; -} -  static ssize_t iwl_legacy_dbgfs_rxon_flags_read(struct file *file,  					 char __user *user_buf,  					 size_t count, loff_t *ppos) { @@ -1236,72 +1143,31 @@ static ssize_t iwl_legacy_dbgfs_missed_beacon_write(struct file *file,  	return count;  } -static ssize_t iwl_legacy_dbgfs_plcp_delta_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[12]; -	const size_t bufsz = sizeof(buf); - -	pos += scnprintf(buf + pos, bufsz - pos, "%u\n", -			priv->cfg->base_params->plcp_delta_threshold); - -	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_legacy_dbgfs_plcp_delta_write(struct file *file, -					const char __user *user_buf, -					size_t count, loff_t *ppos) { - -	struct iwl_priv *priv = file->private_data; -	char buf[8]; -	int buf_size; -	int plcp; - -	memset(buf, 0, sizeof(buf)); -	buf_size = min(count, sizeof(buf) -  1); -	if (copy_from_user(buf, user_buf, buf_size)) -		return -EFAULT; -	if (sscanf(buf, "%d", &plcp) != 1) -		return -EINVAL; -	if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || -		(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) -		priv->cfg->base_params->plcp_delta_threshold = -			IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE; -	else -		priv->cfg->base_params->plcp_delta_threshold = plcp; -	return count; -} -  static ssize_t iwl_legacy_dbgfs_force_reset_read(struct file *file,  					char __user *user_buf,  					size_t count, loff_t *ppos) {  	struct iwl_priv *priv = file->private_data; -	int i, pos = 0; +	int pos = 0;  	char buf[300];  	const size_t bufsz = sizeof(buf);  	struct iwl_force_reset *force_reset; -	for (i = 0; i < IWL_MAX_FORCE_RESET; i++) { -		force_reset = &priv->force_reset[i]; -		pos += scnprintf(buf + pos, bufsz - pos, -				"Force reset method %d\n", i); -		pos += scnprintf(buf + pos, bufsz - pos, -				"\tnumber of reset request: %d\n", -				force_reset->reset_request_count); -		pos += scnprintf(buf + pos, bufsz - pos, -				"\tnumber of reset request success: %d\n", -				force_reset->reset_success_count); -		pos += scnprintf(buf + pos, bufsz - pos, -				"\tnumber of reset request reject: %d\n", -				force_reset->reset_reject_count); -		pos += scnprintf(buf + pos, bufsz - pos, -				"\treset duration: %lu\n", -				force_reset->reset_duration); -	} +	force_reset = &priv->force_reset; + +	pos += scnprintf(buf + pos, bufsz - pos, +			"\tnumber of reset request: %d\n", +			force_reset->reset_request_count); +	pos += scnprintf(buf + pos, bufsz - pos, +			"\tnumber of reset request success: %d\n", +			force_reset->reset_success_count); +	pos += scnprintf(buf + pos, bufsz - pos, +			"\tnumber of reset request reject: %d\n", +			force_reset->reset_reject_count); +	pos += scnprintf(buf + pos, bufsz - pos, +			"\treset duration: %lu\n", +			force_reset->reset_duration); +  	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);  } @@ -1309,25 +1175,11 @@ static ssize_t iwl_legacy_dbgfs_force_reset_write(struct file *file,  					const char __user *user_buf,  					size_t count, loff_t *ppos) { +	int ret;  	struct iwl_priv *priv = file->private_data; -	char buf[8]; -	int buf_size; -	int reset, ret; -	memset(buf, 0, sizeof(buf)); -	buf_size = min(count, sizeof(buf) -  1); -	if (copy_from_user(buf, user_buf, buf_size)) -		return -EFAULT; -	if (sscanf(buf, "%d", &reset) != 1) -		return -EINVAL; -	switch (reset) { -	case IWL_RF_RESET: -	case IWL_FW_RESET: -		ret = iwl_legacy_force_reset(priv, reset, true); -		break; -	default: -		return -EINVAL; -	} +	ret = iwl_legacy_force_reset(priv, true); +  	return ret ? ret : count;  } @@ -1367,10 +1219,8 @@ DEBUGFS_READ_FILE_OPS(chain_noise);  DEBUGFS_READ_FILE_OPS(power_save_status);  DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);  DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); -DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);  DEBUGFS_READ_FILE_OPS(fh_reg);  DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon); -DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);  DEBUGFS_READ_WRITE_FILE_OPS(force_reset);  DEBUGFS_READ_FILE_OPS(rxon_flags);  DEBUGFS_READ_FILE_OPS(rxon_filter_flags); @@ -1403,7 +1253,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)  	DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);  	DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR); -	DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);  	DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);  	DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);  	DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); @@ -1420,7 +1269,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)  	DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);  	DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);  	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); @@ -1430,8 +1278,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)  		DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);  	if (priv->cfg->base_params->chain_noise_calib_by_driver)  		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); -	if (priv->cfg->base_params->ucode_tracing) -		DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);  	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);  	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);  	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h index ea30122669e..9c786edf56f 100644 --- a/drivers/net/wireless/iwlegacy/iwl-dev.h +++ b/drivers/net/wireless/iwlegacy/iwl-dev.h @@ -32,6 +32,7 @@  #ifndef __iwl_legacy_dev_h__  #define __iwl_legacy_dev_h__ +#include <linux/interrupt.h>  #include <linux/pci.h> /* for struct pci_device_id */  #include <linux/kernel.h>  #include <linux/leds.h> @@ -855,32 +856,6 @@ struct traffic_stats {  };  /* - * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds - * to perform continuous uCode event logging operation if enabled - */ -#define UCODE_TRACE_PERIOD (100) - -/* - * iwl_event_log: current uCode event log position - * - * @ucode_trace: enable/disable ucode continuous trace timer - * @num_wraps: how many times the event buffer wraps - * @next_entry:  the entry just before the next one that uCode would fill - * @non_wraps_count: counter for no wrap detected when dump ucode events - * @wraps_once_count: counter for wrap once detected when dump ucode events - * @wraps_more_count: counter for wrap more than once detected - *		      when dump ucode events - */ -struct iwl_event_log { -	bool ucode_trace; -	u32 num_wraps; -	u32 next_entry; -	int non_wraps_count; -	int wraps_once_count; -	int wraps_more_count; -}; - -/*   * host interrupt timeout value   * used with setting interrupt coalescing timer   * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit @@ -895,18 +870,6 @@ struct iwl_event_log {  #define IWL_HOST_INT_CALIB_TIMEOUT_DEF	(0x10)  #define IWL_HOST_INT_CALIB_TIMEOUT_MIN	(0x0) -/* - * This is the threshold value of plcp error rate per 100mSecs.  It is - * used to set and check for the validity of plcp_delta. - */ -#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN	(1) -#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF	(50) -#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF	(100) -#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF	(200) -#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX	(255) -#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE	(0) - -#define IWL_DELAY_NEXT_FORCE_RF_RESET  (HZ*3)  #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)  /* TX queue watchdog timeouts in mSecs */ @@ -914,12 +877,6 @@ struct iwl_event_log {  #define IWL_LONG_WD_TIMEOUT	(10000)  #define IWL_MAX_WD_TIMEOUT	(120000) -enum iwl_reset { -	IWL_RF_RESET = 0, -	IWL_FW_RESET, -	IWL_MAX_FORCE_RESET, -}; -  struct iwl_force_reset {  	int reset_request_count;  	int reset_success_count; @@ -1032,11 +989,8 @@ struct iwl_priv {  	/* track IBSS manager (last beacon) status */  	u32 ibss_manager; -	/* storing the jiffies when the plcp error rate is received */ -	unsigned long plcp_jiffies; -  	/* force reset */ -	struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET]; +	struct iwl_force_reset force_reset;  	/* we allocate array of iwl_channel_info for NIC's valid channels.  	 *    Access via channel # using indirect index array */ @@ -1057,7 +1011,6 @@ struct iwl_priv {  	enum ieee80211_band scan_band;  	struct cfg80211_scan_request *scan_request;  	struct ieee80211_vif *scan_vif; -	bool is_internal_short_scan;  	u8 scan_tx_ant[IEEE80211_NUM_BANDS];  	u8 mgmt_tx_ant; @@ -1212,12 +1165,6 @@ struct iwl_priv {  #endif  #if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)  		struct { -			/* -			 * reporting the number of tids has AGG on. 0 means -			 * no AGGREGATION -			 */ -			u8 agg_tids_count; -  			struct iwl_rx_phy_res last_phy_res;  			bool last_phy_res_valid; @@ -1256,7 +1203,6 @@ struct iwl_priv {  	struct iwl_rxon_context *beacon_ctx;  	struct sk_buff *beacon_skb; -	struct work_struct start_internal_scan;  	struct work_struct tx_flush;  	struct tasklet_struct irq_tasklet; @@ -1293,12 +1239,9 @@ struct iwl_priv {  	u32 disable_tx_power_cal;  	struct work_struct run_time_calib_work;  	struct timer_list statistics_periodic; -	struct timer_list ucode_trace;  	struct timer_list watchdog;  	bool hw_ready; -	struct iwl_event_log event_log; -  	struct led_classdev led;  	unsigned long blink_on, blink_off;  	bool led_registered; diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.c b/drivers/net/wireless/iwlegacy/iwl-devtrace.c index 080b852b33b..acec99197ce 100644 --- a/drivers/net/wireless/iwlegacy/iwl-devtrace.c +++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.c @@ -38,8 +38,5 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ioread32);  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite32);  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_rx);  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_tx); -EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_event);  EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_error); -EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_cont_event); -EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_wrap_event);  #endif diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.h b/drivers/net/wireless/iwlegacy/iwl-devtrace.h index 9612aa0f6ec..a443725ba6b 100644 --- a/drivers/net/wireless/iwlegacy/iwl-devtrace.h +++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.h @@ -96,47 +96,6 @@ TRACE_EVENT(iwlwifi_legacy_dev_iowrite32,  #undef TRACE_SYSTEM  #define TRACE_SYSTEM iwlwifi_legacy_ucode -TRACE_EVENT(iwlwifi_legacy_dev_ucode_cont_event, -	TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev), -	TP_ARGS(priv, time, data, ev), -	TP_STRUCT__entry( -		PRIV_ENTRY - -		__field(u32, time) -		__field(u32, data) -		__field(u32, ev) -	), -	TP_fast_assign( -		PRIV_ASSIGN; -		__entry->time = time; -		__entry->data = data; -		__entry->ev = ev; -	), -	TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", -		  __entry->priv, __entry->time, __entry->data, __entry->ev) -); - -TRACE_EVENT(iwlwifi_legacy_dev_ucode_wrap_event, -	TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry), -	TP_ARGS(priv, wraps, n_entry, p_entry), -	TP_STRUCT__entry( -		PRIV_ENTRY - -		__field(u32, wraps) -		__field(u32, n_entry) -		__field(u32, p_entry) -	), -	TP_fast_assign( -		PRIV_ASSIGN; -		__entry->wraps = wraps; -		__entry->n_entry = n_entry; -		__entry->p_entry = p_entry; -	), -	TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X", -		  __entry->priv, __entry->wraps, __entry->n_entry, -		  __entry->p_entry) -); -  #undef TRACE_SYSTEM  #define TRACE_SYSTEM iwlwifi @@ -242,25 +201,6 @@ TRACE_EVENT(iwlwifi_legacy_dev_ucode_error,  		  __entry->blink2, __entry->ilink1, __entry->ilink2)  ); -TRACE_EVENT(iwlwifi_legacy_dev_ucode_event, -	TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev), -	TP_ARGS(priv, time, data, ev), -	TP_STRUCT__entry( -		PRIV_ENTRY - -		__field(u32, time) -		__field(u32, data) -		__field(u32, ev) -	), -	TP_fast_assign( -		PRIV_ASSIGN; -		__entry->time = time; -		__entry->data = data; -		__entry->ev = ev; -	), -	TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", -		  __entry->priv, __entry->time, __entry->data, __entry->ev) -);  #endif /* __IWLWIFI_DEVICE_TRACE */  #undef TRACE_INCLUDE_PATH diff --git a/drivers/net/wireless/iwlegacy/iwl-eeprom.c b/drivers/net/wireless/iwlegacy/iwl-eeprom.c index cb346d1a9ff..5bf3f49b74a 100644 --- a/drivers/net/wireless/iwlegacy/iwl-eeprom.c +++ b/drivers/net/wireless/iwlegacy/iwl-eeprom.c @@ -316,7 +316,6 @@ static void iwl_legacy_init_band_reference(const struct iwl_priv *priv,  		break;  	default:  		BUG(); -		return;  	}  } diff --git a/drivers/net/wireless/iwlegacy/iwl-helpers.h b/drivers/net/wireless/iwlegacy/iwl-helpers.h index a6effdae63f..5cf23eaecbb 100644 --- a/drivers/net/wireless/iwlegacy/iwl-helpers.h +++ b/drivers/net/wireless/iwlegacy/iwl-helpers.h @@ -132,7 +132,16 @@ static inline void iwl_legacy_stop_queue(struct iwl_priv *priv,  			ieee80211_stop_queue(priv->hw, ac);  } +#ifdef ieee80211_stop_queue +#undef ieee80211_stop_queue +#endif +  #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue + +#ifdef ieee80211_wake_queue +#undef ieee80211_wake_queue +#endif +  #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue  static inline void iwl_legacy_disable_interrupts(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlegacy/iwl-rx.c b/drivers/net/wireless/iwlegacy/iwl-rx.c index 654cf233a38..9b5d0abe8be 100644 --- a/drivers/net/wireless/iwlegacy/iwl-rx.c +++ b/drivers/net/wireless/iwlegacy/iwl-rx.c @@ -227,27 +227,6 @@ void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,  }  EXPORT_SYMBOL(iwl_legacy_rx_spectrum_measure_notif); -void iwl_legacy_recover_from_statistics(struct iwl_priv *priv, -				struct iwl_rx_packet *pkt) -{ -	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -		return; -	if (iwl_legacy_is_any_associated(priv)) { -		if (priv->cfg->ops->lib->check_plcp_health) { -			if (!priv->cfg->ops->lib->check_plcp_health( -			    priv, pkt)) { -				/* -				 * high plcp error detected -				 * reset Radio -				 */ -				iwl_legacy_force_reset(priv, -							IWL_RF_RESET, false); -			} -		} -	} -} -EXPORT_SYMBOL(iwl_legacy_recover_from_statistics); -  /*   * returns non-zero if packet should be dropped   */ diff --git a/drivers/net/wireless/iwlegacy/iwl-scan.c b/drivers/net/wireless/iwlegacy/iwl-scan.c index 353234a02c6..a6b5222fc59 100644 --- a/drivers/net/wireless/iwlegacy/iwl-scan.c +++ b/drivers/net/wireless/iwlegacy/iwl-scan.c @@ -101,7 +101,6 @@ static void iwl_legacy_complete_scan(struct iwl_priv *priv, bool aborted)  		ieee80211_scan_completed(priv->hw, aborted);  	} -	priv->is_internal_short_scan = false;  	priv->scan_vif = NULL;  	priv->scan_request = NULL;  } @@ -329,10 +328,8 @@ void iwl_legacy_init_scan_params(struct iwl_priv *priv)  }  EXPORT_SYMBOL(iwl_legacy_init_scan_params); -static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv, -					  struct ieee80211_vif *vif, -					  bool internal, -					  enum ieee80211_band band) +static int iwl_legacy_scan_initiate(struct iwl_priv *priv, +				    struct ieee80211_vif *vif)  {  	int ret; @@ -359,18 +356,14 @@ static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,  		return -EBUSY;  	} -	IWL_DEBUG_SCAN(priv, "Starting %sscan...\n", -			internal ? "internal short " : ""); +	IWL_DEBUG_SCAN(priv, "Starting scan...\n");  	set_bit(STATUS_SCANNING, &priv->status); -	priv->is_internal_short_scan = internal;  	priv->scan_start = jiffies; -	priv->scan_band = band;  	ret = priv->cfg->ops->utils->request_scan(priv, vif);  	if (ret) {  		clear_bit(STATUS_SCANNING, &priv->status); -		priv->is_internal_short_scan = false;  		return ret;  	} @@ -394,8 +387,7 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,  	mutex_lock(&priv->mutex); -	if (test_bit(STATUS_SCANNING, &priv->status) && -	    !priv->is_internal_short_scan) { +	if (test_bit(STATUS_SCANNING, &priv->status)) {  		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");  		ret = -EAGAIN;  		goto out_unlock; @@ -404,17 +396,9 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,  	/* mac80211 will only ask for one band at a time */  	priv->scan_request = req;  	priv->scan_vif = vif; +	priv->scan_band = req->channels[0]->band; -	/* -	 * If an internal scan is in progress, just set -	 * up the scan_request as per above. -	 */ -	if (priv->is_internal_short_scan) { -		IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n"); -		ret = 0; -	} else -		ret = iwl_legacy_scan_initiate(priv, vif, false, -					req->channels[0]->band); +	ret = iwl_legacy_scan_initiate(priv, vif);  	IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -425,40 +409,6 @@ out_unlock:  }  EXPORT_SYMBOL(iwl_legacy_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 - */ -void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv) -{ -	queue_work(priv->workqueue, &priv->start_internal_scan); -} - -static void iwl_legacy_bg_start_internal_scan(struct work_struct *work) -{ -	struct iwl_priv *priv = -		container_of(work, struct iwl_priv, start_internal_scan); - -	IWL_DEBUG_SCAN(priv, "Start internal scan\n"); - -	mutex_lock(&priv->mutex); - -	if (priv->is_internal_short_scan == true) { -		IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); -		goto unlock; -	} - -	if (test_bit(STATUS_SCANNING, &priv->status)) { -		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); -		goto unlock; -	} - -	if (iwl_legacy_scan_initiate(priv, NULL, true, priv->band)) -		IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n"); - unlock: -	mutex_unlock(&priv->mutex); -} -  static void iwl_legacy_bg_scan_check(struct work_struct *data)  {  	struct iwl_priv *priv = @@ -542,8 +492,7 @@ static void iwl_legacy_bg_scan_completed(struct work_struct *work)  	    container_of(work, struct iwl_priv, scan_completed);  	bool aborted; -	IWL_DEBUG_SCAN(priv, "Completed %sscan.\n", -		       priv->is_internal_short_scan ? "internal short " : ""); +	IWL_DEBUG_SCAN(priv, "Completed scan.\n");  	cancel_delayed_work(&priv->scan_check); @@ -558,27 +507,6 @@ static void iwl_legacy_bg_scan_completed(struct work_struct *work)  		goto out_settings;  	} -	if (priv->is_internal_short_scan && !aborted) { -		int err; - -		/* Check if mac80211 requested scan during our internal scan */ -		if (priv->scan_request == NULL) -			goto out_complete; - -		/* If so request a new scan */ -		err = iwl_legacy_scan_initiate(priv, priv->scan_vif, false, -					priv->scan_request->channels[0]->band); -		if (err) { -			IWL_DEBUG_SCAN(priv, -				"failed to initiate pending scan: %d\n", err); -			aborted = true; -			goto out_complete; -		} - -		goto out; -	} - -out_complete:  	iwl_legacy_complete_scan(priv, aborted);  out_settings: @@ -590,8 +518,7 @@ out_settings:  	 * We do not commit power settings while scan is pending,  	 * do it now if the settings changed.  	 */ -	iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next, -								false); +	iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);  	iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);  	priv->cfg->ops->utils->post_scan(priv); @@ -604,15 +531,12 @@ void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv)  {  	INIT_WORK(&priv->scan_completed, iwl_legacy_bg_scan_completed);  	INIT_WORK(&priv->abort_scan, iwl_legacy_bg_abort_scan); -	INIT_WORK(&priv->start_internal_scan, -				iwl_legacy_bg_start_internal_scan);  	INIT_DELAYED_WORK(&priv->scan_check, iwl_legacy_bg_scan_check);  }  EXPORT_SYMBOL(iwl_legacy_setup_scan_deferred_work);  void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv)  { -	cancel_work_sync(&priv->start_internal_scan);  	cancel_work_sync(&priv->abort_scan);  	cancel_work_sync(&priv->scan_completed); diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c index 0ee6be6a9c5..795826a014e 100644 --- a/drivers/net/wireless/iwlegacy/iwl3945-base.c +++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c @@ -1409,212 +1409,6 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)  	}  } -#define EVENT_START_OFFSET  (6 * sizeof(u32)) - -/** - * iwl3945_print_event_log - Dump error event log to syslog - * - */ -static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, -				  u32 num_events, u32 mode, -				  int pos, char **buf, size_t bufsz) -{ -	u32 i; -	u32 base;       /* SRAM byte address of event log header */ -	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */ -	u32 ptr;        /* SRAM byte address of log data */ -	u32 ev, time, data; /* event log data */ -	unsigned long reg_flags; - -	if (num_events == 0) -		return pos; - -	base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - -	if (mode == 0) -		event_size = 2 * sizeof(u32); -	else -		event_size = 3 * sizeof(u32); - -	ptr = base + EVENT_START_OFFSET + (start_idx * event_size); - -	/* Make sure device is powered up for SRAM reads */ -	spin_lock_irqsave(&priv->reg_lock, reg_flags); -	iwl_grab_nic_access(priv); - -	/* Set starting address; reads will auto-increment */ -	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); -	rmb(); - -	/* "time" is actually "data" for mode 0 (no timestamp). -	 * place event id # at far right for easier visual parsing. */ -	for (i = 0; i < num_events; i++) { -		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT); -		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT); -		if (mode == 0) { -			/* data, ev */ -			if (bufsz) { -				pos += scnprintf(*buf + pos, bufsz - pos, -						"0x%08x:%04u\n", -						time, ev); -			} else { -				IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); -				trace_iwlwifi_legacy_dev_ucode_event(priv, 0, -							      time, ev); -			} -		} else { -			data = _iwl_legacy_read_direct32(priv, -							HBUS_TARG_MEM_RDAT); -			if (bufsz) { -				pos += scnprintf(*buf + pos, bufsz - pos, -						"%010u:0x%08x:%04u\n", -						 time, data, ev); -			} else { -				IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", -					time, data, ev); -				trace_iwlwifi_legacy_dev_ucode_event(priv, time, -							      data, ev); -			} -		} -	} - -	/* Allow device to power down */ -	iwl_release_nic_access(priv); -	spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -	return pos; -} - -/** - * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog - */ -static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, -				      u32 num_wraps, u32 next_entry, -				      u32 size, u32 mode, -				      int pos, char **buf, size_t bufsz) -{ -	/* -	 * display the newest DEFAULT_LOG_ENTRIES entries -	 * i.e the entries just before the next ont that uCode would fill. -	 */ -	if (num_wraps) { -		if (next_entry < size) { -			pos = iwl3945_print_event_log(priv, -					     capacity - (size - next_entry), -					     size - next_entry, mode, -					     pos, buf, bufsz); -			pos = iwl3945_print_event_log(priv, 0, -						      next_entry, mode, -						      pos, buf, bufsz); -		} else -			pos = iwl3945_print_event_log(priv, next_entry - size, -						      size, mode, -						      pos, buf, bufsz); -	} else { -		if (next_entry < size) -			pos = iwl3945_print_event_log(priv, 0, -						      next_entry, mode, -						      pos, buf, bufsz); -		else -			pos = iwl3945_print_event_log(priv, next_entry - size, -						      size, mode, -						      pos, buf, bufsz); -	} -	return pos; -} - -#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) - -int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, -			    char **buf, bool display) -{ -	u32 base;       /* SRAM byte address of event log header */ -	u32 capacity;   /* event log capacity in # entries */ -	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */ -	u32 num_wraps;  /* # times uCode wrapped to top of log */ -	u32 next_entry; /* index of next entry to be written by uCode */ -	u32 size;       /* # entries that we'll print */ -	int pos = 0; -	size_t bufsz = 0; - -	base = le32_to_cpu(priv->card_alive.log_event_table_ptr); -	if (!iwl3945_hw_valid_rtc_data_addr(base)) { -		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); -		return  -EINVAL; -	} - -	/* event log header */ -	capacity = iwl_legacy_read_targ_mem(priv, base); -	mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32))); -	num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32))); -	next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32))); - -	if (capacity > priv->cfg->base_params->max_event_log_size) { -		IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", -			capacity, priv->cfg->base_params->max_event_log_size); -		capacity = priv->cfg->base_params->max_event_log_size; -	} - -	if (next_entry > priv->cfg->base_params->max_event_log_size) { -		IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", -			next_entry, priv->cfg->base_params->max_event_log_size); -		next_entry = priv->cfg->base_params->max_event_log_size; -	} - -	size = num_wraps ? capacity : next_entry; - -	/* bail out if nothing in log */ -	if (size == 0) { -		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); -		return pos; -	} - -#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG -	if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) -		size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES) -			? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size; -#else -	size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES) -		? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size; -#endif - -	IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n", -		  size); - -#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG -	if (display) { -		if (full_log) -			bufsz = capacity * 48; -		else -			bufsz = size * 48; -		*buf = kmalloc(bufsz, GFP_KERNEL); -		if (!*buf) -			return -ENOMEM; -	} -	if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { -		/* if uCode has wrapped back to top of log, -		 * start at the oldest entry, -		 * i.e the next one that uCode would fill. -		 */ -		if (num_wraps) -			pos = iwl3945_print_event_log(priv, next_entry, -						capacity - next_entry, mode, -						pos, buf, bufsz); - -		/* (then/else) start at top of log */ -		pos = iwl3945_print_event_log(priv, 0, next_entry, mode, -					      pos, buf, bufsz); -	} else -		pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, -						    next_entry, size, mode, -						    pos, buf, bufsz); -#else -	pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps, -					    next_entry, size, mode, -					    pos, buf, bufsz); -#endif -	return pos; -} -  static void iwl3945_irq_tasklet(struct iwl_priv *priv)  {  	u32 inta, handled = 0; @@ -1762,49 +1556,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)  #endif  } -static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv, -					       struct ieee80211_vif *vif, -					       enum ieee80211_band band, -					       struct iwl3945_scan_channel *scan_ch) -{ -	const struct ieee80211_supported_band *sband; -	u16 passive_dwell = 0; -	u16 active_dwell = 0; -	int added = 0; -	u8 channel = 0; - -	sband = iwl_get_hw_mode(priv, band); -	if (!sband) { -		IWL_ERR(priv, "invalid band\n"); -		return added; -	} - -	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0); -	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif); - -	if (passive_dwell <= active_dwell) -		passive_dwell = active_dwell + 1; - - -	channel = iwl_legacy_get_single_channel_number(priv, band); - -	if (channel) { -		scan_ch->channel = channel; -		scan_ch->type = 0;	/* 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->tpc.dsp_atten = 110; -		if (band == IEEE80211_BAND_5GHZ) -			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; -		else -			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); -		added++; -	} else -		IWL_ERR(priv, "no valid channel found\n"); -	return added; -} -  static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,  					 enum ieee80211_band band,  				     u8 is_active, u8 n_probes, @@ -2816,6 +2567,7 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)  	enum ieee80211_band band;  	bool is_active = false;  	int ret; +	u16 len;  	lockdep_assert_held(&priv->mutex); @@ -2834,17 +2586,14 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)  	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;  	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) { -		u16 interval = 0; +		u16 interval;  		u32 extra;  		u32 suspend_time = 100;  		u32 scan_suspend_time = 100;  		IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); -		if (priv->is_internal_short_scan) -			interval = 0; -		else -			interval = vif->bss_conf.beacon_int; +		interval = vif->bss_conf.beacon_int;  		scan->suspend_time = 0;  		scan->max_out_time = cpu_to_le32(200 * 1024); @@ -2866,9 +2615,7 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)  			       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) { +	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++) { @@ -2919,36 +2666,17 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)  	scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :  					IWL_GOOD_CRC_TH_DISABLED; -	if (!priv->is_internal_short_scan) { -		scan->tx_cmd.len = cpu_to_le16( -			iwl_legacy_fill_probe_req(priv, -				(struct ieee80211_mgmt *)scan->data, -				vif->addr, -				priv->scan_request->ie, -				priv->scan_request->ie_len, -				IWL_MAX_SCAN_SIZE - sizeof(*scan))); -	} else { -		/* use bcast addr, will not be transmitted but must be valid */ -		scan->tx_cmd.len = cpu_to_le16( -			iwl_legacy_fill_probe_req(priv, -				(struct ieee80211_mgmt *)scan->data, -				iwlegacy_bcast_addr, NULL, 0, -				IWL_MAX_SCAN_SIZE - sizeof(*scan))); -	} +	len = iwl_legacy_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, +					vif->addr, priv->scan_request->ie, +					priv->scan_request->ie_len, +					IWL_MAX_SCAN_SIZE - sizeof(*scan)); +	scan->tx_cmd.len = cpu_to_le16(len); +  	/* select Rx antennas */  	scan->flags |= iwl3945_get_antenna_flags(priv); -	if (priv->is_internal_short_scan) { -		scan->channel_count = -			iwl3945_get_single_channel_for_scan(priv, vif, band, -				(void *)&scan->data[le16_to_cpu( -				scan->tx_cmd.len)]); -	} else { -		scan->channel_count = -			iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, -				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif); -	} - +	scan->channel_count = iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, +							    (void *)&scan->data[len], vif);  	if (scan->channel_count == 0) {  		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);  		return -EIO; @@ -3824,10 +3552,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)  	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;  	/* initialize force reset */ -	priv->force_reset[IWL_RF_RESET].reset_duration = -		IWL_DELAY_NEXT_FORCE_RF_RESET; -	priv->force_reset[IWL_FW_RESET].reset_duration = -		IWL_DELAY_NEXT_FORCE_FW_RELOAD; +	priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;  	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {  		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c index 7157ba52968..14334668034 100644 --- a/drivers/net/wireless/iwlegacy/iwl4965-base.c +++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c @@ -488,134 +488,6 @@ static void iwl4965_bg_statistics_periodic(unsigned long data)  	iwl_legacy_send_statistics_request(priv, CMD_ASYNC, false);  } - -static void iwl4965_print_cont_event_trace(struct iwl_priv *priv, u32 base, -					u32 start_idx, u32 num_events, -					u32 mode) -{ -	u32 i; -	u32 ptr;        /* SRAM byte address of log data */ -	u32 ev, time, data; /* event log data */ -	unsigned long reg_flags; - -	if (mode == 0) -		ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32)); -	else -		ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32)); - -	/* Make sure device is powered up for SRAM reads */ -	spin_lock_irqsave(&priv->reg_lock, reg_flags); -	if (iwl_grab_nic_access(priv)) { -		spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -		return; -	} - -	/* Set starting address; reads will auto-increment */ -	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); -	rmb(); - -	/* -	 * "time" is actually "data" for mode 0 (no timestamp). -	 * place event id # at far right for easier visual parsing. -	 */ -	for (i = 0; i < num_events; i++) { -		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT); -		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT); -		if (mode == 0) { -			trace_iwlwifi_legacy_dev_ucode_cont_event(priv, -							0, time, ev); -		} else { -			data = _iwl_legacy_read_direct32(priv, -						HBUS_TARG_MEM_RDAT); -			trace_iwlwifi_legacy_dev_ucode_cont_event(priv, -						time, data, ev); -		} -	} -	/* Allow device to power down */ -	iwl_release_nic_access(priv); -	spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -static void iwl4965_continuous_event_trace(struct iwl_priv *priv) -{ -	u32 capacity;   /* event log capacity in # entries */ -	u32 base;       /* SRAM byte address of event log header */ -	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */ -	u32 num_wraps;  /* # times uCode wrapped to top of log */ -	u32 next_entry; /* index of next entry to be written by uCode */ - -	if (priv->ucode_type == UCODE_INIT) -		base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); -	else -		base = le32_to_cpu(priv->card_alive.log_event_table_ptr); -	if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { -		capacity = iwl_legacy_read_targ_mem(priv, base); -		num_wraps = iwl_legacy_read_targ_mem(priv, -						base + (2 * sizeof(u32))); -		mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32))); -		next_entry = iwl_legacy_read_targ_mem(priv, -						base + (3 * sizeof(u32))); -	} else -		return; - -	if (num_wraps == priv->event_log.num_wraps) { -		iwl4965_print_cont_event_trace(priv, -				       base, priv->event_log.next_entry, -				       next_entry - priv->event_log.next_entry, -				       mode); -		priv->event_log.non_wraps_count++; -	} else { -		if ((num_wraps - priv->event_log.num_wraps) > 1) -			priv->event_log.wraps_more_count++; -		else -			priv->event_log.wraps_once_count++; -		trace_iwlwifi_legacy_dev_ucode_wrap_event(priv, -				num_wraps - priv->event_log.num_wraps, -				next_entry, priv->event_log.next_entry); -		if (next_entry < priv->event_log.next_entry) { -			iwl4965_print_cont_event_trace(priv, base, -			       priv->event_log.next_entry, -			       capacity - priv->event_log.next_entry, -			       mode); - -			iwl4965_print_cont_event_trace(priv, base, 0, -				next_entry, mode); -		} else { -			iwl4965_print_cont_event_trace(priv, base, -			       next_entry, capacity - next_entry, -			       mode); - -			iwl4965_print_cont_event_trace(priv, base, 0, -				next_entry, mode); -		} -	} -	priv->event_log.num_wraps = num_wraps; -	priv->event_log.next_entry = next_entry; -} - -/** - * iwl4965_bg_ucode_trace - Timer callback to log ucode event - * - * The timer is continually set to execute every - * UCODE_TRACE_PERIOD milliseconds after the last timer expired - * this function is to perform continuous uCode event logging operation - * if enabled - */ -static void iwl4965_bg_ucode_trace(unsigned long data) -{ -	struct iwl_priv *priv = (struct iwl_priv *)data; - -	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) -		return; - -	if (priv->event_log.ucode_trace) { -		iwl4965_continuous_event_trace(priv); -		/* Reschedule the timer to occur in UCODE_TRACE_PERIOD */ -		mod_timer(&priv->ucode_trace, -			 jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD)); -	} -} -  static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,  				struct iwl_rx_mem_buffer *rxb)  { @@ -1612,7 +1484,7 @@ static const char * const desc_lookup_text[] = {  	"NMI_INTERRUPT_DATA_ACTION_PT",  	"NMI_TRM_HW_ER",  	"NMI_INTERRUPT_TRM", -	"NMI_INTERRUPT_BREAK_POINT" +	"NMI_INTERRUPT_BREAK_POINT",  	"DEBUG_0",  	"DEBUG_1",  	"DEBUG_2", @@ -1711,209 +1583,6 @@ void iwl4965_dump_nic_error_log(struct iwl_priv *priv)  		pc, blink1, blink2, ilink1, ilink2, hcmd);  } -#define EVENT_START_OFFSET  (4 * sizeof(u32)) - -/** - * iwl4965_print_event_log - Dump error event log to syslog - * - */ -static int iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx, -			       u32 num_events, u32 mode, -			       int pos, char **buf, size_t bufsz) -{ -	u32 i; -	u32 base;       /* SRAM byte address of event log header */ -	u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ -	u32 ptr;        /* SRAM byte address of log data */ -	u32 ev, time, data; /* event log data */ -	unsigned long reg_flags; - -	if (num_events == 0) -		return pos; - -	if (priv->ucode_type == UCODE_INIT) { -		base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); -	} else { -		base = le32_to_cpu(priv->card_alive.log_event_table_ptr); -	} - -	if (mode == 0) -		event_size = 2 * sizeof(u32); -	else -		event_size = 3 * sizeof(u32); - -	ptr = base + EVENT_START_OFFSET + (start_idx * event_size); - -	/* Make sure device is powered up for SRAM reads */ -	spin_lock_irqsave(&priv->reg_lock, reg_flags); -	iwl_grab_nic_access(priv); - -	/* Set starting address; reads will auto-increment */ -	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr); -	rmb(); - -	/* "time" is actually "data" for mode 0 (no timestamp). -	* place event id # at far right for easier visual parsing. */ -	for (i = 0; i < num_events; i++) { -		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT); -		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT); -		if (mode == 0) { -			/* data, ev */ -			if (bufsz) { -				pos += scnprintf(*buf + pos, bufsz - pos, -						"EVT_LOG:0x%08x:%04u\n", -						time, ev); -			} else { -				trace_iwlwifi_legacy_dev_ucode_event(priv, 0, -					time, ev); -				IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", -					time, ev); -			} -		} else { -			data = _iwl_legacy_read_direct32(priv, -						HBUS_TARG_MEM_RDAT); -			if (bufsz) { -				pos += scnprintf(*buf + pos, bufsz - pos, -						"EVT_LOGT:%010u:0x%08x:%04u\n", -						 time, data, ev); -			} else { -				IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", -					time, data, ev); -				trace_iwlwifi_legacy_dev_ucode_event(priv, time, -					data, ev); -			} -		} -	} - -	/* Allow device to power down */ -	iwl_release_nic_access(priv); -	spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -	return pos; -} - -/** - * iwl4965_print_last_event_logs - Dump the newest # of event log to syslog - */ -static int iwl4965_print_last_event_logs(struct iwl_priv *priv, u32 capacity, -				    u32 num_wraps, u32 next_entry, -				    u32 size, u32 mode, -				    int pos, char **buf, size_t bufsz) -{ -	/* -	 * display the newest DEFAULT_LOG_ENTRIES entries -	 * i.e the entries just before the next ont that uCode would fill. -	 */ -	if (num_wraps) { -		if (next_entry < size) { -			pos = iwl4965_print_event_log(priv, -						capacity - (size - next_entry), -						size - next_entry, mode, -						pos, buf, bufsz); -			pos = iwl4965_print_event_log(priv, 0, -						  next_entry, mode, -						  pos, buf, bufsz); -		} else -			pos = iwl4965_print_event_log(priv, next_entry - size, -						  size, mode, pos, buf, bufsz); -	} else { -		if (next_entry < size) { -			pos = iwl4965_print_event_log(priv, 0, next_entry, -						  mode, pos, buf, bufsz); -		} else { -			pos = iwl4965_print_event_log(priv, next_entry - size, -						  size, mode, pos, buf, bufsz); -		} -	} -	return pos; -} - -#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) - -int iwl4965_dump_nic_event_log(struct iwl_priv *priv, bool full_log, -			    char **buf, bool display) -{ -	u32 base;       /* SRAM byte address of event log header */ -	u32 capacity;   /* event log capacity in # entries */ -	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */ -	u32 num_wraps;  /* # times uCode wrapped to top of log */ -	u32 next_entry; /* index of next entry to be written by uCode */ -	u32 size;       /* # entries that we'll print */ -	int pos = 0; -	size_t bufsz = 0; - -	if (priv->ucode_type == UCODE_INIT) { -		base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); -	} else { -		base = le32_to_cpu(priv->card_alive.log_event_table_ptr); -	} - -	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { -		IWL_ERR(priv, -			"Invalid event log pointer 0x%08X for %s uCode\n", -			base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT"); -		return -EINVAL; -	} - -	/* event log header */ -	capacity = iwl_legacy_read_targ_mem(priv, base); -	mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32))); -	num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32))); -	next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32))); - -	size = num_wraps ? capacity : next_entry; - -	/* bail out if nothing in log */ -	if (size == 0) { -		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); -		return pos; -	} - -#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG -	if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log) -		size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) -			? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; -#else -	size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) -		? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; -#endif -	IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", -		size); - -#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG -	if (display) { -		if (full_log) -			bufsz = capacity * 48; -		else -			bufsz = size * 48; -		*buf = kmalloc(bufsz, GFP_KERNEL); -		if (!*buf) -			return -ENOMEM; -	} -	if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { -		/* -		 * if uCode has wrapped back to top of log, -		 * start at the oldest entry, -		 * i.e the next one that uCode would fill. -		 */ -		if (num_wraps) -			pos = iwl4965_print_event_log(priv, next_entry, -						capacity - next_entry, mode, -						pos, buf, bufsz); -		/* (then/else) start at top of log */ -		pos = iwl4965_print_event_log(priv, 0, -					  next_entry, mode, pos, buf, bufsz); -	} else -		pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps, -						next_entry, size, mode, -						pos, buf, bufsz); -#else -	pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps, -					next_entry, size, mode, -					pos, buf, bufsz); -#endif -	return pos; -} -  static void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)  {  	struct iwl_ct_kill_config cmd; @@ -2773,20 +2442,10 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,  	case IEEE80211_AMPDU_TX_START:  		IWL_DEBUG_HT(priv, "start Tx\n");  		ret = iwl4965_tx_agg_start(priv, vif, sta, tid, ssn); -		if (ret == 0) { -			priv->_4965.agg_tids_count++; -			IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n", -				     priv->_4965.agg_tids_count); -		}  		break;  	case IEEE80211_AMPDU_TX_STOP:  		IWL_DEBUG_HT(priv, "stop Tx\n");  		ret = iwl4965_tx_agg_stop(priv, vif, sta, tid); -		if ((ret == 0) && (priv->_4965.agg_tids_count > 0)) { -			priv->_4965.agg_tids_count--; -			IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n", -				     priv->_4965.agg_tids_count); -		}  		if (test_bit(STATUS_EXIT_PENDING, &priv->status))  			ret = 0;  		break; @@ -2851,7 +2510,6 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,  	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];  	u16 ch; -	unsigned long flags = 0;  	IWL_DEBUG_MAC80211(priv, "enter\n"); @@ -2868,64 +2526,64 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,  	if (!iwl_legacy_is_associated_ctx(ctx))  		goto out; -	if (priv->cfg->ops->lib->set_channel_switch) { - -		ch = channel->hw_value; -		if (le16_to_cpu(ctx->active.channel) != ch) { -			ch_info = iwl_legacy_get_channel_info(priv, -						       channel->band, -						       ch); -			if (!iwl_legacy_is_channel_valid(ch_info)) { -				IWL_DEBUG_MAC80211(priv, "invalid channel\n"); -				goto out; -			} -			spin_lock_irqsave(&priv->lock, flags); +	if (!priv->cfg->ops->lib->set_channel_switch) +		goto out; -			priv->current_ht_config.smps = conf->smps_mode; +	ch = channel->hw_value; +	if (le16_to_cpu(ctx->active.channel) == ch) +		goto out; -			/* Configure HT40 channels */ -			ctx->ht.enabled = conf_is_ht(conf); -			if (ctx->ht.enabled) { -				if (conf_is_ht40_minus(conf)) { -					ctx->ht.extension_chan_offset = -					IEEE80211_HT_PARAM_CHA_SEC_BELOW; -					ctx->ht.is_40mhz = true; -				} else if (conf_is_ht40_plus(conf)) { -					ctx->ht.extension_chan_offset = -					IEEE80211_HT_PARAM_CHA_SEC_ABOVE; -					ctx->ht.is_40mhz = true; -				} else { -					ctx->ht.extension_chan_offset = -						IEEE80211_HT_PARAM_CHA_SEC_NONE; -					ctx->ht.is_40mhz = false; -				} -			} else -				ctx->ht.is_40mhz = false; +	ch_info = iwl_legacy_get_channel_info(priv, channel->band, ch); +	if (!iwl_legacy_is_channel_valid(ch_info)) { +		IWL_DEBUG_MAC80211(priv, "invalid channel\n"); +		goto out; +	} -			if ((le16_to_cpu(ctx->staging.channel) != ch)) -				ctx->staging.flags = 0; +	spin_lock_irq(&priv->lock); -			iwl_legacy_set_rxon_channel(priv, channel, ctx); -			iwl_legacy_set_rxon_ht(priv, ht_conf); -			iwl_legacy_set_flags_for_band(priv, ctx, channel->band, -					       ctx->vif); -			spin_unlock_irqrestore(&priv->lock, flags); +	priv->current_ht_config.smps = conf->smps_mode; -			iwl_legacy_set_rate(priv); -			/* -			 * at this point, staging_rxon has the -			 * configuration for channel switch -			 */ -			set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); -			priv->switch_channel = cpu_to_le16(ch); -			if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) { -				clear_bit(STATUS_CHANNEL_SWITCH_PENDING, -					  &priv->status); -				priv->switch_channel = 0; -				ieee80211_chswitch_done(ctx->vif, false); -			} +	/* Configure HT40 channels */ +	ctx->ht.enabled = conf_is_ht(conf); +	if (ctx->ht.enabled) { +		if (conf_is_ht40_minus(conf)) { +			ctx->ht.extension_chan_offset = +				IEEE80211_HT_PARAM_CHA_SEC_BELOW; +			ctx->ht.is_40mhz = true; +		} else if (conf_is_ht40_plus(conf)) { +			ctx->ht.extension_chan_offset = +				IEEE80211_HT_PARAM_CHA_SEC_ABOVE; +			ctx->ht.is_40mhz = true; +		} else { +			ctx->ht.extension_chan_offset = +				IEEE80211_HT_PARAM_CHA_SEC_NONE; +			ctx->ht.is_40mhz = false;  		} +	} else +		ctx->ht.is_40mhz = false; + +	if ((le16_to_cpu(ctx->staging.channel) != ch)) +		ctx->staging.flags = 0; + +	iwl_legacy_set_rxon_channel(priv, channel, ctx); +	iwl_legacy_set_rxon_ht(priv, ht_conf); +	iwl_legacy_set_flags_for_band(priv, ctx, channel->band, ctx->vif); + +	spin_unlock_irq(&priv->lock); + +	iwl_legacy_set_rate(priv); +	/* +	 * at this point, staging_rxon has the +	 * configuration for channel switch +	 */ +	set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); +	priv->switch_channel = cpu_to_le16(ch); +	if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) { +		clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); +		priv->switch_channel = 0; +		ieee80211_chswitch_done(ctx->vif, false);  	} +  out:  	mutex_unlock(&priv->mutex);  	IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -3034,10 +2692,6 @@ static void iwl4965_setup_deferred_work(struct iwl_priv *priv)  	priv->statistics_periodic.data = (unsigned long)priv;  	priv->statistics_periodic.function = iwl4965_bg_statistics_periodic; -	init_timer(&priv->ucode_trace); -	priv->ucode_trace.data = (unsigned long)priv; -	priv->ucode_trace.function = iwl4965_bg_ucode_trace; -  	init_timer(&priv->watchdog);  	priv->watchdog.data = (unsigned long)priv;  	priv->watchdog.function = iwl_legacy_bg_watchdog; @@ -3056,7 +2710,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)  	iwl_legacy_cancel_scan_deferred_work(priv);  	del_timer_sync(&priv->statistics_periodic); -	del_timer_sync(&priv->ucode_trace);  }  static void iwl4965_init_hw_rates(struct iwl_priv *priv, @@ -3132,13 +2785,9 @@ static int iwl4965_init_drv(struct iwl_priv *priv)  	priv->iw_mode = NL80211_IFTYPE_STATION;  	priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;  	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; -	priv->_4965.agg_tids_count = 0;  	/* initialize force reset */ -	priv->force_reset[IWL_RF_RESET].reset_duration = -		IWL_DELAY_NEXT_FORCE_RF_RESET; -	priv->force_reset[IWL_FW_RESET].reset_duration = -		IWL_DELAY_NEXT_FORCE_FW_RELOAD; +	priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;  	/* Choose which receivers/antennas to use */  	if (priv->cfg->ops->hcmd->set_rxon_chain) diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 822660483f9..19150398a24 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -13,6 +13,8 @@ iwlagn-objs             += iwl-5000.o  iwlagn-objs             += iwl-6000.o  iwlagn-objs             += iwl-1000.o  iwlagn-objs             += iwl-2000.o +iwlagn-objs             += iwl-pci.o +iwlagn-objs             += iwl-trans.o  iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o  iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 61d4a11f566..2f56b343e86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -27,8 +27,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/init.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h>  #include <linux/delay.h>  #include <linux/skbuff.h>  #include <linux/netdevice.h> @@ -36,6 +34,7 @@  #include <net/mac80211.h>  #include <linux/etherdevice.h>  #include <asm/unaligned.h> +#include <linux/stringify.h>  #include "iwl-eeprom.h"  #include "iwl-dev.h" @@ -55,10 +54,10 @@  #define IWL100_UCODE_API_MIN 5  #define IWL1000_FW_PRE "iwlwifi-1000-" -#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" +#define IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE __stringify(api) ".ucode"  #define IWL100_FW_PRE "iwlwifi-100-" -#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE #api ".ucode" +#define IWL100_MODULE_FIRMWARE(api) IWL100_FW_PRE __stringify(api) ".ucode"  /* @@ -126,7 +125,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)  			iwlagn_mod_params.num_of_queues;  	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; -	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;  	priv->hw_params.scd_bc_tbls_size =  			priv->cfg->base_params->num_of_queues *  			sizeof(struct iwlagn_scd_bc_tbl); @@ -139,7 +137,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)  	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);  	if (priv->cfg->rx_with_siso_diversity) @@ -174,12 +171,7 @@ static struct iwl_lib_ops iwl1000_lib = {  	.rx_handler_setup = iwlagn_rx_handler_setup,  	.setup_deferred_work = iwlagn_setup_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.send_tx_power = iwlagn_send_tx_power, -	.update_chain_flags = iwl_update_chain_flags, -	.apm_ops = { -		.init = iwl_apm_init, -		.config = iwl1000_nic_config, -	}, +	.nic_config = iwl1000_nic_config,  	.eeprom_ops = {  		.regulatory_bands = {  			EEPROM_REG_BAND_1_CHANNELS, @@ -190,19 +182,12 @@ static struct iwl_lib_ops iwl1000_lib = {  			EEPROM_REG_BAND_24_HT40_CHANNELS,  			EEPROM_REGULATORY_BAND_NO_HT40,  		}, -		.query_addr = iwlagn_eeprom_query_addr,  	}, -	.temp_ops = { -		.temperature = iwlagn_temperature, -	 }, -	.txfifo_flush = iwlagn_txfifo_flush, -	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, +	.temperature = iwlagn_temperature,  };  static const struct iwl_ops iwl1000_ops = {  	.lib = &iwl1000_lib, -	.hcmd = &iwlagn_hcmd, -	.utils = &iwlagn_hcmd_utils,  };  static struct iwl_base_params iwl1000_base_params = { @@ -223,6 +208,7 @@ static struct iwl_base_params iwl1000_base_params = {  static struct iwl_ht_params iwl1000_ht_params = {  	.ht_greenfield_support = true,  	.use_rts_for_aggregation = true, /* use rts/cts protection */ +	.smps_mode = IEEE80211_SMPS_STATIC,  };  #define IWL_DEVICE_1000						\ diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 2282279cffc..32ac8654b79 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -27,8 +27,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/init.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h>  #include <linux/delay.h>  #include <linux/skbuff.h>  #include <linux/netdevice.h> @@ -36,6 +34,7 @@  #include <net/mac80211.h>  #include <linux/etherdevice.h>  #include <asm/unaligned.h> +#include <linux/stringify.h>  #include "iwl-eeprom.h"  #include "iwl-dev.h" @@ -51,20 +50,25 @@  #define IWL2030_UCODE_API_MAX 5  #define IWL2000_UCODE_API_MAX 5  #define IWL105_UCODE_API_MAX 5 +#define IWL135_UCODE_API_MAX 5  /* Lowest firmware API version supported */  #define IWL2030_UCODE_API_MIN 5  #define IWL2000_UCODE_API_MIN 5  #define IWL105_UCODE_API_MIN 5 +#define IWL135_UCODE_API_MIN 5  #define IWL2030_FW_PRE "iwlwifi-2030-" -#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode" +#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode"  #define IWL2000_FW_PRE "iwlwifi-2000-" -#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode" +#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE __stringify(api) ".ucode"  #define IWL105_FW_PRE "iwlwifi-105-" -#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE #api ".ucode" +#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode" + +#define IWL135_FW_PRE "iwlwifi-135-" +#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE #api ".ucode"  static void iwl2000_set_ct_threshold(struct iwl_priv *priv)  { @@ -76,21 +80,7 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv)  /* NIC configuration for 2000 series */  static void iwl2000_nic_config(struct iwl_priv *priv)  { -	u16 radio_cfg; - -	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); - -	/* write radio config values to register */ -	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) -	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, -			EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | -			EEPROM_RF_CFG_STEP_MSK(radio_cfg) | -			EEPROM_RF_CFG_DASH_MSK(radio_cfg)); - -	/* set CSR_HW_CONFIG_REG for uCode use */ -	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, -		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | -		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); +	iwl_rf_config(priv);  	if (priv->cfg->iq_invert)  		iwl_set_bit(priv, CSR_GP_DRIVER_REG, @@ -133,7 +123,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)  			iwlagn_mod_params.num_of_queues;  	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; -	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;  	priv->hw_params.scd_bc_tbls_size =  		priv->cfg->base_params->num_of_queues *  		sizeof(struct iwlagn_scd_bc_tbl); @@ -146,7 +135,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)  	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);  	if (priv->cfg->rx_with_siso_diversity) @@ -180,15 +168,31 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)  static struct iwl_lib_ops iwl2000_lib = {  	.set_hw_params = iwl2000_hw_set_hw_params,  	.rx_handler_setup = iwlagn_rx_handler_setup, +	.setup_deferred_work = iwlagn_setup_deferred_work, +	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, +	.nic_config = iwl2000_nic_config, +	.eeprom_ops = { +		.regulatory_bands = { +			EEPROM_REG_BAND_1_CHANNELS, +			EEPROM_REG_BAND_2_CHANNELS, +			EEPROM_REG_BAND_3_CHANNELS, +			EEPROM_REG_BAND_4_CHANNELS, +			EEPROM_REG_BAND_5_CHANNELS, +			EEPROM_6000_REG_BAND_24_HT40_CHANNELS, +			EEPROM_REGULATORY_BAND_NO_HT40, +		}, +		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, +	}, +	.temperature = iwlagn_temperature, +}; + +static struct iwl_lib_ops iwl2030_lib = { +	.set_hw_params = iwl2000_hw_set_hw_params, +	.rx_handler_setup = iwlagn_bt_rx_handler_setup,  	.setup_deferred_work = iwlagn_bt_setup_deferred_work,  	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.send_tx_power = iwlagn_send_tx_power, -	.update_chain_flags = iwl_update_chain_flags, -	.apm_ops = { -		.init = iwl_apm_init, -		.config = iwl2000_nic_config, -	}, +	.nic_config = iwl2000_nic_config,  	.eeprom_ops = {  		.regulatory_bands = {  			EEPROM_REG_BAND_1_CHANNELS, @@ -199,38 +203,25 @@ static struct iwl_lib_ops iwl2000_lib = {  			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,  			EEPROM_REGULATORY_BAND_NO_HT40,  		}, -		.query_addr = iwlagn_eeprom_query_addr,  		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,  	}, -	.temp_ops = { -		.temperature = iwlagn_temperature, -	}, -	.txfifo_flush = iwlagn_txfifo_flush, -	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, +	.temperature = iwlagn_temperature,  };  static const struct iwl_ops iwl2000_ops = {  	.lib = &iwl2000_lib, -	.hcmd = &iwlagn_hcmd, -	.utils = &iwlagn_hcmd_utils,  };  static const struct iwl_ops iwl2030_ops = { -	.lib = &iwl2000_lib, -	.hcmd = &iwlagn_bt_hcmd, -	.utils = &iwlagn_hcmd_utils, +	.lib = &iwl2030_lib,  };  static const struct iwl_ops iwl105_ops = {  	.lib = &iwl2000_lib, -	.hcmd = &iwlagn_hcmd, -	.utils = &iwlagn_hcmd_utils,  };  static const struct iwl_ops iwl135_ops = { -	.lib = &iwl2000_lib, -	.hcmd = &iwlagn_bt_hcmd, -	.utils = &iwlagn_hcmd_utils, +	.lib = &iwl2030_lib,  };  static struct iwl_base_params iwl2000_base_params = { @@ -362,9 +353,9 @@ struct iwl_cfg iwl105_bgn_cfg = {  };  #define IWL_DEVICE_135						\ -	.fw_name_pre = IWL105_FW_PRE,				\ -	.ucode_api_max = IWL105_UCODE_API_MAX,			\ -	.ucode_api_min = IWL105_UCODE_API_MIN,			\ +	.fw_name_pre = IWL135_FW_PRE,				\ +	.ucode_api_max = IWL135_UCODE_API_MAX,			\ +	.ucode_api_min = IWL135_UCODE_API_MIN,			\  	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\  	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\  	.ops = &iwl135_ops,					\ @@ -377,12 +368,12 @@ struct iwl_cfg iwl105_bgn_cfg = {  	.rx_with_siso_diversity = true				\  struct iwl_cfg iwl135_bg_cfg = { -	.name = "105 Series 1x1 BG/BT", +	.name = "135 Series 1x1 BG/BT",  	IWL_DEVICE_135,  };  struct iwl_cfg iwl135_bgn_cfg = { -	.name = "105 Series 1x1 BGN/BT", +	.name = "135 Series 1x1 BGN/BT",  	IWL_DEVICE_135,  	.ht_params = &iwl2000_ht_params,  }; @@ -390,3 +381,4 @@ struct iwl_cfg iwl135_bgn_cfg = {  MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX));  MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX));  MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 05ad47628b6..f9630a3c79f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h @@ -75,7 +75,7 @@ static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)  {  	u16 temperature, voltage;  	__le16 *temp_calib = -		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE); +		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);  	temperature = le16_to_cpu(temp_calib[0]);  	voltage = le16_to_cpu(temp_calib[1]); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f99f9c19335..556489302da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -27,8 +27,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/init.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h>  #include <linux/delay.h>  #include <linux/sched.h>  #include <linux/skbuff.h> @@ -37,6 +35,7 @@  #include <net/mac80211.h>  #include <linux/etherdevice.h>  #include <asm/unaligned.h> +#include <linux/stringify.h>  #include "iwl-eeprom.h"  #include "iwl-dev.h" @@ -47,6 +46,7 @@  #include "iwl-agn.h"  #include "iwl-agn-hw.h"  #include "iwl-5000-hw.h" +#include "iwl-trans.h"  /* Highest firmware API version supported */  #define IWL5000_UCODE_API_MAX 5 @@ -57,32 +57,19 @@  #define IWL5150_UCODE_API_MIN 1  #define IWL5000_FW_PRE "iwlwifi-5000-" -#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode" +#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE __stringify(api) ".ucode"  #define IWL5150_FW_PRE "iwlwifi-5150-" -#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" +#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE __stringify(api) ".ucode"  /* NIC configuration for 5000 series */  static void iwl5000_nic_config(struct iwl_priv *priv)  {  	unsigned long flags; -	u16 radio_cfg; -	spin_lock_irqsave(&priv->lock, flags); - -	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); - -	/* write radio config values to register */ -	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_RF_CONFIG_TYPE_MAX) -		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, -			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | -			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) | -			    EEPROM_RF_CFG_DASH_MSK(radio_cfg)); +	iwl_rf_config(priv); -	/* set CSR_HW_CONFIG_REG for uCode use */ -	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, -		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | -		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); +	spin_lock_irqsave(&priv->lock, flags);  	/* W/A : NIC is stuck in a reset state after Early PCIe power off  	 * (PCIe power is lost before PERST# is asserted), @@ -170,7 +157,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)  			iwlagn_mod_params.num_of_queues;  	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; -	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;  	priv->hw_params.scd_bc_tbls_size =  			priv->cfg->base_params->num_of_queues *  			sizeof(struct iwlagn_scd_bc_tbl); @@ -183,7 +169,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)  	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); @@ -215,7 +200,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)  			iwlagn_mod_params.num_of_queues;  	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; -	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;  	priv->hw_params.scd_bc_tbls_size =  			priv->cfg->base_params->num_of_queues *  			sizeof(struct iwlagn_scd_bc_tbl); @@ -228,7 +212,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)  	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); @@ -332,7 +315,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,  		return -EFAULT;  	} -	return iwl_send_cmd_sync(priv, &hcmd); +	return trans_send_cmd(priv, &hcmd);  }  static struct iwl_lib_ops iwl5000_lib = { @@ -340,13 +323,8 @@ static struct iwl_lib_ops iwl5000_lib = {  	.rx_handler_setup = iwlagn_rx_handler_setup,  	.setup_deferred_work = iwlagn_setup_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.send_tx_power = iwlagn_send_tx_power, -	.update_chain_flags = iwl_update_chain_flags,  	.set_channel_switch = iwl5000_hw_channel_switch, -	.apm_ops = { -		.init = iwl_apm_init, -		.config = iwl5000_nic_config, -	}, +	.nic_config = iwl5000_nic_config,  	.eeprom_ops = {  		.regulatory_bands = {  			EEPROM_REG_BAND_1_CHANNELS, @@ -357,13 +335,8 @@ static struct iwl_lib_ops iwl5000_lib = {  			EEPROM_REG_BAND_24_HT40_CHANNELS,  			EEPROM_REG_BAND_52_HT40_CHANNELS  		}, -		.query_addr = iwlagn_eeprom_query_addr,  	}, -	.temp_ops = { -		.temperature = iwlagn_temperature, -	 }, -	.txfifo_flush = iwlagn_txfifo_flush, -	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, +	.temperature = iwlagn_temperature,  };  static struct iwl_lib_ops iwl5150_lib = { @@ -371,13 +344,8 @@ static struct iwl_lib_ops iwl5150_lib = {  	.rx_handler_setup = iwlagn_rx_handler_setup,  	.setup_deferred_work = iwlagn_setup_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.send_tx_power = iwlagn_send_tx_power, -	.update_chain_flags = iwl_update_chain_flags,  	.set_channel_switch = iwl5000_hw_channel_switch, -	.apm_ops = { -		.init = iwl_apm_init, -		.config = iwl5000_nic_config, -	}, +	.nic_config = iwl5000_nic_config,  	.eeprom_ops = {  		.regulatory_bands = {  			EEPROM_REG_BAND_1_CHANNELS, @@ -388,25 +356,16 @@ static struct iwl_lib_ops iwl5150_lib = {  			EEPROM_REG_BAND_24_HT40_CHANNELS,  			EEPROM_REG_BAND_52_HT40_CHANNELS  		}, -		.query_addr = iwlagn_eeprom_query_addr,  	}, -	.temp_ops = { -		.temperature = iwl5150_temperature, -	 }, -	.txfifo_flush = iwlagn_txfifo_flush, -	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, +	.temperature = iwl5150_temperature,  };  static const struct iwl_ops iwl5000_ops = {  	.lib = &iwl5000_lib, -	.hcmd = &iwlagn_hcmd, -	.utils = &iwlagn_hcmd_utils,  };  static const struct iwl_ops iwl5150_ops = {  	.lib = &iwl5150_lib, -	.hcmd = &iwlagn_hcmd, -	.utils = &iwlagn_hcmd_utils,  };  static struct iwl_base_params iwl5000_base_params = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index fbe565c816e..80f1ef61a3d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -27,8 +27,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/init.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h>  #include <linux/delay.h>  #include <linux/skbuff.h>  #include <linux/netdevice.h> @@ -36,6 +34,7 @@  #include <net/mac80211.h>  #include <linux/etherdevice.h>  #include <asm/unaligned.h> +#include <linux/stringify.h>  #include "iwl-eeprom.h"  #include "iwl-dev.h" @@ -46,6 +45,7 @@  #include "iwl-helpers.h"  #include "iwl-agn-hw.h"  #include "iwl-6000-hw.h" +#include "iwl-trans.h"  /* Highest firmware API version supported */  #define IWL6000_UCODE_API_MAX 4 @@ -58,16 +58,16 @@  #define IWL6000G2_UCODE_API_MIN 4  #define IWL6000_FW_PRE "iwlwifi-6000-" -#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" +#define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE __stringify(api) ".ucode"  #define IWL6050_FW_PRE "iwlwifi-6050-" -#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" +#define IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE __stringify(api) ".ucode"  #define IWL6005_FW_PRE "iwlwifi-6000g2a-" -#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode" +#define IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE __stringify(api) ".ucode"  #define IWL6030_FW_PRE "iwlwifi-6000g2b-" -#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode" +#define IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE __stringify(api) ".ucode"  static void iwl6000_set_ct_threshold(struct iwl_priv *priv)  { @@ -97,21 +97,7 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)  /* NIC configuration for 6000 series */  static void iwl6000_nic_config(struct iwl_priv *priv)  { -	u16 radio_cfg; - -	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); - -	/* write radio config values to register */ -	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) -		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, -			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | -			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) | -			    EEPROM_RF_CFG_DASH_MSK(radio_cfg)); - -	/* set CSR_HW_CONFIG_REG for uCode use */ -	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, -		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | -		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); +	iwl_rf_config(priv);  	/* no locking required for register write */  	if (priv->cfg->pa_type == IWL_PA_INTERNAL) { @@ -159,7 +145,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)  			iwlagn_mod_params.num_of_queues;  	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; -	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;  	priv->hw_params.scd_bc_tbls_size =  			priv->cfg->base_params->num_of_queues *  			sizeof(struct iwlagn_scd_bc_tbl); @@ -172,7 +157,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)  	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);  	if (priv->cfg->rx_with_siso_diversity) @@ -271,7 +255,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,  		return -EFAULT;  	} -	return iwl_send_cmd_sync(priv, &hcmd); +	return trans_send_cmd(priv, &hcmd);  }  static struct iwl_lib_ops iwl6000_lib = { @@ -279,13 +263,8 @@ static struct iwl_lib_ops iwl6000_lib = {  	.rx_handler_setup = iwlagn_rx_handler_setup,  	.setup_deferred_work = iwlagn_setup_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.send_tx_power = iwlagn_send_tx_power, -	.update_chain_flags = iwl_update_chain_flags,  	.set_channel_switch = iwl6000_hw_channel_switch, -	.apm_ops = { -		.init = iwl_apm_init, -		.config = iwl6000_nic_config, -	}, +	.nic_config = iwl6000_nic_config,  	.eeprom_ops = {  		.regulatory_bands = {  			EEPROM_REG_BAND_1_CHANNELS, @@ -296,14 +275,9 @@ static struct iwl_lib_ops iwl6000_lib = {  			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,  			EEPROM_REG_BAND_52_HT40_CHANNELS  		}, -		.query_addr = iwlagn_eeprom_query_addr,  		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,  	}, -	.temp_ops = { -		.temperature = iwlagn_temperature, -	 }, -	.txfifo_flush = iwlagn_txfifo_flush, -	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, +	.temperature = iwlagn_temperature,  };  static struct iwl_lib_ops iwl6030_lib = { @@ -312,13 +286,8 @@ static struct iwl_lib_ops iwl6030_lib = {  	.setup_deferred_work = iwlagn_bt_setup_deferred_work,  	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,  	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, -	.send_tx_power = iwlagn_send_tx_power, -	.update_chain_flags = iwl_update_chain_flags,  	.set_channel_switch = iwl6000_hw_channel_switch, -	.apm_ops = { -		.init = iwl_apm_init, -		.config = iwl6000_nic_config, -	}, +	.nic_config = iwl6000_nic_config,  	.eeprom_ops = {  		.regulatory_bands = {  			EEPROM_REG_BAND_1_CHANNELS, @@ -329,14 +298,9 @@ static struct iwl_lib_ops iwl6030_lib = {  			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,  			EEPROM_REG_BAND_52_HT40_CHANNELS  		}, -		.query_addr = iwlagn_eeprom_query_addr,  		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,  	}, -	.temp_ops = { -		.temperature = iwlagn_temperature, -	 }, -	.txfifo_flush = iwlagn_txfifo_flush, -	.dev_txfifo_flush = iwlagn_dev_txfifo_flush, +	.temperature = iwlagn_temperature,  };  static struct iwl_nic_ops iwl6050_nic_ops = { @@ -349,28 +313,20 @@ static struct iwl_nic_ops iwl6150_nic_ops = {  static const struct iwl_ops iwl6000_ops = {  	.lib = &iwl6000_lib, -	.hcmd = &iwlagn_hcmd, -	.utils = &iwlagn_hcmd_utils,  };  static const struct iwl_ops iwl6050_ops = {  	.lib = &iwl6000_lib, -	.hcmd = &iwlagn_hcmd, -	.utils = &iwlagn_hcmd_utils,  	.nic = &iwl6050_nic_ops,  };  static const struct iwl_ops iwl6150_ops = {  	.lib = &iwl6000_lib, -	.hcmd = &iwlagn_hcmd, -	.utils = &iwlagn_hcmd_utils,  	.nic = &iwl6150_nic_ops,  };  static const struct iwl_ops iwl6030_ops = {  	.lib = &iwl6030_lib, -	.hcmd = &iwlagn_bt_hcmd, -	.utils = &iwlagn_hcmd_utils,  };  static struct iwl_base_params iwl6000_base_params = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index c9255def108..02c7c65ee86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -66,6 +66,8 @@  #include "iwl-dev.h"  #include "iwl-core.h"  #include "iwl-agn-calib.h" +#include "iwl-trans.h" +#include "iwl-agn.h"  /*****************************************************************************   * INIT calibrations framework @@ -87,6 +89,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)  	struct iwl_host_cmd hcmd = {  		.id = REPLY_PHY_CALIBRATION_CMD, +		.flags = CMD_SYNC,  	};  	for (i = 0; i < IWL_CALIB_MAX; i++) { @@ -95,7 +98,7 @@ int iwl_send_calib_results(struct iwl_priv *priv)  			hcmd.len[0] = priv->calib_results[i].buf_len;  			hcmd.data[0] = priv->calib_results[i].buf;  			hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; -			ret = iwl_send_cmd_sync(priv, &hcmd); +			ret = trans_send_cmd(priv, &hcmd);  			if (ret) {  				IWL_ERR(priv, "Error %d iteration %d\n",  					ret, i); @@ -481,7 +484,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)  	memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),  	       sizeof(u16)*HD_TABLE_SIZE); -	return iwl_send_cmd(priv, &cmd_out); +	return trans_send_cmd(priv, &cmd_out);  }  /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ @@ -545,7 +548,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)  	       &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]),  	       sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES); -	return iwl_send_cmd(priv, &cmd_out); +	return trans_send_cmd(priv, &cmd_out);  }  void iwl_init_sensitivity(struct iwl_priv *priv) @@ -991,16 +994,14 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)  	IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",  			min_average_noise, min_average_noise_antenna_i); -	if (priv->cfg->ops->utils->gain_computation) -		priv->cfg->ops->utils->gain_computation(priv, average_noise, +	iwlagn_gain_computation(priv, average_noise,  				min_average_noise_antenna_i, min_average_noise,  				find_first_chain(priv->cfg->valid_rx_ant));  	/* Some power changes may have been made during the calibration.  	 * Update and commit the RXON  	 */ -	if (priv->cfg->ops->lib->update_chain_flags) -		priv->cfg->ops->lib->update_chain_flags(priv); +	iwl_update_chain_flags(priv);  	data->state = IWL_CHAIN_NOISE_DONE;  	iwl_power_update_mode(priv, false); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h index 4ef4dd93425..a869fc9205d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h @@ -71,13 +71,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv);  void iwl_init_sensitivity(struct iwl_priv *priv);  void iwl_reset_run_time_calib(struct iwl_priv *priv); -static inline void iwl_chain_noise_reset(struct iwl_priv *priv) -{ - -	if (!priv->disable_chain_noise_cal && -	    priv->cfg->ops->utils->chain_noise_reset) -		priv->cfg->ops->utils->chain_noise_reset(priv); -}  int iwl_send_calib_results(struct iwl_priv *priv);  int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index 2ef9448b1c2..b8347db850e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -108,18 +108,16 @@ err:  int iwl_eeprom_check_sku(struct iwl_priv *priv)  { -	u16 eeprom_sku;  	u16 radio_cfg; -	eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); -  	if (!priv->cfg->sku) {  		/* not using sku overwrite */ -		priv->cfg->sku = -			((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >> -			EEPROM_SKU_CAP_BAND_POS); -		if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE) -			priv->cfg->sku |= IWL_SKU_N; +		priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); +		if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE && +		    !priv->cfg->ht_params) { +			IWL_ERR(priv, "Invalid 11n configuration\n"); +			return -EINVAL; +		}  	}  	if (!priv->cfg->sku) {  		IWL_ERR(priv, "Invalid device sku\n"); @@ -152,7 +150,7 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv)  void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)  { -	const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv, +	const u8 *addr = iwl_eeprom_query_addr(priv,  					EEPROM_MAC_ADDRESS);  	memcpy(mac, addr, ETH_ALEN);  } @@ -247,10 +245,10 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)  	BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);  	/* the length is in 16-bit words, but we want entries */ -	txp_len = (__le16 *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS); +	txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);  	entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; -	txp_array = (void *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_OFFS); +	txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);  	for (idx = 0; idx < entries; idx++) {  		txp = &txp_array[idx]; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 23fa93deae9..f0f5f5eada7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -36,6 +36,7 @@  #include "iwl-core.h"  #include "iwl-io.h"  #include "iwl-agn.h" +#include "iwl-trans.h"  int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)  { @@ -45,7 +46,9 @@ int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)  	if (IWL_UCODE_API(priv->ucode_ver) > 1) {  		IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); -		return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, +		return trans_send_cmd_pdu(priv, +					TX_ANT_CONFIGURATION_CMD, +					CMD_SYNC,  					sizeof(struct iwl_tx_ant_config_cmd),  					&tx_ant_cmd);  	} else { @@ -54,17 +57,7 @@ int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)  	}  } -static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) -{ -	u16 size = (u16)sizeof(struct iwl_addsta_cmd); -	struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; -	memcpy(addsta, cmd, size); -	/* resrved in 5000 */ -	addsta->rate_n_flags = cpu_to_le16(0); -	return size; -} - -static void iwlagn_gain_computation(struct iwl_priv *priv, +void iwlagn_gain_computation(struct iwl_priv *priv,  		u32 average_noise[NUM_RX_CHAINS],  		u16 min_average_noise_antenna_i,  		u32 min_average_noise, @@ -111,105 +104,19 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,  		memset(&cmd, 0, sizeof(cmd)); -		cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_gain_cmd; -		cmd.hdr.first_group = 0; -		cmd.hdr.groups_num = 1; -		cmd.hdr.data_valid = 1; +		iwl_set_calib_hdr(&cmd.hdr, +			priv->_agn.phy_calib_chain_noise_gain_cmd);  		cmd.delta_gain_1 = data->delta_gain_code[1];  		cmd.delta_gain_2 = data->delta_gain_code[2]; -		iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, -			sizeof(cmd), &cmd, NULL); +		trans_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, +			CMD_ASYNC, sizeof(cmd), &cmd);  		data->radio_write = 1;  		data->state = IWL_CHAIN_NOISE_CALIBRATED;  	}  } -static void iwlagn_chain_noise_reset(struct iwl_priv *priv) -{ -	struct iwl_chain_noise_data *data = &priv->chain_noise_data; -	int ret; - -	if ((data->state == IWL_CHAIN_NOISE_ALIVE) && -	    iwl_is_any_associated(priv)) { -		struct iwl_calib_chain_noise_reset_cmd cmd; - -		/* clear data for chain noise calibration algorithm */ -		data->chain_noise_a = 0; -		data->chain_noise_b = 0; -		data->chain_noise_c = 0; -		data->chain_signal_a = 0; -		data->chain_signal_b = 0; -		data->chain_signal_c = 0; -		data->beacon_count = 0; - -		memset(&cmd, 0, sizeof(cmd)); -		cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_reset_cmd; -		cmd.hdr.first_group = 0; -		cmd.hdr.groups_num = 1; -		cmd.hdr.data_valid = 1; -		ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, -					sizeof(cmd), &cmd); -		if (ret) -			IWL_ERR(priv, -				"Could not send REPLY_PHY_CALIBRATION_CMD\n"); -		data->state = IWL_CHAIN_NOISE_ACCUMULATE; -		IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); -	} -} - -static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, -				     struct ieee80211_tx_info *info, -				     __le16 fc, __le32 *tx_flags) -{ -	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || -	    info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT || -	    info->flags & IEEE80211_TX_CTL_AMPDU) -		*tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; -} - -/* Calc max signal level (dBm) among 3 possible receivers */ -static int iwlagn_calc_rssi(struct iwl_priv *priv, -			     struct iwl_rx_phy_res *rx_resp) -{ -	/* data from PHY/DSP regarding signal strength, etc., -	 *   contents are always there, not configurable by host -	 */ -	struct iwlagn_non_cfg_phy *ncphy = -		(struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf; -	u32 val, rssi_a, rssi_b, rssi_c, max_rssi; -	u8 agc; - -	val  = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]); -	agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS; - -	/* Find max rssi among 3 possible receivers. -	 * These values are measured by the digital signal processor (DSP). -	 * They should stay fairly constant even as the signal strength varies, -	 *   if the radio's automatic gain control (AGC) is working right. -	 * AGC value (see below) will provide the "interesting" info. -	 */ -	val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]); -	rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >> -		IWLAGN_OFDM_RSSI_A_BIT_POS; -	rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >> -		IWLAGN_OFDM_RSSI_B_BIT_POS; -	val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]); -	rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >> -		IWLAGN_OFDM_RSSI_C_BIT_POS; - -	max_rssi = max_t(u32, rssi_a, rssi_b); -	max_rssi = max_t(u32, max_rssi, rssi_c); - -	IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", -		rssi_a, rssi_b, rssi_c, max_rssi, agc); - -	/* dBm = max_rssi dB - agc dB - constant. -	 * Higher AGC (higher radio gain) means lower signal. */ -	return max_rssi - agc - IWLAGN_RSSI_OFFSET; -} - -static int iwlagn_set_pan_params(struct iwl_priv *priv) +int iwlagn_set_pan_params(struct iwl_priv *priv)  {  	struct iwl_wipan_params_cmd cmd;  	struct iwl_rxon_context *ctx_bss, *ctx_pan; @@ -294,35 +201,10 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv)  	cmd.slots[0].width = cpu_to_le16(slot0);  	cmd.slots[1].width = cpu_to_le16(slot1); -	ret = iwl_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, sizeof(cmd), &cmd); +	ret = trans_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, CMD_SYNC, +			sizeof(cmd), &cmd);  	if (ret)  		IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);  	return ret;  } - -struct iwl_hcmd_ops iwlagn_hcmd = { -	.commit_rxon = iwlagn_commit_rxon, -	.set_rxon_chain = iwlagn_set_rxon_chain, -	.set_tx_ant = iwlagn_send_tx_ant_config, -	.send_bt_config = iwl_send_bt_config, -	.set_pan_params = iwlagn_set_pan_params, -}; - -struct iwl_hcmd_ops iwlagn_bt_hcmd = { -	.commit_rxon = iwlagn_commit_rxon, -	.set_rxon_chain = iwlagn_set_rxon_chain, -	.set_tx_ant = iwlagn_send_tx_ant_config, -	.send_bt_config = iwlagn_send_advance_bt_config, -	.set_pan_params = iwlagn_set_pan_params, -}; - -struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { -	.build_addsta_hcmd = iwlagn_build_addsta_hcmd, -	.gain_computation = iwlagn_gain_computation, -	.chain_noise_reset = iwlagn_chain_noise_reset, -	.tx_cmd_protection = iwlagn_tx_cmd_protection, -	.calc_rssi = iwlagn_calc_rssi, -	.request_scan = iwlagn_request_scan, -	.post_scan = iwlagn_post_scan, -}; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index 7bd19f4e66d..0e5b842529c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -81,13 +81,6 @@  /* RSSI to dBm */  #define IWLAGN_RSSI_OFFSET	44 -/* PCI registers */ -#define PCI_CFG_RETRY_TIMEOUT	0x041 - -/* PCI register values */ -#define PCI_CFG_LINK_CTRL_VAL_L0S_EN	0x01 -#define PCI_CFG_LINK_CTRL_VAL_L1_EN	0x02 -  #define IWLAGN_DEFAULT_TX_RETRY  15  /* Limit range of txpower output target to be between these values */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index 0d5fda44c3a..f1b40ec1c87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c @@ -44,7 +44,7 @@  void iwl_free_isr_ict(struct iwl_priv *priv)  {  	if (priv->_agn.ict_tbl_vir) { -		dma_free_coherent(&priv->pci_dev->dev, +		dma_free_coherent(priv->bus.dev,  				  (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,  				  priv->_agn.ict_tbl_vir,  				  priv->_agn.ict_tbl_dma); @@ -61,7 +61,7 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv)  	/* allocate shrared data table */  	priv->_agn.ict_tbl_vir = -		dma_alloc_coherent(&priv->pci_dev->dev, +		dma_alloc_coherent(priv->bus.dev,  				   (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,  				   &priv->_agn.ict_tbl_dma, GFP_KERNEL);  	if (!priv->_agn.ict_tbl_vir) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index f803fb62f8b..eb2be0d3048 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -39,6 +39,7 @@  #include "iwl-agn-hw.h"  #include "iwl-agn.h"  #include "iwl-sta.h" +#include "iwl-trans.h"  static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp)  { @@ -408,9 +409,9 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,  	unsigned long flags;  	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { -		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " -			  "is out of range [0-%d] %d %d\n", txq_id, -			  index, txq->q.n_bd, txq->q.write_ptr, +		IWL_ERR(priv, "%s: Read index for DMA queue txq_id (%d) " +			  "index %d is out of range [0-%d] %d %d\n", __func__, +			  txq_id, index, txq->q.n_bd, txq->q.write_ptr,  			  txq->q.read_ptr);  		return;  	} @@ -438,7 +439,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,  		if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&  		    priv->cfg->bt_params &&  		    priv->cfg->bt_params->advanced_bt_coexist) { -			IWL_WARN(priv, "receive reply tx with bt_kill\n"); +			IWL_DEBUG_COEX(priv, "receive reply tx with bt_kill\n");  		}  		iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); @@ -540,8 +541,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)  	else  		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; -	return iwl_send_cmd_pdu(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd), -				&tx_power_cmd); +	return trans_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC, +			sizeof(tx_power_cmd), &tx_power_cmd);  }  void iwlagn_temperature(struct iwl_priv *priv) @@ -610,8 +611,7 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)  	return (address & ADDRESS_MSK) + (offset << 1);  } -const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, -					   size_t offset) +const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)  {  	u32 address = eeprom_indirect_address(priv, offset);  	BUG_ON(address >= priv->cfg->base_params->eeprom_size); @@ -622,41 +622,12 @@ struct iwl_mod_params iwlagn_mod_params = {  	.amsdu_size_8K = 1,  	.restart_fw = 1,  	.plcp_check = true, +	.bt_coex_active = true, +	.no_sleep_autoadjust = true, +	.power_level = IWL_POWER_INDEX_1,  	/* the rest are 0 by default */  }; -void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ -	unsigned long flags; -	int i; -	spin_lock_irqsave(&rxq->lock, flags); -	INIT_LIST_HEAD(&rxq->rx_free); -	INIT_LIST_HEAD(&rxq->rx_used); -	/* Fill the rx_used queue with _all_ of the Rx buffers */ -	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { -		/* In the reset function, these buffers may have been allocated -		 * to an SKB, so we need to unmap and free potential storage */ -		if (rxq->pool[i].page != NULL) { -			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, -				PAGE_SIZE << priv->hw_params.rx_page_order, -				PCI_DMA_FROMDEVICE); -			__iwl_free_pages(priv, rxq->pool[i].page); -			rxq->pool[i].page = NULL; -		} -		list_add_tail(&rxq->pool[i].list, &rxq->rx_used); -	} - -	for (i = 0; i < RX_QUEUE_SIZE; i++) -		rxq->queue[i] = NULL; - -	/* Set us so that we have processed and used all buffers, but have -	 * not restocked the Rx queue with fresh buffers */ -	rxq->read = rxq->write = 0; -	rxq->write_actual = 0; -	rxq->free_count = 0; -	spin_unlock_irqrestore(&rxq->lock, flags); -} -  int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)  {  	u32 rb_size; @@ -728,11 +699,10 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)  {  	unsigned long flags;  	struct iwl_rx_queue *rxq = &priv->rxq; -	int ret;  	/* nic_init */  	spin_lock_irqsave(&priv->lock, flags); -	priv->cfg->ops->lib->apm_ops.init(priv); +	iwl_apm_init(priv);  	/* Set interrupt coalescing calibration timer to default (512 usecs) */  	iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); @@ -741,17 +711,10 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)  	iwlagn_set_pwr_vmain(priv); -	priv->cfg->ops->lib->apm_ops.config(priv); +	priv->cfg->ops->lib->nic_config(priv);  	/* Allocate the RX queue, or reset if it is already allocated */ -	if (!rxq->bd) { -		ret = iwl_rx_queue_alloc(priv); -		if (ret) { -			IWL_ERR(priv, "Unable to initialize Rx queue\n"); -			return -ENOMEM; -		} -	} else -		iwlagn_rx_queue_reset(priv, rxq); +	trans_rx_init(priv);  	iwlagn_rx_replenish(priv); @@ -765,12 +728,8 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)  	spin_unlock_irqrestore(&priv->lock, flags);  	/* Allocate or reset and init all Tx and Command queues */ -	if (!priv->txq) { -		ret = iwlagn_txq_ctx_alloc(priv); -		if (ret) -			return ret; -	} else -		iwlagn_txq_ctx_reset(priv); +	if (trans_tx_init(priv)) +		return -ENOMEM;  	if (priv->cfg->base_params->shadow_reg_enable) {  		/* enable shadow regs in HW */ @@ -911,9 +870,9 @@ void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority)  		BUG_ON(rxb->page);  		rxb->page = page;  		/* Get physical address of the RB */ -		rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, +		rxb->page_dma = dma_map_page(priv->bus.dev, page, 0,  				PAGE_SIZE << priv->hw_params.rx_page_order, -				PCI_DMA_FROMDEVICE); +				DMA_FROM_DEVICE);  		/* dma address must be no more than 36 bits */  		BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));  		/* and also 256 byte aligned! */ @@ -946,43 +905,6 @@ void iwlagn_rx_replenish_now(struct iwl_priv *priv)  	iwlagn_rx_queue_restock(priv);  } -/* Assumes that the skb field of the buffers in 'pool' is kept accurate. - * If an SKB has been detached, the POOL needs to have its SKB set to NULL - * This free routine walks the list of POOL entries and if SKB is set to - * non NULL it is unmapped and freed - */ -void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ -	int i; -	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { -		if (rxq->pool[i].page != NULL) { -			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, -				PAGE_SIZE << priv->hw_params.rx_page_order, -				PCI_DMA_FROMDEVICE); -			__iwl_free_pages(priv, rxq->pool[i].page); -			rxq->pool[i].page = NULL; -		} -	} - -	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, -			  rxq->bd_dma); -	dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), -			  rxq->rb_stts, rxq->rb_stts_dma); -	rxq->bd = NULL; -	rxq->rb_stts  = NULL; -} - -int iwlagn_rxq_stop(struct iwl_priv *priv) -{ - -	/* stop Rx DMA */ -	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); -	iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, -			    FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); - -	return 0; -} -  int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)  {  	int idx = 0; @@ -1141,6 +1063,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)  	struct iwl_host_cmd cmd = {  		.id = REPLY_SCAN_CMD,  		.len = { sizeof(struct iwl_scan_cmd), }, +		.flags = CMD_SYNC,  	};  	struct iwl_scan_cmd *scan;  	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; @@ -1433,17 +1356,14 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)  	/* set scan bit here for PAN params */  	set_bit(STATUS_SCAN_HW, &priv->status); -	if (priv->cfg->ops->hcmd->set_pan_params) { -		ret = priv->cfg->ops->hcmd->set_pan_params(priv); -		if (ret) -			return ret; -	} +	ret = iwlagn_set_pan_params(priv); +	if (ret) +		return ret; -	ret = iwl_send_cmd_sync(priv, &cmd); +	ret = trans_send_cmd(priv, &cmd);  	if (ret) {  		clear_bit(STATUS_SCAN_HW, &priv->status); -		if (priv->cfg->ops->hcmd->set_pan_params) -			priv->cfg->ops->hcmd->set_pan_params(priv); +		iwlagn_set_pan_params(priv);  	}  	return ret; @@ -1528,23 +1448,32 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)  	might_sleep();  	memset(&flush_cmd, 0, sizeof(flush_cmd)); -	flush_cmd.fifo_control = IWL_TX_FIFO_VO_MSK | IWL_TX_FIFO_VI_MSK | -				 IWL_TX_FIFO_BE_MSK | IWL_TX_FIFO_BK_MSK; -	if (priv->cfg->sku & IWL_SKU_N) +	if (flush_control & BIT(IWL_RXON_CTX_BSS)) +		flush_cmd.fifo_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK | +				 IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | +				 IWL_SCD_MGMT_MSK; +	if ((flush_control & BIT(IWL_RXON_CTX_PAN)) && +	    (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))) +		flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK | +				IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK | +				IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | +				IWL_PAN_SCD_MULTICAST_MSK; + +	if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)  		flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;  	IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",  		       flush_cmd.fifo_control);  	flush_cmd.flush_control = cpu_to_le16(flush_control); -	return iwl_send_cmd(priv, &cmd); +	return trans_send_cmd(priv, &cmd);  }  void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)  {  	mutex_lock(&priv->mutex);  	ieee80211_stop_queues(priv->hw); -	if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) { +	if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {  		IWL_ERR(priv, "flush request fail\n");  		goto done;  	} @@ -1699,18 +1628,21 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)  	 * (might be in monitor mode), or the interface is in  	 * IBSS mode (no proper uCode support for coex then).  	 */ -	if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) { +	if (!iwlagn_mod_params.bt_coex_active || +	    priv->iw_mode == NL80211_IFTYPE_ADHOC) {  		basic.flags = IWLAGN_BT_FLAG_COEX_MODE_DISABLED;  	} else {  		basic.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<  					IWLAGN_BT_FLAG_COEX_MODE_SHIFT; -		if (priv->cfg->bt_params && -		    priv->cfg->bt_params->bt_sco_disable) + +		if (!priv->bt_enable_pspoll)  			basic.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE; +		else +			basic.flags &= ~IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;  		if (priv->bt_ch_announce)  			basic.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION; -		IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", basic.flags); +		IWL_DEBUG_COEX(priv, "BT coex flag: 0X%x\n", basic.flags);  	}  	priv->bt_enable_flag = basic.flags;  	if (priv->bt_full_concurrent) @@ -1720,7 +1652,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)  		memcpy(basic.bt3_lookup_table, iwlagn_def_3w_lookup,  			sizeof(iwlagn_def_3w_lookup)); -	IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n", +	IWL_DEBUG_COEX(priv, "BT coex %s in %s mode\n",  		       basic.flags ? "active" : "disabled",  		       priv->bt_full_concurrent ?  		       "full concurrency" : "3-wire"); @@ -1728,19 +1660,97 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)  	if (priv->cfg->bt_params->bt_session_2) {  		memcpy(&bt_cmd_2000.basic, &basic,  			sizeof(basic)); -		ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, -			sizeof(bt_cmd_2000), &bt_cmd_2000); +		ret = trans_send_cmd_pdu(priv, REPLY_BT_CONFIG, +			CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);  	} else {  		memcpy(&bt_cmd_6000.basic, &basic,  			sizeof(basic)); -		ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, -			sizeof(bt_cmd_6000), &bt_cmd_6000); +		ret = trans_send_cmd_pdu(priv, REPLY_BT_CONFIG, +			CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);  	}  	if (ret)  		IWL_ERR(priv, "failed to send BT Coex Config\n");  } +void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena) +{ +	struct iwl_rxon_context *ctx, *found_ctx = NULL; +	bool found_ap = false; + +	lockdep_assert_held(&priv->mutex); + +	/* Check whether AP or GO mode is active. */ +	if (rssi_ena) { +		for_each_context(priv, ctx) { +			if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_AP && +			    iwl_is_associated_ctx(ctx)) { +				found_ap = true; +				break; +			} +		} +	} + +	/* +	 * If disable was received or If GO/AP mode, disable RSSI +	 * measurements. +	 */ +	if (!rssi_ena || found_ap) { +		if (priv->cur_rssi_ctx) { +			ctx = priv->cur_rssi_ctx; +			ieee80211_disable_rssi_reports(ctx->vif); +			priv->cur_rssi_ctx = NULL; +		} +		return; +	} + +	/* +	 * If rssi measurements need to be enabled, consider all cases now. +	 * Figure out how many contexts are active. +	 */ +	for_each_context(priv, ctx) { +		if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION && +		    iwl_is_associated_ctx(ctx)) { +			found_ctx = ctx; +			break; +		} +	} + +	/* +	 * rssi monitor already enabled for the correct interface...nothing +	 * to do. +	 */ +	if (found_ctx == priv->cur_rssi_ctx) +		return; + +	/* +	 * Figure out if rssi monitor is currently enabled, and needs +	 * to be changed. If rssi monitor is already enabled, disable +	 * it first else just enable rssi measurements on the +	 * interface found above. +	 */ +	if (priv->cur_rssi_ctx) { +		ctx = priv->cur_rssi_ctx; +		if (ctx->vif) +			ieee80211_disable_rssi_reports(ctx->vif); +	} + +	priv->cur_rssi_ctx = found_ctx; + +	if (!found_ctx) +		return; + +	ieee80211_enable_rssi_reports(found_ctx->vif, +			IWLAGN_BT_PSP_MIN_RSSI_THRESHOLD, +			IWLAGN_BT_PSP_MAX_RSSI_THRESHOLD); +} + +static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg) +{ +	return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >> +			BT_UART_MSG_FRAME3SCOESCO_POS; +} +  static void iwlagn_bt_traffic_change_work(struct work_struct *work)  {  	struct iwl_priv *priv = @@ -1758,7 +1768,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)  	 * coex profile notifications. Ignore that since only bad consequence  	 * can be not matching debug print with actual state.  	 */ -	IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n", +	IWL_DEBUG_COEX(priv, "BT traffic load changes: %d\n",  		       priv->bt_traffic_load);  	switch (priv->bt_traffic_load) { @@ -1793,23 +1803,43 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)  	if (test_bit(STATUS_SCAN_HW, &priv->status))  		goto out; -	if (priv->cfg->ops->lib->update_chain_flags) -		priv->cfg->ops->lib->update_chain_flags(priv); +	iwl_update_chain_flags(priv);  	if (smps_request != -1) { +		priv->current_ht_config.smps = smps_request;  		for_each_context(priv, ctx) {  			if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)  				ieee80211_request_smps(ctx->vif, smps_request);  		}  	} + +	/* +	 * Dynamic PS poll related functionality. Adjust RSSI measurements if +	 * necessary. +	 */ +	iwlagn_bt_coex_rssi_monitor(priv);  out:  	mutex_unlock(&priv->mutex);  } +/* + * If BT sco traffic, and RSSI monitor is enabled, move measurements to the + * correct interface or disable it if this is the last interface to be + * removed. + */ +void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv) +{ +	if (priv->bt_is_sco && +	    priv->bt_traffic_load == IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS) +		iwlagn_bt_adjust_rssi_monitor(priv, true); +	else +		iwlagn_bt_adjust_rssi_monitor(priv, false); +} +  static void iwlagn_print_uartmsg(struct iwl_priv *priv,  				struct iwl_bt_uart_msg *uart_msg)  { -	IWL_DEBUG_NOTIF(priv, "Message Type = 0x%X, SSN = 0x%X, " +	IWL_DEBUG_COEX(priv, "Message Type = 0x%X, SSN = 0x%X, "  			"Update Req = 0x%X",  		(BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >>  			BT_UART_MSG_FRAME1MSGTYPE_POS, @@ -1818,7 +1848,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,  		(BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >>  			BT_UART_MSG_FRAME1UPDATEREQ_POS); -	IWL_DEBUG_NOTIF(priv, "Open connections = 0x%X, Traffic load = 0x%X, " +	IWL_DEBUG_COEX(priv, "Open connections = 0x%X, Traffic load = 0x%X, "  			"Chl_SeqN = 0x%X, In band = 0x%X",  		(BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >>  			BT_UART_MSG_FRAME2OPENCONNECTIONS_POS, @@ -1829,7 +1859,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,  		(BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >>  			BT_UART_MSG_FRAME2INBAND_POS); -	IWL_DEBUG_NOTIF(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, " +	IWL_DEBUG_COEX(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "  			"ACL = 0x%X, Master = 0x%X, OBEX = 0x%X",  		(BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>  			BT_UART_MSG_FRAME3SCOESCO_POS, @@ -1844,11 +1874,11 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,  		(BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >>  			BT_UART_MSG_FRAME3OBEX_POS); -	IWL_DEBUG_NOTIF(priv, "Idle duration = 0x%X", +	IWL_DEBUG_COEX(priv, "Idle duration = 0x%X",  		(BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >>  			BT_UART_MSG_FRAME4IDLEDURATION_POS); -	IWL_DEBUG_NOTIF(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, " +	IWL_DEBUG_COEX(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "  			"eSCO Retransmissions = 0x%X",  		(BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >>  			BT_UART_MSG_FRAME5TXACTIVITY_POS, @@ -1857,13 +1887,13 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,  		(BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >>  			BT_UART_MSG_FRAME5ESCORETRANSMIT_POS); -	IWL_DEBUG_NOTIF(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X", +	IWL_DEBUG_COEX(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",  		(BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >>  			BT_UART_MSG_FRAME6SNIFFINTERVAL_POS,  		(BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>  			BT_UART_MSG_FRAME6DISCOVERABLE_POS); -	IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Page = " +	IWL_DEBUG_COEX(priv, "Sniff Activity = 0x%X, Page = "  			"0x%X, Inquiry = 0x%X, Connectable = 0x%X",  		(BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >>  			BT_UART_MSG_FRAME7SNIFFACTIVITY_POS, @@ -1913,14 +1943,16 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,  		return;  	} -	IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); -	IWL_DEBUG_NOTIF(priv, "    status: %d\n", coex->bt_status); -	IWL_DEBUG_NOTIF(priv, "    traffic load: %d\n", coex->bt_traffic_load); -	IWL_DEBUG_NOTIF(priv, "    CI compliance: %d\n", +	IWL_DEBUG_COEX(priv, "BT Coex notification:\n"); +	IWL_DEBUG_COEX(priv, "    status: %d\n", coex->bt_status); +	IWL_DEBUG_COEX(priv, "    traffic load: %d\n", coex->bt_traffic_load); +	IWL_DEBUG_COEX(priv, "    CI compliance: %d\n",  			coex->bt_ci_compliance);  	iwlagn_print_uartmsg(priv, uart_msg);  	priv->last_bt_traffic_load = priv->bt_traffic_load; +	priv->bt_is_sco = iwlagn_bt_traffic_is_sco(uart_msg); +  	if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {  		if (priv->bt_status != coex->bt_status ||  		    priv->last_bt_traffic_load != coex->bt_traffic_load) { @@ -2314,7 +2346,8 @@ int iwlagn_start_device(struct iwl_priv *priv)  {  	int ret; -	if (iwl_prepare_card_hw(priv)) { +	if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) && +	     iwl_prepare_card_hw(priv)) {  		IWL_WARN(priv, "Exit HW not ready\n");  		return -EIO;  	} @@ -2379,13 +2412,14 @@ void iwlagn_stop_device(struct iwl_priv *priv)  	 * already dead.  	 */  	if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { -                iwlagn_txq_ctx_stop(priv); -                iwlagn_rxq_stop(priv); +		trans_tx_stop(priv); +		trans_rx_stop(priv); -                /* Power-down device's busmaster DMA clocks */ -                iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); -                udelay(5); -        } +		/* Power-down device's busmaster DMA clocks */ +		iwl_write_prph(priv, APMG_CLK_DIS_REG, +			       APMG_CLK_VAL_DMA_CLK_RQT); +		udelay(5); +	}  	/* Make sure (redundant) we've released our request to stay awake */  	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 592b0cfcf71..ebcd13bc10d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -336,6 +336,12 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,  }  #ifdef CONFIG_MAC80211_DEBUGFS +/** + * Program the device to use fixed rate for frame transmit + * This is for debugging/testing only + * once the device start use fixed rate, we need to reload the module + * to being back the normal operation. + */  static void rs_program_fix_rate(struct iwl_priv *priv,  				struct iwl_lq_sta *lq_sta)  { @@ -348,13 +354,15 @@ static void rs_program_fix_rate(struct iwl_priv *priv,  	lq_sta->active_mimo2_rate  = 0x1FD0;	/* 6 - 60 MBits, no 9, no CCK */  	lq_sta->active_mimo3_rate  = 0x1FD0;	/* 6 - 60 MBits, no 9, no CCK */ -	lq_sta->dbg_fixed_rate = priv->dbg_fixed_rate; +	/* testmode has higher priority to overwirte the fixed rate */ +	if (priv->tm_fixed_rate) +		lq_sta->dbg_fixed_rate = priv->tm_fixed_rate;  	IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", -		lq_sta->lq.sta_id, priv->dbg_fixed_rate); +		lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); -	if (priv->dbg_fixed_rate) { -		rs_fill_link_cmd(NULL, lq_sta, priv->dbg_fixed_rate); +	if (lq_sta->dbg_fixed_rate) { +		rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);  		iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,  				false);  	} @@ -426,7 +434,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,  			ieee80211_stop_tx_ba_session(sta, tid);  		}  	} else { -		IWL_ERR(priv, "Aggregation not enabled for tid %d " +		IWL_DEBUG_HT(priv, "Aggregation not enabled for tid %d "  			"because load = %u\n", tid, load);  	}  	return ret; @@ -1073,7 +1081,8 @@ done:  	if (sta && sta->supp_rates[sband->band])  		rs_rate_scale_perform(priv, skb, sta, lq_sta);  #ifdef CONFIG_MAC80211_DEBUGFS -	if (priv->dbg_fixed_rate != lq_sta->dbg_fixed_rate) +	if ((priv->tm_fixed_rate) && +	    (priv->tm_fixed_rate != lq_sta->dbg_fixed_rate))  		rs_program_fix_rate(priv, lq_sta);  #endif  	if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) @@ -2896,7 +2905,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i  		lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;  	lq_sta->is_agg = 0; -	priv->dbg_fixed_rate = 0; +	priv->tm_fixed_rate = 0;  #ifdef CONFIG_MAC80211_DEBUGFS  	lq_sta->dbg_fixed_rate = 0;  #endif @@ -3095,7 +3104,6 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,  			IWL_DEBUG_RATE(priv, "Fixed rate ON\n");  		} else {  			lq_sta->dbg_fixed_rate = 0; -			priv->dbg_fixed_rate = 0;  			IWL_ERR(priv,  			    "Invalid antenna selection 0x%X, Valid is 0x%X\n",  			    ant_sel_tx, valid_tx_ant); @@ -3123,9 +3131,9 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,  		return -EFAULT;  	if (sscanf(buf, "%x", &parsed_rate) == 1) -		priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = parsed_rate; +		lq_sta->dbg_fixed_rate = parsed_rate;  	else -		priv->dbg_fixed_rate = lq_sta->dbg_fixed_rate = 0; +		lq_sta->dbg_fixed_rate = 0;  	rs_program_fix_rate(priv, lq_sta); @@ -3155,7 +3163,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,  			lq_sta->total_failed, lq_sta->total_success,  			lq_sta->active_legacy_rate);  	desc += sprintf(buff+desc, "fixed rate 0x%X\n", -			priv->dbg_fixed_rate); +			lq_sta->dbg_fixed_rate);  	desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",  	    (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",  	    (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 09f679d6046..dc64f251535 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -30,6 +30,7 @@  #include "iwl-core.h"  #include "iwl-agn-calib.h"  #include "iwl-helpers.h" +#include "iwl-trans.h"  static int iwlagn_disable_bss(struct iwl_priv *priv,  			      struct iwl_rxon_context *ctx, @@ -39,7 +40,8 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,  	int ret;  	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; -	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send); +	ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, +				CMD_SYNC, sizeof(*send), send);  	send->filter_flags = old_filter; @@ -64,7 +66,8 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,  	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;  	send->dev_type = RXON_DEV_TYPE_P2P; -	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send); +	ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, +				CMD_SYNC, sizeof(*send), send);  	send->filter_flags = old_filter;  	send->dev_type = old_dev_type; @@ -81,6 +84,22 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,  	return ret;  } +static int iwlagn_disconn_pan(struct iwl_priv *priv, +			      struct iwl_rxon_context *ctx, +			      struct iwl_rxon_cmd *send) +{ +	__le32 old_filter = send->filter_flags; +	int ret; + +	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; +	ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC, +				sizeof(*send), send); + +	send->filter_flags = old_filter; + +	return ret; +} +  static void iwlagn_update_qos(struct iwl_priv *priv,  			      struct iwl_rxon_context *ctx)  { @@ -102,7 +121,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,  		      ctx->qos_data.qos_active,  		      ctx->qos_data.def_qos_parm.qos_flags); -	ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd, +	ret = trans_send_cmd_pdu(priv, ctx->qos_cmd, CMD_SYNC,  			       sizeof(struct iwl_qosparam_cmd),  			       &ctx->qos_data.def_qos_parm);  	if (ret) @@ -161,11 +180,8 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,  		 ctx->staging.ofdm_ht_triple_stream_basic_rates;  	rxon_assoc.acquisition_data = ctx->staging.acquisition_data; -	ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd, -				     sizeof(rxon_assoc), &rxon_assoc, NULL); -	if (ret) -		return ret; - +	ret = trans_send_cmd_pdu(priv, ctx->rxon_assoc_cmd, +				CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc);  	return ret;  } @@ -175,10 +191,21 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv,  	int ret;  	struct iwl_rxon_cmd *active = (void *)&ctx->active; -	if (ctx->ctxid == IWL_RXON_CTX_BSS) +	if (ctx->ctxid == IWL_RXON_CTX_BSS) {  		ret = iwlagn_disable_bss(priv, ctx, &ctx->staging); -	else +	} else {  		ret = iwlagn_disable_pan(priv, ctx, &ctx->staging); +		if (ret) +			return ret; +		if (ctx->vif) { +			ret = iwl_send_rxon_timing(priv, ctx); +			if (ret) { +				IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); +				return ret; +			} +			ret = iwlagn_disconn_pan(priv, ctx, &ctx->staging); +		} +	}  	if (ret)  		return ret; @@ -187,6 +214,8 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv,  	 * keys, so we have to restore those afterwards.  	 */  	iwl_clear_ucode_stations(priv, ctx); +	/* update -- might need P2P now */ +	iwl_update_bcast_station(priv, ctx);  	iwl_restore_stations(priv, ctx);  	ret = iwl_restore_default_wep_keys(priv, ctx);  	if (ret) { @@ -205,10 +234,12 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,  	struct iwl_rxon_cmd *active = (void *)&ctx->active;  	/* RXON timing must be before associated RXON */ -	ret = iwl_send_rxon_timing(priv, ctx); -	if (ret) { -		IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); -		return ret; +	if (ctx->ctxid == IWL_RXON_CTX_BSS) { +		ret = iwl_send_rxon_timing(priv, ctx); +		if (ret) { +			IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); +			return ret; +		}  	}  	/* QoS info may be cleared by previous un-assoc RXON */  	iwlagn_update_qos(priv, ctx); @@ -235,7 +266,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,  	 * Associated RXON doesn't clear the station table in uCode,  	 * so we don't need to restore stations etc. after this.  	 */ -	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, +	ret = trans_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,  		      sizeof(struct iwl_rxon_cmd), &ctx->staging);  	if (ret) {  		IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); @@ -263,6 +294,12 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,  		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);  		return ret;  	} + +	if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) && +	    priv->cfg->ht_params->smps_mode) +		ieee80211_request_smps(ctx->vif, +				       priv->cfg->ht_params->smps_mode); +  	return 0;  } @@ -375,13 +412,11 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)  		 * do it now if after settings changed.  		 */  		iwl_set_tx_power(priv, priv->tx_power_next, false); -		return 0; -	} -	if (priv->cfg->ops->hcmd->set_pan_params) { -		ret = priv->cfg->ops->hcmd->set_pan_params(priv); -		if (ret) -			return ret; +		/* make sure we are in the right PS state */ +		iwl_power_update_mode(priv, true); + +		return 0;  	}  	iwl_set_rxon_hwcrypto(priv, ctx, !iwlagn_mod_params.sw_crypto); @@ -405,6 +440,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)  	if (ret)  		return ret; +	ret = iwlagn_set_pan_params(priv); +	if (ret) +		return ret; +  	if (new_assoc)  		return iwlagn_rxon_connect(priv, ctx); @@ -446,9 +485,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)  		 * set up the SM PS mode to OFF if an HT channel is  		 * configured.  		 */ -		if (priv->cfg->ops->hcmd->set_rxon_chain) -			for_each_context(priv, ctx) -				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); +		for_each_context(priv, ctx) +			iwlagn_set_rxon_chain(priv, ctx);  	}  	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { @@ -636,6 +674,38 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,  	ht_conf->single_chain_sufficient = !need_multiple;  } +static void iwlagn_chain_noise_reset(struct iwl_priv *priv) +{ +	struct iwl_chain_noise_data *data = &priv->chain_noise_data; +	int ret; + +	if ((data->state == IWL_CHAIN_NOISE_ALIVE) && +	    iwl_is_any_associated(priv)) { +		struct iwl_calib_chain_noise_reset_cmd cmd; + +		/* clear data for chain noise calibration algorithm */ +		data->chain_noise_a = 0; +		data->chain_noise_b = 0; +		data->chain_noise_c = 0; +		data->chain_signal_a = 0; +		data->chain_signal_b = 0; +		data->chain_signal_c = 0; +		data->beacon_count = 0; + +		memset(&cmd, 0, sizeof(cmd)); +		iwl_set_calib_hdr(&cmd.hdr, +			priv->_agn.phy_calib_chain_noise_reset_cmd); +		ret = trans_send_cmd_pdu(priv, +					REPLY_PHY_CALIBRATION_CMD, +					CMD_SYNC, sizeof(cmd), &cmd); +		if (ret) +			IWL_ERR(priv, +				"Could not send REPLY_PHY_CALIBRATION_CMD\n"); +		data->state = IWL_CHAIN_NOISE_ACCUMULATE; +		IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); +	} +} +  void iwlagn_bss_info_changed(struct ieee80211_hw *hw,  			     struct ieee80211_vif *vif,  			     struct ieee80211_bss_conf *bss_conf, @@ -693,6 +763,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,  			}  			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;  		} + +		iwlagn_bt_coex_rssi_monitor(priv);  	}  	if (ctx->ht.enabled) { @@ -704,8 +776,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,  		iwl_set_rxon_ht(priv, &priv->current_ht_config);  	} -	if (priv->cfg->ops->hcmd->set_rxon_chain) -		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); +	iwlagn_set_rxon_chain(priv, ctx);  	if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))  		ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK; @@ -743,7 +814,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,  			iwl_power_update_mode(priv, false);  		/* Enable RX differential gain and sensitivity calibrations */ -		iwl_chain_noise_reset(priv); +		if (!priv->disable_chain_noise_cal) +			iwlagn_chain_noise_reset(priv);  		priv->start_calib = 1;  	} @@ -770,6 +842,13 @@ void iwlagn_post_scan(struct iwl_priv *priv)  	struct iwl_rxon_context *ctx;  	/* +	 * We do not commit power settings while scan is pending, +	 * do it now if the settings changed. +	 */ +	iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false); +	iwl_set_tx_power(priv, priv->tx_power_next, false); + +	/*  	 * Since setting the RXON may have been deferred while  	 * performing the scan, fire one off if needed  	 */ @@ -777,6 +856,5 @@ void iwlagn_post_scan(struct iwl_priv *priv)  		if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))  			iwlagn_commit_rxon(priv, ctx); -	if (priv->cfg->ops->hcmd->set_pan_params) -		priv->cfg->ops->hcmd->set_pan_params(priv); +	iwlagn_set_pan_params(priv);  } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 0bd722cee5a..001622c0652 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -33,9 +33,10 @@  #include "iwl-core.h"  #include "iwl-sta.h"  #include "iwl-agn.h" +#include "iwl-trans.h"  static struct iwl_link_quality_cmd * -iwl_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id) +iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, u8 sta_id)  {  	int i, r;  	struct iwl_link_quality_cmd *link_cmd; @@ -47,10 +48,15 @@ iwl_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id)  		IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");  		return NULL;  	} + +	lockdep_assert_held(&priv->mutex); +  	/* Set up the rate scaling to start at selected rate, fall back  	 * all the way down to 1M in IEEE order, and then spin on 1M */  	if (priv->band == IEEE80211_BAND_5GHZ)  		r = IWL_RATE_6M_INDEX; +	else if (ctx && ctx->vif && ctx->vif->p2p) +		r = IWL_RATE_6M_INDEX;  	else  		r = IWL_RATE_1M_INDEX; @@ -115,7 +121,7 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx  	spin_unlock_irqrestore(&priv->sta_lock, flags);  	/* Set up default rate scaling table in device's station table */ -	link_cmd = iwl_sta_alloc_lq(priv, sta_id); +	link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);  	if (!link_cmd) {  		IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",  			addr); @@ -175,7 +181,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,  	cmd.len[0] = cmd_size;  	if (not_empty || send_if_empty) -		return iwl_send_cmd(priv, &cmd); +		return trans_send_cmd(priv, &cmd);  	else  		return 0;  } @@ -554,7 +560,7 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,  	priv->stations[sta_id].used |= IWL_STA_BCAST;  	spin_unlock_irqrestore(&priv->sta_lock, flags); -	link_cmd = iwl_sta_alloc_lq(priv, sta_id); +	link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);  	if (!link_cmd) {  		IWL_ERR(priv,  			"Unable to initialize rate scaling for bcast station.\n"); @@ -574,14 +580,14 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,   * Only used by iwlagn. Placed here to have all bcast station management   * code together.   */ -static int iwl_update_bcast_station(struct iwl_priv *priv, -				    struct iwl_rxon_context *ctx) +int iwl_update_bcast_station(struct iwl_priv *priv, +			     struct iwl_rxon_context *ctx)  {  	unsigned long flags;  	struct iwl_link_quality_cmd *link_cmd;  	u8 sta_id = ctx->bcast_sta_id; -	link_cmd = iwl_sta_alloc_lq(priv, sta_id); +	link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);  	if (!link_cmd) {  		IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");  		return -ENOMEM; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 348f74f1c8e..f501d742984 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -198,7 +198,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)  		/* Reschedule the ct_kill timer to occur in  		 * CT_KILL_EXIT_DURATION seconds to ensure we get a  		 * thermal update */ -		IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); +		IWL_DEBUG_TEMP(priv, "schedule ct_kill exit timer\n");  		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,  			  jiffies + CT_KILL_EXIT_DURATION * HZ);  	} @@ -208,15 +208,15 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,  			   bool stop)  {  	if (stop) { -		IWL_DEBUG_POWER(priv, "Stop all queues\n"); +		IWL_DEBUG_TEMP(priv, "Stop all queues\n");  		if (priv->mac80211_registered)  			ieee80211_stop_queues(priv->hw); -		IWL_DEBUG_POWER(priv, +		IWL_DEBUG_TEMP(priv,  				"Schedule 5 seconds CT_KILL Timer\n");  		mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,  			  jiffies + CT_KILL_EXIT_DURATION * HZ);  	} else { -		IWL_DEBUG_POWER(priv, "Wake all queues\n"); +		IWL_DEBUG_TEMP(priv, "Wake all queues\n");  		if (priv->mac80211_registered)  			ieee80211_wake_queues(priv->hw);  	} @@ -232,7 +232,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)  	/* temperature timer expired, ready to go into CT_KILL state */  	if (tt->state != IWL_TI_CT_KILL) { -		IWL_DEBUG_POWER(priv, "entering CT_KILL state when " +		IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "  				"temperature timer expired\n");  		tt->state = IWL_TI_CT_KILL;  		set_bit(STATUS_CT_KILL, &priv->status); @@ -242,7 +242,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)  static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)  { -	IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); +	IWL_DEBUG_TEMP(priv, "Prepare to enter IWL_TI_CT_KILL\n");  	/* make request to retrieve statistics information */  	iwl_send_statistics_request(priv, CMD_SYNC, false);  	/* Reschedule the ct_kill wait timer */ @@ -273,7 +273,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)  	    (temp > tt->tt_previous_temp) &&  	    ((temp - tt->tt_previous_temp) >  	    IWL_TT_INCREASE_MARGIN)) { -		IWL_DEBUG_POWER(priv, +		IWL_DEBUG_TEMP(priv,  			"Temperature increase %d degree Celsius\n",  			(temp - tt->tt_previous_temp));  	} @@ -338,9 +338,9 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)  			} else if (old_state == IWL_TI_CT_KILL &&  				 tt->state != IWL_TI_CT_KILL)  				iwl_perform_ct_kill_task(priv, false); -			IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", +			IWL_DEBUG_TEMP(priv, "Temperature state changed %u\n",  					tt->state); -			IWL_DEBUG_POWER(priv, "Power Index change to %u\n", +			IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",  					tt->tt_power_mode);  		}  		mutex_unlock(&priv->mutex); @@ -397,7 +397,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)  			    (temp > tt->tt_previous_temp) &&  			    ((temp - tt->tt_previous_temp) >  			    IWL_TT_INCREASE_MARGIN)) { -				IWL_DEBUG_POWER(priv, +				IWL_DEBUG_TEMP(priv,  					"Temperature increase %d "  					"degree Celsius\n",  					(temp - tt->tt_previous_temp)); @@ -467,13 +467,13 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)  				set_bit(STATUS_CT_KILL, &priv->status);  			tt->state = old_state;  		} else { -			IWL_DEBUG_POWER(priv, +			IWL_DEBUG_TEMP(priv,  					"Thermal Throttling to new state: %u\n",  					tt->state);  			if (old_state != IWL_TI_CT_KILL &&  			    tt->state == IWL_TI_CT_KILL) {  				if (force) { -					IWL_DEBUG_POWER(priv, +					IWL_DEBUG_TEMP(priv,  						"Enter IWL_TI_CT_KILL\n");  					set_bit(STATUS_CT_KILL, &priv->status);  					iwl_perform_ct_kill_task(priv, true); @@ -483,7 +483,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)  				}  			} else if (old_state == IWL_TI_CT_KILL &&  				  tt->state != IWL_TI_CT_KILL) { -				IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); +				IWL_DEBUG_TEMP(priv, "Exit IWL_TI_CT_KILL\n");  				iwl_perform_ct_kill_task(priv, false);  			}  		} @@ -568,7 +568,7 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)  	if (test_bit(STATUS_EXIT_PENDING, &priv->status))  		return; -	IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); +	IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");  	queue_work(priv->workqueue, &priv->ct_enter);  } @@ -577,7 +577,7 @@ void iwl_tt_exit_ct_kill(struct iwl_priv *priv)  	if (test_bit(STATUS_EXIT_PENDING, &priv->status))  		return; -	IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); +	IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");  	queue_work(priv->workqueue, &priv->ct_exit);  } @@ -603,7 +603,7 @@ void iwl_tt_handler(struct iwl_priv *priv)  	if (test_bit(STATUS_EXIT_PENDING, &priv->status))  		return; -	IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); +	IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");  	queue_work(priv->workqueue, &priv->tt_work);  } @@ -618,7 +618,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)  	int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);  	struct iwl_tt_trans *transaction; -	IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); +	IWL_DEBUG_TEMP(priv, "Initialize Thermal Throttling\n");  	memset(tt, 0, sizeof(struct iwl_tt_mgmt)); @@ -638,7 +638,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)  	INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);  	if (priv->cfg->base_params->adv_thermal_throttle) { -		IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); +		IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");  		tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *  					 IWL_TI_STATE_MAX, GFP_KERNEL);  		tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * @@ -671,7 +671,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)  			priv->thermal_throttle.advanced_tt = true;  		}  	} else { -		IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); +		IWL_DEBUG_TEMP(priv, "Legacy Thermal Throttling\n");  		priv->thermal_throttle.advanced_tt = false;  	}  } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 4974cd7837c..7d3aad83e0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -339,6 +339,16 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask)  	iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask);  } +static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, +				     struct ieee80211_tx_info *info, +				     __le16 fc, __le32 *tx_flags) +{ +	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS || +	    info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT || +	    info->flags & IEEE80211_TX_CTL_AMPDU) +		*tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK; +} +  /*   * handle build REPLY_TX command notification.   */ @@ -388,7 +398,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,  		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;  	} -	priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags); +	iwlagn_tx_cmd_protection(priv, info, fc, &tx_flags);  	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);  	if (ieee80211_is_mgmt(fc)) { @@ -436,6 +446,16 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,  	if (ieee80211_is_data(fc)) {  		tx_cmd->initial_rate_index = 0;  		tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; +		if (priv->tm_fixed_rate) { +			/* +			 * rate overwrite by testmode +			 * we not only send lq command to change rate +			 * we also re-enforce per data pkt base. +			 */ +			tx_cmd->tx_flags &= ~TX_CMD_FLG_STA_RATE_MSK; +			memcpy(&tx_cmd->rate_n_flags, &priv->tm_fixed_rate, +			       sizeof(tx_cmd->rate_n_flags)); +		}  		return;  	} @@ -497,8 +517,7 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,  	case WLAN_CIPHER_SUITE_TKIP:  		tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; -		ieee80211_get_tkip_key(keyconf, skb_frag, -			IEEE80211_TKIP_P2_KEY, tx_cmd->key); +		ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);  		IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");  		break; @@ -716,10 +735,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)  	/* Physical address of this Tx command's header (not MAC header!),  	 * within command buffer array. */ -	txcmd_phys = pci_map_single(priv->pci_dev, +	txcmd_phys = dma_map_single(priv->bus.dev,  				    &out_cmd->hdr, firstlen, -				    PCI_DMA_BIDIRECTIONAL); -	if (unlikely(pci_dma_mapping_error(priv->pci_dev, txcmd_phys))) +				    DMA_BIDIRECTIONAL); +	if (unlikely(dma_mapping_error(priv->bus.dev, txcmd_phys)))  		goto drop_unlock_sta;  	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);  	dma_unmap_len_set(out_meta, len, firstlen); @@ -735,13 +754,13 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)  	 * if any (802.11 null frames have no payload). */  	secondlen = skb->len - hdr_len;  	if (secondlen > 0) { -		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, -					   secondlen, PCI_DMA_TODEVICE); -		if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { -			pci_unmap_single(priv->pci_dev, +		phys_addr = dma_map_single(priv->bus.dev, skb->data + hdr_len, +					   secondlen, DMA_TO_DEVICE); +		if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) { +			dma_unmap_single(priv->bus.dev,  					 dma_unmap_addr(out_meta, mapping),  					 dma_unmap_len(out_meta, len), -					 PCI_DMA_BIDIRECTIONAL); +					 DMA_BIDIRECTIONAL);  			goto drop_unlock_sta;  		}  	} @@ -764,8 +783,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)  				offsetof(struct iwl_tx_cmd, scratch);  	/* take back ownership of DMA buffer to enable update */ -	pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, -				    firstlen, PCI_DMA_BIDIRECTIONAL); +	dma_sync_single_for_cpu(priv->bus.dev, txcmd_phys, firstlen, +			DMA_BIDIRECTIONAL);  	tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);  	tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); @@ -780,8 +799,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)  		iwlagn_txq_update_byte_cnt_tbl(priv, txq,  					       le16_to_cpu(tx_cmd->len)); -	pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, -				       firstlen, PCI_DMA_BIDIRECTIONAL); +	dma_sync_single_for_device(priv->bus.dev, txcmd_phys, firstlen, +			DMA_BIDIRECTIONAL);  	trace_iwlwifi_dev_tx(priv,  			     &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], @@ -831,178 +850,6 @@ drop_unlock_priv:  	return -1;  } -static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, -				    struct iwl_dma_ptr *ptr, size_t size) -{ -	ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, -				       GFP_KERNEL); -	if (!ptr->addr) -		return -ENOMEM; -	ptr->size = size; -	return 0; -} - -static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, -				    struct iwl_dma_ptr *ptr) -{ -	if (unlikely(!ptr->addr)) -		return; - -	dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); -	memset(ptr, 0, sizeof(*ptr)); -} - -/** - * iwlagn_hw_txq_ctx_free - Free TXQ Context - * - * Destroy all TX DMA queues and structures - */ -void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) -{ -	int txq_id; - -	/* Tx queues */ -	if (priv->txq) { -		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) -			if (txq_id == priv->cmd_queue) -				iwl_cmd_queue_free(priv); -			else -				iwl_tx_queue_free(priv, txq_id); -	} -	iwlagn_free_dma_ptr(priv, &priv->kw); - -	iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); - -	/* free tx queue structure */ -	iwl_free_txq_mem(priv); -} - -/** - * iwlagn_txq_ctx_alloc - allocate TX queue context - * Allocate all Tx DMA structures and initialize them - * - * @param priv - * @return error code - */ -int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) -{ -	int ret; -	int txq_id, slots_num; -	unsigned long flags; - -	/* Free all tx/cmd queues and keep-warm buffer */ -	iwlagn_hw_txq_ctx_free(priv); - -	ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, -				priv->hw_params.scd_bc_tbls_size); -	if (ret) { -		IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); -		goto error_bc_tbls; -	} -	/* Alloc keep-warm buffer */ -	ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); -	if (ret) { -		IWL_ERR(priv, "Keep Warm allocation failed\n"); -		goto error_kw; -	} - -	/* allocate tx queue structure */ -	ret = iwl_alloc_txq_mem(priv); -	if (ret) -		goto error; - -	spin_lock_irqsave(&priv->lock, flags); - -	/* Turn off all Tx DMA fifos */ -	iwlagn_txq_set_sched(priv, 0); - -	/* Tell NIC where to find the "keep warm" buffer */ -	iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); - -	spin_unlock_irqrestore(&priv->lock, flags); - -	/* Alloc and init all Tx queues, including the command queue (#4/#9) */ -	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { -		slots_num = (txq_id == priv->cmd_queue) ? -					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; -		ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, -				       txq_id); -		if (ret) { -			IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); -			goto error; -		} -	} - -	return ret; - - error: -	iwlagn_hw_txq_ctx_free(priv); -	iwlagn_free_dma_ptr(priv, &priv->kw); - error_kw: -	iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); - error_bc_tbls: -	return ret; -} - -void iwlagn_txq_ctx_reset(struct iwl_priv *priv) -{ -	int txq_id, slots_num; -	unsigned long flags; - -	spin_lock_irqsave(&priv->lock, flags); - -	/* Turn off all Tx DMA fifos */ -	iwlagn_txq_set_sched(priv, 0); - -	/* Tell NIC where to find the "keep warm" buffer */ -	iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); - -	spin_unlock_irqrestore(&priv->lock, flags); - -	/* Alloc and init all Tx queues, including the command queue (#4) */ -	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { -		slots_num = txq_id == priv->cmd_queue ? -			    TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; -		iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); -	} -} - -/** - * iwlagn_txq_ctx_stop - Stop all Tx DMA channels - */ -void iwlagn_txq_ctx_stop(struct iwl_priv *priv) -{ -	int ch, txq_id; -	unsigned long flags; - -	/* Turn off all Tx DMA fifos */ -	spin_lock_irqsave(&priv->lock, flags); - -	iwlagn_txq_set_sched(priv, 0); - -	/* Stop each Tx DMA channel, and wait for it to be idle */ -	for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { -		iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); -		if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, -				    FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), -				    1000)) -			IWL_ERR(priv, "Failing on timeout while stopping" -			    " DMA channel %d [0x%08x]", ch, -			    iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); -	} -	spin_unlock_irqrestore(&priv->lock, flags); - -	if (!priv->txq) -		return; - -	/* Unmap DMA from host system and free skb's */ -	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) -		if (txq_id == priv->cmd_queue) -			iwl_cmd_queue_unmap(priv); -		else -			iwl_tx_queue_unmap(priv, txq_id); -} -  /*   * Find first available (lowest unused) Tx Queue, mark it "active".   * Called only when finding queue for aggregation. @@ -1033,8 +880,8 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,  	if (unlikely(tx_fifo < 0))  		return tx_fifo; -	IWL_WARN(priv, "%s on ra = %pM tid = %d\n", -			__func__, sta->addr, tid); +	IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n", +		     sta->addr, tid);  	sta_id = iwl_sta_id(sta);  	if (sta_id == IWL_INVALID_STATION) { @@ -1236,9 +1083,9 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)  	struct ieee80211_hdr *hdr;  	if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { -		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " -			  "is out of range [0-%d] %d %d.\n", txq_id, -			  index, q->n_bd, q->write_ptr, q->read_ptr); +		IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), " +			  "index %d is out of range [0-%d] %d %d.\n", __func__, +			  txq_id, index, q->n_bd, q->write_ptr, q->read_ptr);  		return 0;  	} @@ -1261,7 +1108,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)  		iwlagn_txq_inval_byte_cnt_tbl(priv, txq); -		iwlagn_txq_free_tfd(priv, txq); +		iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr);  	}  	return nfreed;  } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 97de5d9de67..06304a681ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -39,6 +39,7 @@  #include "iwl-agn-hw.h"  #include "iwl-agn.h"  #include "iwl-agn-calib.h" +#include "iwl-trans.h"  #define IWL_AC_UNSET -1 @@ -143,7 +144,7 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,  		FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE	|  		FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); -	IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); +	IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);  	ret = wait_event_interruptible_timeout(priv->wait_command_queue,  					priv->ucode_write_complete, 5 * HZ);  	if (ret == -ERESTARTSYS) { @@ -183,10 +184,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)  	__le16 *xtal_calib =  		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); -	cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; -	cmd.hdr.first_group = 0; -	cmd.hdr.groups_num = 1; -	cmd.hdr.data_valid = 1; +	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);  	cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);  	cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);  	return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], @@ -197,15 +195,14 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)  {  	struct iwl_calib_temperature_offset_cmd cmd;  	__le16 *offset_calib = -		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE); -	cmd.hdr.op_code = IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD; -	cmd.hdr.first_group = 0; -	cmd.hdr.groups_num = 1; -	cmd.hdr.data_valid = 1; +		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE); + +	memset(&cmd, 0, sizeof(cmd)); +	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);  	cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]);  	if (!(cmd.radio_sensor_offset))  		cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; -	cmd.reserved = 0; +  	IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",  			cmd.radio_sensor_offset);  	return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET], @@ -227,7 +224,7 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)  	calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL;  	calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; -	return iwl_send_cmd(priv, &cmd); +	return trans_send_cmd(priv, &cmd);  }  void iwlagn_rx_calib_result(struct iwl_priv *priv, @@ -325,7 +322,8 @@ static int iwlagn_send_wimax_coex(struct iwl_priv *priv)  		/* coexistence is disabled */  		memset(&coex_cmd, 0, sizeof(coex_cmd));  	} -	return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD, +	return trans_send_cmd_pdu(priv, +				COEX_PRIORITY_TABLE_CMD, CMD_SYNC,  				sizeof(coex_cmd), &coex_cmd);  } @@ -357,7 +355,8 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv)  	memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl,  		sizeof(iwlagn_bt_prio_tbl)); -	if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PRIO_TABLE, +	if (trans_send_cmd_pdu(priv, +				REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,  				sizeof(prio_tbl_cmd), &prio_tbl_cmd))  		IWL_ERR(priv, "failed to send BT prio tbl command\n");  } @@ -369,7 +368,8 @@ int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)  	env_cmd.action = action;  	env_cmd.type = type; -	ret = iwl_send_cmd_pdu(priv, REPLY_BT_COEX_PROT_ENV, +	ret = trans_send_cmd_pdu(priv, +			       REPLY_BT_COEX_PROT_ENV, CMD_SYNC,  			       sizeof(env_cmd), &env_cmd);  	if (ret)  		IWL_ERR(priv, "failed to send BT env command\n"); @@ -390,11 +390,13 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)  	spin_lock_irqsave(&priv->lock, flags);  	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 = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND; +	/* reset conext data memory */ +	for (; a < priv->scd_base_addr + IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND;  		a += 4)  		iwl_write_targ_mem(priv, a, 0); -	for (; a < priv->scd_base_addr + IWLAGN_SCD_TRANSLATE_TBL_OFFSET; +	/* reset tx status memory */ +	for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND;  		a += 4)  		iwl_write_targ_mem(priv, a, 0);  	for (; a < priv->scd_base_addr + @@ -405,7 +407,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv)  		       priv->scd_bc_tbls.dma >> 10);  	/* Enable DMA channel */ -	for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) +	for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++)  		iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),  				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |  				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); @@ -508,7 +510,7 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv,  	u32 val;  	u32 i; -	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); +	IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);  	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {  		/* read data comes through single port, auto-incr addr */ @@ -533,7 +535,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,  	u32 offs;  	int errors = 0; -	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); +	IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);  	iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,  			   IWLAGN_RTC_INST_LOWER_BOUND); @@ -559,7 +561,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,  static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img)  {  	if (!iwlcore_verify_inst_sparse(priv, &img->code)) { -		IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n"); +		IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");  		return 0;  	} @@ -583,7 +585,7 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,  	palive = &pkt->u.alive_frame; -	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " +	IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision "  		       "0x%01X 0x%01X\n",  		       palive->is_valid, palive->ver_type,  		       palive->ver_subtype); @@ -602,12 +604,12 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,  int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,  				 struct fw_img *image, -				 int subtype, int alternate_subtype) +				 enum iwlagn_ucode_type ucode_type)  {  	struct iwl_notification_wait alive_wait;  	struct iwlagn_alive_data alive_data;  	int ret; -	enum iwlagn_ucode_subtype old_type; +	enum iwlagn_ucode_type old_type;  	ret = iwlagn_start_device(priv);  	if (ret) @@ -617,7 +619,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,  				      iwlagn_alive_fn, &alive_data);  	old_type = priv->ucode_type; -	priv->ucode_type = subtype; +	priv->ucode_type = ucode_type;  	ret = iwlagn_load_given_ucode(priv, image);  	if (ret) { @@ -645,15 +647,6 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,  		return -EIO;  	} -	if (alive_data.subtype != subtype && -	    alive_data.subtype != alternate_subtype) { -		IWL_ERR(priv, -			"Loaded ucode is not expected type (got %d, expected %d)!\n", -			alive_data.subtype, subtype); -		priv->ucode_type = old_type; -		return -EIO; -	} -  	ret = iwl_verify_ucode(priv, image);  	if (ret) {  		priv->ucode_type = old_type; @@ -685,7 +678,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)  	if (!priv->ucode_init.code.len)  		return 0; -	if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED) +	if (priv->ucode_type != IWL_UCODE_NONE)  		return 0;  	iwlagn_init_notification_wait(priv, &calib_wait, @@ -694,7 +687,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)  	/* Will also start the device */  	ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, -					   UCODE_SUBTYPE_INIT, -1); +					   IWL_UCODE_INIT);  	if (ret)  		goto error; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8e1942ebd9a..38a1e4f5882 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -32,8 +32,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/init.h> -#include <linux/pci.h> -#include <linux/pci-aspm.h>  #include <linux/slab.h>  #include <linux/dma-mapping.h>  #include <linux/delay.h> @@ -49,8 +47,6 @@  #include <asm/div64.h> -#define DRV_NAME        "iwlagn" -  #include "iwl-eeprom.h"  #include "iwl-dev.h"  #include "iwl-core.h" @@ -59,7 +55,8 @@  #include "iwl-sta.h"  #include "iwl-agn-calib.h"  #include "iwl-agn.h" - +#include "iwl-pci.h" +#include "iwl-trans.h"  /******************************************************************************   * @@ -93,12 +90,10 @@ void iwl_update_chain_flags(struct iwl_priv *priv)  {  	struct iwl_rxon_context *ctx; -	if (priv->cfg->ops->hcmd->set_rxon_chain) { -		for_each_context(priv, ctx) { -			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); -			if (ctx->active.rx_chain != ctx->staging.rx_chain) -				iwlcore_commit_rxon(priv, ctx); -		} +	for_each_context(priv, ctx) { +		iwlagn_set_rxon_chain(priv, ctx); +		if (ctx->active.rx_chain != ctx->staging.rx_chain) +			iwlagn_commit_rxon(priv, ctx);  	}  } @@ -134,7 +129,9 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)  	struct iwl_tx_beacon_cmd *tx_beacon_cmd;  	struct iwl_host_cmd cmd = {  		.id = REPLY_TX_BEACON, +		.flags = CMD_SYNC,  	}; +	struct ieee80211_tx_info *info;  	u32 frame_size;  	u32 rate_flags;  	u32 rate; @@ -175,14 +172,31 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)  			   frame_size);  	/* Set up packet rate and flags */ -	rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx); +	info = IEEE80211_SKB_CB(priv->beacon_skb); + +	/* +	 * Let's set up the rate at least somewhat correctly; +	 * it will currently not actually be used by the uCode, +	 * it uses the broadcast station's rate instead. +	 */ +	if (info->control.rates[0].idx < 0 || +	    info->control.rates[0].flags & IEEE80211_TX_RC_MCS) +		rate = 0; +	else +		rate = info->control.rates[0].idx; +  	priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,  					      priv->hw_params.valid_tx_ant);  	rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); -	if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) + +	/* In mac80211, rates for 5 GHz start at 0 */ +	if (info->band == IEEE80211_BAND_5GHZ) +		rate += IWL_FIRST_OFDM_RATE; +	else if (rate >= IWL_FIRST_CCK_RATE && rate <= IWL_LAST_CCK_RATE)  		rate_flags |= RATE_MCS_CCK_MSK; -	tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate, -			rate_flags); + +	tx_beacon_cmd->tx.rate_n_flags = +			iwl_hw_set_rate_n_flags(rate, rate_flags);  	/* Submit command */  	cmd.len[0] = sizeof(*tx_beacon_cmd); @@ -192,7 +206,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)  	cmd.data[1] = priv->beacon_skb->data;  	cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; -	return iwl_send_cmd_sync(priv, &cmd); +	return trans_send_cmd(priv, &cmd);  }  static void iwl_bg_beacon_update(struct work_struct *work) @@ -245,7 +259,7 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work)  	/* dont send host command if rf-kill is on */  	if (!iwl_is_ready_rf(priv))  		return; -	priv->cfg->ops->hcmd->send_bt_config(priv); +	iwlagn_send_advance_bt_config(priv);  }  static void iwl_bg_bt_full_concurrency(struct work_struct *work) @@ -272,12 +286,11 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)  	 * to avoid 3-wire collisions  	 */  	for_each_context(priv, ctx) { -		if (priv->cfg->ops->hcmd->set_rxon_chain) -			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); -		iwlcore_commit_rxon(priv, ctx); +		iwlagn_set_rxon_chain(priv, ctx); +		iwlagn_commit_rxon(priv, ctx);  	} -	priv->cfg->ops->hcmd->send_bt_config(priv); +	iwlagn_send_advance_bt_config(priv);  out:  	mutex_unlock(&priv->mutex);  } @@ -440,10 +453,8 @@ static void iwl_bg_tx_flush(struct work_struct *work)  	if (!iwl_is_ready_rf(priv))  		return; -	if (priv->cfg->ops->lib->txfifo_flush) { -		IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n"); -		iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); -	} +	IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n"); +	iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);  }  /** @@ -497,9 +508,9 @@ static void iwl_rx_handle(struct iwl_priv *priv)  		rxq->queue[i] = NULL; -		pci_unmap_page(priv->pci_dev, rxb->page_dma, +		dma_unmap_page(priv->bus.dev, rxb->page_dma,  			       PAGE_SIZE << priv->hw_params.rx_page_order, -			       PCI_DMA_FROMDEVICE); +			       DMA_FROM_DEVICE);  		pkt = rxb_addr(rxb);  		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; @@ -568,7 +579,8 @@ static void iwl_rx_handle(struct iwl_priv *priv)  		if (reclaim) {  			/* Invoke any callbacks, transfer the buffer to caller, -			 * and fire off the (possibly) blocking iwl_send_cmd() +			 * and fire off the (possibly) blocking +			 * trans_send_cmd()  			 * as we reclaim the driver command queue */  			if (rxb->page)  				iwl_tx_cmd_complete(priv, rxb); @@ -581,9 +593,9 @@ static void iwl_rx_handle(struct iwl_priv *priv)  		 * rx_free list for reuse later. */  		spin_lock_irqsave(&rxq->lock, flags);  		if (rxb->page != NULL) { -			rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page, +			rxb->page_dma = dma_map_page(priv->bus.dev, rxb->page,  				0, PAGE_SIZE << priv->hw_params.rx_page_order, -				PCI_DMA_FROMDEVICE); +				DMA_FROM_DEVICE);  			list_add_tail(&rxb->list, &rxq->rx_free);  			rxq->free_count++;  		} else @@ -939,22 +951,28 @@ static struct attribute_group iwl_attribute_group = {   *   ******************************************************************************/ -static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) +static void iwl_free_fw_desc(struct iwl_priv *priv, struct fw_desc *desc)  {  	if (desc->v_addr) -		dma_free_coherent(&pci_dev->dev, desc->len, +		dma_free_coherent(priv->bus.dev, desc->len,  				  desc->v_addr, desc->p_addr);  	desc->v_addr = NULL;  	desc->len = 0;  } -static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img) +static void iwl_free_fw_img(struct iwl_priv *priv, struct fw_img *img)  { -	iwl_free_fw_desc(pci_dev, &img->code); -	iwl_free_fw_desc(pci_dev, &img->data); +	iwl_free_fw_desc(priv, &img->code); +	iwl_free_fw_desc(priv, &img->data);  } -static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc, +static void iwl_dealloc_ucode(struct iwl_priv *priv) +{ +	iwl_free_fw_img(priv, &priv->ucode_rt); +	iwl_free_fw_img(priv, &priv->ucode_init); +} + +static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,  			     const void *data, size_t len)  {  	if (!len) { @@ -962,21 +980,16 @@ static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,  		return -EINVAL;  	} -	desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len, +	desc->v_addr = dma_alloc_coherent(priv->bus.dev, len,  					  &desc->p_addr, GFP_KERNEL);  	if (!desc->v_addr)  		return -ENOMEM; +  	desc->len = len;  	memcpy(desc->v_addr, data, len);  	return 0;  } -static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) -{ -	iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt); -	iwl_free_fw_img(priv->pci_dev, &priv->ucode_init); -} -  struct iwlagn_ucode_capabilities {  	u32 max_probe_length;  	u32 standard_phy_calibration_size; @@ -1021,8 +1034,8 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)  		       priv->firmware_name);  	return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, -				       &priv->pci_dev->dev, GFP_KERNEL, priv, -				       iwl_ucode_callback); +				       priv->bus.dev, +				       GFP_KERNEL, priv, iwl_ucode_callback);  }  struct iwlagn_firmware_pieces { @@ -1443,19 +1456,19 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)  	/* Runtime instructions and 2 copies of data:  	 * 1) unmodified from disk  	 * 2) backup cache for save/restore during power-downs */ -	if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code, +	if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.code,  			      pieces.inst, pieces.inst_size))  		goto err_pci_alloc; -	if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data, +	if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.data,  			      pieces.data, pieces.data_size))  		goto err_pci_alloc;  	/* Initialization instructions and data */  	if (pieces.init_size && pieces.init_data_size) { -		if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code, +		if (iwl_alloc_fw_desc(priv, &priv->ucode_init.code,  				      pieces.init, pieces.init_size))  			goto err_pci_alloc; -		if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data, +		if (iwl_alloc_fw_desc(priv, &priv->ucode_init.data,  				      pieces.init_data, pieces.init_data_size))  			goto err_pci_alloc;  	} @@ -1485,7 +1498,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)  	priv->new_scan_threshold_behaviour =  		!!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); -	if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) { +	if ((priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE) && +	    (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) {  		priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);  		priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;  	} else @@ -1523,7 +1537,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)  	if (err)  		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); -	err = sysfs_create_group(&priv->pci_dev->dev.kobj, +	err = sysfs_create_group(&(priv->bus.dev->kobj),  					&iwl_attribute_group);  	if (err) {  		IWL_ERR(priv, "failed to create sysfs device attributes\n"); @@ -1544,14 +1558,14 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)   err_pci_alloc:  	IWL_ERR(priv, "failed to allocate pci memory\n"); -	iwl_dealloc_ucode_pci(priv); +	iwl_dealloc_ucode(priv);   out_unbind:  	complete(&priv->_agn.firmware_loading_complete); -	device_release_driver(&priv->pci_dev->dev); +	device_release_driver(priv->bus.dev);  	release_firmware(ucode_raw);  } -static const char *desc_lookup_text[] = { +static const char * const desc_lookup_text[] = {  	"OK",  	"FAIL",  	"BAD_PARAM", @@ -1575,7 +1589,7 @@ static const char *desc_lookup_text[] = {  	"NMI_INTERRUPT_DATA_ACTION_PT",  	"NMI_TRM_HW_ER",  	"NMI_INTERRUPT_TRM", -	"NMI_INTERRUPT_BREAK_POINT" +	"NMI_INTERRUPT_BREAK_POINT",  	"DEBUG_0",  	"DEBUG_1",  	"DEBUG_2", @@ -1626,7 +1640,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)  	struct iwl_error_event_table table;  	base = priv->device_pointers.error_event_table; -	if (priv->ucode_type == UCODE_SUBTYPE_INIT) { +	if (priv->ucode_type == IWL_UCODE_INIT) {  		if (!base)  			base = priv->_agn.init_errlog_ptr;  	} else { @@ -1638,7 +1652,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)  		IWL_ERR(priv,  			"Not valid error log pointer 0x%08X for %s uCode\n",  			base, -			(priv->ucode_type == UCODE_SUBTYPE_INIT) +			(priv->ucode_type == IWL_UCODE_INIT)  					? "Init" : "RT");  		return;  	} @@ -1702,7 +1716,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,  		return pos;  	base = priv->device_pointers.log_event_table; -	if (priv->ucode_type == UCODE_SUBTYPE_INIT) { +	if (priv->ucode_type == IWL_UCODE_INIT) {  		if (!base)  			base = priv->_agn.init_evtlog_ptr;  	} else { @@ -1815,7 +1829,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,  	size_t bufsz = 0;  	base = priv->device_pointers.log_event_table; -	if (priv->ucode_type == UCODE_SUBTYPE_INIT) { +	if (priv->ucode_type == IWL_UCODE_INIT) {  		logsize = priv->_agn.init_evtlog_size;  		if (!base)  			base = priv->_agn.init_evtlog_ptr; @@ -1829,7 +1843,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,  		IWL_ERR(priv,  			"Invalid event log pointer 0x%08X for %s uCode\n",  			base, -			(priv->ucode_type == UCODE_SUBTYPE_INIT) +			(priv->ucode_type == IWL_UCODE_INIT)  					? "Init" : "RT");  		return -EINVAL;  	} @@ -1928,8 +1942,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)  		adv_cmd.critical_temperature_exit =  			cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); -		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, -				       sizeof(adv_cmd), &adv_cmd); +		ret = trans_send_cmd_pdu(priv, +				       REPLY_CT_KILL_CONFIG_CMD, +				       CMD_SYNC, sizeof(adv_cmd), &adv_cmd);  		if (ret)  			IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");  		else @@ -1943,8 +1958,9 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)  		cmd.critical_temperature_R =  			cpu_to_le32(priv->hw_params.ct_kill_threshold); -		ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, -				       sizeof(cmd), &cmd); +		ret = trans_send_cmd_pdu(priv, +				       REPLY_CT_KILL_CONFIG_CMD, +				       CMD_SYNC, sizeof(cmd), &cmd);  		if (ret)  			IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");  		else @@ -1968,7 +1984,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)  	calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;  	calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg); -	return iwl_send_cmd(priv, &cmd); +	return trans_send_cmd(priv, &cmd);  } @@ -1999,11 +2015,18 @@ int iwl_alive_start(struct iwl_priv *priv)  	if (priv->cfg->bt_params &&  	    priv->cfg->bt_params->advanced_bt_coexist) {  		/* Configure Bluetooth device coexistence support */ +		if (priv->cfg->bt_params->bt_sco_disable) +			priv->bt_enable_pspoll = false; +		else +			priv->bt_enable_pspoll = true; +  		priv->bt_valid = IWLAGN_BT_ALL_VALID_MSK;  		priv->kill_ack_mask = IWLAGN_BT_KILL_ACK_MASK_DEFAULT;  		priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; -		priv->cfg->ops->hcmd->send_bt_config(priv); +		iwlagn_send_advance_bt_config(priv);  		priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; +		priv->cur_rssi_ctx = NULL; +  		iwlagn_send_prio_tbl(priv);  		/* FIXME: w/a to force change uCode BT state machine */ @@ -2015,7 +2038,13 @@ int iwl_alive_start(struct iwl_priv *priv)  					 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);  		if (ret)  			return ret; +	} else { +		/* +		 * default is 2-wire BT coexexistence support +		 */ +		iwl_send_bt_config(priv);  	} +  	if (priv->hw_params.calib_rt_cfg)  		iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); @@ -2024,8 +2053,7 @@ int iwl_alive_start(struct iwl_priv *priv)  	priv->active_rate = IWL_RATES_MASK;  	/* Configure Tx antenna selection based on H/W config */ -	if (priv->cfg->ops->hcmd->set_tx_ant) -		priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant); +	iwlagn_send_tx_ant_config(priv, priv->cfg->valid_tx_ant);  	if (iwl_is_associated_ctx(ctx)) {  		struct iwl_rxon_cmd *active_rxon = @@ -2039,16 +2067,7 @@ int iwl_alive_start(struct iwl_priv *priv)  		for_each_context(priv, tmp)  			iwl_connection_init_rx_config(priv, tmp); -		if (priv->cfg->ops->hcmd->set_rxon_chain) -			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); -	} - -	if (!priv->cfg->bt_params || (priv->cfg->bt_params && -	    !priv->cfg->bt_params->advanced_bt_coexist)) { -		/* -		 * default is 2-wire BT coexexistence support -		 */ -		priv->cfg->ops->hcmd->send_bt_config(priv); +		iwlagn_set_rxon_chain(priv, ctx);  	}  	iwl_reset_run_time_calib(priv); @@ -2056,7 +2075,7 @@ int iwl_alive_start(struct iwl_priv *priv)  	set_bit(STATUS_READY, &priv->status);  	/* Configure the adapter for unassociated operation */ -	ret = iwlcore_commit_rxon(priv, ctx); +	ret = iwlagn_commit_rxon(priv, ctx);  	if (ret)  		return ret; @@ -2090,6 +2109,8 @@ static void __iwl_down(struct iwl_priv *priv)  	/* reset BT coex data */  	priv->bt_status = 0; +	priv->cur_rssi_ctx = NULL; +	priv->bt_is_sco = 0;  	if (priv->cfg->bt_params)  		priv->bt_traffic_load =  			 priv->cfg->bt_params->bt_init_traffic_load; @@ -2210,8 +2231,7 @@ static int __iwl_up(struct iwl_priv *priv)  	ret = iwlagn_load_ucode_wait_alive(priv,  					   &priv->ucode_rt, -					   UCODE_SUBTYPE_REGULAR, -					   UCODE_SUBTYPE_REGULAR_NEW); +					   IWL_UCODE_REGULAR);  	if (ret) {  		IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);  		goto error; @@ -2266,6 +2286,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)  	u8 bt_ci_compliance;  	u8 bt_load;  	u8 bt_status; +	bool bt_is_sco;  	lockdep_assert_held(&priv->mutex); @@ -2286,6 +2307,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)  	bt_ci_compliance = priv->bt_ci_compliance;  	bt_load = priv->bt_traffic_load;  	bt_status = priv->bt_status; +	bt_is_sco = priv->bt_is_sco;  	__iwl_down(priv); @@ -2293,6 +2315,7 @@ static void iwlagn_prepare_restart(struct iwl_priv *priv)  	priv->bt_ci_compliance = bt_ci_compliance;  	priv->bt_traffic_load = bt_load;  	priv->bt_status = bt_status; +	priv->bt_is_sco = bt_is_sco;  }  static void iwl_bg_restart(struct work_struct *data) @@ -2420,6 +2443,77 @@ unlock:   *   *****************************************************************************/ +static const struct ieee80211_iface_limit iwlagn_sta_ap_limits[] = { +	{ +		.max = 1, +		.types = BIT(NL80211_IFTYPE_STATION), +	}, +	{ +		.max = 1, +		.types = BIT(NL80211_IFTYPE_AP), +	}, +}; + +static const struct ieee80211_iface_limit iwlagn_2sta_limits[] = { +	{ +		.max = 2, +		.types = BIT(NL80211_IFTYPE_STATION), +	}, +}; + +static const struct ieee80211_iface_limit iwlagn_p2p_sta_go_limits[] = { +	{ +		.max = 1, +		.types = BIT(NL80211_IFTYPE_STATION), +	}, +	{ +		.max = 1, +		.types = BIT(NL80211_IFTYPE_P2P_GO) | +			 BIT(NL80211_IFTYPE_AP), +	}, +}; + +static const struct ieee80211_iface_limit iwlagn_p2p_2sta_limits[] = { +	{ +		.max = 2, +		.types = BIT(NL80211_IFTYPE_STATION), +	}, +	{ +		.max = 1, +		.types = BIT(NL80211_IFTYPE_P2P_CLIENT), +	}, +}; + +static const struct ieee80211_iface_combination +iwlagn_iface_combinations_dualmode[] = { +	{ .num_different_channels = 1, +	  .max_interfaces = 2, +	  .beacon_int_infra_match = true, +	  .limits = iwlagn_sta_ap_limits, +	  .n_limits = ARRAY_SIZE(iwlagn_sta_ap_limits), +	}, +	{ .num_different_channels = 1, +	  .max_interfaces = 2, +	  .limits = iwlagn_2sta_limits, +	  .n_limits = ARRAY_SIZE(iwlagn_2sta_limits), +	}, +}; + +static const struct ieee80211_iface_combination +iwlagn_iface_combinations_p2p[] = { +	{ .num_different_channels = 1, +	  .max_interfaces = 2, +	  .beacon_int_infra_match = true, +	  .limits = iwlagn_p2p_sta_go_limits, +	  .n_limits = ARRAY_SIZE(iwlagn_p2p_sta_go_limits), +	}, +	{ .num_different_channels = 1, +	  .max_interfaces = 2, +	  .limits = iwlagn_p2p_2sta_limits, +	  .n_limits = ARRAY_SIZE(iwlagn_p2p_2sta_limits), +	}, +}; +  /*   * Not a mac80211 entry point function, but it fits in with all the   * other mac80211 functions grouped here. @@ -2445,7 +2539,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,  	hw->flags |= IEEE80211_HW_SUPPORTS_PS |  		     IEEE80211_HW_SUPPORTS_DYNAMIC_PS; -	if (priv->cfg->sku & IWL_SKU_N) +	if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)  		hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |  			     IEEE80211_HW_SUPPORTS_STATIC_SMPS; @@ -2460,17 +2554,28 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,  		hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;  	} +	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); + +	if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) { +		hw->wiphy->iface_combinations = iwlagn_iface_combinations_p2p; +		hw->wiphy->n_iface_combinations = +			ARRAY_SIZE(iwlagn_iface_combinations_p2p); +	} else if (hw->wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { +		hw->wiphy->iface_combinations = iwlagn_iface_combinations_dualmode; +		hw->wiphy->n_iface_combinations = +			ARRAY_SIZE(iwlagn_iface_combinations_dualmode); +	} +  	hw->wiphy->max_remain_on_channel_duration = 1000;  	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |  			    WIPHY_FLAG_DISABLE_BEACON_HINTS |  			    WIPHY_FLAG_IBSS_RSN; -	/* -	 * For now, disable PS by default because it affects -	 * RX performance significantly. -	 */ -	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; +	if (iwlagn_mod_params.power_save) +		hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; +	else +		hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;  	hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;  	/* we create the 802.11 header and a zero-length SSID element */ @@ -2674,7 +2779,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,  	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",  		     sta->addr, tid); -	if (!(priv->cfg->sku & IWL_SKU_N)) +	if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE))  		return -EACCES;  	mutex_lock(&priv->mutex); @@ -2711,12 +2816,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,  			ret = 0;  		if (priv->cfg->ht_params &&  		    priv->cfg->ht_params->use_rts_for_aggregation) { -			struct iwl_station_priv *sta_priv = -				(void *) sta->drv_priv;  			/*  			 * switch off RTS/CTS if it was previously enabled  			 */ -  			sta_priv->lq_sta.lq.general_params.flags &=  				~LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;  			iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), @@ -2764,6 +2866,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,  		iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),  				&sta_priv->lq_sta.lq, CMD_ASYNC, false); + +		IWL_INFO(priv, "Tx aggregation enabled on ra = %pM tid = %d\n", +			 sta->addr, tid);  		ret = 0;  		break;  	} @@ -2833,7 +2938,6 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,  	 */  	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];  	u16 ch; -	unsigned long flags = 0;  	IWL_DEBUG_MAC80211(priv, "enter\n"); @@ -2850,65 +2954,64 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,  	if (!iwl_is_associated_ctx(ctx))  		goto out; -	if (priv->cfg->ops->lib->set_channel_switch) { - -		ch = channel->hw_value; -		if (le16_to_cpu(ctx->active.channel) != ch) { -			ch_info = iwl_get_channel_info(priv, -						       channel->band, -						       ch); -			if (!is_channel_valid(ch_info)) { -				IWL_DEBUG_MAC80211(priv, "invalid channel\n"); -				goto out; -			} -			spin_lock_irqsave(&priv->lock, flags); +	if (!priv->cfg->ops->lib->set_channel_switch) +		goto out; -			priv->current_ht_config.smps = conf->smps_mode; +	ch = channel->hw_value; +	if (le16_to_cpu(ctx->active.channel) == ch) +		goto out; -			/* Configure HT40 channels */ -			ctx->ht.enabled = conf_is_ht(conf); -			if (ctx->ht.enabled) { -				if (conf_is_ht40_minus(conf)) { -					ctx->ht.extension_chan_offset = -						IEEE80211_HT_PARAM_CHA_SEC_BELOW; -					ctx->ht.is_40mhz = true; -				} else if (conf_is_ht40_plus(conf)) { -					ctx->ht.extension_chan_offset = -						IEEE80211_HT_PARAM_CHA_SEC_ABOVE; -					ctx->ht.is_40mhz = true; -				} else { -					ctx->ht.extension_chan_offset = -						IEEE80211_HT_PARAM_CHA_SEC_NONE; -					ctx->ht.is_40mhz = false; -				} -			} else -				ctx->ht.is_40mhz = false; +	ch_info = iwl_get_channel_info(priv, channel->band, ch); +	if (!is_channel_valid(ch_info)) { +		IWL_DEBUG_MAC80211(priv, "invalid channel\n"); +		goto out; +	} -			if ((le16_to_cpu(ctx->staging.channel) != ch)) -				ctx->staging.flags = 0; +	spin_lock_irq(&priv->lock); -			iwl_set_rxon_channel(priv, channel, ctx); -			iwl_set_rxon_ht(priv, ht_conf); -			iwl_set_flags_for_band(priv, ctx, channel->band, -					       ctx->vif); -			spin_unlock_irqrestore(&priv->lock, flags); +	priv->current_ht_config.smps = conf->smps_mode; -			iwl_set_rate(priv); -			/* -			 * at this point, staging_rxon has the -			 * configuration for channel switch -			 */ -			set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); -			priv->switch_channel = cpu_to_le16(ch); -			if (priv->cfg->ops->lib->set_channel_switch(priv, -								    ch_switch)) { -				clear_bit(STATUS_CHANNEL_SWITCH_PENDING, -					  &priv->status); -				priv->switch_channel = 0; -				ieee80211_chswitch_done(ctx->vif, false); -			} +	/* Configure HT40 channels */ +	ctx->ht.enabled = conf_is_ht(conf); +	if (ctx->ht.enabled) { +		if (conf_is_ht40_minus(conf)) { +			ctx->ht.extension_chan_offset = +				IEEE80211_HT_PARAM_CHA_SEC_BELOW; +			ctx->ht.is_40mhz = true; +		} else if (conf_is_ht40_plus(conf)) { +			ctx->ht.extension_chan_offset = +				IEEE80211_HT_PARAM_CHA_SEC_ABOVE; +			ctx->ht.is_40mhz = true; +		} else { +			ctx->ht.extension_chan_offset = +				IEEE80211_HT_PARAM_CHA_SEC_NONE; +			ctx->ht.is_40mhz = false;  		} +	} else +		ctx->ht.is_40mhz = false; + +	if ((le16_to_cpu(ctx->staging.channel) != ch)) +		ctx->staging.flags = 0; + +	iwl_set_rxon_channel(priv, channel, ctx); +	iwl_set_rxon_ht(priv, ht_conf); +	iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif); + +	spin_unlock_irq(&priv->lock); + +	iwl_set_rate(priv); +	/* +	 * at this point, staging_rxon has the +	 * configuration for channel switch +	 */ +	set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); +	priv->switch_channel = cpu_to_le16(ch); +	if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) { +		clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status); +		priv->switch_channel = 0; +		ieee80211_chswitch_done(ctx->vif, false);  	} +  out:  	mutex_unlock(&priv->mutex);  	IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -2971,10 +3074,6 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)  	mutex_lock(&priv->mutex);  	IWL_DEBUG_MAC80211(priv, "enter\n"); -	/* do not support "flush" */ -	if (!priv->cfg->ops->lib->txfifo_flush) -		goto done; -  	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {  		IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");  		goto done; @@ -2990,7 +3089,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)  	 */  	if (drop) {  		IWL_DEBUG_MAC80211(priv, "send flush command\n"); -		if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) { +		if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {  			IWL_ERR(priv, "flush request fail\n");  			goto done;  		} @@ -3019,7 +3118,7 @@ static void iwlagn_disable_roc(struct iwl_priv *priv)  	priv->_agn.hw_roc_channel = NULL; -	iwlcore_commit_rxon(priv, ctx); +	iwlagn_commit_rxon(priv, ctx);  	ctx->is_active = false;  } @@ -3062,7 +3161,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,  	priv->_agn.hw_roc_channel = channel;  	priv->_agn.hw_roc_chantype = channel_type;  	priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); -	iwlcore_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]); +	iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);  	queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work,  			   msecs_to_jiffies(duration + 20)); @@ -3198,9 +3297,7 @@ static int iwl_init_drv(struct iwl_priv *priv)  	priv->rx_statistics_jiffies = jiffies;  	/* Choose which receivers/antennas to use */ -	if (priv->cfg->ops->hcmd->set_rxon_chain) -		priv->cfg->ops->hcmd->set_rxon_chain(priv, -					&priv->contexts[IWL_RXON_CTX_BSS]); +	iwlagn_set_rxon_chain(priv, &priv->contexts[IWL_RXON_CTX_BSS]);  	iwl_init_scan_params(priv); @@ -3245,6 +3342,29 @@ static void iwl_uninit_drv(struct iwl_priv *priv)  	kfree(priv->beacon_cmd);  } +static void iwl_mac_rssi_callback(struct ieee80211_hw *hw, +			   enum ieee80211_rssi_event rssi_event) +{ +	struct iwl_priv *priv = hw->priv; + +	mutex_lock(&priv->mutex); + +	if (priv->cfg->bt_params && +			priv->cfg->bt_params->advanced_bt_coexist) { +		if (rssi_event == RSSI_EVENT_LOW) +			priv->bt_enable_pspoll = true; +		else if (rssi_event == RSSI_EVENT_HIGH) +			priv->bt_enable_pspoll = false; + +		iwlagn_send_advance_bt_config(priv); +	} else { +		IWL_DEBUG_MAC80211(priv, "Advanced BT coex disabled," +				"ignoring RSSI callback\n"); +	} + +	mutex_unlock(&priv->mutex); +} +  struct ieee80211_ops iwlagn_hw_ops = {  	.tx = iwlagn_mac_tx,  	.start = iwlagn_mac_start, @@ -3270,15 +3390,13 @@ struct ieee80211_ops iwlagn_hw_ops = {  	.cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,  	.offchannel_tx = iwl_mac_offchannel_tx,  	.offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait, +	.rssi_callback = iwl_mac_rssi_callback,  	CFG80211_TESTMODE_CMD(iwl_testmode_cmd) +	CFG80211_TESTMODE_DUMP(iwl_testmode_dump)  };  static u32 iwl_hw_detect(struct iwl_priv *priv)  { -	u8 rev_id; - -	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); -	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);  	return iwl_read32(priv, CSR_HW_REV);  } @@ -3294,7 +3412,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv)  	priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;  	if (iwlagn_mod_params.disable_11n) -		priv->cfg->sku &= ~IWL_SKU_N; +		priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;  	/* Device-specific setup */  	return priv->cfg->ops->lib->set_hw_params(priv); @@ -3344,29 +3462,9 @@ out:  	return hw;  } -static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static void iwl_init_context(struct iwl_priv *priv)  { -	int err = 0, i; -	struct iwl_priv *priv; -	struct ieee80211_hw *hw; -	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); -	unsigned long flags; -	u16 pci_cmd, num_mac; -	u32 hw_rev; - -	/************************ -	 * 1. Allocating HW data -	 ************************/ - -	hw = iwl_alloc_all(cfg); -	if (!hw) { -		err = -ENOMEM; -		goto out; -	} -	priv = hw->priv; -	/* At this point both hw and priv are allocated. */ - -	priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED; +	int i;  	/*  	 * The default context is always valid, @@ -3398,8 +3496,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;  	priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON; -	priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING; -	priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = REPLY_WIPAN_RXON_ASSOC; +	priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = +		REPLY_WIPAN_RXON_TIMING; +	priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = +		REPLY_WIPAN_RXON_ASSOC;  	priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;  	priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;  	priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY; @@ -3419,12 +3519,43 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;  	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); +} + +int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, +		struct iwl_cfg *cfg) +{ +	int err = 0; +	struct iwl_priv *priv; +	struct ieee80211_hw *hw; +	u16 num_mac; +	u32 hw_rev; + +	/************************ +	 * 1. Allocating HW data +	 ************************/ +	hw = iwl_alloc_all(cfg); +	if (!hw) { +		err = -ENOMEM; +		goto out; +	} + +	priv = hw->priv; + +	priv->bus.priv = priv; +	priv->bus.bus_specific = bus_specific; +	priv->bus.ops = bus_ops; +	priv->bus.irq = priv->bus.ops->get_irq(&priv->bus); +	priv->bus.ops->set_drv_data(&priv->bus, priv); +	priv->bus.dev = priv->bus.ops->get_dev(&priv->bus); -	SET_IEEE80211_DEV(hw, &pdev->dev); +	iwl_trans_register(&priv->trans); + +	/* At this point both hw and priv are allocated. */ + +	SET_IEEE80211_DEV(hw, priv->bus.dev);  	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");  	priv->cfg = cfg; -	priv->pci_dev = pdev;  	priv->inta_mask = CSR_INI_SET_MASK;  	/* is antenna coupling more than 35dB ? */ @@ -3440,52 +3571,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	if (iwl_alloc_traffic_mem(priv))  		IWL_ERR(priv, "Not enough memory to generate traffic log\n"); -	/************************** -	 * 2. Initializing PCI bus -	 **************************/ -	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | -				PCIE_LINK_STATE_CLKPM); - -	if (pci_enable_device(pdev)) { -		err = -ENODEV; -		goto out_ieee80211_free_hw; -	} - -	pci_set_master(pdev); - -	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); -	if (!err) -		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); -	if (err) { -		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); -		if (!err) -			err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); -		/* both attempts failed: */ -		if (err) { -			IWL_WARN(priv, "No suitable DMA available.\n"); -			goto out_pci_disable_device; -		} -	} - -	err = pci_request_regions(pdev, DRV_NAME); -	if (err) -		goto out_pci_disable_device; - -	pci_set_drvdata(pdev, priv); - - -	/*********************** -	 * 3. Read REV register -	 ***********************/ -	priv->hw_base = pci_iomap(pdev, 0, 0); -	if (!priv->hw_base) { -		err = -ENODEV; -		goto out_pci_release_regions; -	} - -	IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n", -		(unsigned long long) pci_resource_len(pdev, 0)); -	IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);  	/* these spin locks will be used in apm_ops.init and EEPROM access  	 * we should init now @@ -3500,17 +3585,17 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	 */  	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); +	/*********************** +	 * 3. Read REV register +	 ***********************/  	hw_rev = iwl_hw_detect(priv);  	IWL_INFO(priv, "Detected %s, REV=0x%X\n",  		priv->cfg->name, hw_rev); -	/* 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); -  	if (iwl_prepare_card_hw(priv)) { +		err = -EIO;  		IWL_WARN(priv, "Failed, HW not ready\n"); -		goto out_iounmap; +		goto out_free_traffic_mem;  	}  	/***************** @@ -3520,7 +3605,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	err = iwl_eeprom_init(priv, hw_rev);  	if (err) {  		IWL_ERR(priv, "Unable to init EEPROM\n"); -		goto out_iounmap; +		goto out_free_traffic_mem;  	}  	err = iwl_eeprom_check_version(priv);  	if (err) @@ -3543,10 +3628,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  		priv->hw->wiphy->n_addresses++;  	} +	/* initialize all valid contexts */ +	iwl_init_context(priv); +  	/************************  	 * 5. Setup HW constants  	 ************************/  	if (iwl_set_hw_params(priv)) { +		err = -ENOENT;  		IWL_ERR(priv, "failed to set hw parameters\n");  		goto out_free_eeprom;  	} @@ -3563,19 +3652,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	/********************  	 * 7. Setup services  	 ********************/ -	spin_lock_irqsave(&priv->lock, flags); -	iwl_disable_interrupts(priv); -	spin_unlock_irqrestore(&priv->lock, flags); - -	pci_enable_msi(priv->pci_dev); -  	iwl_alloc_isr_ict(priv); -	err = request_irq(priv->pci_dev->irq, iwl_isr_ict, -			  IRQF_SHARED, DRV_NAME, priv); +	err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED, +			  DRV_NAME, priv);  	if (err) { -		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); -		goto out_disable_msi; +		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq); +		goto out_uninit_drv;  	}  	iwl_setup_deferred_work(priv); @@ -3583,16 +3666,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	iwl_testmode_init(priv);  	/********************************************* -	 * 8. Enable interrupts and read RFKILL state +	 * 8. Enable interrupts  	 *********************************************/ -	/* enable rfkill interrupt: hw bug w/a */ -	pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); -	if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { -		pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; -		pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); -	} -  	iwl_enable_rfkill_int(priv);  	/* If platform's RF_KILL switch is NOT set to KILL */ @@ -3618,41 +3694,30 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)   out_destroy_workqueue:  	destroy_workqueue(priv->workqueue);  	priv->workqueue = NULL; -	free_irq(priv->pci_dev->irq, priv); +	free_irq(priv->bus.irq, priv);  	iwl_free_isr_ict(priv); - out_disable_msi: -	pci_disable_msi(priv->pci_dev); + out_uninit_drv:  	iwl_uninit_drv(priv);   out_free_eeprom:  	iwl_eeprom_free(priv); - out_iounmap: -	pci_iounmap(pdev, priv->hw_base); - out_pci_release_regions: -	pci_set_drvdata(pdev, NULL); -	pci_release_regions(pdev); - out_pci_disable_device: -	pci_disable_device(pdev); - out_ieee80211_free_hw: + out_free_traffic_mem:  	iwl_free_traffic_mem(priv);  	ieee80211_free_hw(priv->hw);   out:  	return err;  } -static void __devexit iwl_pci_remove(struct pci_dev *pdev) +void __devexit iwl_remove(struct iwl_priv * priv)  { -	struct iwl_priv *priv = pci_get_drvdata(pdev);  	unsigned long flags; -	if (!priv) -		return; -  	wait_for_completion(&priv->_agn.firmware_loading_complete);  	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");  	iwl_dbgfs_unregister(priv); -	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); +	sysfs_remove_group(&priv->bus.dev->kobj, +			   &iwl_attribute_group);  	/* ieee80211_unregister_hw call wil cause iwl_mac_stop to  	 * to be called and iwl_down since we are removing the device @@ -3682,11 +3747,10 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)  	iwl_synchronize_irq(priv); -	iwl_dealloc_ucode_pci(priv); +	iwl_dealloc_ucode(priv); -	if (priv->rxq.bd) -		iwlagn_rx_queue_free(priv, &priv->rxq); -	iwlagn_hw_txq_ctx_free(priv); +	trans_rx_free(priv); +	trans_tx_free(priv);  	iwl_eeprom_free(priv); @@ -3701,12 +3765,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)  	priv->workqueue = NULL;  	iwl_free_traffic_mem(priv); -	free_irq(priv->pci_dev->irq, priv); -	pci_disable_msi(priv->pci_dev); -	pci_iounmap(pdev, priv->hw_base); -	pci_release_regions(pdev); -	pci_disable_device(pdev); -	pci_set_drvdata(pdev, NULL); +	free_irq(priv->bus.irq, priv); +	priv->bus.ops->set_drv_data(&priv->bus, NULL);  	iwl_uninit_drv(priv); @@ -3723,206 +3783,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)   * driver and module entry point   *   *****************************************************************************/ - -/* Hardware specific file defines the PCI IDs table for that hardware module */ -static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { -	{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */ - -/* 5300 Series WiFi */ -	{IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */ - -/* 5350 Series WiFi/WiMax */ -	{IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */ - -/* 5150 Series Wifi/WiMax */ -	{IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */ - -	{IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */ -	{IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */ -	{IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */ - -/* 6x00 Series */ -	{IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, -	{IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)}, -	{IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)}, -	{IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, -	{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, - -/* 6x05 Series */ -	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)}, -	{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, - -/* 6x30 Series */ -	{IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)}, -	{IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)}, -	{IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)}, -	{IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)}, - -/* 6x50 WiFi/WiMax Series */ -	{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, - -/* 6150 WiFi/WiMax Series */ -	{IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)}, - -/* 1000 Series WiFi */ -	{IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)}, - -/* 100 Series WiFi */ -	{IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)}, -	{IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)}, -	{IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)}, - -/* 130 Series WiFi */ -	{IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)}, - -/* 2x00 Series */ -	{IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)}, -	{IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)}, -	{IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)}, - -/* 2x30 Series */ -	{IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)}, -	{IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)}, -	{IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)}, - -/* 6x35 Series */ -	{IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)}, -	{IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)}, -	{IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)}, -	{IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)}, -	{IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)}, - -/* 105 Series */ -	{IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)}, - -/* 135 Series */ -	{IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)}, -	{IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)}, -	{IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)}, - -	{0} -}; -MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); - -static struct pci_driver iwl_driver = { -	.name = DRV_NAME, -	.id_table = iwl_hw_card_ids, -	.probe = iwl_pci_probe, -	.remove = __devexit_p(iwl_pci_remove), -	.driver.pm = IWL_PM_OPS, -}; -  static int __init iwl_init(void)  { @@ -3936,12 +3796,10 @@ static int __init iwl_init(void)  		return ret;  	} -	ret = pci_register_driver(&iwl_driver); -	if (ret) { -		pr_err("Unable to initialize PCI module\n"); -		goto error_register; -	} +	ret = iwl_pci_register_driver(); +	if (ret) +		goto error_register;  	return ret;  error_register: @@ -3951,7 +3809,7 @@ error_register:  static void __exit iwl_exit(void)  { -	pci_unregister_driver(&iwl_driver); +	iwl_pci_unregister_driver();  	iwlagn_rate_control_unregister();  } @@ -3993,3 +3851,51 @@ MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");  module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);  MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])"); + +module_param_named(wd_disable, iwlagn_mod_params.wd_disable, bool, S_IRUGO); +MODULE_PARM_DESC(wd_disable, +		"Disable stuck queue watchdog timer (default: 0 [enabled])"); + +/* + * set bt_coex_active to true, uCode will do kill/defer + * every time the priority line is asserted (BT is sending signals on the + * priority line in the PCIx). + * set bt_coex_active to false, uCode will ignore the BT activity and + * perform the normal operation + * + * User might experience transmit issue on some platform due to WiFi/BT + * co-exist problem. The possible behaviors are: + *   Able to scan and finding all the available AP + *   Not able to associate with any AP + * On those platforms, WiFi communication can be restored by set + * "bt_coex_active" module parameter to "false" + * + * default: bt_coex_active = true (BT_COEX_ENABLE) + */ +module_param_named(bt_coex_active, iwlagn_mod_params.bt_coex_active, +		bool, S_IRUGO); +MODULE_PARM_DESC(bt_coex_active, "enable wifi/bt co-exist (default: enable)"); + +module_param_named(led_mode, iwlagn_mod_params.led_mode, int, S_IRUGO); +MODULE_PARM_DESC(led_mode, "0=system default, " +		"1=On(RF On)/Off(RF Off), 2=blinking (default: 0)"); + +module_param_named(power_save, iwlagn_mod_params.power_save, +		bool, S_IRUGO); +MODULE_PARM_DESC(power_save, +		 "enable WiFi power management (default: disable)"); + +module_param_named(power_level, iwlagn_mod_params.power_level, +		int, S_IRUGO); +MODULE_PARM_DESC(power_level, +		 "default power save level (range from 1 - 5, default: 1)"); + +/* + * For now, keep using power level 1 instead of automatically + * adjusting ... + */ +module_param_named(no_sleep_autoadjust, iwlagn_mod_params.no_sleep_autoadjust, +		bool, S_IRUGO); +MODULE_PARM_DESC(no_sleep_autoadjust, +		 "don't automatically adjust sleep level " +		 "according to maximum network latency (default: true)"); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index d1716844002..5f58b44bb2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -109,9 +109,6 @@ extern struct iwl_cfg iwl135_bg_cfg;  extern struct iwl_cfg iwl135_bgn_cfg;  extern struct iwl_mod_params iwlagn_mod_params; -extern struct iwl_hcmd_ops iwlagn_hcmd; -extern struct iwl_hcmd_ops iwlagn_bt_hcmd; -extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;  extern struct ieee80211_ops iwlagn_hw_ops; @@ -125,10 +122,18 @@ irqreturn_t iwl_isr_ict(int irq, void *data);  static inline void iwl_synchronize_irq(struct iwl_priv *priv)  {  	/* wait to make sure we flush pending tasklet*/ -	synchronize_irq(priv->pci_dev->irq); +	synchronize_irq(priv->bus.irq);  	tasklet_kill(&priv->irq_tasklet);  } +static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd) +{ +	hdr->op_code = cmd; +	hdr->first_group = 0; +	hdr->groups_num = 1; +	hdr->data_valid = 1; +} +  int iwl_prepare_card_hw(struct iwl_priv *priv);  int iwlagn_start_device(struct iwl_priv *priv); @@ -161,7 +166,7 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv);  int iwlagn_run_init_ucode(struct iwl_priv *priv);  int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,  				 struct fw_img *image, -				 int subtype, int alternate_subtype); +				 enum iwlagn_ucode_type ucode_type);  /* lib */  void iwl_check_abort_status(struct iwl_priv *priv, @@ -172,9 +177,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr);  int iwlagn_send_tx_power(struct iwl_priv *priv);  void iwlagn_temperature(struct iwl_priv *priv);  u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); -const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, -				   size_t offset); -void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);  int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);  int iwlagn_hw_nic_init(struct iwl_priv *priv);  int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); @@ -186,13 +188,12 @@ void iwlagn_rx_queue_restock(struct iwl_priv *priv);  void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority);  void iwlagn_rx_replenish(struct iwl_priv *priv);  void iwlagn_rx_replenish_now(struct iwl_priv *priv); -void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); -int iwlagn_rxq_stop(struct iwl_priv *priv);  int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);  void iwl_setup_rx_handlers(struct iwl_priv *priv);  /* tx */ -void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, +				int index);  int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,  				 struct iwl_tx_queue *txq,  				 dma_addr_t addr, u16 len, u8 reset); @@ -211,10 +212,6 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,  void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,  				struct iwl_rx_mem_buffer *rxb);  int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); -void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); -int iwlagn_txq_ctx_alloc(struct iwl_priv *priv); -void iwlagn_txq_ctx_reset(struct iwl_priv *priv); -void iwlagn_txq_ctx_stop(struct iwl_priv *priv);  static inline u32 iwl_tx_status_to_mac80211(u32 status)  { @@ -252,6 +249,13 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,  /* hcmd */  int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);  int iwlagn_send_beacon_cmd(struct iwl_priv *priv); +int iwlagn_set_pan_params(struct iwl_priv *priv); +void iwlagn_gain_computation(struct iwl_priv *priv, +                u32 average_noise[NUM_RX_CHAINS], +                u16 min_average_noise_antenna_i, +                u32 min_average_noise, +                u8 default_chain); +  /* bt coex */  void iwlagn_send_advance_bt_config(struct iwl_priv *priv); @@ -260,6 +264,8 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,  void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);  void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);  void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv); +void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv); +void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena);  #ifdef CONFIG_IWLWIFI_DEBUG  const char *iwl_get_tx_fail_reason(u32 status); @@ -296,6 +302,8 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,  int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,  			int tid);  void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); +int iwl_update_bcast_station(struct iwl_priv *priv, +			     struct iwl_rxon_context *ctx);  int iwl_update_bcast_stations(struct iwl_priv *priv);  void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,  			   struct ieee80211_vif *vif, @@ -343,6 +351,9 @@ extern int iwl_alive_start(struct iwl_priv *priv);  /* svtool */  #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL  extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); +extern int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, +			     struct netlink_callback *cb, +			     void *data, int len);  extern void iwl_testmode_init(struct iwl_priv *priv);  extern void iwl_testmode_cleanup(struct iwl_priv *priv);  #else @@ -352,6 +363,13 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)  	return -ENOSYS;  }  static inline +int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, +		      struct netlink_callback *cb, +		      void *data, int len) +{ +	return -ENOSYS; +} +static inline  void iwl_testmode_init(struct iwl_priv *priv)  {  } @@ -361,4 +379,8 @@ void iwl_testmode_cleanup(struct iwl_priv *priv)  }  #endif +int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops, +		struct iwl_cfg *cfg); +void __devexit iwl_remove(struct iwl_priv * priv); +  #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6ee5f1aa555..ee2563777e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -384,18 +384,6 @@ struct iwl_tx_ant_config_cmd {  #define UCODE_VALID_OK	cpu_to_le32(0x1) -enum iwlagn_ucode_subtype { -	UCODE_SUBTYPE_REGULAR	= 0, -	UCODE_SUBTYPE_REGULAR_NEW = 1, -	UCODE_SUBTYPE_INIT	= 9, - -	/* -	 * Not a valid subtype, the ucode has just a u8, so -	 * we can use something > 0xff for this value. -	 */ -	UCODE_SUBTYPE_NONE_LOADED = 0x100, -}; -  /**   * REPLY_ALIVE = 0x1 (response only, not a command)   * @@ -984,15 +972,26 @@ struct iwl_rem_sta_cmd {  	u8 reserved2[2];  } __packed; -#define IWL_TX_FIFO_BK_MSK		cpu_to_le32(BIT(0)) -#define IWL_TX_FIFO_BE_MSK		cpu_to_le32(BIT(1)) -#define IWL_TX_FIFO_VI_MSK		cpu_to_le32(BIT(2)) -#define IWL_TX_FIFO_VO_MSK		cpu_to_le32(BIT(3)) + +/* WiFi queues mask */ +#define IWL_SCD_BK_MSK			cpu_to_le32(BIT(0)) +#define IWL_SCD_BE_MSK			cpu_to_le32(BIT(1)) +#define IWL_SCD_VI_MSK			cpu_to_le32(BIT(2)) +#define IWL_SCD_VO_MSK			cpu_to_le32(BIT(3)) +#define IWL_SCD_MGMT_MSK		cpu_to_le32(BIT(3)) + +/* PAN queues mask */ +#define IWL_PAN_SCD_BK_MSK		cpu_to_le32(BIT(4)) +#define IWL_PAN_SCD_BE_MSK		cpu_to_le32(BIT(5)) +#define IWL_PAN_SCD_VI_MSK		cpu_to_le32(BIT(6)) +#define IWL_PAN_SCD_VO_MSK		cpu_to_le32(BIT(7)) +#define IWL_PAN_SCD_MGMT_MSK		cpu_to_le32(BIT(7)) +#define IWL_PAN_SCD_MULTICAST_MSK	cpu_to_le32(BIT(8)) +  #define IWL_AGG_TX_QUEUE_MSK		cpu_to_le32(0xffc00)  #define IWL_DROP_SINGLE		0 -#define IWL_DROP_SELECTED	1 -#define IWL_DROP_ALL		2 +#define IWL_DROP_ALL		(BIT(IWL_RXON_CTX_BSS) | BIT(IWL_RXON_CTX_PAN))  /*   * REPLY_TXFIFO_FLUSH = 0x1e(command and response) @@ -1932,6 +1931,9 @@ struct iwl_bt_cmd {  /* Disable Sync PSPoll on SCO/eSCO */  #define IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE	BIT(7) +#define IWLAGN_BT_PSP_MIN_RSSI_THRESHOLD	-75 /* dBm */ +#define IWLAGN_BT_PSP_MAX_RSSI_THRESHOLD	-65 /* dBm */ +  #define IWLAGN_BT_PRIO_BOOST_MAX	0xFF  #define IWLAGN_BT_PRIO_BOOST_MIN	0x00  #define IWLAGN_BT_PRIO_BOOST_DEFAULT	0xF0 diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 213c80c6a66..fa3d5bacbde 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -42,27 +42,7 @@  #include "iwl-sta.h"  #include "iwl-helpers.h"  #include "iwl-agn.h" - - -/* - * set bt_coex_active to true, uCode will do kill/defer - * every time the priority line is asserted (BT is sending signals on the - * priority line in the PCIx). - * set bt_coex_active to false, uCode will ignore the BT activity and - * perform the normal operation - * - * User might experience transmit issue on some platform due to WiFi/BT - * co-exist problem. The possible behaviors are: - *   Able to scan and finding all the available AP - *   Not able to associate with any AP - * On those platforms, WiFi communication can be restored by set - * "bt_coex_active" module parameter to "false" - * - * default: bt_coex_active = true (BT_COEX_ENABLE) - */ -bool bt_coex_active = true; -module_param(bt_coex_active, bool, S_IRUGO); -MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); +#include "iwl-trans.h"  u32 iwl_debug_level; @@ -164,7 +144,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)  	sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];  	sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; -	if (priv->cfg->sku & IWL_SKU_N) +	if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)  		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,  					 IEEE80211_BAND_5GHZ); @@ -174,7 +154,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)  	sband->bitrates = rates;  	sband->n_bitrates = IWL_RATE_COUNT_LEGACY; -	if (priv->cfg->sku & IWL_SKU_N) +	if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)  		iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,  					 IEEE80211_BAND_2GHZ); @@ -229,12 +209,12 @@ int iwlcore_init_geos(struct iwl_priv *priv)  	priv->tx_power_next = max_tx_power;  	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && -	     priv->cfg->sku & IWL_SKU_A) { +	     priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) { +		char buf[32]; +		priv->bus.ops->get_hw_id(&priv->bus, buf, sizeof(buf));  		IWL_INFO(priv, "Incorrectly detected BG card as ABG. " -			"Please send your PCI ID 0x%04X:0x%04X to maintainer.\n", -			   priv->pci_dev->device, -			   priv->pci_dev->subsystem_device); -		priv->cfg->sku &= ~IWL_SKU_A; +			"Please send your %s to maintainer.\n", buf); +		priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;  	}  	IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", @@ -396,8 +376,8 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)  			le32_to_cpu(ctx->timing.beacon_init_val),  			le16_to_cpu(ctx->timing.atim_window)); -	return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd, -				sizeof(ctx->timing), &ctx->timing); +	return trans_send_cmd_pdu(priv, ctx->rxon_timing_cmd, +				CMD_SYNC, sizeof(ctx->timing), &ctx->timing);  }  void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, @@ -547,19 +527,6 @@ int iwl_full_rxon_required(struct iwl_priv *priv,  	return 0;  } -u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, -			    struct iwl_rxon_context *ctx) -{ -	/* -	 * Assign the lowest rate -- should really get this from -	 * the beacon skb from mac80211. -	 */ -	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) -		return IWL_RATE_1M_PLCP; -	else -		return IWL_RATE_6M_PLCP; -} -  static void _iwl_set_rxon_ht(struct iwl_priv *priv,  			     struct iwl_ht_config *ht_conf,  			     struct iwl_rxon_context *ctx) @@ -619,8 +586,7 @@ static void _iwl_set_rxon_ht(struct iwl_priv *priv,  		rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;  	} -	if (priv->cfg->ops->hcmd->set_rxon_chain) -		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); +	iwlagn_set_rxon_chain(priv, ctx);  	IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "  			"extension channel offset 0x%x\n", @@ -1018,8 +984,6 @@ void iwl_apm_stop(struct iwl_priv *priv)  int iwl_apm_init(struct iwl_priv *priv)  {  	int ret = 0; -	u16 lctl; -  	IWL_DEBUG_INFO(priv, "Init card's basic functions\n");  	/* @@ -1048,27 +1012,7 @@ int iwl_apm_init(struct iwl_priv *priv)  	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,  				    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); -	/* -	 * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition. -	 * Check if BIOS (or OS) enabled L1-ASPM on this device. -	 * If so (likely), disable L0S, so device moves directly L0->L1; -	 *    costs negligible amount of power savings. -	 * If not (unlikely), enable L0S, so there is at least some -	 *    power savings, even without L1. -	 */ -	lctl = iwl_pcie_link_ctl(priv); -	if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == -				PCI_CFG_LINK_CTRL_VAL_L1_EN) { -		/* L1-ASPM enabled; disable(!) L0S  */ -		iwl_set_bit(priv, CSR_GIO_REG, -				CSR_GIO_REG_VAL_L0S_ENABLED); -		IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n"); -	} else { -		/* L1-ASPM disabled; enable(!) L0S */ -		iwl_clear_bit(priv, CSR_GIO_REG, -				CSR_GIO_REG_VAL_L0S_ENABLED); -		IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n"); -	} +	priv->bus.ops->apm_config(&priv->bus);  	/* Configure analog phase-lock-loop before activating to D0A */  	if (priv->cfg->base_params->pll_cfg_val) @@ -1127,9 +1071,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)  	if (priv->tx_power_user_lmt == tx_power && !force)  		return 0; -	if (!priv->cfg->ops->lib->send_tx_power) -		return -EOPNOTSUPP; -  	if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {  		IWL_WARN(priv,  			 "Requested user TXPOWER %d below lower limit %d.\n", @@ -1163,7 +1104,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)  	prev_tx_power = priv->tx_power_user_lmt;  	priv->tx_power_user_lmt = tx_power; -	ret = priv->cfg->ops->lib->send_tx_power(priv); +	ret = iwlagn_send_tx_power(priv);  	/* if fail to set tx_power, restore the orig. tx power */  	if (ret) { @@ -1182,7 +1123,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)  		.kill_cts_mask = 0,  	}; -	if (!bt_coex_active) +	if (!iwlagn_mod_params.bt_coex_active)  		bt_cmd.flags = BT_COEX_DISABLE;  	else  		bt_cmd.flags = BT_COEX_ENABLE; @@ -1191,8 +1132,8 @@ void iwl_send_bt_config(struct iwl_priv *priv)  	IWL_DEBUG_INFO(priv, "BT coex %s\n",  		(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); -	if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, -			     sizeof(struct iwl_bt_cmd), &bt_cmd)) +	if (trans_send_cmd_pdu(priv, REPLY_BT_CONFIG, +			     CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))  		IWL_ERR(priv, "failed to send BT Coex Config\n");  } @@ -1204,11 +1145,13 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)  	};  	if (flags & CMD_ASYNC) -		return iwl_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD, +		return trans_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, +					      CMD_ASYNC,  					       sizeof(struct iwl_statistics_cmd), -					       &statistics_cmd, NULL); +					       &statistics_cmd);  	else -		return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, +		return trans_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, +					CMD_SYNC,  					sizeof(struct iwl_statistics_cmd),  					&statistics_cmd);  } @@ -1275,10 +1218,9 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)  {  	iwl_connection_init_rx_config(priv, ctx); -	if (priv->cfg->ops->hcmd->set_rxon_chain) -		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); +	iwlagn_set_rxon_chain(priv, ctx); -	return iwlcore_commit_rxon(priv, ctx); +	return iwlagn_commit_rxon(priv, ctx);  }  static int iwl_setup_interface(struct iwl_priv *priv, @@ -1431,26 +1373,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,  } -int iwl_alloc_txq_mem(struct iwl_priv *priv) -{ -	if (!priv->txq) -		priv->txq = kzalloc( -			sizeof(struct iwl_tx_queue) * -				priv->cfg->base_params->num_of_queues, -			GFP_KERNEL); -	if (!priv->txq) { -		IWL_ERR(priv, "Not enough memory for txq\n"); -		return -ENOMEM; -	} -	return 0; -} - -void iwl_free_txq_mem(struct iwl_priv *priv) -{ -	kfree(priv->txq); -	priv->txq = NULL; -} -  #ifdef CONFIG_IWLWIFI_DEBUGFS  #define IWL_TRAFFIC_DUMP_SIZE	(IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) @@ -1763,6 +1685,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);  	struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS];  	struct iwl_rxon_context *tmp; +	enum nl80211_iftype newviftype = newtype;  	u32 interface_modes;  	int err; @@ -1818,7 +1741,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	/* success */  	iwl_teardown_interface(priv, vif, true); -	vif->type = newtype; +	vif->type = newviftype;  	vif->p2p = newp2p;  	err = iwl_setup_interface(priv, ctx);  	WARN_ON(err); @@ -1911,7 +1834,7 @@ void iwl_setup_watchdog(struct iwl_priv *priv)  {  	unsigned int timeout = priv->cfg->base_params->wd_timeout; -	if (timeout) +	if (timeout && !iwlagn_mod_params.wd_disable)  		mod_timer(&priv->watchdog,  			  jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout)));  	else @@ -1972,11 +1895,8 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,  #ifdef CONFIG_PM -int iwl_pci_suspend(struct device *device) +int iwl_suspend(struct iwl_priv *priv)  { -	struct pci_dev *pdev = to_pci_dev(device); -	struct iwl_priv *priv = pci_get_drvdata(pdev); -  	/*  	 * This function is called when system goes into suspend state  	 * mac80211 will call iwl_mac_stop() from the mac80211 suspend function @@ -1989,18 +1909,10 @@ int iwl_pci_suspend(struct device *device)  	return 0;  } -int iwl_pci_resume(struct device *device) +int iwl_resume(struct iwl_priv *priv)  { -	struct pci_dev *pdev = to_pci_dev(device); -	struct iwl_priv *priv = pci_get_drvdata(pdev);  	bool hw_rfkill = false; -	/* -	 * 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); -  	iwl_enable_interrupts(priv);  	if (!(iwl_read32(priv, CSR_GP_CNTRL) & @@ -2017,13 +1929,4 @@ int iwl_pci_resume(struct device *device)  	return 0;  } -const struct dev_pm_ops iwl_pm_ops = { -	.suspend = iwl_pci_suspend, -	.resume = iwl_pci_resume, -	.freeze = iwl_pci_suspend, -	.thaw = iwl_pci_resume, -	.poweroff = iwl_pci_suspend, -	.restore = iwl_pci_resume, -}; -  #endif /* CONFIG_PM */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a54d416ec34..692c30cb2fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -76,54 +76,10 @@ struct iwl_cmd;  #define DRV_COPYRIGHT	"Copyright(c) 2003-2011 Intel Corporation"  #define DRV_AUTHOR     "<ilw@linux.intel.com>" -#define IWL_PCI_DEVICE(dev, subdev, cfg) \ -	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \ -	.subvendor = PCI_ANY_ID, .subdevice = (subdev), \ -	.driver_data = (kernel_ulong_t)&(cfg) -  #define TIME_UNIT		1024 -#define IWL_SKU_G       0x1 -#define IWL_SKU_A       0x2 -#define IWL_SKU_N       0x8 -  #define IWL_CMD(x) case x: return #x -struct iwl_hcmd_ops { -	int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx); -	void (*set_rxon_chain)(struct iwl_priv *priv, -			       struct iwl_rxon_context *ctx); -	int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant); -	void (*send_bt_config)(struct iwl_priv *priv); -	int (*set_pan_params)(struct iwl_priv *priv); -}; - -struct iwl_hcmd_utils_ops { -	u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data); -	void (*gain_computation)(struct iwl_priv *priv, -			u32 *average_noise, -			u16 min_average_noise_antennat_i, -			u32 min_average_noise, -			u8 default_chain); -	void (*chain_noise_reset)(struct iwl_priv *priv); -	void (*tx_cmd_protection)(struct iwl_priv *priv, -				  struct ieee80211_tx_info *info, -				  __le16 fc, __le32 *tx_flags); -	int  (*calc_rssi)(struct iwl_priv *priv, -			  struct iwl_rx_phy_res *rx_resp); -	int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif); -	void (*post_scan)(struct iwl_priv *priv); -}; - -struct iwl_apm_ops { -	int (*init)(struct iwl_priv *priv); -	void (*config)(struct iwl_priv *priv); -}; - -struct iwl_temp_ops { -	void (*temperature)(struct iwl_priv *priv); -}; -  struct iwl_lib_ops {  	/* set hw dependent parameters */  	int (*set_hw_params)(struct iwl_priv *priv); @@ -137,22 +93,14 @@ struct iwl_lib_ops {  	int (*is_valid_rtc_data_addr)(u32 addr);  	int (*set_channel_switch)(struct iwl_priv *priv,  				  struct ieee80211_channel_switch *ch_switch); -	/* power management */ -	struct iwl_apm_ops apm_ops; - -	/* power */ -	int (*send_tx_power) (struct iwl_priv *priv); -	void (*update_chain_flags)(struct iwl_priv *priv); +	/* device specific configuration */ +	void (*nic_config)(struct iwl_priv *priv);  	/* eeprom operations (as defined in iwl-eeprom.h) */  	struct iwl_eeprom_ops eeprom_ops;  	/* temperature */ -	struct iwl_temp_ops temp_ops; - -	int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control); -	void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); - +	void (*temperature)(struct iwl_priv *priv);  };  /* NIC specific ops */ @@ -162,8 +110,6 @@ struct iwl_nic_ops {  struct iwl_ops {  	const struct iwl_lib_ops *lib; -	const struct iwl_hcmd_ops *hcmd; -	const struct iwl_hcmd_utils_ops *utils;  	const struct iwl_nic_ops *nic;  }; @@ -176,6 +122,12 @@ struct iwl_mod_params {  	int restart_fw;		/* def: 1 = restart firmware */  	bool plcp_check;	/* def: true = enable plcp health check */  	bool ack_check;		/* def: false = disable ack health check */ +	bool wd_disable;	/* def: false = enable stuck queue check */ +	bool bt_coex_active;	/* def: true = enable bt coex */ +	int led_mode;		/* def: 0 = system default */ +	bool no_sleep_autoadjust; /* def: true = disable autoadjust */ +	bool power_save;	/* def: false = disable power save */ +	int power_level;	/* def: 1 = power level */  };  /* @@ -225,7 +177,7 @@ struct iwl_base_params {   * @ampdu_factor: Maximum A-MPDU length factor   * @ampdu_density: Minimum A-MPDU spacing   * @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode -*/ + */  struct iwl_bt_params {  	bool advanced_bt_coexist;  	u8 bt_init_traffic_load; @@ -238,10 +190,11 @@ struct iwl_bt_params {  };  /*   * @use_rts_for_aggregation: use rts/cts protection for HT traffic -*/ + */  struct iwl_ht_params {  	const bool ht_greenfield_support; /* if used set to true */  	bool use_rts_for_aggregation; +	enum ieee80211_smps_mode smps_mode;  };  /** @@ -291,7 +244,7 @@ struct iwl_cfg {  	const unsigned int ucode_api_min;  	u8   valid_tx_ant;  	u8   valid_rx_ant; -	unsigned int sku; +	u16  sku;  	u16  eeprom_ver;  	u16  eeprom_calib_ver;  	const struct iwl_ops *ops; @@ -346,9 +299,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,  int iwl_mac_change_interface(struct ieee80211_hw *hw,  			     struct ieee80211_vif *vif,  			     enum nl80211_iftype newtype, bool newp2p); -int iwl_alloc_txq_mem(struct iwl_priv *priv); -void iwl_free_txq_mem(struct iwl_priv *priv); -  #ifdef CONFIG_IWLWIFI_DEBUGFS  int iwl_alloc_traffic_mem(struct iwl_priv *priv);  void iwl_free_traffic_mem(struct iwl_priv *priv); @@ -390,9 +340,6 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,  /*****************************************************  * RX  ******************************************************/ -void iwl_cmd_queue_free(struct iwl_priv *priv); -void iwl_cmd_queue_unmap(struct iwl_priv *priv); -int iwl_rx_queue_alloc(struct iwl_priv *priv);  void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,  				  struct iwl_rx_queue *q);  int iwl_rx_queue_space(const struct iwl_rx_queue *q); @@ -406,12 +353,8 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);  * TX  ******************************************************/  void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); -int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, -		      int slots_num, u32 txq_id); -void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, -			int slots_num, u32 txq_id); -void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); -void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id); +int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, +			  int count, int slots_num, u32 id);  void iwl_setup_watchdog(struct iwl_priv *priv);  /*****************************************************   * TX power @@ -419,13 +362,6 @@ void iwl_setup_watchdog(struct iwl_priv *priv);  int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);  /******************************************************************************* - * Rate - ******************************************************************************/ - -u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, -			    struct iwl_rxon_context *ctx); - -/*******************************************************************************   * Scanning   ******************************************************************************/  void iwl_init_scan_params(struct iwl_priv *priv); @@ -469,49 +405,20 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,   *****************************************************/  const char *get_cmd_string(u8 cmd); -int __must_check iwl_send_cmd_sync(struct iwl_priv *priv, -				   struct iwl_host_cmd *cmd);  int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); -int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, +int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags,  				  u16 len, const void *data); -int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, -			   const void *data, -			   void (*callback)(struct iwl_priv *priv, -					    struct iwl_device_cmd *cmd, -					    struct iwl_rx_packet *pkt));  int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); - -/***************************************************** - * PCI						     * - *****************************************************/ - -static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) -{ -	int pos; -	u16 pci_lnk_ctl; -	pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP); -	pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); -	return pci_lnk_ctl; -} -  void iwl_bg_watchdog(unsigned long data);  u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);  __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,  			   u32 addon, u32 beacon_interval);  #ifdef CONFIG_PM -int iwl_pci_suspend(struct device *device); -int iwl_pci_resume(struct device *device); -extern const struct dev_pm_ops iwl_pm_ops; - -#define IWL_PM_OPS	(&iwl_pm_ops) - -#else /* !CONFIG_PM */ - -#define IWL_PM_OPS	NULL - +int iwl_suspend(struct iwl_priv *priv); +int iwl_resume(struct iwl_priv *priv);  #endif /* !CONFIG_PM */  /***************************************************** @@ -613,11 +520,7 @@ void iwl_apm_stop(struct iwl_priv *priv);  int iwl_apm_init(struct iwl_priv *priv);  int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx); -static inline int iwlcore_commit_rxon(struct iwl_priv *priv, -				      struct iwl_rxon_context *ctx) -{ -	return priv->cfg->ops->hcmd->commit_rxon(priv, ctx); -} +  static inline const struct ieee80211_supported_band *iwl_get_hw_mode(  			struct iwl_priv *priv, enum ieee80211_band band)  { @@ -630,7 +533,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)  	       priv->cfg->bt_params->advanced_bt_coexist;  } -extern bool bt_coex_active;  extern bool bt_siso_mode; diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 2824ccbcc1f..eb95d1a3748 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -32,10 +32,10 @@  struct iwl_priv;  extern u32 iwl_debug_level; -#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a) -#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a) -#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a) -#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a) +#define IWL_ERR(p, f, a...) dev_err(p->bus.ops->get_dev(&p->bus), f, ## a) +#define IWL_WARN(p, f, a...) dev_warn(p->bus.ops->get_dev(&p->bus), f, ## a) +#define IWL_INFO(p, f, a...) dev_info(p->bus.ops->get_dev(&p->bus), f, ## a) +#define IWL_CRIT(p, f, a...) dev_crit(p->bus.ops->get_dev(&p->bus), f, ## a)  #define iwl_print_hex_error(priv, p, len) 				\  do {									\ @@ -125,13 +125,13 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)  /* 0x00000F00 - 0x00000100 */  #define IWL_DL_POWER		(1 << 8)  #define IWL_DL_TEMP		(1 << 9) -#define IWL_DL_NOTIF		(1 << 10) +/* reserved (1 << 10) */  #define IWL_DL_SCAN		(1 << 11)  /* 0x0000F000 - 0x00001000 */  #define IWL_DL_ASSOC		(1 << 12)  #define IWL_DL_DROP		(1 << 13) -#define IWL_DL_TXPOWER		(1 << 14) -#define IWL_DL_AP		(1 << 15) +/* reserved (1 << 14) */ +#define IWL_DL_COEX		(1 << 15)  /* 0x000F0000 - 0x00010000 */  #define IWL_DL_FW		(1 << 16)  #define IWL_DL_RF_KILL		(1 << 17) @@ -171,12 +171,10 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)  #define IWL_DEBUG_DROP(p, f, a...)	IWL_DEBUG(p, IWL_DL_DROP, f, ## a)  #define IWL_DEBUG_DROP_LIMIT(p, f, a...)	\  		IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_AP(p, f, a...)	IWL_DEBUG(p, IWL_DL_AP, f, ## a) -#define IWL_DEBUG_TXPOWER(p, f, a...)	IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a) +#define IWL_DEBUG_COEX(p, f, a...)	IWL_DEBUG(p, IWL_DL_COEX, f, ## a)  #define IWL_DEBUG_RATE(p, f, a...)	IWL_DEBUG(p, IWL_DL_RATE, f, ## a)  #define IWL_DEBUG_RATE_LIMIT(p, f, a...)	\  		IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_NOTIF(p, f, a...)	IWL_DEBUG(p, IWL_DL_NOTIF, f, ## a)  #define IWL_DEBUG_ASSOC(p, f, a...)	\  		IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)  #define IWL_DEBUG_ASSOC_LIMIT(p, f, a...)	\ diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 0e6a04b739a..6f9ebae8ca0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -227,7 +227,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,  	/* default is to dump the entire data segment */  	if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {  		priv->dbgfs_sram_offset = 0x800000; -		if (priv->ucode_type == UCODE_SUBTYPE_INIT) +		if (priv->ucode_type == IWL_UCODE_INIT)  			priv->dbgfs_sram_len = priv->ucode_init.data.len;  		else  			priv->dbgfs_sram_len = priv->ucode_rt.data.len; @@ -2493,7 +2493,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,  	if (iwl_is_rfkill(priv))  		return -EFAULT; -	priv->cfg->ops->lib->dev_txfifo_flush(priv, IWL_DROP_ALL); +	iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);  	return count;  } @@ -2693,8 +2693,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)  	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->cfg->ops->lib->dev_txfifo_flush) -		DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR); +	DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);  	DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);  	DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c8de236c141..424c45c43f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -31,6 +31,7 @@  #ifndef __iwl_dev_h__  #define __iwl_dev_h__ +#include <linux/interrupt.h>  #include <linux/pci.h> /* for struct pci_device_id */  #include <linux/kernel.h>  #include <linux/wait.h> @@ -48,6 +49,8 @@  #include "iwl-agn-rs.h"  #include "iwl-agn-tt.h" +#define DRV_NAME        "iwlagn" +  struct iwl_tx_queue;  /* CT-KILL constants */ @@ -257,11 +260,9 @@ struct iwl_channel_info {  enum {  	CMD_SYNC = 0, -	CMD_SIZE_NORMAL = 0, -	CMD_NO_SKB = 0, -	CMD_ASYNC = (1 << 1), -	CMD_WANT_SKB = (1 << 2), -	CMD_MAPPED = (1 << 3), +	CMD_ASYNC = BIT(0), +	CMD_WANT_SKB = BIT(1), +	CMD_ON_DEMAND = BIT(2),  };  #define DEF_CMD_PAYLOAD_SIZE 320 @@ -294,6 +295,16 @@ enum iwl_hcmd_dataflag {  	IWL_HCMD_DFL_NOCOPY	= BIT(0),  }; +/** + * struct iwl_host_cmd - Host command to the uCode + * @data: array of chunks that composes the data of the host command + * @reply_page: pointer to the page that holds the response to the host command + * @callback: + * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC + * @len: array of the lenths of the chunks in data + * @dataflags: + * @id: id of the host command + */  struct iwl_host_cmd {  	const void *data[IWL_MAX_CMD_TFDS];  	unsigned long reply_page; @@ -631,7 +642,6 @@ struct iwl_sensitivity_ranges {  /**   * struct iwl_hw_params   * @max_txq_num: Max # Tx queues supported - * @dma_chnl_num: Number of Tx DMA/FIFO channels   * @scd_bc_tbls_size: size of scheduler byte count tables   * @tfd_size: TFD size   * @tx/rx_chains_num: Number of TX/RX chains @@ -653,7 +663,6 @@ struct iwl_sensitivity_ranges {   */  struct iwl_hw_params {  	u8 max_txq_num; -	u8 dma_chnl_num;  	u16 scd_bc_tbls_size;  	u32 tfd_size;  	u8  tx_chains_num; @@ -663,7 +672,6 @@ struct iwl_hw_params {  	u16 max_rxq_size;  	u16 max_rxq_log;  	u32 rx_page_order; -	u32 rx_wrt_ptr_reg;  	u8  max_stations;  	u8  ht40_channel;  	u8  max_beacon_itrvl;	/* in 1024 ms */ @@ -694,8 +702,6 @@ struct iwl_hw_params {   ****************************************************************************/  extern void iwl_update_chain_flags(struct iwl_priv *priv);  extern const u8 iwl_bcast_addr[ETH_ALEN]; -extern int iwl_rxq_stop(struct iwl_priv *priv); -extern void iwl_txq_ctx_stop(struct iwl_priv *priv);  extern int iwl_queue_space(const struct iwl_queue *q);  static inline int iwl_queue_used(const struct iwl_queue *q, int i)  { @@ -1168,14 +1174,100 @@ enum iwl_scan_type {  	IWL_SCAN_OFFCH_TX,  }; +enum iwlagn_ucode_type { +	IWL_UCODE_NONE, +	IWL_UCODE_REGULAR, +	IWL_UCODE_INIT, +	IWL_UCODE_WOWLAN, +}; +  #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL  struct iwl_testmode_trace { +	u32 buff_size; +	u32 total_size; +	u32 num_chunks;  	u8 *cpu_addr;  	u8 *trace_addr;  	dma_addr_t dma_addr;  	bool trace_enabled;  };  #endif + +struct iwl_bus; + +/** + * struct iwl_bus_ops - bus specific operations + + * @get_pm_support: must returns true if the bus can go to sleep + * @apm_config: will be called during the config of the APM configuration + * @set_drv_data: set the priv pointer to the bus layer + * @get_dev: returns the device struct + * @get_irq: returns the irq number + * @get_hw_id: prints the hw_id in the provided buffer + * @write8: write a byte to register at offset ofs + * @write32: write a dword to register at offset ofs + * @wread32: read a dword at register at offset ofs + */ +struct iwl_bus_ops { +	bool (*get_pm_support)(struct iwl_bus *bus); +	void (*apm_config)(struct iwl_bus *bus); +	void (*set_drv_data)(struct iwl_bus *bus, void *priv); +	struct device *(*get_dev)(const struct iwl_bus *bus); +	unsigned int (*get_irq)(const struct iwl_bus *bus); +	void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len); +	void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val); +	void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val); +	u32 (*read32)(struct iwl_bus *bus, u32 ofs); +}; + +struct iwl_bus { +	/* pointer to bus specific struct */ +	void *bus_specific; + +	/* Common data to all buses */ +	struct iwl_priv *priv; /* driver's context */ +	struct device *dev; +	struct iwl_bus_ops *ops; +	unsigned int irq; +}; + +struct iwl_trans; + +/** + * struct iwl_trans_ops - transport specific operations + + * @rx_init: inits the rx memory, allocate it if needed + * @rx_stop: stop the rx + * @rx_free: frees the rx memory + * @tx_init:inits the tx memory, allocate if needed + * @tx_stop: stop the tx + * @tx_free: frees the tx memory + * @send_cmd:send a host command + * @send_cmd_pdu:send a host command: flags can be CMD_* + */ +struct iwl_trans_ops { +	int (*rx_init)(struct iwl_priv *priv); +	int (*rx_stop)(struct iwl_priv *priv); +	void (*rx_free)(struct iwl_priv *priv); + +	int (*tx_init)(struct iwl_priv *priv); +	int (*tx_stop)(struct iwl_priv *priv); +	void (*tx_free)(struct iwl_priv *priv); + +	int (*send_cmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); + +	int (*send_cmd_pdu)(struct iwl_priv *priv, u8 id, u32 flags, u16 len, +		     const void *data); +}; + +struct iwl_trans { +	const struct iwl_trans_ops *ops; +}; + +/* uCode ownership */ +#define IWL_OWNERSHIP_DRIVER	0 +#define IWL_OWNERSHIP_TM	1 +  struct iwl_priv {  	/* ieee device used by generic ieee processing code */ @@ -1243,11 +1335,8 @@ struct iwl_priv {  	spinlock_t reg_lock;	/* protect hw register access */  	struct mutex mutex; -	/* basic pci-network driver stuff */ -	struct pci_dev *pci_dev; - -	/* pci hardware address support */ -	void __iomem *hw_base; +	struct iwl_bus bus;	/* bus specific data */ +	struct iwl_trans trans;  	/* microcode/device supports multiple contexts */  	u8 valid_contexts; @@ -1267,10 +1356,14 @@ struct iwl_priv {  	int fw_index;			/* firmware we're trying to load */  	u32 ucode_ver;			/* version of ucode, copy of  					   iwl_ucode.ver */ + +	/* uCode owner: default: IWL_OWNERSHIP_DRIVER */ +	u8 ucode_owner; +  	struct fw_img ucode_rt;  	struct fw_img ucode_init; -	enum iwlagn_ucode_subtype ucode_type; +	enum iwlagn_ucode_type ucode_type;  	u8 ucode_write_complete;	/* the image write is complete */  	char firmware_name[25]; @@ -1442,6 +1535,9 @@ struct iwl_priv {  	u16 dynamic_frag_thresh;  	u8 bt_ci_compliance;  	struct work_struct bt_traffic_change_work; +	bool bt_enable_pspoll; +	struct iwl_rxon_context *cur_rssi_ctx; +	bool bt_is_sco;  	struct iwl_hw_params hw_params; @@ -1510,7 +1606,7 @@ struct iwl_priv {  #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL  	struct iwl_testmode_trace testmode_trace;  #endif -	u32 dbg_fixed_rate; +	u32 tm_fixed_rate;  }; /*iwl_priv */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 47a56bc1cd1..eee97bcf980 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -407,11 +407,6 @@ static int iwl_find_otp_image(struct iwl_priv *priv,  	return -EINVAL;  } -const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) -{ -	return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset); -} -  u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)  {  	if (!priv->eeprom) @@ -449,7 +444,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)  	}  	e = (__le16 *)priv->eeprom; -	priv->cfg->ops->lib->apm_ops.init(priv); +	iwl_apm_init(priv);  	ret = iwl_eeprom_verify_signature(priv);  	if (ret < 0) { @@ -834,3 +829,28 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,  	return NULL;  } + +void iwl_rf_config(struct iwl_priv *priv) +{ +	u16 radio_cfg; + +	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); + +	/* write radio config values to register */ +	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { +		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, +			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | +			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) | +			    EEPROM_RF_CFG_DASH_MSK(radio_cfg)); +		IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n", +			 EEPROM_RF_CFG_TYPE_MSK(radio_cfg), +			 EEPROM_RF_CFG_STEP_MSK(radio_cfg), +			 EEPROM_RF_CFG_DASH_MSK(radio_cfg)); +	} else +		WARN_ON(1); + +	/* set CSR_HW_CONFIG_REG for uCode use */ +	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, +		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | +		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index c960c6fa009..e4bf8ac5e64 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -110,12 +110,10 @@ enum {  };  /* SKU Capabilities */ -/* 5000 and up */ -#define EEPROM_SKU_CAP_BAND_POS				(4) -#define EEPROM_SKU_CAP_BAND_SELECTION	                \ -		(3 << EEPROM_SKU_CAP_BAND_POS) +#define EEPROM_SKU_CAP_BAND_24GHZ			(1 << 4) +#define EEPROM_SKU_CAP_BAND_52GHZ			(1 << 5)  #define EEPROM_SKU_CAP_11N_ENABLE	                (1 << 6) -#define EEPROM_SKU_CAP_AMT_ENABLE	                (1 << 7) +#define EEPROM_SKU_CAP_AMT_ENABLE			(1 << 7)  #define EEPROM_SKU_CAP_IPAN_ENABLE	                (1 << 8)  /* *regulatory* channel data format in eeprom, one for each channel. @@ -164,16 +162,12 @@ struct iwl_eeprom_enhanced_txpwr {  	s8 mimo3_max;  } __packed; -/* 5000 Specific */ -#define EEPROM_5000_TX_POWER_VERSION    (4) -#define EEPROM_5000_EEPROM_VERSION	(0x11A) - -/* 5000 and up calibration */ +/* calibration */  #define EEPROM_CALIB_ALL	(INDIRECT_ADDRESS | INDIRECT_CALIBRATION)  #define EEPROM_XTAL		((2*0x128) | EEPROM_CALIB_ALL) -/* 5000 temperature */ -#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL) +/* temperature */ +#define EEPROM_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)  /* agn links */  #define EEPROM_LINK_HOST             (2*0x64) @@ -205,6 +199,10 @@ struct iwl_eeprom_enhanced_txpwr {  #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS  ((0x80)\  		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 14  bytes */ +/* 5000 Specific */ +#define EEPROM_5000_TX_POWER_VERSION    (4) +#define EEPROM_5000_EEPROM_VERSION	(0x11A) +  /* 5050 Specific */  #define EEPROM_5050_TX_POWER_VERSION    (4)  #define EEPROM_5050_EEPROM_VERSION	(0x21E) @@ -270,13 +268,13 @@ extern const u8 iwl_eeprom_band_1[14];  /* General */  #define EEPROM_DEVICE_ID                    (2*0x08)	/* 2 bytes */ +#define EEPROM_SUBSYSTEM_ID		    (2*0x0A)	/* 2 bytes */  #define EEPROM_MAC_ADDRESS                  (2*0x15)	/* 6  bytes */  #define EEPROM_BOARD_REVISION               (2*0x35)	/* 2  bytes */  #define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1)	/* 9  bytes */  #define EEPROM_VERSION                      (2*0x44)	/* 2  bytes */  #define EEPROM_SKU_CAP                      (2*0x45)	/* 2  bytes */  #define EEPROM_OEM_MODE                     (2*0x46)	/* 2  bytes */ -#define EEPROM_WOWLAN_MODE                  (2*0x47)	/* 2  bytes */  #define EEPROM_RADIO_CONFIG                 (2*0x48)	/* 2  bytes */  #define EEPROM_NUM_MAC_ADDRESS              (2*0x4C)	/* 2  bytes */ @@ -294,7 +292,6 @@ extern const u8 iwl_eeprom_band_1[14];  struct iwl_eeprom_ops {  	const u32 regulatory_bands[7]; -	const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset);  	void (*update_enhanced_txpower) (struct iwl_priv *priv);  }; @@ -311,5 +308,6 @@ void iwl_free_channel_map(struct iwl_priv *priv);  const struct iwl_channel_info *iwl_get_channel_info(  		const struct iwl_priv *priv,  		enum ieee80211_band band, u16 channel); +void iwl_rf_config(struct iwl_priv *priv);  #endif  /* __iwl_eeprom_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 6dfa806aefe..0ad60b3c04d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -326,7 +326,7 @@  #define FH_TCSR_UPPER_BOUND  (FH_MEM_LOWER_BOUND + 0xE60)  /* Find Control/Status reg for given Tx DMA/FIFO channel */ -#define FH50_TCSR_CHNL_NUM                            (8) +#define FH_TCSR_CHNL_NUM                            (8)  /* TCSR: tx_config register values */  #define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl)	\ diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 76f99662314..6cff8c165ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -113,7 +113,7 @@ const char *get_cmd_string(u8 cmd)  	}  } -#define HOST_COMPLETE_TIMEOUT (HZ / 2) +#define HOST_COMPLETE_TIMEOUT (2 * HZ)  static void iwl_generic_cmd_callback(struct iwl_priv *priv,  				     struct iwl_device_cmd *cmd, @@ -143,9 +143,6 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  {  	int ret; -	if (WARN_ON(!(cmd->flags & CMD_ASYNC))) -		return -EINVAL; -  	/* An asynchronous command can not expect an SKB to be set. */  	if (WARN_ON(cmd->flags & CMD_WANT_SKB))  		return -EINVAL; @@ -166,13 +163,12 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  	return 0;  } -int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +static int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  {  	int cmd_idx;  	int ret; -	if (WARN_ON(cmd->flags & CMD_ASYNC)) -		return -EINVAL; +	lockdep_assert_held(&priv->mutex);  	 /* A synchronous command can not have a callback set. */  	if (WARN_ON(cmd->callback)) @@ -261,31 +257,15 @@ int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  	return iwl_send_cmd_sync(priv, cmd);  } -int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) +int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, u16 len, +		     const void *data)  {  	struct iwl_host_cmd cmd = {  		.id = id,  		.len = { len, },  		.data = { data, }, +		.flags = flags,  	}; -	return iwl_send_cmd_sync(priv, &cmd); -} - -int iwl_send_cmd_pdu_async(struct iwl_priv *priv, -			   u8 id, u16 len, const void *data, -			   void (*callback)(struct iwl_priv *priv, -					    struct iwl_device_cmd *cmd, -					    struct iwl_rx_packet *pkt)) -{ -	struct iwl_host_cmd cmd = { -		.id = id, -		.len = { len, }, -		.data = { data, }, -	}; - -	cmd.flags |= CMD_ASYNC; -	cmd.callback = callback; - -	return iwl_send_cmd_async(priv, &cmd); +	return iwl_send_cmd(priv, &cmd);  } diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 41207a3645b..9d91552d13c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -120,7 +120,16 @@ static inline void iwl_wake_any_queue(struct iwl_priv *priv,  	}  } +#ifdef ieee80211_stop_queue +#undef ieee80211_stop_queue +#endif +  #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue + +#ifdef ieee80211_wake_queue +#undef ieee80211_wake_queue +#endif +  #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue  static inline void iwl_disable_interrupts(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 869edc580ec..c56eae74c3c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -38,18 +38,18 @@  static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val)  {  	trace_iwlwifi_dev_iowrite8(priv, ofs, val); -	iowrite8(val, priv->hw_base + ofs); +	priv->bus.ops->write8(&priv->bus, ofs, val);  }  static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val)  {  	trace_iwlwifi_dev_iowrite32(priv, ofs, val); -	iowrite32(val, priv->hw_base + ofs); +	priv->bus.ops->write32(&priv->bus, ofs, val);  }  static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs)  { -	u32 val = ioread32(priv->hw_base + ofs); +	u32 val = priv->bus.ops->read32(&priv->bus, ofs);  	trace_iwlwifi_dev_ioread32(priv, ofs, val);  	return val;  } diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 7c23beb49d7..60e4169f25e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -28,8 +28,6 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/init.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h>  #include <linux/delay.h>  #include <linux/skbuff.h>  #include <linux/netdevice.h> @@ -40,13 +38,9 @@  #include "iwl-dev.h"  #include "iwl-core.h" +#include "iwl-agn.h"  #include "iwl-io.h" - -/* default: IWL_LED_BLINK(0) using blinking index table */ -static int led_mode; -module_param(led_mode, int, S_IRUGO); -MODULE_PARM_DESC(led_mode, "0=system default, " -		"1=On(RF On)/Off(RF Off), 2=blinking"); +#include "iwl-trans.h"  /* Throughput		OFF time(ms)	ON time (ms)   *	>300			25		25 @@ -118,7 +112,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)  	if (reg != (reg & CSR_LED_BSM_CTRL_MSK))  		iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); -	return iwl_send_cmd(priv, &cmd); +	return trans_send_cmd(priv, &cmd);  }  /* Set led pattern command */ @@ -181,7 +175,7 @@ static int iwl_led_blink_set(struct led_classdev *led_cdev,  void iwl_leds_init(struct iwl_priv *priv)  { -	int mode = led_mode; +	int mode = iwlagn_mod_params.led_mode;  	int ret;  	if (mode == IWL_LED_DEFAULT) @@ -209,7 +203,8 @@ void iwl_leds_init(struct iwl_priv *priv)  		break;  	} -	ret = led_classdev_register(&priv->pci_dev->dev, &priv->led); +	ret = led_classdev_register(priv->bus.dev, +				    &priv->led);  	if (ret) {  		kfree(priv->led.name);  		return; diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c new file mode 100644 index 00000000000..74911348a2e --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -0,0 +1,560 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license.  When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2007 - 2011 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 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + *  * Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + *  * Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in + *    the documentation and/or other materials provided with the + *    distribution. + *  * Neither the name Intel Corporation nor the names of its + *    contributors may be used to endorse or promote products derived + *    from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include <linux/pci.h> +#include <linux/pci-aspm.h> + +#include "iwl-pci.h" +#include "iwl-agn.h" +#include "iwl-core.h" +#include "iwl-io.h" +#include "iwl-trans.h" + +/* PCI registers */ +#define PCI_CFG_RETRY_TIMEOUT	0x041 +#define PCI_CFG_LINK_CTRL_VAL_L0S_EN	0x01 +#define PCI_CFG_LINK_CTRL_VAL_L1_EN	0x02 + +struct iwl_pci_bus { +	/* basic pci-network driver stuff */ +	struct pci_dev *pci_dev; + +	/* pci hardware address support */ +	void __iomem *hw_base; +}; + +#define IWL_BUS_GET_PCI_BUS(_iwl_bus) \ +			((struct iwl_pci_bus *) ((_iwl_bus)->bus_specific)) + +#define IWL_BUS_GET_PCI_DEV(_iwl_bus) \ +			((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev) + +static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus) +{ +	int pos; +	u16 pci_lnk_ctl; +	struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); + +	pos = pci_pcie_cap(pci_dev); +	pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); +	return pci_lnk_ctl; +} + +static bool iwl_pci_is_pm_supported(struct iwl_bus *bus) +{ +	u16 lctl = iwl_pciexp_link_ctrl(bus); + +	return !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); +} + +static void iwl_pci_apm_config(struct iwl_bus *bus) +{ +	/* +	 * HW bug W/A for instability in PCIe bus L0S->L1 transition. +	 * Check if BIOS (or OS) enabled L1-ASPM on this device. +	 * If so (likely), disable L0S, so device moves directly L0->L1; +	 *    costs negligible amount of power savings. +	 * If not (unlikely), enable L0S, so there is at least some +	 *    power savings, even without L1. +	 */ +	u16 lctl = iwl_pciexp_link_ctrl(bus); + +	if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == +				PCI_CFG_LINK_CTRL_VAL_L1_EN) { +		/* L1-ASPM enabled; disable(!) L0S */ +		iwl_set_bit(bus->priv, CSR_GIO_REG, +				CSR_GIO_REG_VAL_L0S_ENABLED); +		IWL_DEBUG_POWER(bus->priv, "L1 Enabled; Disabling L0S\n"); +	} else { +		/* L1-ASPM disabled; enable(!) L0S */ +		iwl_clear_bit(bus->priv, CSR_GIO_REG, +				CSR_GIO_REG_VAL_L0S_ENABLED); +		IWL_DEBUG_POWER(bus->priv, "L1 Disabled; Enabling L0S\n"); +	} +} + +static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_priv) +{ +	pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_priv); +} + +static struct device *iwl_pci_get_dev(const struct iwl_bus *bus) +{ +	return &(IWL_BUS_GET_PCI_DEV(bus)->dev); +} + +static unsigned int iwl_pci_get_irq(const struct iwl_bus *bus) +{ +	return IWL_BUS_GET_PCI_DEV(bus)->irq; +} + +static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[], +			      int buf_len) +{ +	struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus); + +	snprintf(buf, buf_len, "PCI ID: 0x%04X:0x%04X", pci_dev->device, +		 pci_dev->subsystem_device); +} + +static void iwl_pci_write8(struct iwl_bus *bus, u32 ofs, u8 val) +{ +	iowrite8(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); +} + +static void iwl_pci_write32(struct iwl_bus *bus, u32 ofs, u32 val) +{ +	iowrite32(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); +} + +static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs) +{ +	u32 val = ioread32(IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs); +	return val; +} + +static struct iwl_bus_ops pci_ops = { +	.get_pm_support = iwl_pci_is_pm_supported, +	.apm_config = iwl_pci_apm_config, +	.set_drv_data = iwl_pci_set_drv_data, +	.get_dev = iwl_pci_get_dev, +	.get_irq = iwl_pci_get_irq, +	.get_hw_id = iwl_pci_get_hw_id, +	.write8 = iwl_pci_write8, +	.write32 = iwl_pci_write32, +	.read32 = iwl_pci_read32, +}; + +#define IWL_PCI_DEVICE(dev, subdev, cfg) \ +	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \ +	.subvendor = PCI_ANY_ID, .subdevice = (subdev), \ +	.driver_data = (kernel_ulong_t)&(cfg) + +/* Hardware specific file defines the PCI IDs table for that hardware module */ +static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { +	{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */ + +/* 5300 Series WiFi */ +	{IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */ + +/* 5350 Series WiFi/WiMax */ +	{IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */ + +/* 5150 Series Wifi/WiMax */ +	{IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */ + +	{IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */ +	{IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */ +	{IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */ + +/* 6x00 Series */ +	{IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, +	{IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)}, +	{IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)}, +	{IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, +	{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, + +/* 6x05 Series */ +	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)}, +	{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)}, + +/* 6x30 Series */ +	{IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)}, +	{IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)}, +	{IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)}, +	{IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)}, + +/* 6x50 WiFi/WiMax Series */ +	{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, + +/* 6150 WiFi/WiMax Series */ +	{IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)}, + +/* 1000 Series WiFi */ +	{IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)}, + +/* 100 Series WiFi */ +	{IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)}, +	{IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)}, +	{IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)}, + +/* 130 Series WiFi */ +	{IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)}, + +/* 2x00 Series */ +	{IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)}, +	{IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)}, +	{IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)}, + +/* 2x30 Series */ +	{IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)}, +	{IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)}, +	{IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)}, + +/* 6x35 Series */ +	{IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)}, +	{IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)}, +	{IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)}, +	{IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)}, +	{IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)}, + +/* 105 Series */ +	{IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)}, + +/* 135 Series */ +	{IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)}, +	{IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)}, +	{IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)}, + +	{0} +}; +MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); + +static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ +	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); +	struct iwl_pci_bus *bus; +	u16 pci_cmd; +	int err; + +	bus = kzalloc(sizeof(*bus), GFP_KERNEL); +	if (!bus) { +		pr_err("Couldn't allocate iwl_pci_bus"); +		err = -ENOMEM; +		goto out_no_pci; +	} + +	bus->pci_dev = pdev; + +	/* W/A - seems to solve weird behavior. We need to remove this if we +	 * don't want to stay in L1 all the time. This wastes a lot of power */ +	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | +				PCIE_LINK_STATE_CLKPM); + +	if (pci_enable_device(pdev)) { +		err = -ENODEV; +		goto out_no_pci; +	} + +	pci_set_master(pdev); + +	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); +	if (!err) +		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); +	if (err) { +		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); +		if (!err) +			err = pci_set_consistent_dma_mask(pdev, +							DMA_BIT_MASK(32)); +		/* both attempts failed: */ +		if (err) { +			pr_err("No suitable DMA available.\n"); +			goto out_pci_disable_device; +		} +	} + +	err = pci_request_regions(pdev, DRV_NAME); +	if (err) { +		pr_err("pci_request_regions failed"); +		goto out_pci_disable_device; +	} + +	bus->hw_base = pci_iomap(pdev, 0, 0); +	if (!bus->hw_base) { +		pr_err("pci_iomap failed"); +		err = -ENODEV; +		goto out_pci_release_regions; +	} + +	pr_info("pci_resource_len = 0x%08llx\n", +		(unsigned long long) pci_resource_len(pdev, 0)); +	pr_info("pci_resource_base = %p\n", bus->hw_base); + +	pr_info("HW Revision ID = 0x%X\n", pdev->revision); + +	/* 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); + +	err = pci_enable_msi(pdev); +	if (err) { +		pr_err("pci_enable_msi failed"); +		goto out_iounmap; +	} + +	/* TODO: Move this away, not needed if not MSI */ +	/* enable rfkill interrupt: hw bug w/a */ +	pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); +	if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { +		pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; +		pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); +	} + +	err = iwl_probe((void *) bus, &pci_ops, cfg); +	if (err) +		goto out_disable_msi; +	return 0; + +out_disable_msi: +	pci_disable_msi(pdev); +out_iounmap: +	pci_iounmap(pdev, bus->hw_base); +out_pci_release_regions: +	pci_set_drvdata(pdev, NULL); +	pci_release_regions(pdev); +out_pci_disable_device: +	pci_disable_device(pdev); +out_no_pci: +	kfree(bus); +	return err; +} + +static void iwl_pci_down(void *bus) +{ +	struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus; + +	pci_disable_msi(pci_bus->pci_dev); +	pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base); +	pci_release_regions(pci_bus->pci_dev); +	pci_disable_device(pci_bus->pci_dev); +	pci_set_drvdata(pci_bus->pci_dev, NULL); + +	kfree(pci_bus); +} + +static void __devexit iwl_pci_remove(struct pci_dev *pdev) +{ +	struct iwl_priv *priv = pci_get_drvdata(pdev); +	void *bus_specific = priv->bus.bus_specific; + +	iwl_remove(priv); + +	iwl_pci_down(bus_specific); +} + +#ifdef CONFIG_PM + +static int iwl_pci_suspend(struct device *device) +{ +	struct pci_dev *pdev = to_pci_dev(device); +	struct iwl_priv *priv = pci_get_drvdata(pdev); + +	return iwl_suspend(priv); +} + +static int iwl_pci_resume(struct device *device) +{ +	struct pci_dev *pdev = to_pci_dev(device); +	struct iwl_priv *priv = pci_get_drvdata(pdev); + +	/* +	 * 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); + +	return iwl_resume(priv); +} + +static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); + +#define IWL_PM_OPS	(&iwl_dev_pm_ops) + +#else + +#define IWL_PM_OPS	NULL + +#endif + +static struct pci_driver iwl_pci_driver = { +	.name = DRV_NAME, +	.id_table = iwl_hw_card_ids, +	.probe = iwl_pci_probe, +	.remove = __devexit_p(iwl_pci_remove), +	.driver.pm = IWL_PM_OPS, +}; + +int __must_check iwl_pci_register_driver(void) +{ +	int ret; +	ret = pci_register_driver(&iwl_pci_driver); +	if (ret) +		pr_err("Unable to initialize PCI module\n"); + +	return ret; +} + +void iwl_pci_unregister_driver(void) +{ +	pci_unregister_driver(&iwl_pci_driver); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.h b/drivers/net/wireless/iwlwifi/iwl-pci.h new file mode 100644 index 00000000000..9396c7c8d6a --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-pci.h @@ -0,0 +1,69 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license.  When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2007 - 2011 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 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + *  * Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + *  * Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in + *    the documentation and/or other materials provided with the + *    distribution. + *  * Neither the name Intel Corporation nor the names of its + *    contributors may be used to endorse or promote products derived + *    from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#ifndef __iwl_pci_h__ +#define __iwl_pci_h__ + +int __must_check iwl_pci_register_driver(void); +void iwl_pci_unregister_driver(void); + +#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 595c930b28a..64ff40ae102 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -36,11 +36,13 @@  #include "iwl-eeprom.h"  #include "iwl-dev.h" +#include "iwl-agn.h"  #include "iwl-core.h"  #include "iwl-io.h"  #include "iwl-commands.h"  #include "iwl-debug.h"  #include "iwl-power.h" +#include "iwl-trans.h"  /*   * Setting power level allows the card to go to sleep when not busy. @@ -51,16 +53,6 @@   */  /* - * For now, keep using power level 1 instead of automatically - * adjusting ... - */ -bool no_sleep_autoadjust = true; -module_param(no_sleep_autoadjust, bool, S_IRUGO); -MODULE_PARM_DESC(no_sleep_autoadjust, -		 "don't automatically adjust sleep level " -		 "according to maximum network latency"); - -/*   * This defines the old power levels. They are still used by default   * (level 1) and for thermal throttle (levels 3 through 5)   */ @@ -254,7 +246,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,  		}  	} -	if (priv->power_data.pci_pm) +	if (priv->power_data.bus_pm)  		cmd->flags |= IWL_POWER_PCI_PM_MSK;  	else  		cmd->flags &= ~IWL_POWER_PCI_PM_MSK; @@ -269,7 +261,7 @@ static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,  {  	memset(cmd, 0, sizeof(*cmd)); -	if (priv->power_data.pci_pm) +	if (priv->power_data.bus_pm)  		cmd->flags |= IWL_POWER_PCI_PM_MSK;  	IWL_DEBUG_POWER(priv, "Sleep command for CAM\n"); @@ -305,7 +297,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,  	cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |  		     IWL_POWER_FAST_PD; /* no use seeing frames for others */ -	if (priv->power_data.pci_pm) +	if (priv->power_data.bus_pm)  		cmd->flags |= IWL_POWER_PCI_PM_MSK;  	if (priv->cfg->base_params->shadow_reg_enable) @@ -343,7 +335,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)  			le32_to_cpu(cmd->sleep_interval[3]),  			le32_to_cpu(cmd->sleep_interval[4])); -	return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, +	return trans_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC,  				sizeof(struct iwl_powertable_cmd), cmd);  } @@ -367,9 +359,15 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,  		iwl_static_sleep_cmd(priv, cmd,  				     priv->power_data.debug_sleep_level_override,  				     dtimper); -	else if (no_sleep_autoadjust) -		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper); -	else +	else if (iwlagn_mod_params.no_sleep_autoadjust) { +		if (iwlagn_mod_params.power_level > IWL_POWER_INDEX_1 && +		    iwlagn_mod_params.power_level <= IWL_POWER_INDEX_5) +			iwl_static_sleep_cmd(priv, cmd, +				iwlagn_mod_params.power_level, dtimper); +		else +			iwl_static_sleep_cmd(priv, cmd, +				IWL_POWER_INDEX_1, dtimper); +	} else  		iwl_power_fill_sleep_cmd(priv, cmd,  					 priv->hw->conf.dynamic_ps_timeout,  					 priv->hw->conf.max_sleep_period); @@ -408,9 +406,9 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,  		if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))  			clear_bit(STATUS_POWER_PMI, &priv->status); -		if (priv->cfg->ops->lib->update_chain_flags && update_chains) -			priv->cfg->ops->lib->update_chain_flags(priv); -		else if (priv->cfg->ops->lib->update_chain_flags) +		if (update_chains) +			iwl_update_chain_flags(priv); +		else  			IWL_DEBUG_POWER(priv,  					"Cannot update the power, chain noise "  					"calibration running: %d\n", @@ -434,9 +432,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)  /* initialize to default */  void iwl_power_initialize(struct iwl_priv *priv)  { -	u16 lctl = iwl_pcie_link_ctl(priv); - -	priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); +	priv->power_data.bus_pm = priv->bus.ops->get_pm_support(&priv->bus);  	priv->power_data.debug_sleep_level_override = -1; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 59635d784e2..5f7b720cf1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -43,7 +43,7 @@ struct iwl_power_mgr {  	struct iwl_powertable_cmd sleep_cmd;  	struct iwl_powertable_cmd sleep_cmd_next;  	int debug_sleep_level_override; -	bool pci_pm; +	bool bus_pm;  };  int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index f00d188b2cf..1cc0ed1f488 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -168,6 +168,7 @@   * the scheduler (especially for queue #4/#9, the command queue, otherwise   * the driver can't issue commands!):   */ +#define SCD_MEM_LOWER_BOUND		(0x0000)  /**   * Max Tx window size is the max number of contiguous TFDs that the scheduler @@ -197,15 +198,23 @@  #define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS	(16)  #define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK	(0x007F0000) -#define IWLAGN_SCD_CONTEXT_DATA_OFFSET		(0x600) -#define IWLAGN_SCD_TX_STTS_BITMAP_OFFSET		(0x7B1) -#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET		(0x7E0) +/* Context Data */ +#define IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND	(SCD_MEM_LOWER_BOUND + 0x600) +#define IWLAGN_SCD_CONTEXT_MEM_UPPER_BOUND	(SCD_MEM_LOWER_BOUND + 0x6A0) + +/* Tx status */ +#define IWLAGN_SCD_TX_STTS_MEM_LOWER_BOUND	(SCD_MEM_LOWER_BOUND + 0x6A0) +#define IWLAGN_SCD_TX_STTS_MEM_UPPER_BOUND	(SCD_MEM_LOWER_BOUND + 0x7E0) + +/* Translation Data */ +#define IWLAGN_SCD_TRANS_TBL_MEM_LOWER_BOUND	(SCD_MEM_LOWER_BOUND + 0x7E0) +#define IWLAGN_SCD_TRANS_TBL_MEM_UPPER_BOUND	(SCD_MEM_LOWER_BOUND + 0x808)  #define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\ -	(IWLAGN_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) +	(IWLAGN_SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))  #define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ -	((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) +	((IWLAGN_SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)  #define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv)	\  	(((1<<(priv)->hw_params.max_txq_num) - 1) &\ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index b774517aa9f..f3f3efe38ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -134,7 +134,6 @@ int iwl_rx_queue_space(const struct iwl_rx_queue *q)  void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)  {  	unsigned long flags; -	u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;  	u32 reg;  	spin_lock_irqsave(&q->lock, flags); @@ -146,7 +145,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q  		/* shadow register enabled */  		/* Device expects a multiple of 8 */  		q->write_actual = (q->write & ~0x7); -		iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual); +		iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write_actual);  	} else {  		/* If power-saving is in use, make sure device is awake */  		if (test_bit(STATUS_POWER_PMI, &priv->status)) { @@ -162,14 +161,14 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q  			}  			q->write_actual = (q->write & ~0x7); -			iwl_write_direct32(priv, rx_wrt_ptr_reg, +			iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,  					q->write_actual);  		/* Else device is assumed to be awake */  		} else {  			/* Device expects a multiple of 8 */  			q->write_actual = (q->write & ~0x7); -			iwl_write_direct32(priv, rx_wrt_ptr_reg, +			iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,  				q->write_actual);  		}  	} @@ -179,46 +178,6 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q  	spin_unlock_irqrestore(&q->lock, flags);  } -int iwl_rx_queue_alloc(struct iwl_priv *priv) -{ -	struct iwl_rx_queue *rxq = &priv->rxq; -	struct device *dev = &priv->pci_dev->dev; -	int i; - -	spin_lock_init(&rxq->lock); -	INIT_LIST_HEAD(&rxq->rx_free); -	INIT_LIST_HEAD(&rxq->rx_used); - -	/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ -	rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma, -				     GFP_KERNEL); -	if (!rxq->bd) -		goto err_bd; - -	rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status), -					  &rxq->rb_stts_dma, GFP_KERNEL); -	if (!rxq->rb_stts) -		goto err_rb; - -	/* Fill the rx_used queue with _all_ of the Rx buffers */ -	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) -		list_add_tail(&rxq->pool[i].list, &rxq->rx_used); - -	/* Set us so that we have processed and used all buffers, but have -	 * not restocked the Rx queue with fresh buffers */ -	rxq->read = rxq->write = 0; -	rxq->write_actual = 0; -	rxq->free_count = 0; -	rxq->need_update = 0; -	return 0; - -err_rb: -	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, -			  rxq->bd_dma); -err_bd: -	return -ENOMEM; -} -  /******************************************************************************   *   * Generic RX handler implementations @@ -665,8 +624,8 @@ static void iwl_rx_statistics(struct iwl_priv *priv,  		iwl_rx_calc_noise(priv);  		queue_work(priv->workqueue, &priv->run_time_calib_work);  	} -	if (priv->cfg->ops->lib->temp_ops.temperature && change) -		priv->cfg->ops->lib->temp_ops.temperature(priv); +	if (priv->cfg->ops->lib->temperature && change) +		priv->cfg->ops->lib->temperature(priv);  }  static void iwl_rx_reply_statistics(struct iwl_priv *priv, @@ -943,6 +902,47 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)  	return decrypt_out;  } +/* Calc max signal level (dBm) among 3 possible receivers */ +static int iwlagn_calc_rssi(struct iwl_priv *priv, +			     struct iwl_rx_phy_res *rx_resp) +{ +	/* data from PHY/DSP regarding signal strength, etc., +	 *   contents are always there, not configurable by host +	 */ +	struct iwlagn_non_cfg_phy *ncphy = +		(struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf; +	u32 val, rssi_a, rssi_b, rssi_c, max_rssi; +	u8 agc; + +	val  = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]); +	agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS; + +	/* Find max rssi among 3 possible receivers. +	 * These values are measured by the digital signal processor (DSP). +	 * They should stay fairly constant even as the signal strength varies, +	 *   if the radio's automatic gain control (AGC) is working right. +	 * AGC value (see below) will provide the "interesting" info. +	 */ +	val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]); +	rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >> +		IWLAGN_OFDM_RSSI_A_BIT_POS; +	rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >> +		IWLAGN_OFDM_RSSI_B_BIT_POS; +	val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]); +	rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >> +		IWLAGN_OFDM_RSSI_C_BIT_POS; + +	max_rssi = max_t(u32, rssi_a, rssi_b); +	max_rssi = max_t(u32, max_rssi, rssi_c); + +	IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", +		rssi_a, rssi_b, rssi_c, max_rssi, agc); + +	/* dBm = max_rssi dB - agc dB - constant. +	 * Higher AGC (higher radio gain) means lower signal. */ +	return max_rssi - agc - IWLAGN_RSSI_OFFSET; +} +  /* Called for REPLY_RX (legacy ABG frames), or   * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */  static void iwl_rx_reply_rx(struct iwl_priv *priv, @@ -1024,7 +1024,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,  	priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);  	/* Find max signal strength (dBm) among 3 antenna/receiver chains */ -	rx_status.signal = priv->cfg->ops->utils->calc_rssi(priv, phy_res); +	rx_status.signal = iwlagn_calc_rssi(priv, phy_res);  	iwl_dbg_log_rx_data_frame(priv, len, header);  	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index d60d630cb93..f6ebe29eb79 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -36,6 +36,8 @@  #include "iwl-sta.h"  #include "iwl-io.h"  #include "iwl-helpers.h" +#include "iwl-agn.h" +#include "iwl-trans.h"  /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after   * sending probe req.  This should be set long enough to hear probe responses @@ -60,7 +62,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)  	struct iwl_rx_packet *pkt;  	struct iwl_host_cmd cmd = {  		.id = REPLY_SCAN_ABORT_CMD, -		.flags = CMD_WANT_SKB, +		.flags = CMD_SYNC | CMD_WANT_SKB,  	};  	/* Exit instantly with error when device is not ready @@ -73,7 +75,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)  	    test_bit(STATUS_EXIT_PENDING, &priv->status))  		return -EIO; -	ret = iwl_send_cmd_sync(priv, &cmd); +	ret = trans_send_cmd(priv, &cmd);  	if (ret)  		return ret; @@ -348,9 +350,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,  	lockdep_assert_held(&priv->mutex); -	if (WARN_ON(!priv->cfg->ops->utils->request_scan)) -		return -EOPNOTSUPP; -  	cancel_delayed_work(&priv->scan_check);  	if (!iwl_is_ready_rf(priv)) { @@ -379,7 +378,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,  	priv->scan_start = jiffies;  	priv->scan_band = band; -	ret = priv->cfg->ops->utils->request_scan(priv, vif); +	ret = iwlagn_request_scan(priv, vif);  	if (ret) {  		clear_bit(STATUS_SCANNING, &priv->status);  		priv->scan_type = IWL_SCAN_NORMAL; @@ -600,14 +599,7 @@ out_settings:  	if (!iwl_is_ready_rf(priv))  		goto out; -	/* -	 * We do not commit power settings while scan is pending, -	 * do it now if the settings changed. -	 */ -	iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false); -	iwl_set_tx_power(priv, priv->tx_power_next, false); - -	priv->cfg->ops->utils->post_scan(priv); +	iwlagn_post_scan(priv);  out:  	mutex_unlock(&priv->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 7df2814fd4f..65386e575b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -35,6 +35,8 @@  #include "iwl-dev.h"  #include "iwl-core.h"  #include "iwl-sta.h" +#include "iwl-trans.h" +#include "iwl-agn.h"  /* priv->sta_lock must be held */  static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) @@ -132,6 +134,16 @@ static void iwl_add_sta_callback(struct iwl_priv *priv,  } +static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) +{ +	u16 size = (u16)sizeof(struct iwl_addsta_cmd); +	struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; +	memcpy(addsta, cmd, size); +	/* resrved in 5000 */ +	addsta->rate_n_flags = cpu_to_le16(0); +	return size; +} +  int iwl_send_add_sta(struct iwl_priv *priv,  		     struct iwl_addsta_cmd *sta, u8 flags)  { @@ -155,8 +167,8 @@ int iwl_send_add_sta(struct iwl_priv *priv,  		might_sleep();  	} -	cmd.len[0] = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); -	ret = iwl_send_cmd(priv, &cmd); +	cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data); +	ret = trans_send_cmd(priv, &cmd);  	if (ret || (flags & CMD_ASYNC))  		return ret; @@ -412,7 +424,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,  	cmd.flags |= CMD_WANT_SKB; -	ret = iwl_send_cmd(priv, &cmd); +	ret = trans_send_cmd(priv, &cmd);  	if (ret)  		return ret; @@ -781,7 +793,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,  		return -EINVAL;  	if (is_lq_table_valid(priv, ctx, lq)) -		ret = iwl_send_cmd(priv, &cmd); +		ret = trans_send_cmd(priv, &cmd);  	else  		ret = -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c index 69b7e6bf2d6..77ed1c295da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sv-open.c +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -69,7 +69,6 @@  #include <net/mac80211.h>  #include <net/netlink.h> -  #include "iwl-dev.h"  #include "iwl-core.h"  #include "iwl-debug.h" @@ -77,7 +76,7 @@  #include "iwl-io.h"  #include "iwl-agn.h"  #include "iwl-testmode.h" - +#include "iwl-trans.h"  /* The TLVs used in the gnl message policy between the kernel module and   * user space application. iwl_testmode_gnl_msg_policy is to be carried @@ -101,9 +100,12 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {  	[IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },  	[IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, }, -	[IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, }, +	[IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, }, +	[IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, },  	[IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, + +	[IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, },  };  /* @@ -179,19 +181,21 @@ void iwl_testmode_init(struct iwl_priv *priv)  static void iwl_trace_cleanup(struct iwl_priv *priv)  { -	struct device *dev = &priv->pci_dev->dev; +	struct device *dev = priv->bus.dev;  	if (priv->testmode_trace.trace_enabled) {  		if (priv->testmode_trace.cpu_addr &&  		    priv->testmode_trace.dma_addr)  			dma_free_coherent(dev, -					TRACE_TOTAL_SIZE, +					priv->testmode_trace.total_size,  					priv->testmode_trace.cpu_addr,  					priv->testmode_trace.dma_addr);  		priv->testmode_trace.trace_enabled = false;  		priv->testmode_trace.cpu_addr = NULL;  		priv->testmode_trace.trace_addr = NULL;  		priv->testmode_trace.dma_addr = 0; +		priv->testmode_trace.buff_size = 0; +		priv->testmode_trace.total_size = 0;  	}  } @@ -229,6 +233,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)  		return -ENOMSG;  	} +	cmd.flags = CMD_ON_DEMAND;  	cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);  	cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);  	cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); @@ -236,7 +241,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)  	IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"  				" len %d\n", cmd.id, cmd.flags, cmd.len[0]);  	/* ok, let's submit the command to ucode */ -	return iwl_send_cmd(priv, &cmd); +	return trans_send_cmd(priv, &cmd);  } @@ -394,7 +399,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)  	case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:  		status = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, -					   UCODE_SUBTYPE_INIT, -1); +						      IWL_UCODE_INIT);  		if (status)  			IWL_DEBUG_INFO(priv,  				"Error loading init ucode: %d\n", status); @@ -408,8 +413,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)  	case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:  		status = iwlagn_load_ucode_wait_alive(priv,  					   &priv->ucode_rt, -					   UCODE_SUBTYPE_REGULAR, -					   UCODE_SUBTYPE_REGULAR_NEW); +					   IWL_UCODE_REGULAR);  		if (status) {  			IWL_DEBUG_INFO(priv,  				"Error loading runtime ucode: %d\n", status); @@ -450,7 +454,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)  				       "Error finding fixrate setting\n");  			return -ENOMSG;  		} -		priv->dbg_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); +		priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);  		break;  	default: @@ -482,16 +486,29 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)  	struct iwl_priv *priv = hw->priv;  	struct sk_buff *skb;  	int status = 0; -	struct device *dev = &priv->pci_dev->dev; +	struct device *dev = priv->bus.dev;  	switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {  	case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:  		if (priv->testmode_trace.trace_enabled)  			return -EBUSY; +		if (!tb[IWL_TM_ATTR_TRACE_SIZE]) +			priv->testmode_trace.buff_size = TRACE_BUFF_SIZE_DEF; +		else +			priv->testmode_trace.buff_size = +				nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]); +		if (!priv->testmode_trace.buff_size) +			return -EINVAL; +		if (priv->testmode_trace.buff_size < TRACE_BUFF_SIZE_MIN || +		    priv->testmode_trace.buff_size > TRACE_BUFF_SIZE_MAX) +			return -EINVAL; + +		priv->testmode_trace.total_size = +			priv->testmode_trace.buff_size + TRACE_BUFF_PADD;  		priv->testmode_trace.cpu_addr =  			dma_alloc_coherent(dev, -					   TRACE_TOTAL_SIZE, +					   priv->testmode_trace.total_size,  					   &priv->testmode_trace.dma_addr,  					   GFP_KERNEL);  		if (!priv->testmode_trace.cpu_addr) @@ -500,7 +517,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)  		priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(  			priv->testmode_trace.cpu_addr, 0x100);  		memset(priv->testmode_trace.trace_addr, 0x03B, -			TRACE_BUFF_SIZE); +			priv->testmode_trace.buff_size);  		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,  			sizeof(priv->testmode_trace.dma_addr) + 20);  		if (!skb) { @@ -518,34 +535,14 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)  				       "Error sending msg : %d\n",  				       status);  		} +		priv->testmode_trace.num_chunks = +			DIV_ROUND_UP(priv->testmode_trace.buff_size, +				     TRACE_CHUNK_SIZE);  		break;  	case IWL_TM_CMD_APP2DEV_END_TRACE:  		iwl_trace_cleanup(priv);  		break; - -	case IWL_TM_CMD_APP2DEV_READ_TRACE: -		if (priv->testmode_trace.trace_enabled && -		    priv->testmode_trace.trace_addr) { -			skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, -				20 + TRACE_BUFF_SIZE); -			if (skb == NULL) { -				IWL_DEBUG_INFO(priv, -					"Error allocating memory\n"); -				return -ENOMEM; -			} -			NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA, -				TRACE_BUFF_SIZE, -				priv->testmode_trace.trace_addr); -			status = cfg80211_testmode_reply(skb); -			if (status < 0) { -				IWL_DEBUG_INFO(priv, -				       "Error sending msg : %d\n", status); -			} -		} else -			return -EFAULT; -		break; -  	default:  		IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");  		return -ENOSYS; @@ -560,6 +557,73 @@ nla_put_failure:  	return -EMSGSIZE;  } +static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb, +				   struct sk_buff *skb, +				   struct netlink_callback *cb) +{ +	struct iwl_priv *priv = hw->priv; +	int idx, length; + +	if (priv->testmode_trace.trace_enabled && +	    priv->testmode_trace.trace_addr) { +		idx = cb->args[4]; +		if (idx >= priv->testmode_trace.num_chunks) +			return -ENOENT; +		length = TRACE_CHUNK_SIZE; +		if (((idx + 1) == priv->testmode_trace.num_chunks) && +		    (priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE)) +			length = priv->testmode_trace.buff_size % +				TRACE_CHUNK_SIZE; + +		NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length, +			priv->testmode_trace.trace_addr + +			(TRACE_CHUNK_SIZE * idx)); +		idx++; +		cb->args[4] = idx; +		return 0; +	} else +		return -EFAULT; + + nla_put_failure: +	return -ENOBUFS; +} + +/* + * This function handles the user application switch ucode ownership. + * + * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_OWNER and + * decide who the current owner of the uCode + * + * If the current owner is OWNERSHIP_TM, then the only host command + * can deliver to uCode is from testmode, all the other host commands + * will dropped. + * + * default driver is the owner of uCode in normal operational mode + * + * @hw: ieee80211_hw object that represents the device + * @tb: gnl message fields from the user space + */ +static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) +{ +	struct iwl_priv *priv = hw->priv; +	u8 owner; + +	if (!tb[IWL_TM_ATTR_UCODE_OWNER]) { +		IWL_DEBUG_INFO(priv, "Error finding ucode owner\n"); +		return -ENOMSG; +	} + +	owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]); +	if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) +		priv->ucode_owner = owner; +	else { +		IWL_DEBUG_INFO(priv, "Invalid owner\n"); +		return -EINVAL; +	} +	return 0; +} + +  /* The testmode gnl message handler that takes the gnl message from the   * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then   * invoke the corresponding handlers. @@ -581,7 +645,7 @@ nla_put_failure:   */  int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)  { -	struct nlattr *tb[IWL_TM_ATTR_MAX - 1]; +	struct nlattr *tb[IWL_TM_ATTR_MAX];  	struct iwl_priv *priv = hw->priv;  	int result; @@ -629,6 +693,11 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)  		result = iwl_testmode_trace(hw, tb);  		break; +	case IWL_TM_CMD_APP2DEV_OWNERSHIP: +		IWL_DEBUG_INFO(priv, "testmode change uCode ownership\n"); +		result = iwl_testmode_ownership(hw, tb); +		break; +  	default:  		IWL_DEBUG_INFO(priv, "Unknown testmode command\n");  		result = -ENOSYS; @@ -638,3 +707,50 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)  	mutex_unlock(&priv->mutex);  	return result;  } + +int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, +		      struct netlink_callback *cb, +		      void *data, int len) +{ +	struct nlattr *tb[IWL_TM_ATTR_MAX]; +	struct iwl_priv *priv = hw->priv; +	int result; +	u32 cmd; + +	if (cb->args[3]) { +		/* offset by 1 since commands start at 0 */ +		cmd = cb->args[3] - 1; +	} else { +		result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, +				iwl_testmode_gnl_msg_policy); +		if (result) { +			IWL_DEBUG_INFO(priv, +			       "Error parsing the gnl message : %d\n", result); +			return result; +		} + +		/* IWL_TM_ATTR_COMMAND is absolutely mandatory */ +		if (!tb[IWL_TM_ATTR_COMMAND]) { +			IWL_DEBUG_INFO(priv, +				"Error finding testmode command type\n"); +			return -ENOMSG; +		} +		cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); +		cb->args[3] = cmd + 1; +	} + +	/* in case multiple accesses to the device happens */ +	mutex_lock(&priv->mutex); +	switch (cmd) { +	case IWL_TM_CMD_APP2DEV_READ_TRACE: +		IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); +		result = iwl_testmode_trace_dump(hw, tb, skb, cb); +		break; +	default: +		result = -EINVAL; +		break; +	} + +	mutex_unlock(&priv->mutex); +	return result; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index a88085e9b36..b980bda4b0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -66,120 +66,161 @@  #include <linux/types.h> -/* Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and +/* + * Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and   * from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX). - * The command ID is carried with IWL_TM_ATTR_COMMAND. There are three types of - * of command from user space and two types of command from kernel space. - * See below. + * The command ID is carried with IWL_TM_ATTR_COMMAND. + * + * @IWL_TM_CMD_APP2DEV_UCODE: + *	commands from user application to the uCode, + *	the actual uCode host command ID is carried with + *	IWL_TM_ATTR_UCODE_CMD_ID + * + * @IWL_TM_CMD_APP2DEV_REG_READ32: + * @IWL_TM_CMD_APP2DEV_REG_WRITE32: + * @IWL_TM_CMD_APP2DEV_REG_WRITE8: + *	commands from user applicaiton to access register + * + * @IWL_TM_CMD_APP2DEV_GET_DEVICENAME: retrieve device name + * @IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: load initial uCode image + * @IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: perform calibration + * @IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: load runtime uCode image + * @IWL_TM_CMD_APP2DEV_GET_EEPROM: request EEPROM data + * @IWL_TM_CMD_APP2DEV_FIXRATE_REQ: set fix MCS + *	commands fom user space for pure driver level operations + * + * @IWL_TM_CMD_APP2DEV_BEGIN_TRACE: + * @IWL_TM_CMD_APP2DEV_END_TRACE: + * @IWL_TM_CMD_APP2DEV_READ_TRACE: + *	commands fom user space for uCode trace operations + * + * @IWL_TM_CMD_DEV2APP_SYNC_RSP: + *	commands from kernel space to carry the synchronous response + *	to user application + * @IWL_TM_CMD_DEV2APP_UCODE_RX_PKT: + *	commands from kernel space to multicast the spontaneous messages + *	to user application + * @IWL_TM_CMD_DEV2APP_EEPROM_RSP: + *	commands from kernel space to carry the eeprom response + *	to user application + * @IWL_TM_CMD_APP2DEV_OWNERSHIP: + *	commands from user application to own change the ownership of the uCode + *	if application has the ownership, the only host command from + *	testmode will deliver to uCode. Default owner is driver   */  enum iwl_tm_cmd_t { -	/* commands from user application to the uCode, -	 * the actual uCode host command ID is carried with -	 * IWL_TM_ATTR_UCODE_CMD_ID */ -	IWL_TM_CMD_APP2DEV_UCODE = 1, - -	/* commands from user applicaiton to access register */ -	IWL_TM_CMD_APP2DEV_REG_READ32, -	IWL_TM_CMD_APP2DEV_REG_WRITE32, -	IWL_TM_CMD_APP2DEV_REG_WRITE8, - -	/* commands fom user space for pure driver level operations */ -	IWL_TM_CMD_APP2DEV_GET_DEVICENAME, -	IWL_TM_CMD_APP2DEV_LOAD_INIT_FW, -	IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB, -	IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW, -	IWL_TM_CMD_APP2DEV_GET_EEPROM, -	IWL_TM_CMD_APP2DEV_FIXRATE_REQ, -	/* if there is other new command for the driver layer operation, -	 * append them here */ - -	/* commands fom user space for uCode trace operations */ -	IWL_TM_CMD_APP2DEV_BEGIN_TRACE, -	IWL_TM_CMD_APP2DEV_END_TRACE, -	IWL_TM_CMD_APP2DEV_READ_TRACE, - -	/* commands from kernel space to carry the synchronous response -	 * to user application */ -	IWL_TM_CMD_DEV2APP_SYNC_RSP, - -	/* commands from kernel space to multicast the spontaneous messages -	 * to user application */ -	IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, - -	/* commands from kernel space to carry the eeprom response -	 * to user application */ -	IWL_TM_CMD_DEV2APP_EEPROM_RSP, - -	IWL_TM_CMD_MAX, +	IWL_TM_CMD_APP2DEV_UCODE		= 1, +	IWL_TM_CMD_APP2DEV_REG_READ32		= 2, +	IWL_TM_CMD_APP2DEV_REG_WRITE32		= 3, +	IWL_TM_CMD_APP2DEV_REG_WRITE8		= 4, +	IWL_TM_CMD_APP2DEV_GET_DEVICENAME	= 5, +	IWL_TM_CMD_APP2DEV_LOAD_INIT_FW		= 6, +	IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB	= 7, +	IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW	= 8, +	IWL_TM_CMD_APP2DEV_GET_EEPROM		= 9, +	IWL_TM_CMD_APP2DEV_FIXRATE_REQ		= 10, +	IWL_TM_CMD_APP2DEV_BEGIN_TRACE		= 11, +	IWL_TM_CMD_APP2DEV_END_TRACE		= 12, +	IWL_TM_CMD_APP2DEV_READ_TRACE		= 13, +	IWL_TM_CMD_DEV2APP_SYNC_RSP		= 14, +	IWL_TM_CMD_DEV2APP_UCODE_RX_PKT		= 15, +	IWL_TM_CMD_DEV2APP_EEPROM_RSP		= 16, +	IWL_TM_CMD_APP2DEV_OWNERSHIP		= 17, +	IWL_TM_CMD_MAX				= 18,  }; +/* + * Atrribute filed in testmode command + * See enum iwl_tm_cmd_t. + * + * @IWL_TM_ATTR_NOT_APPLICABLE: + *	The attribute is not applicable or invalid + * @IWL_TM_ATTR_COMMAND: + *	From user space to kernel space: + *	the command either destines to ucode, driver, or register; + *	From kernel space to user space: + *	the command either carries synchronous response, + *	or the spontaneous message multicast from the device; + * + * @IWL_TM_ATTR_UCODE_CMD_ID: + * @IWL_TM_ATTR_UCODE_CMD_DATA: + *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE, + *	The mandatory fields are : + *	IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID; + *	IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands; + *	The optional fields are: + *	IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload + *	to the ucode + * + * @IWL_TM_ATTR_REG_OFFSET: + * @IWL_TM_ATTR_REG_VALUE8: + * @IWL_TM_ATTR_REG_VALUE32: + *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX, + *	The mandatory fields are: + *	IWL_TM_ATTR_REG_OFFSET for the offset of the target register; + *	IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value + * + * @IWL_TM_ATTR_SYNC_RSP: + *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP, + *	The mandatory fields are: + *	IWL_TM_ATTR_SYNC_RSP for the data content responding to the user + *	application command + * + * @IWL_TM_ATTR_UCODE_RX_PKT: + *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, + *	The mandatory fields are: + *	IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user + *	application + * + * @IWL_TM_ATTR_EEPROM: + *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM, + *	The mandatory fields are: + *	IWL_TM_ATTR_EEPROM for the data content responging to the user + *	application + * + * @IWL_TM_ATTR_TRACE_ADDR: + * @IWL_TM_ATTR_TRACE_SIZE: + * @IWL_TM_ATTR_TRACE_DUMP: + *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE, + *	The mandatory fields are: + *	IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address + *	IWL_TM_ATTR_MEM_TRACE_SIZE for the trace buffer size + *	IWL_TM_ATTR_MEM_TRACE_DUMP for the trace dump + * + * @IWL_TM_ATTR_FIXRATE: + *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ, + *	The mandatory fields are: + *	IWL_TM_ATTR_FIXRATE for the fixed rate + * + * @IWL_TM_ATTR_UCODE_OWNER: + *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP, + *	The mandatory fields are: + *	IWL_TM_ATTR_UCODE_OWNER for the new owner + */  enum iwl_tm_attr_t { -	IWL_TM_ATTR_NOT_APPLICABLE = 0, - -	/* From user space to kernel space: -	 * the command either destines to ucode, driver, or register; -	 * See enum iwl_tm_cmd_t. -	 * -	 * From kernel space to user space: -	 * the command either carries synchronous response, -	 * or the spontaneous message multicast from the device; -	 * See enum iwl_tm_cmd_t. */ -	IWL_TM_ATTR_COMMAND, - -	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE, -	 * The mandatory fields are : -	 * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID; -	 * IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands; -	 * The optional fields are: -	 * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload -	 * to the ucode */ -	IWL_TM_ATTR_UCODE_CMD_ID, -	IWL_TM_ATTR_UCODE_CMD_DATA, - -	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX, -	 * The mandatory fields are: -	 * IWL_TM_ATTR_REG_OFFSET for the offset of the target register; -	 * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value */ -	IWL_TM_ATTR_REG_OFFSET, -	IWL_TM_ATTR_REG_VALUE8, -	IWL_TM_ATTR_REG_VALUE32, - -	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP, -	 * The mandatory fields are: -	 * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user -	 * application command */ -	IWL_TM_ATTR_SYNC_RSP, -	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, -	 * The mandatory fields are: -	 * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user -	 * application */ -	IWL_TM_ATTR_UCODE_RX_PKT, - -	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_EEPROM, -	 * The mandatory fields are: -	 * IWL_TM_ATTR_EEPROM for the data content responging to the user -	 * application */ -	IWL_TM_ATTR_EEPROM, - -	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_XXX_TRACE, -	 * The mandatory fields are: -	 * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address -	 */ -	IWL_TM_ATTR_TRACE_ADDR, -	IWL_TM_ATTR_TRACE_DATA, - -	/* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ, -	 * The mandatory fields are: -	 * IWL_TM_ATTR_FIXRATE for the fixed rate -	 */ -	IWL_TM_ATTR_FIXRATE, - -	IWL_TM_ATTR_MAX, +	IWL_TM_ATTR_NOT_APPLICABLE		= 0, +	IWL_TM_ATTR_COMMAND			= 1, +	IWL_TM_ATTR_UCODE_CMD_ID		= 2, +	IWL_TM_ATTR_UCODE_CMD_DATA		= 3, +	IWL_TM_ATTR_REG_OFFSET			= 4, +	IWL_TM_ATTR_REG_VALUE8			= 5, +	IWL_TM_ATTR_REG_VALUE32			= 6, +	IWL_TM_ATTR_SYNC_RSP			= 7, +	IWL_TM_ATTR_UCODE_RX_PKT		= 8, +	IWL_TM_ATTR_EEPROM			= 9, +	IWL_TM_ATTR_TRACE_ADDR			= 10, +	IWL_TM_ATTR_TRACE_SIZE			= 11, +	IWL_TM_ATTR_TRACE_DUMP			= 12, +	IWL_TM_ATTR_FIXRATE			= 13, +	IWL_TM_ATTR_UCODE_OWNER			= 14, +	IWL_TM_ATTR_MAX				= 15,  };  /* uCode trace buffer */ -#define TRACE_BUFF_SIZE		0x20000 +#define TRACE_BUFF_SIZE_MAX	0x200000 +#define TRACE_BUFF_SIZE_MIN	0x20000 +#define TRACE_BUFF_SIZE_DEF	TRACE_BUFF_SIZE_MIN  #define TRACE_BUFF_PADD		0x2000 -#define TRACE_TOTAL_SIZE	(TRACE_BUFF_SIZE + TRACE_BUFF_PADD) +#define TRACE_CHUNK_SIZE	(PAGE_SIZE - 1024)  #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c new file mode 100644 index 00000000000..d760857c863 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -0,0 +1,571 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license.  When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2007 - 2011 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 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + *  * Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + *  * Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in + *    the documentation and/or other materials provided with the + *    distribution. + *  * Neither the name Intel Corporation nor the names of its + *    contributors may be used to endorse or promote products derived + *    from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +#include "iwl-dev.h" +#include "iwl-trans.h" +#include "iwl-core.h" +#include "iwl-helpers.h" +/*TODO remove uneeded includes when the transport layer tx_free will be here */ +#include "iwl-agn.h" +#include "iwl-core.h" + +static int iwl_trans_rx_alloc(struct iwl_priv *priv) +{ +	struct iwl_rx_queue *rxq = &priv->rxq; +	struct device *dev = priv->bus.dev; + +	memset(&priv->rxq, 0, sizeof(priv->rxq)); + +	spin_lock_init(&rxq->lock); +	INIT_LIST_HEAD(&rxq->rx_free); +	INIT_LIST_HEAD(&rxq->rx_used); + +	if (WARN_ON(rxq->bd || rxq->rb_stts)) +		return -EINVAL; + +	/* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */ +	rxq->bd = dma_alloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, +				     &rxq->bd_dma, GFP_KERNEL); +	if (!rxq->bd) +		goto err_bd; +	memset(rxq->bd, 0, sizeof(__le32) * RX_QUEUE_SIZE); + +	/*Allocate the driver's pointer to receive buffer status */ +	rxq->rb_stts = dma_alloc_coherent(dev, sizeof(*rxq->rb_stts), +					  &rxq->rb_stts_dma, GFP_KERNEL); +	if (!rxq->rb_stts) +		goto err_rb_stts; +	memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); + +	return 0; + +err_rb_stts: +	dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, +			rxq->bd, rxq->bd_dma); +	memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); +	rxq->bd = NULL; +err_bd: +	return -ENOMEM; +} + +static void iwl_trans_rxq_free_rx_bufs(struct iwl_priv *priv) +{ +	struct iwl_rx_queue *rxq = &priv->rxq; +	int i; + +	/* Fill the rx_used queue with _all_ of the Rx buffers */ +	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { +		/* In the reset function, these buffers may have been allocated +		 * to an SKB, so we need to unmap and free potential storage */ +		if (rxq->pool[i].page != NULL) { +			dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma, +				PAGE_SIZE << priv->hw_params.rx_page_order, +				DMA_FROM_DEVICE); +			__iwl_free_pages(priv, rxq->pool[i].page); +			rxq->pool[i].page = NULL; +		} +		list_add_tail(&rxq->pool[i].list, &rxq->rx_used); +	} +} + +static int iwl_trans_rx_init(struct iwl_priv *priv) +{ +	struct iwl_rx_queue *rxq = &priv->rxq; +	int i, err; +	unsigned long flags; + +	if (!rxq->bd) { +		err = iwl_trans_rx_alloc(priv); +		if (err) +			return err; +	} + +	spin_lock_irqsave(&rxq->lock, flags); +	INIT_LIST_HEAD(&rxq->rx_free); +	INIT_LIST_HEAD(&rxq->rx_used); + +	iwl_trans_rxq_free_rx_bufs(priv); + +	for (i = 0; i < RX_QUEUE_SIZE; i++) +		rxq->queue[i] = NULL; + +	/* Set us so that we have processed and used all buffers, but have +	 * not restocked the Rx queue with fresh buffers */ +	rxq->read = rxq->write = 0; +	rxq->write_actual = 0; +	rxq->free_count = 0; +	spin_unlock_irqrestore(&rxq->lock, flags); + +	return 0; +} + +static void iwl_trans_rx_free(struct iwl_priv *priv) +{ +	struct iwl_rx_queue *rxq = &priv->rxq; +	unsigned long flags; + +	/*if rxq->bd is NULL, it means that nothing has been allocated, +	 * exit now */ +	if (!rxq->bd) { +		IWL_DEBUG_INFO(priv, "Free NULL rx context\n"); +		return; +	} + +	spin_lock_irqsave(&rxq->lock, flags); +	iwl_trans_rxq_free_rx_bufs(priv); +	spin_unlock_irqrestore(&rxq->lock, flags); + +	dma_free_coherent(priv->bus.dev, sizeof(__le32) * RX_QUEUE_SIZE, +			  rxq->bd, rxq->bd_dma); +	memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma)); +	rxq->bd = NULL; + +	if (rxq->rb_stts) +		dma_free_coherent(priv->bus.dev, +				  sizeof(struct iwl_rb_status), +				  rxq->rb_stts, rxq->rb_stts_dma); +	else +		IWL_DEBUG_INFO(priv, "Free rxq->rb_stts which is NULL\n"); +	memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma)); +	rxq->rb_stts = NULL; +} + +static int iwl_trans_rx_stop(struct iwl_priv *priv) +{ + +	/* stop Rx DMA */ +	iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); +	return iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, +			    FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); +} + +static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, +				    struct iwl_dma_ptr *ptr, size_t size) +{ +	if (WARN_ON(ptr->addr)) +		return -EINVAL; + +	ptr->addr = dma_alloc_coherent(priv->bus.dev, size, +				       &ptr->dma, GFP_KERNEL); +	if (!ptr->addr) +		return -ENOMEM; +	ptr->size = size; +	return 0; +} + +static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, +				    struct iwl_dma_ptr *ptr) +{ +	if (unlikely(!ptr->addr)) +		return; + +	dma_free_coherent(priv->bus.dev, ptr->size, ptr->addr, ptr->dma); +	memset(ptr, 0, sizeof(*ptr)); +} + +static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, +		      int slots_num, u32 txq_id) +{ +	size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; +	int i; + +	if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds)) +		return -EINVAL; + +	txq->q.n_window = slots_num; + +	txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num, +			    GFP_KERNEL); +	txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num, +			   GFP_KERNEL); + +	if (!txq->meta || !txq->cmd) +		goto error; + +	for (i = 0; i < slots_num; i++) { +		txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd), +					GFP_KERNEL); +		if (!txq->cmd[i]) +			goto error; +	} + +	/* Alloc driver data array and TFD circular buffer */ +	/* Driver private data, only for Tx (not command) queues, +	 * not shared with device. */ +	if (txq_id != priv->cmd_queue) { +		txq->txb = kzalloc(sizeof(txq->txb[0]) * +				   TFD_QUEUE_SIZE_MAX, GFP_KERNEL); +		if (!txq->txb) { +			IWL_ERR(priv, "kmalloc for auxiliary BD " +				  "structures failed\n"); +			goto error; +		} +	} else { +		txq->txb = NULL; +	} + +	/* Circular buffer of transmit frame descriptors (TFDs), +	 * shared with device */ +	txq->tfds = dma_alloc_coherent(priv->bus.dev, tfd_sz, &txq->q.dma_addr, +				       GFP_KERNEL); +	if (!txq->tfds) { +		IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz); +		goto error; +	} +	txq->q.id = txq_id; + +	return 0; +error: +	kfree(txq->txb); +	txq->txb = NULL; +	/* since txq->cmd has been zeroed, +	 * all non allocated cmd[i] will be NULL */ +	if (txq->cmd) +		for (i = 0; i < slots_num; i++) +			kfree(txq->cmd[i]); +	kfree(txq->meta); +	kfree(txq->cmd); +	txq->meta = NULL; +	txq->cmd = NULL; + +	return -ENOMEM; + +} + +static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, +		      int slots_num, u32 txq_id) +{ +	int ret; + +	txq->need_update = 0; +	memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num); + +	/* +	 * For the default queues 0-3, set up the swq_id +	 * already -- all others need to get one later +	 * (if they need one at all). +	 */ +	if (txq_id < 4) +		iwl_set_swq_id(txq, txq_id, txq_id); + +	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise +	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ +	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); + +	/* Initialize queue's high/low-water marks, and head/tail indexes */ +	ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, +			txq_id); +	if (ret) +		return ret; + +	/* +	 * Tell nic where to find circular buffer of Tx Frame Descriptors for +	 * given Tx queue, and enable the DMA channel used for that queue. +	 * Circular buffer (TFD queue in DRAM) physical base address */ +	iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), +			     txq->q.dma_addr >> 8); + +	return 0; +} + +/** + * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's + */ +static void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) +{ +	struct iwl_tx_queue *txq = &priv->txq[txq_id]; +	struct iwl_queue *q = &txq->q; + +	if (!q->n_bd) +		return; + +	while (q->write_ptr != q->read_ptr) { +		/* The read_ptr needs to bound by q->n_window */ +		iwlagn_txq_free_tfd(priv, txq, get_cmd_index(q, q->read_ptr)); +		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); +	} +} + +/** + * iwl_tx_queue_free - Deallocate DMA queue. + * @txq: Transmit queue to deallocate. + * + * Empty queue by removing and destroying all BD's. + * Free all buffers. + * 0-fill, but do not free "txq" descriptor structure. + */ +static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) +{ +	struct iwl_tx_queue *txq = &priv->txq[txq_id]; +	struct device *dev = priv->bus.dev; +	int i; +	if (WARN_ON(!txq)) +		return; + +	iwl_tx_queue_unmap(priv, txq_id); + +	/* De-alloc array of command/tx buffers */ +	for (i = 0; i < txq->q.n_window; i++) +		kfree(txq->cmd[i]); + +	/* De-alloc circular buffer of TFDs */ +	if (txq->q.n_bd) { +		dma_free_coherent(dev, priv->hw_params.tfd_size * +				  txq->q.n_bd, txq->tfds, txq->q.dma_addr); +		memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr)); +	} + +	/* De-alloc array of per-TFD driver data */ +	kfree(txq->txb); +	txq->txb = NULL; + +	/* deallocate arrays */ +	kfree(txq->cmd); +	kfree(txq->meta); +	txq->cmd = NULL; +	txq->meta = NULL; + +	/* 0-fill queue descriptor structure */ +	memset(txq, 0, sizeof(*txq)); +} + +/** + * iwl_trans_tx_free - Free TXQ Context + * + * Destroy all TX DMA queues and structures + */ +static void iwl_trans_tx_free(struct iwl_priv *priv) +{ +	int txq_id; + +	/* Tx queues */ +	if (priv->txq) { +		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) +			iwl_tx_queue_free(priv, txq_id); +	} + +	kfree(priv->txq); +	priv->txq = NULL; + +	iwlagn_free_dma_ptr(priv, &priv->kw); + +	iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); +} + +/** + * iwl_trans_tx_alloc - allocate TX context + * Allocate all Tx DMA structures and initialize them + * + * @param priv + * @return error code + */ +static int iwl_trans_tx_alloc(struct iwl_priv *priv) +{ +	int ret; +	int txq_id, slots_num; + +	/*It is not allowed to alloc twice, so warn when this happens. +	 * We cannot rely on the previous allocation, so free and fail */ +	if (WARN_ON(priv->txq)) { +		ret = -EINVAL; +		goto error; +	} + +	ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, +				priv->hw_params.scd_bc_tbls_size); +	if (ret) { +		IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); +		goto error; +	} + +	/* Alloc keep-warm buffer */ +	ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); +	if (ret) { +		IWL_ERR(priv, "Keep Warm allocation failed\n"); +		goto error; +	} + +	priv->txq = kzalloc(sizeof(struct iwl_tx_queue) * +			priv->cfg->base_params->num_of_queues, GFP_KERNEL); +	if (!priv->txq) { +		IWL_ERR(priv, "Not enough memory for txq\n"); +		ret = ENOMEM; +		goto error; +	} + +	/* Alloc and init all Tx queues, including the command queue (#4/#9) */ +	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { +		slots_num = (txq_id == priv->cmd_queue) ? +					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; +		ret = iwl_trans_txq_alloc(priv, &priv->txq[txq_id], slots_num, +				       txq_id); +		if (ret) { +			IWL_ERR(priv, "Tx %d queue alloc failed\n", txq_id); +			goto error; +		} +	} + +	return 0; + +error: +	trans_tx_free(priv); + +	return ret; +} +static int iwl_trans_tx_init(struct iwl_priv *priv) +{ +	int ret; +	int txq_id, slots_num; +	unsigned long flags; +	bool alloc = false; + +	if (!priv->txq) { +		ret = iwl_trans_tx_alloc(priv); +		if (ret) +			goto error; +		alloc = true; +	} + +	spin_lock_irqsave(&priv->lock, flags); + +	/* Turn off all Tx DMA fifos */ +	iwl_write_prph(priv, IWLAGN_SCD_TXFACT, 0); + +	/* Tell NIC where to find the "keep warm" buffer */ +	iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); + +	spin_unlock_irqrestore(&priv->lock, flags); + +	/* Alloc and init all Tx queues, including the command queue (#4/#9) */ +	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { +		slots_num = (txq_id == priv->cmd_queue) ? +					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; +		ret = iwl_trans_txq_init(priv, &priv->txq[txq_id], slots_num, +				       txq_id); +		if (ret) { +			IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); +			goto error; +		} +	} + +	return 0; +error: +	/*Upon error, free only if we allocated something */ +	if (alloc) +		trans_tx_free(priv); +	return ret; +} + +/** + * iwlagn_txq_ctx_stop - Stop all Tx DMA channels + */ +static int iwl_trans_tx_stop(struct iwl_priv *priv) +{ +	int ch, txq_id; +	unsigned long flags; + +	/* Turn off all Tx DMA fifos */ +	spin_lock_irqsave(&priv->lock, flags); + +	iwlagn_txq_set_sched(priv, 0); + +	/* Stop each Tx DMA channel, and wait for it to be idle */ +	for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) { +		iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); +		if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, +				    FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), +				    1000)) +			IWL_ERR(priv, "Failing on timeout while stopping" +			    " DMA channel %d [0x%08x]", ch, +			    iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); +	} +	spin_unlock_irqrestore(&priv->lock, flags); + +	if (!priv->txq) { +		IWL_WARN(priv, "Stopping tx queues that aren't allocated..."); +		return 0; +	} + +	/* Unmap DMA from host system and free skb's */ +	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) +		iwl_tx_queue_unmap(priv, txq_id); + +	return 0; +} + +static const struct iwl_trans_ops trans_ops = { +	.rx_init = iwl_trans_rx_init, +	.rx_stop = iwl_trans_rx_stop, +	.rx_free = iwl_trans_rx_free, + +	.tx_init = iwl_trans_tx_init, +	.tx_stop = iwl_trans_tx_stop, +	.tx_free = iwl_trans_tx_free, + +	.send_cmd = iwl_send_cmd, +	.send_cmd_pdu = iwl_send_cmd_pdu, +}; + +void iwl_trans_register(struct iwl_trans *trans) +{ +	trans->ops = &trans_ops; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h new file mode 100644 index 00000000000..111acca07d7 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license.  When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2007 - 2011 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 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + *  * Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + *  * Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in + *    the documentation and/or other materials provided with the + *    distribution. + *  * Neither the name Intel Corporation nor the names of its + *    contributors may be used to endorse or promote products derived + *    from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +static inline int trans_rx_init(struct iwl_priv *priv) +{ +	return priv->trans.ops->rx_init(priv); +} + +static inline int trans_rx_stop(struct iwl_priv *priv) +{ +	return priv->trans.ops->rx_stop(priv); +} + +static inline void trans_rx_free(struct iwl_priv *priv) +{ +	priv->trans.ops->rx_free(priv); +} + +static inline int trans_tx_init(struct iwl_priv *priv) +{ +	return priv->trans.ops->tx_init(priv); +} + +static inline int trans_tx_stop(struct iwl_priv *priv) +{ +	return priv->trans.ops->tx_stop(priv); +} + +static inline void trans_tx_free(struct iwl_priv *priv) +{ +	priv->trans.ops->tx_free(priv); +} + +static inline int trans_send_cmd(struct iwl_priv *priv, +				struct iwl_host_cmd *cmd) +{ +	return priv->trans.ops->send_cmd(priv, cmd); +} + +static inline int trans_send_cmd_pdu(struct iwl_priv *priv, u8 id, u32 flags, +					u16 len, const void *data) +{ +	return priv->trans.ops->send_cmd_pdu(priv, id, flags, len, data); +} + +void iwl_trans_register(struct iwl_trans *trans); diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 686e176b5eb..9b07e07f168 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -126,9 +126,8 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)  }  static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta, -			     struct iwl_tfd *tfd) +			     struct iwl_tfd *tfd, enum dma_data_direction dma_dir)  { -	struct pci_dev *dev = priv->pci_dev;  	int i;  	int num_tbs; @@ -143,42 +142,44 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,  	/* Unmap tx_cmd */  	if (num_tbs) -		pci_unmap_single(dev, +		dma_unmap_single(priv->bus.dev,  				dma_unmap_addr(meta, mapping),  				dma_unmap_len(meta, len), -				PCI_DMA_BIDIRECTIONAL); +				DMA_BIDIRECTIONAL);  	/* Unmap chunks, if any. */  	for (i = 1; i < num_tbs; i++) -		pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), -				iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); +		dma_unmap_single(priv->bus.dev, iwl_tfd_tb_get_addr(tfd, i), +				iwl_tfd_tb_get_len(tfd, i), dma_dir);  }  /**   * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]   * @priv - driver private data   * @txq - tx queue + * @index - the index of the TFD to be freed   *   * Does NOT advance any TFD circular buffer read/write indexes   * Does NOT free the TFD itself (which is within circular buffer)   */ -void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) +void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq, +	int index)  {  	struct iwl_tfd *tfd_tmp = txq->tfds; -	int index = txq->q.read_ptr; -	iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index]); +	iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index], +			 DMA_TO_DEVICE);  	/* free SKB */  	if (txq->txb) {  		struct sk_buff *skb; -		skb = txq->txb[txq->q.read_ptr].skb; +		skb = txq->txb[index].skb;  		/* can be called from irqs-disabled context */  		if (skb) {  			dev_kfree_skb_any(skb); -			txq->txb[txq->q.read_ptr].skb = NULL; +			txq->txb[index].skb = NULL;  		}  	}  } @@ -220,142 +221,6 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,  	return 0;  } -/* - * Tell nic where to find circular buffer of Tx Frame Descriptors for - * given Tx queue, and enable the DMA channel used for that queue. - * - * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA - * channels supported in hardware. - */ -static int iwlagn_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) -{ -	int txq_id = txq->q.id; - -	/* Circular buffer (TFD queue in DRAM) physical base address */ -	iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), -			     txq->q.dma_addr >> 8); - -	return 0; -} - -/** - * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's - */ -void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) -{ -	struct iwl_tx_queue *txq = &priv->txq[txq_id]; -	struct iwl_queue *q = &txq->q; - -	if (q->n_bd == 0) -		return; - -	 while (q->write_ptr != q->read_ptr) { -		iwlagn_txq_free_tfd(priv, txq); -		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); -	} -} - -/** - * iwl_tx_queue_free - Deallocate DMA queue. - * @txq: Transmit queue to deallocate. - * - * Empty queue by removing and destroying all BD's. - * Free all buffers. - * 0-fill, but do not free "txq" descriptor structure. - */ -void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) -{ -	struct iwl_tx_queue *txq = &priv->txq[txq_id]; -	struct device *dev = &priv->pci_dev->dev; -	int i; - -	iwl_tx_queue_unmap(priv, txq_id); - -	/* De-alloc array of command/tx buffers */ -	for (i = 0; i < TFD_TX_CMD_SLOTS; i++) -		kfree(txq->cmd[i]); - -	/* De-alloc circular buffer of TFDs */ -	if (txq->q.n_bd) -		dma_free_coherent(dev, priv->hw_params.tfd_size * -				  txq->q.n_bd, txq->tfds, txq->q.dma_addr); - -	/* De-alloc array of per-TFD driver data */ -	kfree(txq->txb); -	txq->txb = NULL; - -	/* deallocate arrays */ -	kfree(txq->cmd); -	kfree(txq->meta); -	txq->cmd = NULL; -	txq->meta = NULL; - -	/* 0-fill queue descriptor structure */ -	memset(txq, 0, sizeof(*txq)); -} - -/** - * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue - */ -void iwl_cmd_queue_unmap(struct iwl_priv *priv) -{ -	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; -	struct iwl_queue *q = &txq->q; -	int i; - -	if (q->n_bd == 0) -		return; - -	while (q->read_ptr != q->write_ptr) { -		i = get_cmd_index(q, q->read_ptr); - -		if (txq->meta[i].flags & CMD_MAPPED) { -			pci_unmap_single(priv->pci_dev, -					 dma_unmap_addr(&txq->meta[i], mapping), -					 dma_unmap_len(&txq->meta[i], len), -					 PCI_DMA_BIDIRECTIONAL); -			txq->meta[i].flags = 0; -		} - -		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); -	} -} - -/** - * iwl_cmd_queue_free - Deallocate DMA queue. - * @txq: Transmit queue to deallocate. - * - * Empty queue by removing and destroying all BD's. - * Free all buffers. - * 0-fill, but do not free "txq" descriptor structure. - */ -void iwl_cmd_queue_free(struct iwl_priv *priv) -{ -	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; -	struct device *dev = &priv->pci_dev->dev; -	int i; - -	iwl_cmd_queue_unmap(priv); - -	/* De-alloc array of command/tx buffers */ -	for (i = 0; i < TFD_CMD_SLOTS; i++) -		kfree(txq->cmd[i]); - -	/* De-alloc circular buffer of TFDs */ -	if (txq->q.n_bd) -		dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd, -				  txq->tfds, txq->q.dma_addr); - -	/* deallocate arrays */ -	kfree(txq->cmd); -	kfree(txq->meta); -	txq->cmd = NULL; -	txq->meta = NULL; - -	/* 0-fill queue descriptor structure */ -	memset(txq, 0, sizeof(*txq)); -} -  /*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****   * DMA services   * @@ -394,11 +259,10 @@ int iwl_queue_space(const struct iwl_queue *q)  	return s;  } -  /**   * iwl_queue_init - Initialize queue's high/low-water and read/write indexes   */ -static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, +int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,  			  int count, int slots_num, u32 id)  {  	q->n_bd = count; @@ -428,129 +292,6 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,  	return 0;  } -/** - * iwl_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue - */ -static int iwl_tx_queue_alloc(struct iwl_priv *priv, -			      struct iwl_tx_queue *txq, u32 id) -{ -	struct device *dev = &priv->pci_dev->dev; -	size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; - -	/* Driver private data, only for Tx (not command) queues, -	 * not shared with device. */ -	if (id != priv->cmd_queue) { -		txq->txb = kzalloc(sizeof(txq->txb[0]) * -				   TFD_QUEUE_SIZE_MAX, GFP_KERNEL); -		if (!txq->txb) { -			IWL_ERR(priv, "kmalloc for auxiliary BD " -				  "structures failed\n"); -			goto error; -		} -	} else { -		txq->txb = NULL; -	} - -	/* Circular buffer of transmit frame descriptors (TFDs), -	 * shared with device */ -	txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, -				       GFP_KERNEL); -	if (!txq->tfds) { -		IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); -		goto error; -	} -	txq->q.id = id; - -	return 0; - - error: -	kfree(txq->txb); -	txq->txb = NULL; - -	return -ENOMEM; -} - -/** - * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue - */ -int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, -		      int slots_num, u32 txq_id) -{ -	int i, len; -	int ret; - -	txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * slots_num, -			    GFP_KERNEL); -	txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * slots_num, -			   GFP_KERNEL); - -	if (!txq->meta || !txq->cmd) -		goto out_free_arrays; - -	len = sizeof(struct iwl_device_cmd); -	for (i = 0; i < slots_num; i++) { -		txq->cmd[i] = kmalloc(len, GFP_KERNEL); -		if (!txq->cmd[i]) -			goto err; -	} - -	/* Alloc driver data array and TFD circular buffer */ -	ret = iwl_tx_queue_alloc(priv, txq, txq_id); -	if (ret) -		goto err; - -	txq->need_update = 0; - -	/* -	 * For the default queues 0-3, set up the swq_id -	 * already -- all others need to get one later -	 * (if they need one at all). -	 */ -	if (txq_id < 4) -		iwl_set_swq_id(txq, txq_id, txq_id); - -	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise -	 * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ -	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); - -	/* Initialize queue's high/low-water marks, and head/tail indexes */ -	ret = iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); -	if (ret) -		return ret; - -	/* Tell device where to find queue */ -	iwlagn_tx_queue_init(priv, txq); - -	return 0; -err: -	for (i = 0; i < slots_num; i++) -		kfree(txq->cmd[i]); -out_free_arrays: -	kfree(txq->meta); -	kfree(txq->cmd); - -	return -ENOMEM; -} - -void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, -			int slots_num, u32 txq_id) -{ -	int actual_slots = slots_num; - -	if (txq_id == priv->cmd_queue) -		actual_slots++; - -	memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); - -	txq->need_update = 0; - -	/* Initialize queue's high/low-water marks, and head/tail indexes */ -	iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); - -	/* Tell device where to find queue */ -	iwlagn_tx_queue_init(priv, txq); -} -  /*************** HOST COMMAND QUEUE FUNCTIONS   *****/  /** @@ -587,6 +328,12 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  		return -EIO;  	} +	if ((priv->ucode_owner == IWL_OWNERSHIP_TM) && +	    !(cmd->flags & CMD_ON_DEMAND)) { +		IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n"); +		return -EIO; +	} +  	copy_size = sizeof(out_cmd->hdr);  	cmd_size = sizeof(out_cmd->hdr); @@ -640,11 +387,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  	out_cmd = txq->cmd[idx];  	out_meta = &txq->meta[idx]; -	if (WARN_ON(out_meta->flags & CMD_MAPPED)) { -		spin_unlock_irqrestore(&priv->hcmd_lock, flags); -		return -ENOSPC; -	} -  	memset(out_meta, 0, sizeof(*out_meta));	/* re-initialize to NULL */  	if (cmd->flags & CMD_WANT_SKB)  		out_meta->source = cmd; @@ -677,9 +419,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  			le16_to_cpu(out_cmd->hdr.sequence), cmd_size,  			q->write_ptr, idx, priv->cmd_queue); -	phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, -				   copy_size, PCI_DMA_BIDIRECTIONAL); -	if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { +	phys_addr = dma_map_single(priv->bus.dev, &out_cmd->hdr, copy_size, +				DMA_BIDIRECTIONAL); +	if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) {  		idx = -ENOMEM;  		goto out;  	} @@ -699,11 +441,12 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  			continue;  		if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))  			continue; -		phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i], -					   cmd->len[i], PCI_DMA_TODEVICE); -		if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) { +		phys_addr = dma_map_single(priv->bus.dev, (void *)cmd->data[i], +					   cmd->len[i], DMA_BIDIRECTIONAL); +		if (dma_mapping_error(priv->bus.dev, phys_addr)) {  			iwlagn_unmap_tfd(priv, out_meta, -					 &txq->tfds[q->write_ptr]); +					 &txq->tfds[q->write_ptr], +					 DMA_BIDIRECTIONAL);  			idx = -ENOMEM;  			goto out;  		} @@ -717,7 +460,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)  #endif  	} -	out_meta->flags = cmd->flags | CMD_MAPPED; +	out_meta->flags = cmd->flags;  	txq->need_update = 1; @@ -753,9 +496,9 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int idx)  	int nfreed = 0;  	if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) { -		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " -			  "is out of range [0-%d] %d %d.\n", txq_id, -			  idx, q->n_bd, q->write_ptr, q->read_ptr); +		IWL_ERR(priv, "%s: Read index for DMA queue txq id (%d), " +			  "index %d is out of range [0-%d] %d %d.\n", __func__, +			  txq_id, idx, q->n_bd, q->write_ptr, q->read_ptr);  		return;  	} @@ -807,7 +550,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)  	cmd = txq->cmd[cmd_index];  	meta = &txq->meta[cmd_index]; -	iwlagn_unmap_tfd(priv, meta, &txq->tfds[index]); +	iwlagn_unmap_tfd(priv, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);  	/* Input error checking is done when commands are added to queue. */  	if (meta->flags & CMD_WANT_SKB) { @@ -827,7 +570,6 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)  		wake_up_interruptible(&priv->wait_command_queue);  	} -	/* Mark as unmapped */  	meta->flags = 0;  	spin_unlock_irqrestore(&priv->hcmd_lock, flags); diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c index 49067092d33..6f1afe6bbc8 100644 --- a/drivers/net/wireless/iwmc3200wifi/fw.c +++ b/drivers/net/wireless/iwmc3200wifi/fw.c @@ -187,7 +187,7 @@ static int iwm_load_img(struct iwm_priv *iwm, const char *img_name)  		if (ret < 0)  			goto err_release_fw;  		opcode_idx++; -	}; +	}  	/* Read firmware version */  	fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0); diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 5d637af2d7c..b456a53b64b 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -8,6 +8,7 @@  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/hardirq.h>  #include <linux/sched.h>  #include <linux/wait.h>  #include <linux/slab.h> diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 71c8f3fccfa..dbd24a4607e 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -3,6 +3,7 @@   * It prepares command and sends it to firmware when it is ready.   */ +#include <linux/hardirq.h>  #include <linux/kfifo.h>  #include <linux/sched.h>  #include <linux/slab.h> @@ -873,6 +874,7 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)  	memset(&cmd, 0, sizeof(cmd));  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.action = cpu_to_le16(CMD_ACT_GET); +	cmd.offset = cpu_to_le16(offset);  	if (reg != CMD_MAC_REG_ACCESS &&  	    reg != CMD_BBP_REG_ACCESS && @@ -882,7 +884,7 @@ int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)  	}  	ret = lbs_cmd_with_response(priv, reg, &cmd); -	if (ret) { +	if (!ret) {  		if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)  			*value = cmd.value.bbp_rf;  		else if (reg == CMD_MAC_REG_ACCESS) @@ -915,6 +917,7 @@ int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)  	memset(&cmd, 0, sizeof(cmd));  	cmd.hdr.size = cpu_to_le16(sizeof(cmd));  	cmd.action = cpu_to_le16(CMD_ACT_SET); +	cmd.offset = cpu_to_le16(offset);  	if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)  		cmd.value.bbp_rf = (u8) (value & 0xFF); @@ -1067,16 +1070,34 @@ static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,  	spin_unlock_irqrestore(&priv->driver_lock, flags);  } -void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, -			  int result) +void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, +			    int result)  { +	/* +	 * Normally, commands are removed from cmdpendingq before being +	 * submitted. However, we can arrive here on alternative codepaths +	 * where the command is still pending. Make sure the command really +	 * isn't part of a list at this point. +	 */ +	list_del_init(&cmd->list); +  	cmd->result = result;  	cmd->cmdwaitqwoken = 1; -	wake_up_interruptible(&cmd->cmdwait_q); +	wake_up(&cmd->cmdwait_q);  	if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)  		__lbs_cleanup_and_insert_cmd(priv, cmd);  	priv->cur_cmd = NULL; +	wake_up_interruptible(&priv->waitq); +} + +void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, +			  int result) +{ +	unsigned long flags; +	spin_lock_irqsave(&priv->driver_lock, flags); +	__lbs_complete_command(priv, cmd, result); +	spin_unlock_irqrestore(&priv->driver_lock, flags);  }  int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) @@ -1248,7 +1269,7 @@ static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)  	if (!list_empty(&priv->cmdfreeq)) {  		tempnode = list_first_entry(&priv->cmdfreeq,  					    struct cmd_ctrl_node, list); -		list_del(&tempnode->list); +		list_del_init(&tempnode->list);  	} else {  		lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");  		tempnode = NULL; @@ -1356,10 +1377,7 @@ int lbs_execute_next_command(struct lbs_private *priv)  				    cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {  					lbs_deb_host(  					       "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n"); -					spin_lock_irqsave(&priv->driver_lock, flags); -					list_del(&cmdnode->list);  					lbs_complete_command(priv, cmdnode, 0); -					spin_unlock_irqrestore(&priv->driver_lock, flags);  					ret = 0;  					goto done; @@ -1369,10 +1387,7 @@ int lbs_execute_next_command(struct lbs_private *priv)  				    (priv->psstate == PS_STATE_PRE_SLEEP)) {  					lbs_deb_host(  					       "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n"); -					spin_lock_irqsave(&priv->driver_lock, flags); -					list_del(&cmdnode->list);  					lbs_complete_command(priv, cmdnode, 0); -					spin_unlock_irqrestore(&priv->driver_lock, flags);  					priv->needtowakeup = 1;  					ret = 0; @@ -1384,7 +1399,7 @@ int lbs_execute_next_command(struct lbs_private *priv)  			}  		}  		spin_lock_irqsave(&priv->driver_lock, flags); -		list_del(&cmdnode->list); +		list_del_init(&cmdnode->list);  		spin_unlock_irqrestore(&priv->driver_lock, flags);  		lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",  			    le16_to_cpu(cmd->command)); @@ -1667,7 +1682,13 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,  	}  	might_sleep(); -	wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken); + +	/* +	 * Be careful with signals here. A signal may be received as the system +	 * goes into suspend or resume. We do not want this to interrupt the +	 * command, so we perform an uninterruptible sleep. +	 */ +	wait_event(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);  	spin_lock_irqsave(&priv->driver_lock, flags);  	ret = cmdnode->result; diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index 7109d6b717e..b280ef7a0ae 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h @@ -59,6 +59,8 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv);  int lbs_free_cmd_buffer(struct lbs_private *priv);  int lbs_execute_next_command(struct lbs_private *priv); +void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, +			    int result);  void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,  			  int result);  int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 207fc361db8..178b222b3ce 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -3,6 +3,7 @@   * responses as well as events generated by firmware.   */ +#include <linux/hardirq.h>  #include <linux/slab.h>  #include <linux/delay.h>  #include <linux/sched.h> @@ -165,7 +166,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)  			lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);  		} -		lbs_complete_command(priv, priv->cur_cmd, result); +		__lbs_complete_command(priv, priv->cur_cmd, result);  		spin_unlock_irqrestore(&priv->driver_lock, flags);  		ret = 0; @@ -186,7 +187,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)  			break;  		} -		lbs_complete_command(priv, priv->cur_cmd, result); +		__lbs_complete_command(priv, priv->cur_cmd, result);  		spin_unlock_irqrestore(&priv->driver_lock, flags);  		ret = -1; @@ -204,7 +205,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)  	if (priv->cur_cmd) {  		/* Clean up and Put current command back to cmdfreeq */ -		lbs_complete_command(priv, priv->cur_cmd, result); +		__lbs_complete_command(priv, priv->cur_cmd, result);  	}  	spin_unlock_irqrestore(&priv->driver_lock, flags); diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 23250f62176..1af18277884 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -1,6 +1,7 @@  #include <linux/dcache.h>  #include <linux/debugfs.h>  #include <linux/delay.h> +#include <linux/hardirq.h>  #include <linux/mm.h>  #include <linux/string.h>  #include <linux/slab.h> diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 29dbce4a9f8..4dfb3bfd2cf 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -1,3 +1,4 @@ +#include <linux/hardirq.h>  #include <linux/netdevice.h>  #include <linux/ethtool.h>  #include <linux/delay.h> diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 224e9853c48..387786e1b39 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -892,6 +892,37 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)  } +static struct mmc_host *reset_host; + +static void if_sdio_reset_card_worker(struct work_struct *work) +{ +	/* +	 * The actual reset operation must be run outside of lbs_thread. This +	 * is because mmc_remove_host() will cause the device to be instantly +	 * destroyed, and the libertas driver then needs to end lbs_thread, +	 * leading to a deadlock. +	 * +	 * We run it in a workqueue totally independent from the if_sdio_card +	 * instance for that reason. +	 */ + +	pr_info("Resetting card..."); +	mmc_remove_host(reset_host); +	mmc_add_host(reset_host); +} +static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker); + +static void if_sdio_reset_card(struct lbs_private *priv) +{ +	struct if_sdio_card *card = priv->card; + +	if (work_pending(&card_reset_work)) +		return; + +	reset_host = card->func->card->host; +	schedule_work(&card_reset_work); +} +  /*******************************************************************/  /* SDIO callbacks                                                  */  /*******************************************************************/ @@ -1065,6 +1096,7 @@ static int if_sdio_probe(struct sdio_func *func,  	priv->enter_deep_sleep = if_sdio_enter_deep_sleep;  	priv->exit_deep_sleep = if_sdio_exit_deep_sleep;  	priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; +	priv->reset_card = if_sdio_reset_card;  	sdio_claim_host(func); @@ -1301,6 +1333,8 @@ static void __exit if_sdio_exit_module(void)  	/* Set the flag as user is removing this module. */  	user_rmmod = 1; +	cancel_work_sync(&card_reset_work); +  	sdio_unregister_driver(&if_sdio_driver);  	lbs_deb_leave(LBS_DEB_SDIO); diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 463352c890d..e0286cfbc91 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -19,6 +19,8 @@  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/hardirq.h> +#include <linux/interrupt.h>  #include <linux/moduleparam.h>  #include <linux/firmware.h>  #include <linux/jiffies.h> @@ -1032,7 +1034,6 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)  static int if_spi_init_card(struct if_spi_card *card)  {  	struct lbs_private *priv = card->priv; -	struct spi_device *spi = card->spi;  	int err, i;  	u32 scratch;  	const struct firmware *helper = NULL; @@ -1080,8 +1081,9 @@ static int if_spi_init_card(struct if_spi_card *card)  				"attached to SPI bus_num %d, chip_select %d. "  				"spi->max_speed_hz=%d\n",  				card->card_id, card->card_rev, -				spi->master->bus_num, spi->chip_select, -				spi->max_speed_hz); +				card->spi->master->bus_num, +				card->spi->chip_select, +				card->spi->max_speed_hz);  		err = if_spi_prog_helper_firmware(card, helper);  		if (err)  			goto out; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 8c40949cb07..c79aac4b1da 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -9,6 +9,7 @@  #include <linux/moduleparam.h>  #include <linux/delay.h>  #include <linux/etherdevice.h> +#include <linux/hardirq.h>  #include <linux/netdevice.h>  #include <linux/if_arp.h>  #include <linux/kthread.h> @@ -638,6 +639,14 @@ static void lbs_cmd_timeout_handler(unsigned long data)  		    le16_to_cpu(priv->cur_cmd->cmdbuf->command));  	priv->cmd_timed_out = 1; + +	/* +	 * If the device didn't even acknowledge the command, reset the state +	 * so that we don't block all future commands due to this one timeout. +	 */ +	if (priv->dnld_sent == DNLD_CMD_SENT) +		priv->dnld_sent = DNLD_RES_RECEIVED; +  	wake_up_interruptible(&priv->waitq);  out:  	spin_unlock_irqrestore(&priv->driver_lock, flags); @@ -994,7 +1003,7 @@ void lbs_stop_card(struct lbs_private *priv)  	list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {  		cmdnode->result = -ENOENT;  		cmdnode->cmdwaitqwoken = 1; -		wake_up_interruptible(&cmdnode->cmdwait_q); +		wake_up(&cmdnode->cmdwait_q);  	}  	/* Flush the command the card is currently processing */ @@ -1002,7 +1011,7 @@ void lbs_stop_card(struct lbs_private *priv)  		lbs_deb_main("clearing current command\n");  		priv->cur_cmd->result = -ENOENT;  		priv->cur_cmd->cmdwaitqwoken = 1; -		wake_up_interruptible(&priv->cur_cmd->cmdwait_q); +		wake_up(&priv->cur_cmd->cmdwait_q);  	}  	lbs_deb_main("done clearing commands\n");  	spin_unlock_irqrestore(&priv->driver_lock, flags); diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 24cf06680c6..7969d104189 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c @@ -2,6 +2,7 @@  #include <linux/delay.h>  #include <linux/etherdevice.h> +#include <linux/hardirq.h>  #include <linux/netdevice.h>  #include <linux/if_ether.h>  #include <linux/if_arp.h> diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index fdb0448301a..bfb8898ae51 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -5,6 +5,7 @@  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt  #include <linux/etherdevice.h> +#include <linux/hardirq.h>  #include <linux/slab.h>  #include <linux/types.h>  #include <net/cfg80211.h> diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index bbb95f88dc0..f19495b178f 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -1,6 +1,7 @@  /*   * This file contains the handling of TX in wlan driver.   */ +#include <linux/hardirq.h>  #include <linux/netdevice.h>  #include <linux/etherdevice.h>  #include <linux/sched.h> diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c index 8945afd6ce3..13557fe0bf9 100644 --- a/drivers/net/wireless/libertas_tf/cmd.c +++ b/drivers/net/wireless/libertas_tf/cmd.c @@ -9,6 +9,7 @@   */  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/hardirq.h>  #include <linux/slab.h>  #include "libertas_tf.h" diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index d4005081f1d..acc461aa385 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c @@ -9,6 +9,7 @@   */  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/hardirq.h>  #include <linux/slab.h>  #include <linux/etherdevice.h> @@ -585,7 +586,7 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)  	need_padding ^= ieee80211_has_a4(hdr->frame_control);  	need_padding ^= ieee80211_is_data_qos(hdr->frame_control) &&  			(*ieee80211_get_qos_ctl(hdr) & -			 IEEE80211_QOS_CONTROL_A_MSDU_PRESENT); +			 IEEE80211_QOS_CTL_A_MSDU_PRESENT);  	if (need_padding) {  		memmove(skb->data + 2, skb->data, skb->len); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 9d4a40ee16c..031cd89b176 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1,6 +1,7 @@  /*   * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211   * Copyright (c) 2008, Jouni Malinen <j@w1.fi> + * Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License version 2 as @@ -25,11 +26,17 @@  #include <linux/rtnetlink.h>  #include <linux/etherdevice.h>  #include <linux/debugfs.h> +#include <net/genetlink.h> +#include "mac80211_hwsim.h" + +#define WARN_QUEUE 100 +#define MAX_QUEUE 200  MODULE_AUTHOR("Jouni Malinen");  MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");  MODULE_LICENSE("GPL"); +int wmediumd_pid;  static int radios = 2;  module_param(radios, int, 0444);  MODULE_PARM_DESC(radios, "Number of simulated radios"); @@ -302,6 +309,7 @@ struct mac80211_hwsim_data {  	struct dentry *debugfs;  	struct dentry *debugfs_ps; +	struct sk_buff_head pending;	/* packets pending */  	/*  	 * Only radios in the same group can communicate together (the  	 * channel has to match too). Each bit represents a group. A @@ -322,6 +330,32 @@ struct hwsim_radiotap_hdr {  	__le16 rt_chbitmask;  } __packed; +/* MAC80211_HWSIM netlinf family */ +static struct genl_family hwsim_genl_family = { +	.id = GENL_ID_GENERATE, +	.hdrsize = 0, +	.name = "MAC80211_HWSIM", +	.version = 1, +	.maxattr = HWSIM_ATTR_MAX, +}; + +/* MAC80211_HWSIM netlink policy */ + +static struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { +	[HWSIM_ATTR_ADDR_RECEIVER] = { .type = NLA_UNSPEC, +				       .len = 6*sizeof(u8) }, +	[HWSIM_ATTR_ADDR_TRANSMITTER] = { .type = NLA_UNSPEC, +					  .len = 6*sizeof(u8) }, +	[HWSIM_ATTR_FRAME] = { .type = NLA_BINARY, +			       .len = IEEE80211_MAX_DATA_LEN }, +	[HWSIM_ATTR_FLAGS] = { .type = NLA_U32 }, +	[HWSIM_ATTR_RX_RATE] = { .type = NLA_U32 }, +	[HWSIM_ATTR_SIGNAL] = { .type = NLA_U32 }, +	[HWSIM_ATTR_TX_INFO] = { .type = NLA_UNSPEC, +				 .len = IEEE80211_TX_MAX_RATES*sizeof( +					struct hwsim_tx_rate)}, +	[HWSIM_ATTR_COOKIE] = { .type = NLA_U64 }, +};  static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb,  					struct net_device *dev) @@ -478,9 +512,89 @@ static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data,  	return md.ret;  } +static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, +				       struct sk_buff *my_skb, +				       int dst_pid) +{ +	struct sk_buff *skb; +	struct mac80211_hwsim_data *data = hw->priv; +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) my_skb->data; +	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(my_skb); +	void *msg_head; +	unsigned int hwsim_flags = 0; +	int i; +	struct hwsim_tx_rate tx_attempts[IEEE80211_TX_MAX_RATES]; + +	if (data->idle) { +		wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); +		dev_kfree_skb(my_skb); +		return; +	} + +	if (data->ps != PS_DISABLED) +		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); +	/* If the queue contains MAX_QUEUE skb's drop some */ +	if (skb_queue_len(&data->pending) >= MAX_QUEUE) { +		/* Droping until WARN_QUEUE level */ +		while (skb_queue_len(&data->pending) >= WARN_QUEUE) +			skb_dequeue(&data->pending); +	} + +	skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); +	if (skb == NULL) +		goto nla_put_failure; + +	msg_head = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, +			       HWSIM_CMD_FRAME); +	if (msg_head == NULL) { +		printk(KERN_DEBUG "mac80211_hwsim: problem with msg_head\n"); +		goto nla_put_failure; +	} + +	NLA_PUT(skb, HWSIM_ATTR_ADDR_TRANSMITTER, +		     sizeof(struct mac_address), data->addresses[1].addr); + +	/* We get the skb->data */ +	NLA_PUT(skb, HWSIM_ATTR_FRAME, my_skb->len, my_skb->data); + +	/* We get the flags for this transmission, and we translate them to +	   wmediumd flags  */ + +	if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) +		hwsim_flags |= HWSIM_TX_CTL_REQ_TX_STATUS; + +	if (info->flags & IEEE80211_TX_CTL_NO_ACK) +		hwsim_flags |= HWSIM_TX_CTL_NO_ACK; + +	NLA_PUT_U32(skb, HWSIM_ATTR_FLAGS, hwsim_flags); + +	/* We get the tx control (rate and retries) info*/ + +	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { +		tx_attempts[i].idx = info->status.rates[i].idx; +		tx_attempts[i].count = info->status.rates[i].count; +	} + +	NLA_PUT(skb, HWSIM_ATTR_TX_INFO, +		     sizeof(struct hwsim_tx_rate)*IEEE80211_TX_MAX_RATES, +		     tx_attempts); + +	/* We create a cookie to identify this skb */ +	NLA_PUT_U64(skb, HWSIM_ATTR_COOKIE, (unsigned long) my_skb); -static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, -				    struct sk_buff *skb) +	genlmsg_end(skb, msg_head); +	genlmsg_unicast(&init_net, skb, dst_pid); + +	/* Enqueue the packet */ +	skb_queue_tail(&data->pending, my_skb); +	return; + +nla_put_failure: +	printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__); +} + +static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, +					  struct sk_buff *skb)  {  	struct mac80211_hwsim_data *data = hw->priv, *data2;  	bool ack = false; @@ -540,11 +654,11 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,  	return ack;  } -  static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  {  	bool ack;  	struct ieee80211_tx_info *txi; +	int _pid;  	mac80211_hwsim_monitor_rx(hw, skb); @@ -554,7 +668,15 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  		return;  	} -	ack = mac80211_hwsim_tx_frame(hw, skb); +	/* wmediumd mode check */ +	_pid = wmediumd_pid; + +	if (_pid) +		return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); + +	/* NO wmediumd detected, perfect medium simulation */ +	ack = mac80211_hwsim_tx_frame_no_nl(hw, skb); +  	if (ack && skb->len >= 16) {  		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;  		mac80211_hwsim_monitor_ack(hw, hdr->addr2); @@ -635,6 +757,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,  	struct ieee80211_hw *hw = arg;  	struct sk_buff *skb;  	struct ieee80211_tx_info *info; +	int _pid;  	hwsim_check_magic(vif); @@ -649,7 +772,14 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,  	info = IEEE80211_SKB_CB(skb);  	mac80211_hwsim_monitor_rx(hw, skb); -	mac80211_hwsim_tx_frame(hw, skb); + +	/* wmediumd mode check */ +	_pid = wmediumd_pid; + +	if (_pid) +		return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); + +	mac80211_hwsim_tx_frame_no_nl(hw, skb);  	dev_kfree_skb(skb);  } @@ -966,12 +1096,7 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,  static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)  { -	/* -	 * In this special case, there's nothing we need to -	 * do because hwsim does transmission synchronously. -	 * In the future, when it does transmissions via -	 * userspace, we may need to do something. -	 */ +	/* Not implemented, queues only on kernel side */  }  struct hw_scan_done { @@ -1005,6 +1130,8 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,  	for (i = 0; i < req->n_channels; i++)  		printk(KERN_DEBUG "hwsim hw_scan freq %d\n",  			req->channels[i]->center_freq); +	print_hex_dump(KERN_DEBUG, "scan IEs: ", DUMP_PREFIX_OFFSET, +			16, 1, req->ie, req->ie_len, 1);  	ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ); @@ -1119,6 +1246,7 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)  	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;  	struct sk_buff *skb;  	struct ieee80211_pspoll *pspoll; +	int _pid;  	if (!vp->assoc)  		return; @@ -1137,8 +1265,15 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)  	pspoll->aid = cpu_to_le16(0xc000 | vp->aid);  	memcpy(pspoll->bssid, vp->bssid, ETH_ALEN);  	memcpy(pspoll->ta, mac, ETH_ALEN); -	if (!mac80211_hwsim_tx_frame(data->hw, skb)) -		printk(KERN_DEBUG "%s: PS-Poll frame not ack'ed\n", __func__); + +	/* wmediumd mode check */ +	_pid = wmediumd_pid; + +	if (_pid) +		return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid); + +	if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb)) +		printk(KERN_DEBUG "%s: PS-poll frame not ack'ed\n", __func__);  	dev_kfree_skb(skb);  } @@ -1149,6 +1284,7 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,  	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;  	struct sk_buff *skb;  	struct ieee80211_hdr *hdr; +	int _pid;  	if (!vp->assoc)  		return; @@ -1168,7 +1304,14 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,  	memcpy(hdr->addr1, vp->bssid, ETH_ALEN);  	memcpy(hdr->addr2, mac, ETH_ALEN);  	memcpy(hdr->addr3, vp->bssid, ETH_ALEN); -	if (!mac80211_hwsim_tx_frame(data->hw, skb)) + +	/* wmediumd mode check */ +	_pid = wmediumd_pid; + +	if (_pid) +		return mac80211_hwsim_tx_frame_nl(data->hw, skb, _pid); + +	if (!mac80211_hwsim_tx_frame_no_nl(data->hw, skb))  		printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__);  	dev_kfree_skb(skb);  } @@ -1248,6 +1391,273 @@ DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group,  			hwsim_fops_group_read, hwsim_fops_group_write,  			"%llx\n"); +struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr( +			     struct mac_address *addr) +{ +	struct mac80211_hwsim_data *data; +	bool _found = false; + +	spin_lock_bh(&hwsim_radio_lock); +	list_for_each_entry(data, &hwsim_radios, list) { +		if (memcmp(data->addresses[1].addr, addr, +			  sizeof(struct mac_address)) == 0) { +			_found = true; +			break; +		} +	} +	spin_unlock_bh(&hwsim_radio_lock); + +	if (!_found) +		return NULL; + +	return data; +} + +static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2, +					   struct genl_info *info) +{ + +	struct ieee80211_hdr *hdr; +	struct mac80211_hwsim_data *data2; +	struct ieee80211_tx_info *txi; +	struct hwsim_tx_rate *tx_attempts; +	struct sk_buff __user *ret_skb; +	struct sk_buff *skb, *tmp; +	struct mac_address *src; +	unsigned int hwsim_flags; + +	int i; +	bool found = false; + +	if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] || +	   !info->attrs[HWSIM_ATTR_FLAGS] || +	   !info->attrs[HWSIM_ATTR_COOKIE] || +	   !info->attrs[HWSIM_ATTR_TX_INFO]) +		goto out; + +	src = (struct mac_address *)nla_data( +				   info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER]); +	hwsim_flags = nla_get_u32(info->attrs[HWSIM_ATTR_FLAGS]); + +	ret_skb = (struct sk_buff __user *) +		  (unsigned long) nla_get_u64(info->attrs[HWSIM_ATTR_COOKIE]); + +	data2 = get_hwsim_data_ref_from_addr(src); + +	if (data2 == NULL) +		goto out; + +	/* look for the skb matching the cookie passed back from user */ +	skb_queue_walk_safe(&data2->pending, skb, tmp) { +		if (skb == ret_skb) { +			skb_unlink(skb, &data2->pending); +			found = true; +			break; +		} +	} + +	/* not found */ +	if (!found) +		goto out; + +	/* Tx info received because the frame was broadcasted on user space, +	 so we get all the necessary info: tx attempts and skb control buff */ + +	tx_attempts = (struct hwsim_tx_rate *)nla_data( +		       info->attrs[HWSIM_ATTR_TX_INFO]); + +	/* now send back TX status */ +	txi = IEEE80211_SKB_CB(skb); + +	if (txi->control.vif) +		hwsim_check_magic(txi->control.vif); +	if (txi->control.sta) +		hwsim_check_sta_magic(txi->control.sta); + +	ieee80211_tx_info_clear_status(txi); + +	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { +		txi->status.rates[i].idx = tx_attempts[i].idx; +		txi->status.rates[i].count = tx_attempts[i].count; +		/*txi->status.rates[i].flags = 0;*/ +	} + +	txi->status.ack_signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); + +	if (!(hwsim_flags & HWSIM_TX_CTL_NO_ACK) && +	   (hwsim_flags & HWSIM_TX_STAT_ACK)) { +		if (skb->len >= 16) { +			hdr = (struct ieee80211_hdr *) skb->data; +			mac80211_hwsim_monitor_ack(data2->hw, hdr->addr2); +		} +	} +	ieee80211_tx_status_irqsafe(data2->hw, skb); +	return 0; +out: +	return -EINVAL; + +} + +static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, +					  struct genl_info *info) +{ + +	struct mac80211_hwsim_data  *data2; +	struct ieee80211_rx_status rx_status; +	struct mac_address *dst; +	int frame_data_len; +	char *frame_data; +	struct sk_buff *skb = NULL; + +	if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || +	   !info->attrs[HWSIM_ATTR_FRAME] || +	   !info->attrs[HWSIM_ATTR_RX_RATE] || +	   !info->attrs[HWSIM_ATTR_SIGNAL]) +		goto out; + +	dst = (struct mac_address *)nla_data( +				   info->attrs[HWSIM_ATTR_ADDR_RECEIVER]); + +	frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]); +	frame_data = (char *)nla_data(info->attrs[HWSIM_ATTR_FRAME]); + +	/* Allocate new skb here */ +	skb = alloc_skb(frame_data_len, GFP_KERNEL); +	if (skb == NULL) +		goto err; + +	if (frame_data_len <= IEEE80211_MAX_DATA_LEN) { +		/* Copy the data */ +		memcpy(skb_put(skb, frame_data_len), frame_data, +		       frame_data_len); +	} else +		goto err; + +	data2 = get_hwsim_data_ref_from_addr(dst); + +	if (data2 == NULL) +		goto out; + +	/* check if radio is configured properly */ + +	if (data2->idle || !data2->started || !data2->channel) +		goto out; + +	/*A frame is received from user space*/ +	memset(&rx_status, 0, sizeof(rx_status)); +	rx_status.freq = data2->channel->center_freq; +	rx_status.band = data2->channel->band; +	rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); +	rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); + +	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); +	ieee80211_rx_irqsafe(data2->hw, skb); + +	return 0; +err: +	printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__); +	goto out; +out: +	dev_kfree_skb(skb); +	return -EINVAL; +} + +static int hwsim_register_received_nl(struct sk_buff *skb_2, +				      struct genl_info *info) +{ +	if (info == NULL) +		goto out; + +	wmediumd_pid = info->snd_pid; + +	printk(KERN_DEBUG "mac80211_hwsim: received a REGISTER, " +	"switching to wmediumd mode with pid %d\n", info->snd_pid); + +	return 0; +out: +	printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__); +	return -EINVAL; +} + +/* Generic Netlink operations array */ +static struct genl_ops hwsim_ops[] = { +	{ +		.cmd = HWSIM_CMD_REGISTER, +		.policy = hwsim_genl_policy, +		.doit = hwsim_register_received_nl, +		.flags = GENL_ADMIN_PERM, +	}, +	{ +		.cmd = HWSIM_CMD_FRAME, +		.policy = hwsim_genl_policy, +		.doit = hwsim_cloned_frame_received_nl, +	}, +	{ +		.cmd = HWSIM_CMD_TX_INFO_FRAME, +		.policy = hwsim_genl_policy, +		.doit = hwsim_tx_info_frame_received_nl, +	}, +}; + +static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, +					 unsigned long state, +					 void *_notify) +{ +	struct netlink_notify *notify = _notify; + +	if (state != NETLINK_URELEASE) +		return NOTIFY_DONE; + +	if (notify->pid == wmediumd_pid) { +		printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink" +		       " socket, switching to perfect channel medium\n"); +		wmediumd_pid = 0; +	} +	return NOTIFY_DONE; + +} + +static struct notifier_block hwsim_netlink_notifier = { +	.notifier_call = mac80211_hwsim_netlink_notify, +}; + +static int hwsim_init_netlink(void) +{ +	int rc; +	printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); + +	wmediumd_pid = 0; + +	rc = genl_register_family_with_ops(&hwsim_genl_family, +		hwsim_ops, ARRAY_SIZE(hwsim_ops)); +	if (rc) +		goto failure; + +	rc = netlink_register_notifier(&hwsim_netlink_notifier); +	if (rc) +		goto failure; + +	return 0; + +failure: +	printk(KERN_DEBUG "mac80211_hwsim: error occured in %s\n", __func__); +	return -EINVAL; +} + +static void hwsim_exit_netlink(void) +{ +	int ret; + +	printk(KERN_INFO "mac80211_hwsim: closing netlink\n"); +	/* unregister the notifier */ +	netlink_unregister_notifier(&hwsim_netlink_notifier); +	/* unregister the family */ +	ret = genl_unregister_family(&hwsim_genl_family); +	if (ret) +		printk(KERN_DEBUG "mac80211_hwsim: " +		       "unregister family %i\n", ret); +} +  static int __init init_mac80211_hwsim(void)  {  	int i, err = 0; @@ -1298,6 +1708,7 @@ static int __init init_mac80211_hwsim(void)  			goto failed_drvdata;  		}  		data->dev->driver = &mac80211_hwsim_driver; +		skb_queue_head_init(&data->pending);  		SET_IEEE80211_DEV(hw, data->dev);  		addr[3] = i >> 8; @@ -1379,6 +1790,10 @@ static int __init init_mac80211_hwsim(void)  		data->group = 1;  		mutex_init(&data->mutex); +		/* Enable frame retransmissions for lossy channels */ +		hw->max_rates = 4; +		hw->max_rate_tries = 11; +  		/* Work to be done prior to ieee80211_register_hw() */  		switch (regtest) {  		case HWSIM_REGTEST_DISABLED: @@ -1515,12 +1930,29 @@ static int __init init_mac80211_hwsim(void)  	if (hwsim_mon == NULL)  		goto failed; -	err = register_netdev(hwsim_mon); +	rtnl_lock(); + +	err = dev_alloc_name(hwsim_mon, hwsim_mon->name);  	if (err < 0)  		goto failed_mon; + +	err = register_netdevice(hwsim_mon); +	if (err < 0) +		goto failed_mon; + +	rtnl_unlock(); + +	err = hwsim_init_netlink(); +	if (err < 0) +		goto failed_nl; +  	return 0; +failed_nl: +	printk(KERN_DEBUG "mac_80211_hwsim: failed initializing netlink\n"); +	return err; +  failed_mon:  	rtnl_unlock();  	free_netdev(hwsim_mon); @@ -1541,6 +1973,8 @@ static void __exit exit_mac80211_hwsim(void)  {  	printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n"); +	hwsim_exit_netlink(); +  	mac80211_hwsim_free();  	unregister_netdev(hwsim_mon);  } diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h new file mode 100644 index 00000000000..afaad5a443b --- /dev/null +++ b/drivers/net/wireless/mac80211_hwsim.h @@ -0,0 +1,133 @@ +/* + * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211 + * Copyright (c) 2008, Jouni Malinen <j@w1.fi> + * Copyright (c) 2011, Javier Lopez <jlopex@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __MAC80211_HWSIM_H +#define __MAC80211_HWSIM_H + +/** + * enum hwsim_tx_control_flags - flags to describe transmission info/status + * + * These flags are used to give the wmediumd extra information in order to + * modify its behavior for each frame + * + * @HWSIM_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame. + * @HWSIM_TX_CTL_NO_ACK: tell the wmediumd not to wait for an ack + * @HWSIM_TX_STAT_ACK: Frame was acknowledged + * + */ +enum hwsim_tx_control_flags { +	HWSIM_TX_CTL_REQ_TX_STATUS		= BIT(0), +	HWSIM_TX_CTL_NO_ACK			= BIT(1), +	HWSIM_TX_STAT_ACK			= BIT(2), +}; + +/** + * DOC: Frame transmission/registration support + * + * Frame transmission and registration support exists to allow userspace + * entities such as wmediumd to receive and process all broadcasted + * frames from a mac80211_hwsim radio device. + * + * This allow user space applications to decide if the frame should be + * dropped or not and implement a wireless medium simulator at user space. + * + * Registration is done by sending a register message to the driver and + * will be automatically unregistered if the user application doesn't + * responds to sent frames. + * Once registered the user application has to take responsibility of + * broadcasting the frames to all listening mac80211_hwsim radio + * interfaces. + * + * For more technical details, see the corresponding command descriptions + * below. + */ + +/** + * enum hwsim_commands - supported hwsim commands + * + * @HWSIM_CMD_UNSPEC: unspecified command to catch errors + * + * @HWSIM_CMD_REGISTER: request to register and received all broadcasted + *	frames by any mac80211_hwsim radio device. + * @HWSIM_CMD_FRAME: send/receive a broadcasted frame from/to kernel/user + * space, uses: + *	%HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER, + *	%HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE, + *	%HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE + * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to + * kernel, uses: + *	%HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, + *	%HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE + * @__HWSIM_CMD_MAX: enum limit + */ +enum { +	HWSIM_CMD_UNSPEC, +	HWSIM_CMD_REGISTER, +	HWSIM_CMD_FRAME, +	HWSIM_CMD_TX_INFO_FRAME, +	__HWSIM_CMD_MAX, +}; +#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) + +/** + * enum hwsim_attrs - hwsim netlink attributes + * + * @HWSIM_ATTR_UNSPEC: unspecified attribute to catch errors + * + * @HWSIM_ATTR_ADDR_RECEIVER: MAC address of the radio device that + *	the frame is broadcasted to + * @HWSIM_ATTR_ADDR_TRANSMITTER: MAC address of the radio device that + *	the frame was broadcasted from + * @HWSIM_ATTR_FRAME: Data array + * @HWSIM_ATTR_FLAGS: mac80211 transmission flags, used to process +	properly the frame at user space + * @HWSIM_ATTR_RX_RATE: estimated rx rate index for this frame at user +	space + * @HWSIM_ATTR_SIGNAL: estimated RX signal for this frame at user +	space + * @HWSIM_ATTR_TX_INFO: ieee80211_tx_rate array + * @HWSIM_ATTR_COOKIE: sk_buff cookie to identify the frame + * @__HWSIM_ATTR_MAX: enum limit + */ + + +enum { +	HWSIM_ATTR_UNSPEC, +	HWSIM_ATTR_ADDR_RECEIVER, +	HWSIM_ATTR_ADDR_TRANSMITTER, +	HWSIM_ATTR_FRAME, +	HWSIM_ATTR_FLAGS, +	HWSIM_ATTR_RX_RATE, +	HWSIM_ATTR_SIGNAL, +	HWSIM_ATTR_TX_INFO, +	HWSIM_ATTR_COOKIE, +	__HWSIM_ATTR_MAX, +}; +#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) + +/** + * struct hwsim_tx_rate - rate selection/status + * + * @idx: rate index to attempt to send with + * @count: number of tries in this rate before going to the next rate + * + * A value of -1 for @idx indicates an invalid rate and, if used + * in an array of retry rates, that no more rates should be tried. + * + * When used for transmit status reporting, the driver should + * always report the rate and number of retries used. + * + */ +struct hwsim_tx_rate { +	s8 idx; +	u8 count; +} __packed; + +#endif /* __MAC80211_HWSIM_H */ diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 916183d3900..34bba523429 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c @@ -185,13 +185,12 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,   *   * Handling includes changing the header fields into CPU format.   */ -int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf) +int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, +			struct mwifiex_ds_11n_tx_cfg *tx_cfg)  { -	struct mwifiex_ds_11n_tx_cfg *tx_cfg;  	struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg; -	if (data_buf) { -		tx_cfg = (struct mwifiex_ds_11n_tx_cfg *) data_buf; +	if (tx_cfg) {  		tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap);  		tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info);  	} @@ -208,11 +207,10 @@ int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)   */  int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,  			     struct host_cmd_ds_command *cmd, int cmd_action, -			     void *data_buf) +			     u16 *buf_size)  {  	struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf;  	u16 action = (u16) cmd_action; -	u16 buf_size = *((u16 *) data_buf);  	cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);  	cmd->size = @@ -220,8 +218,8 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,  	tx_buf->action = cpu_to_le16(action);  	switch (action) {  	case HostCmd_ACT_GEN_SET: -		dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", buf_size); -		tx_buf->buff_size = cpu_to_le16(buf_size); +		dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", *buf_size); +		tx_buf->buff_size = cpu_to_le16(*buf_size);  		break;  	case HostCmd_ACT_GEN_GET:  	default: @@ -240,13 +238,12 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,   *      - Ensuring correct endian-ness   */  int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, -				int cmd_action, void *data_buf) +				int cmd_action, +				struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl)  {  	struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =  		&cmd->params.amsdu_aggr_ctrl;  	u16 action = (u16) cmd_action; -	struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl = -		(struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;  	cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);  	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl) @@ -272,15 +269,13 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,   * Handling includes changing the header fields into CPU format.   */  int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, -				void *data_buf) +				struct mwifiex_ds_11n_amsdu_aggr_ctrl +				*amsdu_aggr_ctrl)  { -	struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl;  	struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =  		&resp->params.amsdu_aggr_ctrl; -	if (data_buf) { -		amsdu_aggr_ctrl = -			(struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf; +	if (amsdu_aggr_ctrl) {  		amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable);  		amsdu_aggr_ctrl->curr_buf_size =  			le16_to_cpu(amsdu_ctrl->curr_buf_size); @@ -296,12 +291,10 @@ int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,   *      - Setting HT Tx capability and HT Tx information fields   *      - Ensuring correct endian-ness   */ -int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, -			u16 cmd_action, void *data_buf) +int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, +			struct mwifiex_ds_11n_tx_cfg *txcfg)  {  	struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg; -	struct mwifiex_ds_11n_tx_cfg *txcfg = -		(struct mwifiex_ds_11n_tx_cfg *) data_buf;  	cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG);  	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN); diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index a4390a1a2a9..90b421e343d 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h @@ -29,9 +29,9 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,  int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,  			      struct host_cmd_ds_command *resp);  int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, -			void *data_buf); -int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, -			u16 cmd_action, void *data_buf); +			struct mwifiex_ds_11n_tx_cfg *tx_cfg); +int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, +			struct mwifiex_ds_11n_tx_cfg *txcfg);  int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,  			       struct mwifiex_bssdescriptor *bss_desc, @@ -62,12 +62,14 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,  int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,  			       struct mwifiex_ds_tx_ba_stream_tbl *buf);  int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, -				void *data_buf); +				struct mwifiex_ds_11n_amsdu_aggr_ctrl +				*amsdu_aggr_ctrl);  int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,  			     struct host_cmd_ds_command *cmd, -			     int cmd_action, void *data_buf); +			     int cmd_action, u16 *buf_size);  int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, -				int cmd_action, void *data_buf); +				int cmd_action, +				struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);  /*   * This function checks whether AMPDU is allowed or not for a particular TID. diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index f807447e4d9..1a453a605b3 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c @@ -164,12 +164,13 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,  	struct mwifiex_tx_param tx_param;  	struct txpd *ptx_pd = NULL; -	if (skb_queue_empty(&pra_list->skb_head)) { +	skb_src = skb_peek(&pra_list->skb_head); +	if (!skb_src) {  		spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,  				       ra_list_flags);  		return 0;  	} -	skb_src = skb_peek(&pra_list->skb_head); +  	tx_info_src = MWIFIEX_SKB_TXCB(skb_src);  	skb_aggr = dev_alloc_skb(adapter->tx_buf_size);  	if (!skb_aggr) { @@ -184,17 +185,15 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,  	tx_info_aggr->bss_index = tx_info_src->bss_index;  	skb_aggr->priority = skb_src->priority; -	while (skb_src && ((skb_headroom(skb_aggr) + skb_src->len -					+ LLC_SNAP_LEN) -				<= adapter->tx_buf_size)) { +	do { +		/* Check if AMSDU can accommodate this MSDU */ +		if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN)) +			break; -		if (!skb_queue_empty(&pra_list->skb_head)) -			skb_src = skb_dequeue(&pra_list->skb_head); -		else -			skb_src = NULL; +		skb_src = skb_dequeue(&pra_list->skb_head); -		if (skb_src) -			pra_list->total_pkts_size -= skb_src->len; +		pra_list->total_pkts_size -= skb_src->len; +		pra_list->total_pkts--;  		atomic_dec(&priv->wmm.tx_pkts_queued); @@ -212,11 +211,15 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,  			return -1;  		} -		if (!skb_queue_empty(&pra_list->skb_head)) -			skb_src = skb_peek(&pra_list->skb_head); -		else -			skb_src = NULL; -	} +		if (skb_tailroom(skb_aggr) < pad) { +			pad = 0; +			break; +		} +		skb_put(skb_aggr, pad); + +		skb_src = skb_peek(&pra_list->skb_head); + +	} while (skb_src);  	spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); @@ -230,11 +233,19 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,  	skb_push(skb_aggr, headroom); -	tx_param.next_pkt_len = ((pra_list->total_pkts_size) ? -				 (((pra_list->total_pkts_size) > -				   adapter->tx_buf_size) ? adapter-> -				  tx_buf_size : pra_list->total_pkts_size + -				  LLC_SNAP_LEN + sizeof(struct txpd)) : 0); +	/* +	 * Padding per MSDU will affect the length of next +	 * packet and hence the exact length of next packet +	 * is uncertain here. +	 * +	 * Also, aggregation of transmission buffer, while +	 * downloading the data to the card, wont gain much +	 * on the AMSDU packets as the AMSDU packets utilizes +	 * the transmission buffer space to the maximum +	 * (adapter->tx_buf_size). +	 */ +	tx_param.next_pkt_len = 0; +  	ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA,  					     skb_aggr->data,  					     skb_aggr->len, &tx_param); @@ -258,6 +269,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,  		skb_queue_tail(&pra_list->skb_head, skb_aggr);  		pra_list->total_pkts_size += skb_aggr->len; +		pra_list->total_pkts++;  		atomic_inc(&priv->wmm.tx_pkts_queued); diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index e5dfdc39a92..7aa9aa0ac95 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -328,13 +328,12 @@ int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf)   */  int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,  				  struct host_cmd_ds_command *cmd, -				  void *data_buf) +				  struct host_cmd_ds_11n_addba_req +				  *cmd_addba_req)  {  	struct host_cmd_ds_11n_addba_rsp *add_ba_rsp =  		(struct host_cmd_ds_11n_addba_rsp *)  		&cmd->params.add_ba_rsp; -	struct host_cmd_ds_11n_addba_req *cmd_addba_req = -		(struct host_cmd_ds_11n_addba_req *) data_buf;  	u8 tid;  	int win_size;  	uint16_t block_ack_param_set; diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index f3ca8c8c18f..033c8adbdcd 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -52,8 +52,9 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,  int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd,  			  void *data_buf);  int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, -				  struct host_cmd_ds_command -				  *cmd, void *data_buf); +				  struct host_cmd_ds_command *cmd, +				  struct host_cmd_ds_11n_addba_req +				  *cmd_addba_req);  int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd,  			      void *data_buf);  void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv); diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 660831ce293..352d2c5da1f 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -672,6 +672,59 @@ static const u32 mwifiex_cipher_suites[] = {  };  /* + * CFG802.11 operation handler for setting bit rates. + * + * Function selects legacy bang B/G/BG from corresponding bitrates selection. + * Currently only 2.4GHz band is supported. + */ +static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, +				struct net_device *dev, +				const u8 *peer, +				const struct cfg80211_bitrate_mask *mask) +{ +	struct mwifiex_ds_band_cfg band_cfg; +	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); +	int index = 0, mode = 0, i; + +	/* Currently only 2.4GHz is supported */ +	for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) { +		/* +		 * Rates below 6 Mbps in the table are CCK rates; 802.11b +		 * and from 6 they are OFDM; 802.11G +		 */ +		if (mwifiex_rates[i].bitrate == 60) { +			index = 1 << i; +			break; +		} +	} + +	if (mask->control[IEEE80211_BAND_2GHZ].legacy < index) { +		mode = BAND_B; +	} else { +		mode = BAND_G; +		if (mask->control[IEEE80211_BAND_2GHZ].legacy % index) +			mode |=  BAND_B; +	} + +	memset(&band_cfg, 0, sizeof(band_cfg)); +	band_cfg.config_bands = mode; + +	if (priv->bss_mode == NL80211_IFTYPE_ADHOC) +		band_cfg.adhoc_start_band = mode; + +	band_cfg.sec_chan_offset = NO_SEC_CHANNEL; + +	if (mwifiex_set_radio_band_cfg(priv, &band_cfg)) +		return -EFAULT; + +	wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n", +				(mode & BAND_B) ? "b" : "", +				(mode & BAND_G) ? "g" : ""); + +	return 0; +} + +/*   * CFG802.11 operation handler for disconnection request.   *   * This function does not work when there is already a disconnection @@ -960,7 +1013,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,  		ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);  	if (sme->key) { -		if (mwifiex_is_alg_wep(0) | mwifiex_is_alg_wep(0)) { +		if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {  			dev_dbg(priv->adapter->dev,  				"info: setting wep encryption"  				" with key len %d\n", sme->key_len); @@ -1225,6 +1278,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {  	.set_default_key = mwifiex_cfg80211_set_default_key,  	.set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,  	.set_tx_power = mwifiex_cfg80211_set_tx_power, +	.set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,  };  /* @@ -1288,6 +1342,8 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,  	*(unsigned long *) wdev_priv = (unsigned long) priv; +	set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev); +  	ret = wiphy_register(wdev->wiphy);  	if (ret < 0) {  		dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index cd89fed206a..b5352afb871 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -104,13 +104,11 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,   * main thread.   */  static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv, -				struct host_cmd_ds_command *cmd, void *data_buf) +				struct host_cmd_ds_command *cmd, +				struct mwifiex_ds_misc_cmd *pcmd_ptr)  { -	struct mwifiex_ds_misc_cmd *pcmd_ptr = -		(struct mwifiex_ds_misc_cmd *) data_buf; -  	/* Copy the HOST command to command buffer */ -	memcpy((void *) cmd, pcmd_ptr->cmd, pcmd_ptr->len); +	memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len);  	dev_dbg(priv->adapter->dev, "cmd: host cmd size = %d\n", pcmd_ptr->len);  	return 0;  } @@ -707,15 +705,14 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)  	if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {  		/* Copy original response back to response buffer */ -		struct mwifiex_ds_misc_cmd *hostcmd = NULL; +		struct mwifiex_ds_misc_cmd *hostcmd;  		uint16_t size = le16_to_cpu(resp->size);  		dev_dbg(adapter->dev, "info: host cmd resp size = %d\n", size);  		size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER);  		if (adapter->curr_cmd->data_buf) { -			hostcmd = (struct mwifiex_ds_misc_cmd *) -						adapter->curr_cmd->data_buf; +			hostcmd = adapter->curr_cmd->data_buf;  			hostcmd->len = size; -			memcpy(hostcmd->cmd, (void *) resp, size); +			memcpy(hostcmd->cmd, resp, size);  		}  	}  	orig_cmdresp_no = le16_to_cpu(resp->command); @@ -1155,7 +1152,7 @@ EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp);  int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,  			       struct host_cmd_ds_command *cmd,  			       u16 cmd_action, uint16_t ps_bitmap, -			       void *data_buf) +			       struct mwifiex_ds_auto_ds *auto_ds)  {  	struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =  		&cmd->params.psmode_enh; @@ -1218,9 +1215,8 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,  					sizeof(struct mwifiex_ie_types_header));  			cmd_size += sizeof(*auto_ds_tlv);  			tlv += sizeof(*auto_ds_tlv); -			if (data_buf) -				idletime = ((struct mwifiex_ds_auto_ds *) -					     data_buf)->idle_time; +			if (auto_ds) +				idletime = auto_ds->idle_time;  			dev_dbg(priv->adapter->dev,  					"cmd: PS Command: Enter Auto Deep Sleep\n");  			auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime); @@ -1239,7 +1235,7 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,   */  int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,  			       struct host_cmd_ds_command *resp, -			       void *data_buf) +			       struct mwifiex_ds_pm_cfg *pm_cfg)  {  	struct mwifiex_adapter *adapter = priv->adapter;  	struct host_cmd_ds_802_11_ps_mode_enh *ps_mode = @@ -1282,10 +1278,8 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,  		dev_dbg(adapter->dev, "cmd: ps_bitmap=%#x\n", ps_bitmap); -		if (data_buf) { +		if (pm_cfg) {  			/* This section is for get power save mode */ -			struct mwifiex_ds_pm_cfg *pm_cfg = -					(struct mwifiex_ds_pm_cfg *)data_buf;  			if (ps_bitmap & BITMAP_STA_PS)  				pm_cfg->param.ps_mode = 1;  			else diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 46d65e02c7b..1bcf9eaa107 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c @@ -27,8 +27,8 @@ static struct dentry *mwifiex_dfs_dir;  static char *bss_modes[] = {  	"Unknown", -	"Managed",  	"Ad-hoc", +	"Managed",  	"Auto"  }; diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 0e90b0986ed..94ddc9038cb 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -30,7 +30,9 @@  #define MWIFIEX_MAX_BSS_NUM         (1) -#define MWIFIEX_MIN_DATA_HEADER_LEN 32	/* (sizeof(mwifiex_txpd)) */ +#define MWIFIEX_MIN_DATA_HEADER_LEN 36	/* sizeof(mwifiex_txpd) +					 *   + 4 byte alignment +					 */  #define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED	2  #define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED	16 diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index afdd145dff0..4fee0993b18 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -157,6 +157,17 @@ enum MWIFIEX_802_11_WEP_STATUS {  #define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26))  #define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) +/* httxcfg bitmap + * 0		reserved + * 1		20/40 Mhz enable(1)/disable(0) + * 2-3		reserved + * 4		green field enable(1)/disable(0) + * 5		short GI in 20 Mhz enable(1)/disable(0) + * 6		short GI in 40 Mhz enable(1)/disable(0) + * 7-15		reserved + */ +#define MWIFIEX_FW_DEF_HTTXCFG (BIT(1) | BIT(4) | BIT(5) | BIT(6)) +  #define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f)  #define SETHT_MCS32(x) (x[4] |= 1) diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 5eab3dc29b1..644e2e405cb 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -364,10 +364,9 @@ static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv,   */  int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,  				 struct host_cmd_ds_command *cmd, -				 void *data_buf) +				 struct mwifiex_bssdescriptor *bss_desc)  {  	struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate; -	struct mwifiex_bssdescriptor *bss_desc;  	struct mwifiex_ie_types_ssid_param_set *ssid_tlv;  	struct mwifiex_ie_types_phy_param_set *phy_tlv;  	struct mwifiex_ie_types_ss_param_set *ss_tlv; @@ -380,7 +379,6 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,  	u8 *pos;  	int rsn_ie_len = 0; -	bss_desc = (struct mwifiex_bssdescriptor *) data_buf;  	pos = (u8 *) assoc;  	mwifiex_cfg_tx_buf(priv, bss_desc); @@ -748,7 +746,8 @@ done:   */  int  mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, -				struct host_cmd_ds_command *cmd, void *data_buf) +				struct host_cmd_ds_command *cmd, +				struct mwifiex_802_11_ssid *req_ssid)  {  	int rsn_ie_len = 0;  	struct mwifiex_adapter *adapter = priv->adapter; @@ -786,20 +785,15 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,  	memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN); -	memcpy(adhoc_start->ssid, -	       ((struct mwifiex_802_11_ssid *) data_buf)->ssid, -	       ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len); +	memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);  	dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n",  				adhoc_start->ssid);  	memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN); -	memcpy(bss_desc->ssid.ssid, -	       ((struct mwifiex_802_11_ssid *) data_buf)->ssid, -	       ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len); +	memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len); -	bss_desc->ssid.ssid_len = -		((struct mwifiex_802_11_ssid *) data_buf)->ssid_len; +	bss_desc->ssid.ssid_len = req_ssid->ssid_len;  	/* Set the BSS mode */  	adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS; @@ -1036,13 +1030,12 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,   */  int  mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, -			       struct host_cmd_ds_command *cmd, void *data_buf) +			       struct host_cmd_ds_command *cmd, +			       struct mwifiex_bssdescriptor *bss_desc)  {  	int rsn_ie_len = 0;  	struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =  		&cmd->params.adhoc_join; -	struct mwifiex_bssdescriptor *bss_desc = -		(struct mwifiex_bssdescriptor *) data_buf;  	struct mwifiex_ie_types_chan_list_param_set *chan_tlv;  	u32 cmd_append_size = 0;  	u16 tmp_cap; diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index f0582259c93..e5fc53dc688 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -26,17 +26,12 @@  const char driver_version[] = "mwifiex " VERSION " (%s) "; -struct mwifiex_adapter *g_adapter; -EXPORT_SYMBOL_GPL(g_adapter); -  static struct mwifiex_bss_attr mwifiex_bss_sta[] = {  	{MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0},  };  static int drv_mode = DRV_MODE_STA; -static char fw_name[32] = DEFAULT_FW_NAME; -  /* Supported drv_mode table */  static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {  	{ @@ -62,7 +57,8 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {   * proper cleanup before exiting.   */  static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, -			    struct mwifiex_drv_mode *drv_mode_ptr) +			    struct mwifiex_drv_mode *drv_mode_ptr, +			    void **padapter)  {  	struct mwifiex_adapter *adapter;  	int i; @@ -71,7 +67,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,  	if (!adapter)  		return -ENOMEM; -	g_adapter = adapter; +	*padapter = adapter;  	adapter->card = card;  	/* Save interface specific operations in adapter */ @@ -326,7 +322,7 @@ exit_main_proc:   * and initializing the private structures.   */  static int -mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops) +mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **padapter)  {  	int i;  	struct mwifiex_drv_mode *drv_mode_ptr; @@ -345,7 +341,7 @@ mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)  		return -1;  	} -	if (mwifiex_register(card, if_ops, drv_mode_ptr)) +	if (mwifiex_register(card, if_ops, drv_mode_ptr, padapter))  		return -1;  	return 0; @@ -384,20 +380,8 @@ static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)  	memset(&fw, 0, sizeof(struct mwifiex_fw_image)); -	switch (adapter->revision_id) { -	case SD8787_W0: -	case SD8787_W1: -		strcpy(fw_name, SD8787_W1_FW_NAME); -		break; -	case SD8787_A0: -	case SD8787_A1: -		strcpy(fw_name, SD8787_AX_FW_NAME); -		break; -	default: -		break; -	} - -	err = request_firmware(&adapter->firmware, fw_name, adapter->dev); +	err = request_firmware(&adapter->firmware, adapter->fw_name, +			       adapter->dev);  	if (err < 0) {  		dev_err(adapter->dev, "request_firmware() returned"  				" error code %#x\n", err); @@ -569,7 +553,7 @@ static int  mwifiex_set_mac_address(struct net_device *dev, void *addr)  {  	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); -	struct sockaddr *hw_addr = (struct sockaddr *) addr; +	struct sockaddr *hw_addr = addr;  	int ret;  	memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); @@ -869,13 +853,11 @@ mwifiex_add_card(void *card, struct semaphore *sem,  	if (down_interruptible(sem))  		goto exit_sem_err; -	if (mwifiex_init_sw(card, if_ops)) { +	if (mwifiex_init_sw(card, if_ops, (void **)&adapter)) {  		pr_err("%s: software init failed\n", __func__);  		goto err_init_sw;  	} -	adapter = g_adapter; -  	adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;  	adapter->surprise_removed = false;  	init_waitqueue_head(&adapter->init_wait_q); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 8316b3cd92c..03691c02a6e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -39,7 +39,6 @@  #include "fw.h"  extern const char driver_version[]; -extern struct mwifiex_adapter *g_adapter;  enum {  	MWIFIEX_ASYNC_CMD, @@ -48,15 +47,6 @@ enum {  #define DRV_MODE_STA       0x1 -#define SD8787_W0   0x30 -#define SD8787_W1   0x31 -#define SD8787_A0   0x40 -#define SD8787_A1   0x41 - -#define DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin" -#define SD8787_W1_FW_NAME "mrvl/sd8787_uapsta_w1.bin" -#define SD8787_AX_FW_NAME "mrvl/sd8787_uapsta.bin" -  struct mwifiex_drv_mode {  	u16 drv_mode;  	u16 intf_num; @@ -190,6 +180,7 @@ struct mwifiex_ra_list_tbl {  	struct sk_buff_head skb_head;  	u8 ra[ETH_ALEN];  	u32 total_pkts_size; +	u32 total_pkts;  	u32 is_11n_enabled;  }; @@ -576,10 +567,10 @@ struct mwifiex_adapter {  	u8 priv_num;  	struct mwifiex_drv_mode *drv_mode;  	const struct firmware *firmware; +	char fw_name[32];  	struct device *dev;  	bool surprise_removed;  	u32 fw_release_number; -	u32 revision_id;  	u16 init_wait_q_woken;  	wait_queue_head_t init_wait_q;  	void *card; @@ -745,10 +736,10 @@ void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *,  int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,  			       struct host_cmd_ds_command *cmd,  			       u16 cmd_action, uint16_t ps_bitmap, -			       void *data_buf); +			       struct mwifiex_ds_auto_ds *auto_ds);  int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,  			       struct host_cmd_ds_command *resp, -			       void *data_buf); +			       struct mwifiex_ds_pm_cfg *pm_cfg);  void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);  void mwifiex_hs_activated_event(struct mwifiex_private *priv,  					u8 activated); @@ -760,7 +751,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,  			    u16 cmd_action, u32 cmd_oid,  			    void *data_buf, void *cmd_buf);  int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, -				void *cmd_buf); +				struct host_cmd_ds_command *resp);  int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,  				  struct sk_buff *skb);  int mwifiex_process_sta_event(struct mwifiex_private *); @@ -769,7 +760,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);  int mwifiex_scan_networks(struct mwifiex_private *priv,  			  const struct mwifiex_user_scan_cfg *user_scan_in);  int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, -			    void *data_buf); +			    struct mwifiex_scan_cmd_config *scan_cfg);  void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,  			    struct cmd_ctrl_node *cmd_node);  int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, @@ -786,8 +777,8 @@ s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,  int mwifiex_associate(struct mwifiex_private *priv,  		      struct mwifiex_bssdescriptor *bss_desc);  int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, -				 struct host_cmd_ds_command -				 *cmd, void *data_buf); +				 struct host_cmd_ds_command *cmd, +				 struct mwifiex_bssdescriptor *bss_desc);  int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,  				 struct host_cmd_ds_command *resp);  void mwifiex_reset_connect_state(struct mwifiex_private *priv); @@ -800,10 +791,10 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,  		       struct mwifiex_bssdescriptor *bss_desc);  int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,  				    struct host_cmd_ds_command *cmd, -				    void *data_buf); +				    struct mwifiex_802_11_ssid *req_ssid);  int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,  				   struct host_cmd_ds_command *cmd, -				   void *data_buf); +				   struct mwifiex_bssdescriptor *bss_desc);  int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,  			      struct host_cmd_ds_command *resp);  int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 5c22860fb40..6f88c8ab5de 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -2357,12 +2357,10 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,   *      - Setting command ID, and proper size   *      - Ensuring correct endian-ness   */ -int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf) +int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, +			    struct mwifiex_scan_cmd_config *scan_cfg)  {  	struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan; -	struct mwifiex_scan_cmd_config *scan_cfg; - -	scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf;  	/* Set fixed field variables in scan command */  	scan_cmd->bss_mode = scan_cfg->bss_mode; diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index d425dbd91d1..711fa689a95 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -31,10 +31,27 @@  #define SDIO_VERSION	"1.0" +/* The mwifiex_sdio_remove() callback function is called when + * user removes this module from kernel space or ejects + * the card from the slot. The driver handles these 2 cases + * differently. + * If the user is removing the module, the few commands (FUNC_SHUTDOWN, + * HS_CANCEL etc.) are sent to the firmware. + * If the card is removed, there is no need to send these command. + * + * The variable 'user_rmmod' is used to distinguish these two + * scenarios. This flag is initialized as FALSE in case the card + * is removed, and will be set to TRUE for module removal when + * module_exit function is called. + */ +static u8 user_rmmod; +  static struct mwifiex_if_ops sdio_ops;  static struct semaphore add_remove_card_sem; +static int mwifiex_sdio_resume(struct device *dev); +  /*   * SDIO probe.   * @@ -93,17 +110,36 @@ static void  mwifiex_sdio_remove(struct sdio_func *func)  {  	struct sdio_mmc_card *card; +	struct mwifiex_adapter *adapter; +	int i;  	pr_debug("info: SDIO func num=%d\n", func->num); -	if (func) { -		card = sdio_get_drvdata(func); -		if (card) { -			mwifiex_remove_card(card->adapter, -					&add_remove_card_sem); -			kfree(card); -		} +	card = sdio_get_drvdata(func); +	if (!card) +		return; + +	adapter = card->adapter; +	if (!adapter || !adapter->priv_num) +		return; + +	if (user_rmmod) { +		if (adapter->is_suspended) +			mwifiex_sdio_resume(adapter->dev); + +		for (i = 0; i < adapter->priv_num; i++) +			if ((GET_BSS_ROLE(adapter->priv[i]) == +						MWIFIEX_BSS_ROLE_STA) && +					adapter->priv[i]->media_connected) +				mwifiex_deauthenticate(adapter->priv[i], NULL); + +		mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, +						MWIFIEX_BSS_ROLE_ANY), +					 MWIFIEX_FUNC_SHUTDOWN);  	} + +	mwifiex_remove_card(card->adapter, &add_remove_card_sem); +	kfree(card);  }  /* @@ -1531,6 +1567,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)  	sdio_set_drvdata(func, card);  	adapter->dev = &func->dev; +	strcpy(adapter->fw_name, SD8787_DEFAULT_FW_NAME);  	return 0; @@ -1552,7 +1589,6 @@ disable_func:   *        the first interrupt got from bootloader   *      - Disable host interrupt mask register   *      - Get SDIO port - *      - Get revision ID   *      - Initialize SDIO variables in card   *      - Allocate MP registers   *      - Allocate MPA Tx and Rx buffers @@ -1576,10 +1612,6 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)  	/* Get SDIO ioport */  	mwifiex_init_sdio_ioport(adapter); -	/* Get revision ID */ -#define REV_ID_REG	0x5c -	mwifiex_read_reg(adapter, REV_ID_REG, &adapter->revision_id); -  	/* Initialize SDIO variables in card */  	card->mp_rd_bitmap = 0;  	card->mp_wr_bitmap = 0; @@ -1700,6 +1732,9 @@ mwifiex_sdio_init_module(void)  {  	sema_init(&add_remove_card_sem, 1); +	/* Clear the flag in case user removes the card. */ +	user_rmmod = 0; +  	return sdio_register_driver(&mwifiex_sdio);  } @@ -1715,32 +1750,12 @@ mwifiex_sdio_init_module(void)  static void  mwifiex_sdio_cleanup_module(void)  { -	struct mwifiex_adapter *adapter = g_adapter; -	int i; - -	if (down_interruptible(&add_remove_card_sem)) -		goto exit_sem_err; - -	if (!adapter || !adapter->priv_num) -		goto exit; - -	if (adapter->is_suspended) -		mwifiex_sdio_resume(adapter->dev); - -	for (i = 0; i < adapter->priv_num; i++) -		if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) && -		    adapter->priv[i]->media_connected) -			mwifiex_deauthenticate(adapter->priv[i], NULL); - -	if (!adapter->surprise_removed) -		mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, -							  MWIFIEX_BSS_ROLE_ANY), -					 MWIFIEX_FUNC_SHUTDOWN); +	if (!down_interruptible(&add_remove_card_sem)) +		up(&add_remove_card_sem); -exit: -	up(&add_remove_card_sem); +	/* Set the flag as user is removing this module. */ +	user_rmmod = 1; -exit_sem_err:  	sdio_unregister_driver(&mwifiex_sdio);  } @@ -1751,4 +1766,4 @@ MODULE_AUTHOR("Marvell International Ltd.");  MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION);  MODULE_VERSION(SDIO_VERSION);  MODULE_LICENSE("GPL v2"); -MODULE_FIRMWARE("sd8787.bin"); +MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 4e97e90aa39..524f78f4ee6 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h @@ -28,6 +28,8 @@  #include "main.h" +#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin" +  #define BLOCK_MODE	1  #define BYTE_MODE	0 @@ -52,10 +54,10 @@  #define SDIO_MP_AGGR_DEF_PKT_LIMIT	8 -#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE        (4096)	/* 4K */ +#define SDIO_MP_TX_AGGR_DEF_BUF_SIZE        (8192)	/* 8K */  /* Multi port RX aggregation buffer size */ -#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE        (4096)	/* 4K */ +#define SDIO_MP_RX_AGGR_DEF_BUF_SIZE        (16384)	/* 16K */  /* Misc. Config Register : Auto Re-enable interrupts */  #define AUTO_RE_ENABLE_INT              BIT(4) diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 8af3a78d272..c54ee287b87 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -67,10 +67,9 @@ mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv,   */  static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,  				   struct host_cmd_ds_command *cmd, -				   u16 cmd_action, void *data_buf) +				   u16 cmd_action, u16 *action)  {  	struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl; -	u16 action = *((u16 *) data_buf);  	if (cmd_action != HostCmd_ACT_GEN_SET) {  		dev_err(priv->adapter->dev, @@ -81,7 +80,7 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,  	cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL);  	cmd->size =  		cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN); -	mac_ctrl->action = cpu_to_le16(action); +	mac_ctrl->action = cpu_to_le16(*action);  	return 0;  } @@ -104,10 +103,9 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,  static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,  				       struct host_cmd_ds_command *cmd,  				       u16 cmd_action, u32 cmd_oid, -				       void *data_buf) +				       u32 *ul_temp)  {  	struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib; -	u32 ul_temp;  	dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);  	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB); @@ -127,9 +125,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,  		if (cmd_action == HostCmd_ACT_GEN_SET) {  			snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);  			snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); -			ul_temp = *((u32 *) data_buf);  			*((__le16 *) (snmp_mib->value)) = -				cpu_to_le16((u16) ul_temp); +				cpu_to_le16((u16) *ul_temp);  			cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)  				+ sizeof(u16));  		} @@ -139,9 +136,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,  		if (cmd_action == HostCmd_ACT_GEN_SET) {  			snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);  			snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); -			ul_temp = *((u32 *) data_buf);  			*(__le16 *) (snmp_mib->value) = -				cpu_to_le16((u16) ul_temp); +				cpu_to_le16((u16) *ul_temp);  			cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)  				+ sizeof(u16));  		} @@ -152,9 +148,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,  		if (cmd_action == HostCmd_ACT_GEN_SET) {  			snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);  			snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); -			ul_temp = (*(u32 *) data_buf);  			*((__le16 *) (snmp_mib->value)) = -				cpu_to_le16((u16) ul_temp); +				cpu_to_le16((u16) *ul_temp);  			cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)  				+ sizeof(u16));  		} @@ -164,9 +159,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,  		if (cmd_action == HostCmd_ACT_GEN_SET) {  			snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);  			snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); -			ul_temp = *(u32 *) data_buf;  			*((__le16 *) (snmp_mib->value)) = -				cpu_to_le16((u16) ul_temp); +				cpu_to_le16((u16) *ul_temp);  			cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)  				+ sizeof(u16));  		} @@ -209,13 +203,11 @@ mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd)   */  static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,  				   struct host_cmd_ds_command *cmd, -				   u16 cmd_action, void *data_buf) +				   u16 cmd_action, u16 *pbitmap_rates)  {  	struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg;  	struct mwifiex_rate_scope *rate_scope;  	struct mwifiex_rate_drop_pattern *rate_drop; -	u16 *pbitmap_rates = (u16 *) data_buf; -  	u32 i;  	cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG); @@ -272,10 +264,10 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,   *      - Ensuring correct endian-ness   */  static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd, -				    u16 cmd_action, void *data_buf) +				    u16 cmd_action, +				    struct host_cmd_ds_txpwr_cfg *txp)  {  	struct mwifiex_types_power_group *pg_tlv; -	struct host_cmd_ds_txpwr_cfg *txp;  	struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg;  	cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG); @@ -283,12 +275,11 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,  		cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg));  	switch (cmd_action) {  	case HostCmd_ACT_GEN_SET: -		txp = (struct host_cmd_ds_txpwr_cfg *) data_buf;  		if (txp->mode) {  			pg_tlv = (struct mwifiex_types_power_group -				  *) ((unsigned long) data_buf + +				  *) ((unsigned long) txp +  				     sizeof(struct host_cmd_ds_txpwr_cfg)); -			memmove(cmd_txp_cfg, data_buf, +			memmove(cmd_txp_cfg, txp,  				sizeof(struct host_cmd_ds_txpwr_cfg) +  				sizeof(struct mwifiex_types_power_group) +  				pg_tlv->length); @@ -300,8 +291,7 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,  				  sizeof(struct mwifiex_types_power_group) +  				  pg_tlv->length);  		} else { -			memmove(cmd_txp_cfg, data_buf, -				sizeof(struct host_cmd_ds_txpwr_cfg)); +			memmove(cmd_txp_cfg, txp, sizeof(*txp));  		}  		cmd_txp_cfg->action = cpu_to_le16(cmd_action);  		break; @@ -322,22 +312,23 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,   *        (as required)   *      - Ensuring correct endian-ness   */ -static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, -				     struct host_cmd_ds_command *cmd, -				     u16 cmd_action, -				     struct mwifiex_hs_config_param *data_buf) +static int +mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, +			  struct host_cmd_ds_command *cmd, +			  u16 cmd_action, +			  struct mwifiex_hs_config_param *hscfg_param)  {  	struct mwifiex_adapter *adapter = priv->adapter;  	struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;  	u16 hs_activate = false; -	if (data_buf == NULL) +	if (!hscfg_param)  		/* New Activate command */  		hs_activate = true;  	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);  	if (!hs_activate && -	    (data_buf->conditions +	    (hscfg_param->conditions  	    != cpu_to_le32(HOST_SLEEP_CFG_CANCEL))  	    && ((adapter->arp_filter_size > 0)  		&& (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { @@ -359,9 +350,9 @@ static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,  		hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED;  	} else {  		hs_cfg->action = cpu_to_le16(HS_CONFIGURE); -		hs_cfg->params.hs_config.conditions = data_buf->conditions; -		hs_cfg->params.hs_config.gpio = data_buf->gpio; -		hs_cfg->params.hs_config.gap = data_buf->gap; +		hs_cfg->params.hs_config.conditions = hscfg_param->conditions; +		hs_cfg->params.hs_config.gpio = hscfg_param->gpio; +		hs_cfg->params.hs_config.gap = hscfg_param->gap;  		dev_dbg(adapter->dev,  			"cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",  		       hs_cfg->params.hs_config.conditions, @@ -405,11 +396,11 @@ static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv,   *      - Setting MAC multicast address   *      - Ensuring correct endian-ness   */ -static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd, -					 u16 cmd_action, void *data_buf) +static int +mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd, +			      u16 cmd_action, +			      struct mwifiex_multicast_list *mcast_list)  { -	struct mwifiex_multicast_list *mcast_list = -		(struct mwifiex_multicast_list *) data_buf;  	struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr;  	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) + @@ -435,7 +426,7 @@ static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,   */  static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,  					     struct host_cmd_ds_command *cmd, -					     void *data_buf) +					     u8 *mac)  {  	struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth; @@ -444,7 +435,7 @@ static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,  				+ S_DS_GEN);  	/* Set AP MAC address */ -	memcpy(deauth->mac_addr, (u8 *) data_buf, ETH_ALEN); +	memcpy(deauth->mac_addr, mac, ETH_ALEN);  	dev_dbg(priv->adapter->dev, "cmd: Deauth: %pM\n", deauth->mac_addr); @@ -543,15 +534,14 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,   *        encryption (TKIP, AES) (as required)   *      - Ensuring correct endian-ness   */ -static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, -					   struct host_cmd_ds_command *cmd, -					   u16 cmd_action, -					   u32 cmd_oid, void *data_buf) +static int +mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, +				struct host_cmd_ds_command *cmd, +				u16 cmd_action, u32 cmd_oid, +				struct mwifiex_ds_encrypt_key *enc_key)  {  	struct host_cmd_ds_802_11_key_material *key_material =  		&cmd->params.key_material; -	struct mwifiex_ds_encrypt_key *enc_key = -		(struct mwifiex_ds_encrypt_key *) data_buf;  	u16 key_param_len = 0;  	int ret = 0;  	const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -741,7 +731,7 @@ static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv,   */  static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,  					 struct host_cmd_ds_command *cmd, -					 u16 cmd_action, void *data_buf) +					 u16 cmd_action, u16 *channel)  {  	struct host_cmd_ds_802_11_rf_channel *rf_chan =  		&cmd->params.rf_channel; @@ -759,7 +749,7 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,  		rf_type = le16_to_cpu(rf_chan->rf_type);  		SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset); -		rf_chan->current_channel = cpu_to_le16(*((u16 *) data_buf)); +		rf_chan->current_channel = cpu_to_le16(*channel);  	}  	rf_chan->action = cpu_to_le16(cmd_action);  	return 0; @@ -774,11 +764,10 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,   *      - Ensuring correct endian-ness   */  static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd, -					      u16 cmd_action, void *data_buf) +					      u16 cmd_action, u16 *enable)  {  	struct host_cmd_ds_802_11_ibss_status *ibss_coal =  		&(cmd->params.ibss_coalescing); -	u16 enable = 0;  	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);  	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) + @@ -788,9 +777,10 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,  	switch (cmd_action) {  	case HostCmd_ACT_GEN_SET: -		if (data_buf != NULL) -			enable = *(u16 *) data_buf; -		ibss_coal->enable = cpu_to_le16(enable); +		if (enable) +			ibss_coal->enable = cpu_to_le16(*enable); +		else +			ibss_coal->enable = 0;  		break;  		/* In other case.. Nothing to do */ @@ -822,9 +812,8 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,  static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,  				  u16 cmd_action, void *data_buf)  { -	struct mwifiex_ds_reg_rw *reg_rw; +	struct mwifiex_ds_reg_rw *reg_rw = data_buf; -	reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;  	switch (le16_to_cpu(cmd->command)) {  	case HostCmd_CMD_MAC_REG_ACCESS:  	{ @@ -893,8 +882,7 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,  	}  	case HostCmd_CMD_802_11_EEPROM_ACCESS:  	{ -		struct mwifiex_ds_read_eeprom *rd_eeprom = -			(struct mwifiex_ds_read_eeprom *) data_buf; +		struct mwifiex_ds_read_eeprom *rd_eeprom = data_buf;  		struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =  			(struct host_cmd_ds_802_11_eeprom_access *)  			&cmd->params.eeprom; @@ -923,8 +911,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,  			    u16 cmd_action, u32 cmd_oid,  			    void *data_buf, void *cmd_buf)  { -	struct host_cmd_ds_command *cmd_ptr = -		(struct host_cmd_ds_command *) cmd_buf; +	struct host_cmd_ds_command *cmd_ptr = cmd_buf;  	int ret = 0;  	/* Prepare command */ @@ -1126,6 +1113,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)  	struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl;  	struct mwifiex_ds_auto_ds auto_ds;  	enum state_11d_t state_11d; +	struct mwifiex_ds_11n_tx_cfg tx_cfg;  	if (first_sta) { @@ -1181,7 +1169,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)  	/* Send request to firmware */  	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL,  				     HostCmd_ACT_GEN_SET, 0, -				     (void *) &amsdu_aggr_ctrl); +				     &amsdu_aggr_ctrl);  	if (ret)  		return -1;  	/* MAC Control must be the last command in init_fw */ @@ -1211,8 +1199,15 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)  	if (ret)  		dev_err(priv->adapter->dev, "11D: failed to enable 11D\n"); +	/* Send cmd to FW to configure 11n specific configuration +	 * (Short GI, Channel BW, Green field support etc.) for transmit +	 */ +	tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG; +	ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_CFG, +				     HostCmd_ACT_GEN_SET, 0, &tx_cfg); +  	/* set last_init_cmd */ -	priv->adapter->last_init_cmd = HostCmd_CMD_802_11_SNMP_MIB; +	priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG;  	ret = -EINPROGRESS;  	return ret; diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index d08f76429a0..6804239d87b 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -120,11 +120,10 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,   */  static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,  					struct host_cmd_ds_command *resp, -					void *data_buf) +					struct mwifiex_ds_get_signal *signal)  {  	struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =  		&resp->params.rssi_info_rsp; -	struct mwifiex_ds_get_signal *signal;  	priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);  	priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); @@ -139,9 +138,8 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,  	priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);  	/* Need to indicate IOCTL complete */ -	if (data_buf) { -		signal = (struct mwifiex_ds_get_signal *) data_buf; -		memset(signal, 0, sizeof(struct mwifiex_ds_get_signal)); +	if (signal) { +		memset(signal, 0, sizeof(*signal));  		signal->selector = ALL_RSSI_INFO_MASK; @@ -185,7 +183,7 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,   */  static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,  				       struct host_cmd_ds_command *resp, -				       void *data_buf) +				       u32 *data_buf)  {  	struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;  	u16 oid = le16_to_cpu(smib->oid); @@ -198,7 +196,7 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,  	if (query_type == HostCmd_ACT_GEN_GET) {  		ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));  		if (data_buf) -			*(u32 *)data_buf = ul_temp; +			*data_buf = ul_temp;  		switch (oid) {  		case FRAG_THRESH_I:  			dev_dbg(priv->adapter->dev, @@ -228,14 +226,12 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,   */  static int mwifiex_ret_get_log(struct mwifiex_private *priv,  			       struct host_cmd_ds_command *resp, -			       void *data_buf) +			       struct mwifiex_ds_get_stats *stats)  {  	struct host_cmd_ds_802_11_get_log *get_log =  		(struct host_cmd_ds_802_11_get_log *) &resp->params.get_log; -	struct mwifiex_ds_get_stats *stats; -	if (data_buf) { -		stats = (struct mwifiex_ds_get_stats *) data_buf; +	if (stats) {  		stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);  		stats->failed = le32_to_cpu(get_log->failed);  		stats->retry = le32_to_cpu(get_log->retry); @@ -278,9 +274,8 @@ static int mwifiex_ret_get_log(struct mwifiex_private *priv,   */  static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,  				   struct host_cmd_ds_command *resp, -				   void *data_buf) +				   struct mwifiex_rate_cfg *ds_rate)  { -	struct mwifiex_rate_cfg *ds_rate;  	struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;  	struct mwifiex_rate_scope *rate_scope;  	struct mwifiex_ie_types_header *head; @@ -329,8 +324,7 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,  					  HostCmd_CMD_802_11_TX_RATE_QUERY,  					  HostCmd_ACT_GEN_GET, 0, NULL); -	if (data_buf) { -		ds_rate = (struct mwifiex_rate_cfg *) data_buf; +	if (ds_rate) {  		if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {  			if (priv->is_data_rate_auto) {  				ds_rate->is_rate_auto = 1; @@ -413,8 +407,7 @@ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)   * and saving the current Tx power level in driver.   */  static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, -				    struct host_cmd_ds_command *resp, -				    void *data_buf) +				    struct host_cmd_ds_command *resp)  {  	struct mwifiex_adapter *adapter = priv->adapter;  	struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; @@ -631,7 +624,7 @@ static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,   */  static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,  					 struct host_cmd_ds_command *resp, -					 void *data_buf) +					 u16 *data_buf)  {  	struct host_cmd_ds_802_11_rf_channel *rf_channel =  		&resp->params.rf_channel; @@ -644,8 +637,9 @@ static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,  		/* Update the channel again */  		priv->curr_bss_params.bss_descriptor.channel = new_channel;  	} +  	if (data_buf) -		*((u16 *)data_buf) = new_channel; +		*data_buf = new_channel;  	return 0;  } @@ -658,13 +652,11 @@ static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,   */  static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,  			       struct host_cmd_ds_command *resp, -			       void *data_buf) +			       struct host_cmd_ds_version_ext *version_ext)  {  	struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; -	struct host_cmd_ds_version_ext *version_ext; -	if (data_buf) { -		version_ext = (struct host_cmd_ds_version_ext *)data_buf; +	if (version_ext) {  		version_ext->version_str_sel = ver_ext->version_str_sel;  		memcpy(version_ext->version_str, ver_ext->version_str,  		       sizeof(char) * 128); @@ -686,8 +678,8 @@ static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,  	struct mwifiex_ds_read_eeprom *eeprom;  	if (data_buf) { -		reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; -		eeprom = (struct mwifiex_ds_read_eeprom *) data_buf; +		reg_rw = data_buf; +		eeprom = data_buf;  		switch (type) {  		case HostCmd_CMD_MAC_REG_ACCESS:  			{ @@ -825,13 +817,11 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,   * This is a generic function, which calls command specific   * response handlers based on the command ID.   */ -int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, -				u16 cmdresp_no, void *cmd_buf) +int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, +				struct host_cmd_ds_command *resp)  {  	int ret = 0;  	struct mwifiex_adapter *adapter = priv->adapter; -	struct host_cmd_ds_command *resp = -		(struct host_cmd_ds_command *) cmd_buf;  	void *data_buf = adapter->curr_cmd->data_buf;  	/* If the command is not successful, cleanup and return failure */ @@ -865,7 +855,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,  			"info: CMD_RESP: BG_SCAN result is ready!\n");  		break;  	case HostCmd_CMD_TXPWR_CFG: -		ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf); +		ret = mwifiex_ret_tx_power_cfg(priv, resp);  		break;  	case HostCmd_CMD_802_11_PS_MODE_ENH:  		ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf); diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index 1fdddece747..27430512f7c 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -187,7 +187,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,  	ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num,  					     local_rx_pd->priority, ta,  					     (u8) local_rx_pd->rx_pkt_type, -						(void *) skb); +					     skb);  	if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {  		if (priv && (ret == -1)) diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index fa6221bc910..1822bfad889 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -47,6 +47,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,  	struct mwifiex_adapter *adapter = priv->adapter;  	struct txpd *local_tx_pd;  	struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); +	u8 pad;  	if (!skb->len) {  		dev_err(adapter->dev, "Tx: bad packet length: %d\n", @@ -55,15 +56,19 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,  		return skb->data;  	} -	BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN)); -	skb_push(skb, sizeof(*local_tx_pd)); +	/* If skb->data is not aligned; add padding */ +	pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4; + +	BUG_ON(skb_headroom(skb) < (sizeof(*local_tx_pd) + INTF_HEADER_LEN +								+ pad)); +	skb_push(skb, sizeof(*local_tx_pd) + pad);  	local_tx_pd = (struct txpd *) skb->data;  	memset(local_tx_pd, 0, sizeof(struct txpd));  	local_tx_pd->bss_num = priv->bss_num;  	local_tx_pd->bss_type = priv->bss_type;  	local_tx_pd->tx_pkt_length = cpu_to_le16((u16) (skb->len - -							sizeof(struct txpd))); +						(sizeof(struct txpd) + pad)));  	local_tx_pd->priority = (u8) skb->priority;  	local_tx_pd->pkt_delay_2ms = @@ -88,7 +93,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv,  	}  	/* Offset of actual data */ -	local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); +	local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) + pad);  	/* make space for INTF_HEADER_LEN */  	skb_push(skb, INTF_HEADER_LEN); diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index aaa50c07419..6190b2fa57a 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -71,7 +71,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,  	u8 *head_ptr;  	struct txpd *local_tx_pd = NULL; -	head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb); +	head_ptr = mwifiex_process_sta_txpd(priv, skb);  	if (head_ptr) {  		if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)  			local_tx_pd = diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 91634daec30..67b2d0b78c7 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -121,6 +121,7 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)  	memcpy(ra_list->ra, ra, ETH_ALEN);  	ra_list->total_pkts_size = 0; +	ra_list->total_pkts = 0;  	dev_dbg(adapter->dev, "info: allocated ra_list %p\n", ra_list); @@ -645,6 +646,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_adapter *adapter,  	skb_queue_tail(&ra_list->skb_head, skb);  	ra_list->total_pkts_size += skb->len; +	ra_list->total_pkts++;  	atomic_inc(&priv->wmm.tx_pkts_queued); @@ -971,28 +973,6 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,  }  /* - * This function gets the number of packets in the Tx queue of a - * particular RA list. - */ -static int -mwifiex_num_pkts_in_txq(struct mwifiex_private *priv, -			struct mwifiex_ra_list_tbl *ptr, int max_buf_size) -{ -	int count = 0, total_size = 0; -	struct sk_buff *skb, *tmp; - -	skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { -		total_size += skb->len; -		if (total_size < max_buf_size) -			++count; -		else -			break; -	} - -	return count; -} - -/*   * This function sends a single packet to firmware for transmission.   */  static void @@ -1019,6 +999,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,  	dev_dbg(adapter->dev, "data: dequeuing the packet %p %p\n", ptr, skb);  	ptr->total_pkts_size -= skb->len; +	ptr->total_pkts--;  	if (!skb_queue_empty(&ptr->skb_head))  		skb_next = skb_peek(&ptr->skb_head); @@ -1044,6 +1025,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,  		skb_queue_tail(&ptr->skb_head, skb);  		ptr->total_pkts_size += skb->len; +		ptr->total_pkts++;  		tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;  		spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,  				       ra_list_flags); @@ -1231,9 +1213,9 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)  		}  /* Minimum number of AMSDU */  #define MIN_NUM_AMSDU 2 +  		if (mwifiex_is_amsdu_allowed(priv, tid) && -		    (mwifiex_num_pkts_in_txq(priv, ptr, adapter->tx_buf_size) >= -		     MIN_NUM_AMSDU)) +				(ptr->total_pkts >= MIN_NUM_AMSDU))  			mwifiex_11n_aggregate_pkt(priv, ptr, INTF_HEADER_LEN,  						  ptr_index, flags);  			/* ra_list_spinlock has been freed in diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 32261189bce..d633edbd979 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -10,6 +10,7 @@   */  #include <linux/init.h> +#include <linux/interrupt.h>  #include <linux/module.h>  #include <linux/kernel.h>  #include <linux/sched.h> @@ -2474,6 +2475,7 @@ struct mwl8k_cmd_set_hw_spec {   * faster client.   */  #define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY	0x00000400 +#define MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR	0x00000200  #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT		0x00000080  #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP	0x00000020  #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON		0x00000010 @@ -2510,7 +2512,8 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw)  	cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT |  				 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP |  				 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON | -				 MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY); +				 MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY | +				 MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR);  	cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);  	cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 62c6b2b37db..b0f233f1100 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -1958,7 +1958,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)  		evstat = hermes_read_regn(hw, EVSTAT);  		events = evstat & hw->inten; -	}; +	}  	orinoco_unlock(priv, &flags);  	return IRQ_HANDLED; diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h index ee9bc62a4fa..7aa509f7e38 100644 --- a/drivers/net/wireless/p54/p54pci.h +++ b/drivers/net/wireless/p54/p54pci.h @@ -1,5 +1,6 @@  #ifndef P54PCI_H  #define P54PCI_H +#include <linux/interrupt.h>  /*   * Defines for PCI based mac80211 Prism54 driver diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index ec2c75d77ce..5d0f61508a2 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -18,6 +18,7 @@   *   */ +#include <linux/hardirq.h>  #include <linux/module.h>  #include <linux/slab.h> diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index c4d0f19b7cb..c40403877f9 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -22,6 +22,7 @@  #ifndef _ISLPCI_DEV_H  #define _ISLPCI_DEV_H +#include <linux/irqreturn.h>  #include <linux/netdevice.h>  #include <linux/wireless.h>  #include <net/iw_handler.h> diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index b5e64d71b7a..9e68e0cb718 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -17,6 +17,7 @@   *   */ +#include <linux/interrupt.h>  #include <linux/module.h>  #include <linux/pci.h>  #include <linux/delay.h> diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index b2f8b8fd4d2..a0a7854facc 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -83,14 +83,12 @@ config RT2800PCI_RT33XX  config RT2800PCI_RT35XX  	bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)"  	depends on EXPERIMENTAL -	default n +	default y  	---help---  	  This adds support for rt35xx wireless chipset family to the  	  rt2800pci driver.  	  Supported chips: RT3060, RT3062, RT3562, RT3592 -	  Support for these devices is non-functional at the moment and is -	  intended for testers and developers.  config RT2800PCI_RT53XX         bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)" @@ -154,15 +152,12 @@ config RT2800USB_RT33XX  config RT2800USB_RT35XX  	bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)"  	depends on EXPERIMENTAL -	default n +	default y  	---help---  	  This adds support for rt35xx wireless chipset family to the  	  rt2800usb driver.  	  Supported chips: RT3572 -	  Support for these devices is non-functional at the moment and is -	  intended for testers and developers. -  config RT2800USB_RT53XX         bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"         depends on EXPERIMENTAL diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 937f9e8bf05..76bcc354797 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1723,6 +1723,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {  	.set_antenna		= rt2x00mac_set_antenna,  	.get_antenna		= rt2x00mac_get_antenna,  	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d27d7b8ba3b..c288d951c03 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -2016,6 +2016,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {  	.set_antenna		= rt2x00mac_set_antenna,  	.get_antenna		= rt2x00mac_get_antenna,  	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 15237c27548..53c5f878f61 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1827,6 +1827,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {  	.set_antenna		= rt2x00mac_set_antenna,  	.get_antenna		= rt2x00mac_get_antenna,  	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index f67bc9b31b2..c69a7d71f4c 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1740,6 +1740,7 @@ struct mac_iveiv_entry {  /*   * BBP 3: RX Antenna   */ +#define BBP3_RX_ADC				FIELD8(0x03)  #define BBP3_RX_ANTENNA			FIELD8(0x18)  #define BBP3_HT40_MINUS			FIELD8(0x20) @@ -1783,6 +1784,8 @@ struct mac_iveiv_entry {  #define RFCSR1_TX0_PD			FIELD8(0x08)  #define RFCSR1_RX1_PD			FIELD8(0x10)  #define RFCSR1_TX1_PD			FIELD8(0x20) +#define RFCSR1_RX2_PD			FIELD8(0x40) +#define RFCSR1_TX2_PD			FIELD8(0x80)  /*   * RFCSR 2: @@ -1790,15 +1793,25 @@ struct mac_iveiv_entry {  #define RFCSR2_RESCAL_EN		FIELD8(0x80)  /* + * FRCSR 5: + */ +#define RFCSR5_R1			FIELD8(0x0c) + +/*   * RFCSR 6:   */  #define RFCSR6_R1			FIELD8(0x03)  #define RFCSR6_R2			FIELD8(0x40) +#define RFCSR6_TXDIV		FIELD8(0x0c)  /*   * RFCSR 7:   */  #define RFCSR7_RF_TUNING		FIELD8(0x01) +#define RFCSR7_R02				FIELD8(0x07) +#define RFCSR7_R3				FIELD8(0x08) +#define RFCSR7_R45				FIELD8(0x30) +#define RFCSR7_R67				FIELD8(0xc0)  /*   * RFCSR 11: @@ -1809,11 +1822,13 @@ struct mac_iveiv_entry {   * RFCSR 12:   */  #define RFCSR12_TX_POWER		FIELD8(0x1f) +#define RFCSR12_DR0				FIELD8(0xe0)  /*   * RFCSR 13:   */  #define RFCSR13_TX_POWER		FIELD8(0x1f) +#define RFCSR13_DR0				FIELD8(0xe0)  /*   * RFCSR 15: @@ -2256,6 +2271,7 @@ struct mac_iveiv_entry {  #define MCU_ANT_SELECT			0X73  #define MCU_BBP_SIGNAL			0x80  #define MCU_POWER_SAVE			0x83 +#define MCU_BAND_SELECT		0x91  /*   * MCU mailbox tokens diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2a6aa85cc6c..84ab7d1acb6 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -401,7 +401,8 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,  		return -EBUSY;  	if (rt2x00_is_pci(rt2x00dev)) { -		if (rt2x00_rt(rt2x00dev, RT5390)) { +		if (rt2x00_rt(rt2x00dev, RT3572) || +		    rt2x00_rt(rt2x00dev, RT5390)) {  			rt2800_register_read(rt2x00dev, AUX_CTRL, ®);  			rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1);  			rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); @@ -600,49 +601,6 @@ void rt2800_process_rxwi(struct queue_entry *entry,  }  EXPORT_SYMBOL_GPL(rt2800_process_rxwi); -static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg) -{ -	__le32 *txwi; -	u32 word; -	int wcid, ack, pid; -	int tx_wcid, tx_ack, tx_pid; - -	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID); -	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); -	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); - -	/* -	 * This frames has returned with an IO error, -	 * so the status report is not intended for this -	 * frame. -	 */ -	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) { -		rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); -		return false; -	} - -	/* -	 * Validate if this TX status report is intended for -	 * this entry by comparing the WCID/ACK/PID fields. -	 */ -	txwi = rt2800_drv_get_txwi(entry); - -	rt2x00_desc_read(txwi, 1, &word); -	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); -	tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK); -	tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID); - -	if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) { -		WARNING(entry->queue->rt2x00dev, -			"TX status report missed for queue %d entry %d\n", -		entry->queue->qid, entry->entry_idx); -		rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); -		return false; -	} - -	return true; -} -  void rt2800_txdone_entry(struct queue_entry *entry, u32 status)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; @@ -725,45 +683,6 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)  }  EXPORT_SYMBOL_GPL(rt2800_txdone_entry); -void rt2800_txdone(struct rt2x00_dev *rt2x00dev) -{ -	struct data_queue *queue; -	struct queue_entry *entry; -	u32 reg; -	u8 qid; - -	while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { - -		/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus -		 * qid is guaranteed to be one of the TX QIDs -		 */ -		qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); -		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); -		if (unlikely(!queue)) { -			WARNING(rt2x00dev, "Got TX status for an unavailable " -					   "queue %u, dropping\n", qid); -			continue; -		} - -		/* -		 * Inside each queue, we process each entry in a chronological -		 * order. We first check that the queue is not empty. -		 */ -		entry = NULL; -		while (!rt2x00queue_empty(queue)) { -			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); -			if (rt2800_txdone_entry_check(entry, reg)) -				break; -		} - -		if (!entry || rt2x00queue_empty(queue)) -			break; - -		rt2800_txdone_entry(entry, reg); -	} -} -EXPORT_SYMBOL_GPL(rt2800_txdone); -  void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; @@ -1355,7 +1274,7 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,  			gf20_rate = gf40_rate = 0x0003;  		}  		break; -	}; +	}  	/* check for STAs not supporting greenfield mode */  	if (any_sta_nongf) @@ -1433,6 +1352,40 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,  }  EXPORT_SYMBOL_GPL(rt2800_config_erp); +static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; +	u16 eeprom; +	u8 led_ctrl, led_g_mode, led_r_mode; + +	rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); +	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { +		rt2x00_set_field32(®, GPIO_SWITCH_0, 1); +		rt2x00_set_field32(®, GPIO_SWITCH_1, 1); +	} else { +		rt2x00_set_field32(®, GPIO_SWITCH_0, 0); +		rt2x00_set_field32(®, GPIO_SWITCH_1, 0); +	} +	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); + +	rt2800_register_read(rt2x00dev, LED_CFG, ®); +	led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0; +	led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3; +	if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) || +	    led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) { +		rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); +		led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE); +		if (led_ctrl == 0 || led_ctrl > 0x40) { +			rt2x00_set_field32(®, LED_CFG_G_LED_MODE, led_g_mode); +			rt2x00_set_field32(®, LED_CFG_R_LED_MODE, led_r_mode); +			rt2800_register_write(rt2x00dev, LED_CFG, reg); +		} else { +			rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff, +					   (led_g_mode << 2) | led_r_mode, 1); +		} +	} +} +  static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,  				     enum antenna ant)  { @@ -1463,6 +1416,10 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)  	rt2800_bbp_read(rt2x00dev, 1, &r1);  	rt2800_bbp_read(rt2x00dev, 3, &r3); +	if (rt2x00_rt(rt2x00dev, RT3572) && +	    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) +		rt2800_config_3572bt_ant(rt2x00dev); +  	/*  	 * Configure the TX antenna.  	 */ @@ -1471,7 +1428,11 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)  		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);  		break;  	case 2: -		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); +		if (rt2x00_rt(rt2x00dev, RT3572) && +		    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) +			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1); +		else +			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);  		break;  	case 3:  		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); @@ -1496,7 +1457,15 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)  		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);  		break;  	case 2: -		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); +		if (rt2x00_rt(rt2x00dev, RT3572) && +		    test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { +			rt2x00_set_field8(&r3, BBP3_RX_ADC, 1); +			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, +				rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); +			rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B); +		} else { +			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); +		}  		break;  	case 3:  		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); @@ -1630,6 +1599,161 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,  	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);  } +static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	u8 rfcsr; +	u32 reg; + +	if (rf->channel <= 14) { +		rt2800_bbp_write(rt2x00dev, 25, 0x15); +		rt2800_bbp_write(rt2x00dev, 26, 0x85); +	} else { +		rt2800_bbp_write(rt2x00dev, 25, 0x09); +		rt2800_bbp_write(rt2x00dev, 26, 0xff); +	} + +	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); + +	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2); +	else +		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1); +	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1); +	else +		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2); +	rt2800_rfcsr_write(rt2x00dev, 5, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3); +		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, +				(info->default_power1 & 0x3) | +				((info->default_power1 & 0xC) << 1)); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7); +		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, +				(info->default_power1 & 0x3) | +				((info->default_power1 & 0xC) << 1)); +	} +	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3); +		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, +				(info->default_power2 & 0x3) | +				((info->default_power2 & 0xC) << 1)); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7); +		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, +				(info->default_power2 & 0x3) | +				((info->default_power2 & 0xC) << 1)); +	} +	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); +	if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) { +		if (rf->channel <= 14) { +			rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +			rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); +		} +		rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +		rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +	} else { +		switch (rt2x00dev->default_ant.tx_chain_num) { +		case 1: +			rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +		case 2: +			rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +			break; +		} + +		switch (rt2x00dev->default_ant.rx_chain_num) { +		case 1: +			rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +		case 2: +			rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +			break; +		} +	} +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); +	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); + +	rt2800_rfcsr_write(rt2x00dev, 24, +			      rt2x00dev->calibration[conf_is_ht40(conf)]); +	rt2800_rfcsr_write(rt2x00dev, 31, +			      rt2x00dev->calibration[conf_is_ht40(conf)]); + +	if (rf->channel <= 14) { +		rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); +		rt2800_rfcsr_write(rt2x00dev, 9, 0xc3); +		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x53); +		rt2800_rfcsr_write(rt2x00dev, 16, 0x4c); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +		rt2800_rfcsr_write(rt2x00dev, 19, 0x93); +		rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); +		rt2800_rfcsr_write(rt2x00dev, 25, 0x15); +		rt2800_rfcsr_write(rt2x00dev, 26, 0x85); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); +	} else { +		rt2800_rfcsr_write(rt2x00dev, 7, 0x14); +		rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); +		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 11, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x43); +		rt2800_rfcsr_write(rt2x00dev, 16, 0x7a); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +		if (rf->channel <= 64) { +			rt2800_rfcsr_write(rt2x00dev, 19, 0xb7); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf6); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); +		} else if (rf->channel <= 128) { +			rt2800_rfcsr_write(rt2x00dev, 19, 0x74); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf4); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +		} else { +			rt2800_rfcsr_write(rt2x00dev, 19, 0x72); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf3); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +		} +		rt2800_rfcsr_write(rt2x00dev, 26, 0x87); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x01); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x9f); +	} + +	rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); +	rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT7, 0); +	if (rf->channel <= 14) +		rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT7, 1); +	else +		rt2x00_set_field32(®, GPIO_CTRL_CFG_BIT7, 0); +	rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + +	rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); +	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); +}  #define RT5390_POWER_BOUND     0x27  #define RT5390_FREQ_OFFSET_BOUND       0x5f @@ -1748,9 +1872,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	    rt2x00_rf(rt2x00dev, RF3020) ||  	    rt2x00_rf(rt2x00dev, RF3021) ||  	    rt2x00_rf(rt2x00dev, RF3022) || -	    rt2x00_rf(rt2x00dev, RF3052) ||  	    rt2x00_rf(rt2x00dev, RF3320))  		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); +	else if (rt2x00_rf(rt2x00dev, RF3052)) +		rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info);  	else if (rt2x00_rf(rt2x00dev, RF5370) ||  		 rt2x00_rf(rt2x00dev, RF5390))  		rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); @@ -1777,7 +1902,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  			}  		}  	} else { -		rt2800_bbp_write(rt2x00dev, 82, 0xf2); +		if (rt2x00_rt(rt2x00dev, RT3572)) +			rt2800_bbp_write(rt2x00dev, 82, 0x94); +		else +			rt2800_bbp_write(rt2x00dev, 82, 0xf2);  		if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags))  			rt2800_bbp_write(rt2x00dev, 75, 0x46); @@ -1791,12 +1919,17 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14);  	rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg); +	if (rt2x00_rt(rt2x00dev, RT3572)) +		rt2800_rfcsr_write(rt2x00dev, 8, 0); +  	tx_pin = 0;  	/* Turn on unused PA or LNA when not using 1T or 1R */  	if (rt2x00dev->default_ant.tx_chain_num == 2) { -		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); -		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, +				   rf->channel > 14); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, +				   rf->channel <= 14);  	}  	/* Turn on unused PA or LNA when not using 1T or 1R */ @@ -1809,11 +1942,18 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); -	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); +	if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); +	else +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, +				   rf->channel <= 14);  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);  	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); +	if (rt2x00_rt(rt2x00dev, RT3572)) +		rt2800_rfcsr_write(rt2x00dev, 8, 0x80); +  	rt2800_bbp_read(rt2x00dev, 4, &bbp);  	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));  	rt2800_bbp_write(rt2x00dev, 4, bbp); @@ -2413,6 +2553,9 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);  		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030); +	} else if (rt2x00_rt(rt2x00dev, RT3572)) { +		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); +		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);  	} else if (rt2x00_rt(rt2x00dev, RT5390)) {  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); @@ -2799,6 +2942,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  	}  	if (rt2800_is_305x_soc(rt2x00dev) || +	    rt2x00_rt(rt2x00dev, RT3572) ||  	    rt2x00_rt(rt2x00dev, RT5390))  		rt2800_bbp_write(rt2x00dev, 31, 0x08); @@ -2828,6 +2972,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  	    rt2x00_rt(rt2x00dev, RT3071) ||  	    rt2x00_rt(rt2x00dev, RT3090) ||  	    rt2x00_rt(rt2x00dev, RT3390) || +	    rt2x00_rt(rt2x00dev, RT3572) ||  	    rt2x00_rt(rt2x00dev, RT5390)) {  		rt2800_bbp_write(rt2x00dev, 79, 0x13);  		rt2800_bbp_write(rt2x00dev, 80, 0x05); @@ -2868,6 +3013,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  	    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(rt2x00dev, RT3572) ||  	    rt2x00_rt(rt2x00dev, RT5390) ||  	    rt2800_is_305x_soc(rt2x00dev))  		rt2800_bbp_write(rt2x00dev, 103, 0xc0); @@ -2895,6 +3041,7 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  	if (rt2x00_rt(rt2x00dev, RT3071) ||  	    rt2x00_rt(rt2x00dev, RT3090) ||  	    rt2x00_rt(rt2x00dev, RT3390) || +	    rt2x00_rt(rt2x00dev, RT3572) ||  	    rt2x00_rt(rt2x00dev, RT5390)) {  		rt2800_bbp_read(rt2x00dev, 138, &value); @@ -3031,6 +3178,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  	    !rt2x00_rt(rt2x00dev, RT3071) &&  	    !rt2x00_rt(rt2x00dev, RT3090) &&  	    !rt2x00_rt(rt2x00dev, RT3390) && +	    !rt2x00_rt(rt2x00dev, RT3572) &&  	    !rt2x00_rt(rt2x00dev, RT5390) &&  	    !rt2800_is_305x_soc(rt2x00dev))  		return 0; @@ -3109,6 +3257,38 @@ static 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 (rt2x00_rt(rt2x00dev, RT3572)) { +		rt2800_rfcsr_write(rt2x00dev, 0, 0x70); +		rt2800_rfcsr_write(rt2x00dev, 1, 0x81); +		rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 3, 0x02); +		rt2800_rfcsr_write(rt2x00dev, 4, 0x4c); +		rt2800_rfcsr_write(rt2x00dev, 5, 0x05); +		rt2800_rfcsr_write(rt2x00dev, 6, 0x4a); +		rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); +		rt2800_rfcsr_write(rt2x00dev, 9, 0xc3); +		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); +		rt2800_rfcsr_write(rt2x00dev, 12, 0x70); +		rt2800_rfcsr_write(rt2x00dev, 13, 0x65); +		rt2800_rfcsr_write(rt2x00dev, 14, 0xa0); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x53); +		rt2800_rfcsr_write(rt2x00dev, 16, 0x4c); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +		rt2800_rfcsr_write(rt2x00dev, 18, 0xac); +		rt2800_rfcsr_write(rt2x00dev, 19, 0x93); +		rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); +		rt2800_rfcsr_write(rt2x00dev, 21, 0xd0); +		rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 23, 0x3c); +		rt2800_rfcsr_write(rt2x00dev, 24, 0x16); +		rt2800_rfcsr_write(rt2x00dev, 25, 0x15); +		rt2800_rfcsr_write(rt2x00dev, 26, 0x85); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); +		rt2800_rfcsr_write(rt2x00dev, 30, 0x09); +		rt2800_rfcsr_write(rt2x00dev, 31, 0x10);  	} else if (rt2800_is_305x_soc(rt2x00dev)) {  		rt2800_rfcsr_write(rt2x00dev, 0, 0x50);  		rt2800_rfcsr_write(rt2x00dev, 1, 0x01); @@ -3258,6 +3438,19 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  		rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®);  		rt2x00_set_field32(®, GPIO_SWITCH_5, 0);  		rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); +	} else if (rt2x00_rt(rt2x00dev, RT3572)) { +		rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); +		rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); +		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +		rt2800_register_write(rt2x00dev, LDO_CFG0, reg); +		msleep(1); +		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);  	}  	/* @@ -3270,7 +3463,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  			rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);  	} else if (rt2x00_rt(rt2x00dev, RT3071) ||  		   rt2x00_rt(rt2x00dev, RT3090) || -		   rt2x00_rt(rt2x00dev, RT3390)) { +		   rt2x00_rt(rt2x00dev, RT3390) || +		   rt2x00_rt(rt2x00dev, RT3572)) {  		rt2x00dev->calibration[0] =  			rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13);  		rt2x00dev->calibration[1] = diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index f2d15941c71..69deb3148ae 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -152,7 +152,6 @@ void rt2800_write_tx_data(struct queue_entry *entry,  			  struct txentry_desc *txdesc);  void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); -void rt2800_txdone(struct rt2x00_dev *rt2x00dev);  void rt2800_txdone_entry(struct queue_entry *entry, u32 status);  void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index cc4a54f571b..ebc17ad61de 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -219,7 +219,7 @@ static void rt2800pci_start_queue(struct data_queue *queue)  		break;  	default:  		break; -	}; +	}  }  static void rt2800pci_kick_queue(struct data_queue *queue) @@ -501,7 +501,9 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);  	rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); -	if (rt2x00_rt(rt2x00dev, RT5390)) { +	if (rt2x00_is_pcie(rt2x00dev) && +	    (rt2x00_rt(rt2x00dev, RT3572) || +	     rt2x00_rt(rt2x00dev, RT5390))) {  		rt2x00pci_register_read(rt2x00dev, AUX_CTRL, ®);  		rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1);  		rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); @@ -1029,6 +1031,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {  	.flush			= rt2x00mac_flush,  	.get_survey		= rt2800_get_survey,  	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2800_ops rt2800pci_rt2800_ops = { @@ -1158,6 +1161,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {  #endif  #ifdef CONFIG_RT2800PCI_RT53XX  	{ PCI_DEVICE(0x1814, 0x5390) }, +	{ PCI_DEVICE(0x1814, 0x539f) },  #endif  	{ 0, }  }; diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index ba82c972703..507559361d8 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -457,6 +457,87 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)  /*   * TX control handlers   */ +static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg) +{ +	__le32 *txwi; +	u32 word; +	int wcid, ack, pid; +	int tx_wcid, tx_ack, tx_pid; + +	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID); +	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); +	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); + +	/* +	 * This frames has returned with an IO error, +	 * so the status report is not intended for this +	 * frame. +	 */ +	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) { +		rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); +		return false; +	} + +	/* +	 * Validate if this TX status report is intended for +	 * this entry by comparing the WCID/ACK/PID fields. +	 */ +	txwi = rt2800usb_get_txwi(entry); + +	rt2x00_desc_read(txwi, 1, &word); +	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); +	tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK); +	tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID); + +	if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) { +		WARNING(entry->queue->rt2x00dev, +			"TX status report missed for queue %d entry %d\n", +		entry->queue->qid, entry->entry_idx); +		rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); +		return false; +	} + +	return true; +} + +static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; +	struct queue_entry *entry; +	u32 reg; +	u8 qid; + +	while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { + +		/* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus +		 * qid is guaranteed to be one of the TX QIDs +		 */ +		qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); +		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); +		if (unlikely(!queue)) { +			WARNING(rt2x00dev, "Got TX status for an unavailable " +					   "queue %u, dropping\n", qid); +			continue; +		} + +		/* +		 * Inside each queue, we process each entry in a chronological +		 * order. We first check that the queue is not empty. +		 */ +		entry = NULL; +		while (!rt2x00queue_empty(queue)) { +			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); +			if (rt2800usb_txdone_entry_check(entry, reg)) +				break; +		} + +		if (!entry || rt2x00queue_empty(queue)) +			break; + +		rt2800_txdone_entry(entry, reg); +	} +} +  static void rt2800usb_work_txdone(struct work_struct *work)  {  	struct rt2x00_dev *rt2x00dev = @@ -464,7 +545,7 @@ static void rt2800usb_work_txdone(struct work_struct *work)  	struct data_queue *queue;  	struct queue_entry *entry; -	rt2800_txdone(rt2x00dev); +	rt2800usb_txdone(rt2x00dev);  	/*  	 * Process any trailing TX status reports for IO failures, @@ -676,6 +757,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {  	.flush			= rt2x00mac_flush,  	.get_survey		= rt2800_get_survey,  	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2800_ops rt2800usb_rt2800_ops = { @@ -939,6 +1021,7 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x0df6, 0x0048) },  	{ USB_DEVICE(0x0df6, 0x0051) },  	{ USB_DEVICE(0x0df6, 0x005f) }, +	{ USB_DEVICE(0x0df6, 0x0060) },  	/* SMC */  	{ USB_DEVICE(0x083a, 0x6618) },  	{ USB_DEVICE(0x083a, 0x7511) }, @@ -971,6 +1054,8 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x0586, 0x341e) },  	{ USB_DEVICE(0x0586, 0x343e) },  #ifdef CONFIG_RT2800USB_RT33XX +	/* Belkin */ +	{ USB_DEVICE(0x050d, 0x945b) },  	/* Ralink */  	{ USB_DEVICE(0x148f, 0x3370) },  	{ USB_DEVICE(0x148f, 0x8070) }, @@ -995,6 +1080,7 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x148f, 0x3572) },  	/* Sitecom */  	{ USB_DEVICE(0x0df6, 0x0041) }, +	{ USB_DEVICE(0x0df6, 0x0062) },  	/* Toshiba */  	{ USB_DEVICE(0x0930, 0x0a07) },  	/* Zinwell */ @@ -1093,8 +1179,6 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x0df6, 0x004a) },  	{ USB_DEVICE(0x0df6, 0x004d) },  	{ USB_DEVICE(0x0df6, 0x0053) }, -	{ USB_DEVICE(0x0df6, 0x0060) }, -	{ USB_DEVICE(0x0df6, 0x0062) },  	/* SMC */  	{ USB_DEVICE(0x083a, 0xa512) },  	{ USB_DEVICE(0x083a, 0xc522) }, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c446db69bd3..f82bfeb79eb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -29,6 +29,7 @@  #define RT2X00_H  #include <linux/bitops.h> +#include <linux/interrupt.h>  #include <linux/skbuff.h>  #include <linux/workqueue.h>  #include <linux/firmware.h> @@ -1276,6 +1277,7 @@ int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);  int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);  void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,  			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); +bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw);  /*   * Driver allocation handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 1bb9d46077f..1ca4c7ffc18 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -45,11 +45,11 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)  	}  } -void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, +void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, +				       struct sk_buff *skb,  				       struct txentry_desc *txdesc)  { -	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;  	if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 939821b4af2..0955c941317 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -583,6 +583,18 @@ void rt2x00lib_rxdone(struct queue_entry *entry)  	rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);  	/* +	 * Check for valid size in case we get corrupted descriptor from +	 * hardware. +	 */ +	if (unlikely(rxdesc.size == 0 || +		     rxdesc.size > entry->queue->data_size)) { +		WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", +			rxdesc.size, entry->queue->data_size); +		dev_kfree_skb(entry->skb); +		goto renew_skb; +	} + +	/*  	 * The data behind the ieee80211 header must be  	 * aligned on a 4 byte boundary.  	 */ @@ -642,6 +654,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)  	ieee80211_rx_ni(rt2x00dev->hw, entry->skb); +renew_skb:  	/*  	 * Replace the skb with the freshly allocated one.  	 */ diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 322cc4f3de5..15cdc7e57fc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -336,7 +336,8 @@ static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,   */  #ifdef CONFIG_RT2X00_LIB_CRYPTO  enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key); -void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, +void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, +				       struct sk_buff *skb,  				       struct txentry_desc *txdesc);  unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,  				      struct sk_buff *skb); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 93bec140e59..8efab398352 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -818,3 +818,17 @@ void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,  	*rx_max = rt2x00dev->rx->limit;  }  EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam); + +bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct data_queue *queue; + +	tx_queue_for_each(rt2x00dev, queue) { +		if (!rt2x00queue_empty(queue)) +			return true; +	} + +	return false; +} +EXPORT_SYMBOL_GPL(rt2x00mac_tx_frames_pending); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index ab8c16f8bca..29edb9fbe6f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -200,20 +200,20 @@ void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)  	skb_pull(skb, l2pad);  } -static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, +static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, +						 struct sk_buff *skb,  						 struct txentry_desc *txdesc)  { -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); -	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;  	struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); -	unsigned long irqflags;  	if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))  		return;  	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); -	if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags)) +	if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags))  		return;  	/* @@ -227,23 +227,23 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,  	 * sequence counting per-frame, since those will override the  	 * sequence counter given by mac80211.  	 */ -	spin_lock_irqsave(&intf->seqlock, irqflags); +	spin_lock(&intf->seqlock);  	if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))  		intf->seqno += 0x10;  	hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);  	hdr->seq_ctrl |= cpu_to_le16(intf->seqno); -	spin_unlock_irqrestore(&intf->seqlock, irqflags); +	spin_unlock(&intf->seqlock);  } -static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry, +static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev, +						  struct sk_buff *skb,  						  struct txentry_desc *txdesc,  						  const struct rt2x00_rate *hwrate)  { -	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];  	unsigned int data_length;  	unsigned int duration; @@ -260,8 +260,8 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,  		txdesc->u.plcp.ifs = IFS_SIFS;  	/* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */ -	data_length = entry->skb->len + 4; -	data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb); +	data_length = skb->len + 4; +	data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);  	/*  	 * PLCP setup @@ -302,13 +302,14 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,  	}  } -static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry, +static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev, +						struct sk_buff *skb,  						struct txentry_desc *txdesc,  						const struct rt2x00_rate *hwrate)  { -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; -	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;  	if (tx_info->control.sta)  		txdesc->u.ht.mpdu_density = @@ -381,12 +382,12 @@ static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,  		txdesc->u.ht.txop = TXOP_HTTXOP;  } -static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, +static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, +					     struct sk_buff *skb,  					     struct txentry_desc *txdesc)  { -	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); -	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;  	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];  	struct ieee80211_rate *rate;  	const struct rt2x00_rate *hwrate = NULL; @@ -396,8 +397,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,  	/*  	 * Header and frame information.  	 */ -	txdesc->length = entry->skb->len; -	txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); +	txdesc->length = skb->len; +	txdesc->header_length = ieee80211_get_hdrlen_from_skb(skb);  	/*  	 * Check whether this frame is to be acked. @@ -472,13 +473,15 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,  	/*  	 * Apply TX descriptor handling by components  	 */ -	rt2x00crypto_create_tx_descriptor(entry, txdesc); -	rt2x00queue_create_tx_descriptor_seq(entry, txdesc); +	rt2x00crypto_create_tx_descriptor(rt2x00dev, skb, txdesc); +	rt2x00queue_create_tx_descriptor_seq(rt2x00dev, skb, txdesc);  	if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags)) -		rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate); +		rt2x00queue_create_tx_descriptor_ht(rt2x00dev, skb, txdesc, +						    hwrate);  	else -		rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); +		rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc, +						      hwrate);  }  static int rt2x00queue_write_tx_data(struct queue_entry *entry, @@ -556,33 +559,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  			       bool local)  {  	struct ieee80211_tx_info *tx_info; -	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); +	struct queue_entry *entry;  	struct txentry_desc txdesc;  	struct skb_frame_desc *skbdesc;  	u8 rate_idx, rate_flags; - -	if (unlikely(rt2x00queue_full(queue))) { -		ERROR(queue->rt2x00dev, -		      "Dropping frame due to full tx queue %d.\n", queue->qid); -		return -ENOBUFS; -	} - -	if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, -				      &entry->flags))) { -		ERROR(queue->rt2x00dev, -		      "Arrived at non-free entry in the non-full queue %d.\n" -		      "Please file bug report to %s.\n", -		      queue->qid, DRV_PROJECT); -		return -EINVAL; -	} +	int ret = 0;  	/*  	 * Copy all TX descriptor information into txdesc,  	 * after that we are free to use the skb->cb array  	 * for our information.  	 */ -	entry->skb = skb; -	rt2x00queue_create_tx_descriptor(entry, &txdesc); +	rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc);  	/*  	 * All information is retrieved from the skb->cb array, @@ -594,7 +582,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	rate_flags = tx_info->control.rates[0].flags;  	skbdesc = get_skb_frame_desc(skb);  	memset(skbdesc, 0, sizeof(*skbdesc)); -	skbdesc->entry = entry;  	skbdesc->tx_rate_idx = rate_idx;  	skbdesc->tx_rate_flags = rate_flags; @@ -623,9 +610,33 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	 * for PCI devices.  	 */  	if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags)) -		rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length); +		rt2x00queue_insert_l2pad(skb, txdesc.header_length);  	else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags)) -		rt2x00queue_align_frame(entry->skb); +		rt2x00queue_align_frame(skb); + +	spin_lock(&queue->tx_lock); + +	if (unlikely(rt2x00queue_full(queue))) { +		ERROR(queue->rt2x00dev, +		      "Dropping frame due to full tx queue %d.\n", queue->qid); +		ret = -ENOBUFS; +		goto out; +	} + +	entry = rt2x00queue_get_entry(queue, Q_INDEX); + +	if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, +				      &entry->flags))) { +		ERROR(queue->rt2x00dev, +		      "Arrived at non-free entry in the non-full queue %d.\n" +		      "Please file bug report to %s.\n", +		      queue->qid, DRV_PROJECT); +		ret = -EINVAL; +		goto out; +	} + +	skbdesc->entry = entry; +	entry->skb = skb;  	/*  	 * It could be possible that the queue was corrupted and this @@ -635,7 +646,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {  		clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);  		entry->skb = NULL; -		return -EIO; +		ret = -EIO; +		goto out;  	}  	set_bit(ENTRY_DATA_PENDING, &entry->flags); @@ -644,7 +656,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	rt2x00queue_write_tx_descriptor(entry, &txdesc);  	rt2x00queue_kick_tx_queue(queue, &txdesc); -	return 0; +out: +	spin_unlock(&queue->tx_lock); +	return ret;  }  int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev, @@ -698,7 +712,7 @@ int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,  	 * after that we are free to use the skb->cb array  	 * for our information.  	 */ -	rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); +	rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc);  	/*  	 * Fill in skb descriptor @@ -1185,6 +1199,7 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,  			     struct data_queue *queue, enum data_queue_qid qid)  {  	mutex_init(&queue->status_lock); +	spin_lock_init(&queue->tx_lock);  	spin_lock_init(&queue->index_lock);  	queue->rt2x00dev = rt2x00dev; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 167d45873dc..f2100f4ddcf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -54,7 +54,7 @@   * @QID_RX: RX queue   * @QID_OTHER: None of the above (don't use, only present for completeness)   * @QID_BEACON: Beacon queue (value unspecified, don't send it to device) - * @QID_ATIM: Atim queue (value unspeficied, don't send it to device) + * @QID_ATIM: Atim queue (value unspecified, don't send it to device)   */  enum data_queue_qid {  	QID_AC_VO = 0, @@ -432,6 +432,7 @@ enum data_queue_flags {   * @flags: Entry flags, see &enum queue_entry_flags.   * @status_lock: The mutex for protecting the start/stop/flush   *	handling on this queue. + * @tx_lock: Spinlock to serialize tx operations on this queue.   * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or   *	@index_crypt needs to be changed this lock should be grabbed to prevent   *	index corruption due to concurrency. @@ -458,6 +459,7 @@ struct data_queue {  	unsigned long flags;  	struct mutex status_lock; +	spinlock_t tx_lock;  	spinlock_t index_lock;  	unsigned int count; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 8f90f626807..b6b4542c246 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -802,6 +802,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,  	int retval;  	usb_dev = usb_get_dev(usb_dev); +	usb_reset_device(usb_dev);  	hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);  	if (!hw) { diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 9d35ec16a3a..53110b83bf6 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2982,6 +2982,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {  	.set_antenna		= rt2x00mac_set_antenna,  	.get_antenna		= rt2x00mac_get_antenna,  	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ad20953cbf0..6a93939f44e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2314,6 +2314,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {  	.set_antenna		= rt2x00mac_set_antenna,  	.get_antenna		= rt2x00mac_get_antenna,  	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index 80db5cabc9b..66b29dc07cc 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c @@ -16,6 +16,7 @@   */  #include <linux/init.h> +#include <linux/interrupt.h>  #include <linux/pci.h>  #include <linux/slab.h>  #include <linux/delay.h> diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig index 5aee8b22d74..45e14760c16 100644 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ b/drivers/net/wireless/rtlwifi/Kconfig @@ -21,6 +21,17 @@ config RTL8192SE  	If you choose to build it as a module, it will be called rtl8192se +config RTL8192DE +	tristate "Realtek RTL8192DE/RTL8188DE PCIe Wireless Network Adapter" +	depends on MAC80211 && EXPERIMENTAL +	select FW_LOADER +	select RTLWIFI +	---help--- +	This is the driver for Realtek RTL8192DE/RTL8188DE 802.11n PCIe +	wireless network adapters. + +	If you choose to build it as a module, it will be called rtl8192de +  config RTL8192CU  	tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"  	depends on MAC80211 && USB && EXPERIMENTAL @@ -35,10 +46,10 @@ config RTL8192CU  config RTLWIFI  	tristate -	depends on RTL8192CE || RTL8192CU || RTL8192SE +	depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE  	default m  config RTL8192C_COMMON  	tristate -	depends on RTL8192CE || RTL8192CU || RTL8192SE +	depends on RTL8192CE || RTL8192CU  	default m diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile index 7acce83c378..97935c565ba 100644 --- a/drivers/net/wireless/rtlwifi/Makefile +++ b/drivers/net/wireless/rtlwifi/Makefile @@ -23,5 +23,6 @@ obj-$(CONFIG_RTL8192C_COMMON)	+= rtl8192c/  obj-$(CONFIG_RTL8192CE)		+= rtl8192ce/  obj-$(CONFIG_RTL8192CU)		+= rtl8192cu/  obj-$(CONFIG_RTL8192SE)		+= rtl8192se/ +obj-$(CONFIG_RTL8192DE)		+= rtl8192de/  ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index ccb6da38fe2..bc13533a541 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -523,7 +523,7 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw,  		mac->opmode == NL80211_IFTYPE_ADHOC)  		bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; -	if ((bw_40 == true) && sgi_40) +	if (bw_40 && sgi_40)  		tcb_desc->use_shortgi = true;  	else if ((bw_40 == false) && sgi_20)  		tcb_desc->use_shortgi = true; @@ -888,7 +888,6 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw,  {  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -	struct rtl_tid_data *tid_data;  	struct rtl_sta_info *sta_entry = NULL;  	if (sta == NULL) @@ -906,7 +905,6 @@ int rtl_tx_agg_stop(struct ieee80211_hw *hw,  		return -EINVAL;  	sta_entry = (struct rtl_sta_info *)sta->drv_priv; -	tid_data = &sta_entry->tids[tid];  	sta_entry->tids[tid].agg.agg_state = RTL_AGG_STOP;  	ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, sta->addr, tid); @@ -918,7 +916,6 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,  		struct ieee80211_sta *sta, u16 tid)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw); -	struct rtl_tid_data *tid_data;  	struct rtl_sta_info *sta_entry = NULL;  	if (sta == NULL) @@ -936,7 +933,6 @@ int rtl_tx_agg_oper(struct ieee80211_hw *hw,  		return -EINVAL;  	sta_entry = (struct rtl_sta_info *)sta->drv_priv; -	tid_data = &sta_entry->tids[tid];  	sta_entry->tids[tid].agg.agg_state = RTL_AGG_OPERATIONAL;  	return 0; diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index d2ec2535aa3..03ce69660b2 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -335,8 +335,8 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)  		 * before going offchannel, or dis-association or delete BA will  		 * happen by AP  		 */ -		if (rtlpriv->mac80211.offchan_deley) { -			rtlpriv->mac80211.offchan_deley = false; +		if (rtlpriv->mac80211.offchan_delay) { +			rtlpriv->mac80211.offchan_delay = false;  			mdelay(50);  		}  		rtlphy->current_channel = wide_chan; @@ -443,11 +443,11 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,  			sta_entry->wireless_mode = WIRELESS_MODE_G;  			if (sta->supp_rates[0] <= 0xf)  				sta_entry->wireless_mode = WIRELESS_MODE_B; -			if (sta->ht_cap.ht_supported == true) +			if (sta->ht_cap.ht_supported)  				sta_entry->wireless_mode = WIRELESS_MODE_N_24G;  		} else if (rtlhal->current_bandtype == BAND_ON_5G) {  			sta_entry->wireless_mode = WIRELESS_MODE_A; -			if (sta->ht_cap.ht_supported == true) +			if (sta->ht_cap.ht_supported)  				sta_entry->wireless_mode = WIRELESS_MODE_N_24G;  		} @@ -650,7 +650,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,  		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,  			 ("BSS_CHANGED_HT\n"));  		rcu_read_lock(); -		sta = get_sta(hw, vif, (u8 *)bss_conf->bssid); +		sta = get_sta(hw, vif, bss_conf->bssid);  		if (sta) {  			if (sta->ht_cap.ampdu_density >  			    mac->current_ampdu_density) @@ -685,7 +685,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,  		rtlpriv->cfg->ops->set_network_type(hw, vif->type);  		rcu_read_lock(); -		sta = get_sta(hw, vif, (u8 *)bss_conf->bssid); +		sta = get_sta(hw, vif, bss_conf->bssid);  		if (!sta) {  			rcu_read_unlock();  			goto out; diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h index 4b247db2861..f02824a3b74 100644 --- a/drivers/net/wireless/rtlwifi/core.h +++ b/drivers/net/wireless/rtlwifi/core.h @@ -30,6 +30,8 @@  #ifndef __RTL_CORE_H__  #define __RTL_CORE_H__ +#include <net/mac80211.h> +  #define RTL_SUPPORTED_FILTERS		\  	(FIF_PROMISC_IN_BSS | \  	FIF_ALLMULTI | FIF_CONTROL | \ diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 50de6f5d8a5..3fc21f60bb0 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c @@ -382,7 +382,7 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw)  			}  		} -		if (wordchanged == true) +		if (wordchanged)  			hdr_num++;  	} @@ -453,7 +453,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw)  		base = offset * 8;  		for (i = 0; i < 8; i++) { -			if (first_pg == true) { +			if (first_pg) {  				word_en &= ~(BIT(i / 2)); @@ -505,7 +505,7 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); -	if (rtlefuse->autoload_failflag == true) +	if (rtlefuse->autoload_failflag)  		memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF,  			rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);  	else @@ -690,7 +690,7 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr,  			}  		} -		if (dataempty == true) { +		if (dataempty) {  			*readstate = PG_STATE_DATA;  		} else {  			*efuse_addr = *efuse_addr + (word_cnts * 2) + 1; @@ -925,7 +925,7 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct pgpkt_struct target_pkt;  	u8 write_state = PG_STATE_HEADER; -	int continual = true, dataempty = true, result = true; +	int continual = true, result = true;  	u16 efuse_addr = 0;  	u8 efuse_data;  	u8 target_word_cnts = 0; @@ -953,7 +953,6 @@ static int efuse_pg_packet_write(struct ieee80211_hw *hw,  	       (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) {  		if (write_state == PG_STATE_HEADER) { -			dataempty = true;  			badworden = 0x0F;  			RTPRINT(rtlpriv, FEEPROM, EFUSE_PG,  				("efuse PG_STATE_HEADER\n")); @@ -1176,13 +1175,12 @@ static u16 efuse_get_current_size(struct ieee80211_hw *hw)  {  	int continual = true;  	u16 efuse_addr = 0; -	u8 hoffset, hworden; +	u8 hworden;  	u8 efuse_data, word_cnts;  	while (continual && efuse_one_byte_read(hw, efuse_addr, &efuse_data)  	       && (efuse_addr < EFUSE_MAX_SIZE)) {  		if (efuse_data != 0xFF) { -			hoffset = (efuse_data >> 4) & 0x0F;  			hworden = efuse_data & 0x0F;  			word_cnts = efuse_calculate_word_cnts(hworden);  			efuse_addr = efuse_addr + (word_cnts * 2) + 1; diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 9f8ccae9331..5efd5783348 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -35,10 +35,10 @@  #include "efuse.h"  static const u16 pcibridge_vendors[PCI_BRIDGE_VENDOR_MAX] = { -	INTEL_VENDOR_ID, -	ATI_VENDOR_ID, -	AMD_VENDOR_ID, -	SIS_VENDOR_ID +	PCI_VENDOR_ID_INTEL, +	PCI_VENDOR_ID_ATI, +	PCI_VENDOR_ID_AMD, +	PCI_VENDOR_ID_SI  };  static const u8 ac_to_hwq[] = { @@ -390,7 +390,7 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,  	u8 linkctrl_reg;  	/*Link Control Register */ -	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); +	pos = pci_pcie_cap(pdev);  	pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &linkctrl_reg);  	pcipriv->ndis_adapter.linkctrl_reg = linkctrl_reg; @@ -581,7 +581,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)  		fc = rtl_get_fc(skb);  		if (ieee80211_is_nullfunc(fc)) {  			if (ieee80211_has_pm(fc)) { -				rtlpriv->mac80211.offchan_deley = true; +				rtlpriv->mac80211.offchan_delay = true;  				rtlpriv->psc.state_inap = 1;  			} else {  				rtlpriv->psc.state_inap = 0; @@ -622,10 +622,60 @@ tx_status_ok:  	if (((rtlpriv->link_info.num_rx_inperiod +  		rtlpriv->link_info.num_tx_inperiod) > 8) ||  		(rtlpriv->link_info.num_rx_inperiod > 2)) { -		rtl_lps_leave(hw); +		tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);  	}  } +static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb, +			     struct ieee80211_rx_status rx_status) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct ieee80211_hdr *hdr = rtl_get_hdr(skb); +	__le16 fc = rtl_get_fc(skb); +	bool unicast = false; +	struct sk_buff *uskb = NULL; +	u8 *pdata; + + +	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); + +	if (is_broadcast_ether_addr(hdr->addr1)) { +		;/*TODO*/ +	} else if (is_multicast_ether_addr(hdr->addr1)) { +		;/*TODO*/ +	} else { +		unicast = true; +		rtlpriv->stats.rxbytesunicast += skb->len; +	} + +	rtl_is_special_data(hw, skb, false); + +	if (ieee80211_is_data(fc)) { +		rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX); + +		if (unicast) +			rtlpriv->link_info.num_rx_inperiod++; +	} + +	/* for sw lps */ +	rtl_swlps_beacon(hw, (void *)skb->data, skb->len); +	rtl_recognize_peer(hw, (void *)skb->data, skb->len); +	if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) && +	    (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) && +	     (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc))) +		return; + +	if (unlikely(!rtl_action_proc(hw, skb, false))) +		return; + +	uskb = dev_alloc_skb(skb->len + 128); +	memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status)); +	pdata = (u8 *)skb_put(uskb, skb->len); +	memcpy(pdata, skb->data, skb->len); + +	ieee80211_rx_irqsafe(hw, uskb); +} +  static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -637,185 +687,112 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)  	u8 own;  	u8 tmp_one;  	u32 bufferaddress; -	bool unicast = false;  	struct rtl_stats stats = {  		.signal = 0,  		.noise = -98,  		.rate = 0,  	}; +	int index = rtlpci->rx_ring[rx_queue_idx].idx;  	/*RX NORMAL PKT */  	while (count--) {  		/*rx descriptor */  		struct rtl_rx_desc *pdesc = &rtlpci->rx_ring[rx_queue_idx].desc[ -				rtlpci->rx_ring[rx_queue_idx].idx]; +				index];  		/*rx pkt */  		struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[ -				rtlpci->rx_ring[rx_queue_idx].idx]; +				index]; +		struct sk_buff *new_skb = NULL;  		own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,  						       false, HW_DESC_OWN); -		if (own) { -			/*wait data to be filled by hardware */ -			return; -		} else { -			struct ieee80211_hdr *hdr; -			__le16 fc; -			struct sk_buff *new_skb = NULL; - -			rtlpriv->cfg->ops->query_rx_desc(hw, &stats, -							 &rx_status, -							 (u8 *) pdesc, skb); - -			new_skb = dev_alloc_skb(rtlpci->rxbuffersize); -			if (unlikely(!new_skb)) { -				RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), -					 DBG_DMESG, -					 ("can't alloc skb for rx\n")); -				goto done; -			} - -			pci_unmap_single(rtlpci->pdev, -					 *((dma_addr_t *) skb->cb), -					 rtlpci->rxbuffersize, -					 PCI_DMA_FROMDEVICE); - -			skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, -							 false, -							 HW_DESC_RXPKT_LEN)); -			skb_reserve(skb, -				    stats.rx_drvinfo_size + stats.rx_bufshift); - -			/* -			 *NOTICE This can not be use for mac80211, -			 *this is done in mac80211 code, -			 *if you done here sec DHCP will fail -			 *skb_trim(skb, skb->len - 4); -			 */ - -			hdr = rtl_get_hdr(skb); -			fc = rtl_get_fc(skb); +		/*wait data to be filled by hardware */ +		if (own) +			break; -			if (!stats.crc && !stats.hwerror) { -				memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, -				       sizeof(rx_status)); +		rtlpriv->cfg->ops->query_rx_desc(hw, &stats, +						 &rx_status, +						 (u8 *) pdesc, skb); -				if (is_broadcast_ether_addr(hdr->addr1)) { -					;/*TODO*/ -				} else if (is_multicast_ether_addr(hdr->addr1)) { -					;/*TODO*/ -				} else { -					unicast = true; -					rtlpriv->stats.rxbytesunicast += -					    skb->len; -				} +		if (stats.crc || stats.hwerror) +			goto done; -				rtl_is_special_data(hw, skb, false); +		new_skb = dev_alloc_skb(rtlpci->rxbuffersize); +		if (unlikely(!new_skb)) { +			RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), +				 DBG_DMESG, +				 ("can't alloc skb for rx\n")); +			goto done; +		} -				if (ieee80211_is_data(fc)) { -					rtlpriv->cfg->ops->led_control(hw, -							       LED_CTL_RX); +		pci_unmap_single(rtlpci->pdev, +				 *((dma_addr_t *) skb->cb), +				 rtlpci->rxbuffersize, +				 PCI_DMA_FROMDEVICE); -					if (unicast) -						rtlpriv->link_info. -						    num_rx_inperiod++; -				} +		skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, false, +			HW_DESC_RXPKT_LEN)); +		skb_reserve(skb, stats.rx_drvinfo_size + stats.rx_bufshift); -				/* for sw lps */ -				rtl_swlps_beacon(hw, (void *)skb->data, -						 skb->len); -				rtl_recognize_peer(hw, (void *)skb->data, -						   skb->len); -				if ((rtlpriv->mac80211.opmode == -				     NL80211_IFTYPE_AP) && -				    (rtlpriv->rtlhal.current_bandtype == -				     BAND_ON_2_4G) && -				     (ieee80211_is_beacon(fc) || -				     ieee80211_is_probe_resp(fc))) { -					dev_kfree_skb_any(skb); -				} else { -					if (unlikely(!rtl_action_proc(hw, skb, -					    false))) { -						dev_kfree_skb_any(skb); -					} else { -						struct sk_buff *uskb = NULL; -						u8 *pdata; -						uskb = dev_alloc_skb(skb->len -								     + 128); -						memcpy(IEEE80211_SKB_RXCB(uskb), -						       &rx_status, -						       sizeof(rx_status)); -						pdata = (u8 *)skb_put(uskb, -							skb->len); -						memcpy(pdata, skb->data, -						       skb->len); -						dev_kfree_skb_any(skb); +		/* +		 * NOTICE This can not be use for mac80211, +		 * this is done in mac80211 code, +		 * if you done here sec DHCP will fail +		 * skb_trim(skb, skb->len - 4); +		 */ -						ieee80211_rx_irqsafe(hw, uskb); -					} -				} -			} else { -				dev_kfree_skb_any(skb); -			} +		_rtl_receive_one(hw, skb, rx_status); -			if (((rtlpriv->link_info.num_rx_inperiod + -				rtlpriv->link_info.num_tx_inperiod) > 8) || -				(rtlpriv->link_info.num_rx_inperiod > 2)) { -				rtl_lps_leave(hw); -			} +		if (((rtlpriv->link_info.num_rx_inperiod + +			rtlpriv->link_info.num_tx_inperiod) > 8) || +			(rtlpriv->link_info.num_rx_inperiod > 2)) { +			tasklet_schedule(&rtlpriv->works.ips_leave_tasklet); +		} -			skb = new_skb; +		dev_kfree_skb_any(skb); +		skb = new_skb; -			rtlpci->rx_ring[rx_queue_idx].rx_buf[rtlpci-> -							     rx_ring -							     [rx_queue_idx]. -							     idx] = skb; -			*((dma_addr_t *) skb->cb) = +		rtlpci->rx_ring[rx_queue_idx].rx_buf[index] = skb; +		*((dma_addr_t *) skb->cb) =  			    pci_map_single(rtlpci->pdev, skb_tail_pointer(skb),  					   rtlpci->rxbuffersize,  					   PCI_DMA_FROMDEVICE); -		}  done:  		bufferaddress = (*((dma_addr_t *)skb->cb));  		tmp_one = 1;  		rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,  					    HW_DESC_RXBUFF_ADDR,  					    (u8 *)&bufferaddress); -		rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN, -					    (u8 *)&tmp_one);  		rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,  					    HW_DESC_RXPKT_LEN,  					    (u8 *)&rtlpci->rxbuffersize); -		if (rtlpci->rx_ring[rx_queue_idx].idx == -		    rtlpci->rxringcount - 1) +		if (index == rtlpci->rxringcount - 1)  			rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false,  						    HW_DESC_RXERO,  						    (u8 *)&tmp_one); -		rtlpci->rx_ring[rx_queue_idx].idx = -		    (rtlpci->rx_ring[rx_queue_idx].idx + 1) % -		    rtlpci->rxringcount; +		rtlpriv->cfg->ops->set_desc((u8 *)pdesc, false, HW_DESC_RXOWN, +					    (u8 *)&tmp_one); + +		index = (index + 1) % rtlpci->rxringcount;  	} +	rtlpci->rx_ring[rx_queue_idx].idx = index;  }  static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)  {  	struct ieee80211_hw *hw = dev_id;  	struct rtl_priv *rtlpriv = rtl_priv(hw); -	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));  	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));  	unsigned long flags;  	u32 inta = 0;  	u32 intb = 0; -	if (rtlpci->irq_enabled == 0) -		return IRQ_HANDLED; -  	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);  	/*read ISR: 4/8bytes */ @@ -938,6 +915,11 @@ static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw)  	_rtl_pci_tx_chk_waitq(hw);  } +static void _rtl_pci_ips_leave_tasklet(struct ieee80211_hw *hw) +{ +	rtl_lps_leave(hw); +} +  static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -1036,6 +1018,9 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,  	tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet,  		     (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet,  		     (unsigned long)hw); +	tasklet_init(&rtlpriv->works.ips_leave_tasklet, +		     (void (*)(unsigned long))_rtl_pci_ips_leave_tasklet, +		     (unsigned long)hw);  }  static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw, @@ -1505,6 +1490,7 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw)  	synchronize_irq(rtlpci->pdev->irq);  	tasklet_kill(&rtlpriv->works.irq_tasklet); +	tasklet_kill(&rtlpriv->works.ips_leave_tasklet);  	flush_workqueue(rtlpriv->works.rtl_wq);  	destroy_workqueue(rtlpriv->works.rtl_wq); @@ -1579,6 +1565,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw)  	set_hal_stop(rtlhal);  	rtlpriv->cfg->ops->disable_interrupt(hw); +	tasklet_kill(&rtlpriv->works.ips_leave_tasklet);  	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags);  	while (ppsc->rfchange_inprogress) { @@ -1624,6 +1611,16 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,  	pci_read_config_byte(pdev, 0x8, &revisionid);  	pci_read_config_word(pdev, 0x3C, &irqline); +	/* PCI ID 0x10ec:0x8192 occurs for both RTL8192E, which uses +	 * r8192e_pci, and RTL8192SE, which uses this driver. If the +	 * revision ID is RTL_PCI_REVISION_ID_8192PCIE (0x01), then +	 * the correct driver is r8192e_pci, thus this routine should +	 * return false. +	 */ +	if (deviceid == RTL_PCI_8192SE_DID && +	    revisionid == RTL_PCI_REVISION_ID_8192PCIE) +		return false; +  	if (deviceid == RTL_PCI_8192_DID ||  	    deviceid == RTL_PCI_0044_DID ||  	    deviceid == RTL_PCI_0047_DID || @@ -1856,7 +1853,8 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,  	pci_write_config_byte(pdev, 0x04, 0x07);  	/* find adapter */ -	_rtl_pci_find_adapter(pdev, hw); +	if (!_rtl_pci_find_adapter(pdev, hw)) +		goto fail3;  	/* Init IO handler */  	_rtl_pci_io_handler_init(&pdev->dev, hw); diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index 671b1f5aa0c..c53c6204674 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h @@ -62,12 +62,6 @@  	.subdevice = PCI_ANY_ID,\  	.driver_data = (kernel_ulong_t)&(cfg) -#define INTEL_VENDOR_ID				0x8086 -#define SIS_VENDOR_ID				0x1039 -#define ATI_VENDOR_ID				0x1002 -#define ATI_DEVICE_ID				0x7914 -#define AMD_VENDOR_ID				0x1022 -  #define PCI_MAX_BRIDGE_NUMBER			255  #define PCI_MAX_DEVICES				32  #define PCI_MAX_FUNCTION			8 @@ -75,11 +69,6 @@  #define PCI_CONF_ADDRESS	0x0CF8	/*PCI Configuration Space Address */  #define PCI_CONF_DATA		0x0CFC	/*PCI Configuration Space Data */ -#define PCI_CLASS_BRIDGE_DEV		0x06 -#define PCI_SUBCLASS_BR_PCI_TO_PCI	0x04 -#define PCI_CAPABILITY_ID_PCI_EXPRESS	0x10 -#define PCI_CAP_ID_EXP			0x10 -  #define U1DONTCARE			0xFF  #define U2DONTCARE			0xFFFF  #define U4DONTCARE			0xFFFFFFFF @@ -169,7 +158,6 @@ struct rtl_pci {  	bool first_init;  	bool being_init_adapter;  	bool init_ready; -	bool irq_enabled;  	/*Tx */  	struct rtl8192_tx_ring tx_ring[RTL_PCI_MAX_TX_QUEUE_COUNT]; diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 39b0297ce92..a693feffbe7 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -68,6 +68,7 @@ bool rtl_ps_disable_nic(struct ieee80211_hw *hw)  	/*<2> Disable Interrupt */  	rtlpriv->cfg->ops->disable_interrupt(hw); +	tasklet_kill(&rtlpriv->works.irq_tasklet);  	/*<3> Disable Adapter */  	rtlpriv->cfg->ops->hw_disable(hw); @@ -78,65 +79,18 @@ EXPORT_SYMBOL(rtl_ps_disable_nic);  bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,  			 enum rf_pwrstate state_toset, -			 u32 changesource, bool protect_or_not) +			 u32 changesource)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -	enum rf_pwrstate rtstate;  	bool actionallowed = false; -	u16 rfwait_cnt = 0; -	unsigned long flag; - -	/*protect_or_not = true; */ - -	if (protect_or_not) -		goto no_protect; - -	/* -	 *Only one thread can change -	 *the RF state at one time, and others -	 *should wait to be executed. -	 */ -	while (true) { -		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); -		if (ppsc->rfchange_inprogress) { -			spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, -					       flag); - -			RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, -				 ("RF Change in progress!" -				  "Wait to set..state_toset(%d).\n", -				  state_toset)); - -			/* Set RF after the previous action is done.  */ -			while (ppsc->rfchange_inprogress) { -				rfwait_cnt++; -				mdelay(1); - -				/* -				 *Wait too long, return false to avoid -				 *to be stuck here. -				 */ -				if (rfwait_cnt > 100) -					return false; -			} -		} else { -			ppsc->rfchange_inprogress = true; -			spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, -					       flag); -			break; -		} -	} - -no_protect: -	rtstate = ppsc->rfpwr_state;  	switch (state_toset) {  	case ERFON:  		ppsc->rfoff_reason &= (~changesource);  		if ((changesource == RF_CHANGE_BY_HW) && -		    (ppsc->hwradiooff == true)) { +		    (ppsc->hwradiooff)) {  			ppsc->hwradiooff = false;  		} @@ -172,12 +126,6 @@ no_protect:  	if (actionallowed)  		rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset); -	if (!protect_or_not) { -		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); -		ppsc->rfchange_inprogress = false; -		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -	} -  	return actionallowed;  }  EXPORT_SYMBOL(rtl_ps_set_rf_state); @@ -200,8 +148,7 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)  		}  	} -	rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, -			    RF_CHANGE_BY_IPS, false); +	rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, RF_CHANGE_BY_IPS);  	if (ppsc->inactive_pwrstate == ERFOFF &&  	    rtlhal->interface == INTF_PCI) { @@ -289,12 +236,11 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)  	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));  	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));  	enum rf_pwrstate rtstate; -	unsigned long flags;  	if (mac->opmode != NL80211_IFTYPE_STATION)  		return; -	spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags); +	spin_lock(&rtlpriv->locks.ips_lock);  	if (ppsc->inactiveps) {  		rtstate = ppsc->rfpwr_state; @@ -310,7 +256,7 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)  		}  	} -	spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags); +	spin_unlock(&rtlpriv->locks.ips_lock);  }  /*for FW LPS*/ @@ -428,7 +374,6 @@ void rtl_lps_enter(struct ieee80211_hw *hw)  	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));  	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));  	struct rtl_priv *rtlpriv = rtl_priv(hw); -	unsigned long flag;  	if (!ppsc->fwctrl_lps)  		return; @@ -449,7 +394,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)  	if (mac->link_state != MAC80211_LINKED)  		return; -	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); +	spin_lock(&rtlpriv->locks.lps_lock);  	/* Idle for a while if we connect to AP a while ago. */  	if (mac->cnt_after_linked >= 2) { @@ -461,7 +406,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)  		}  	} -	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +	spin_unlock(&rtlpriv->locks.lps_lock);  }  /*Leave the leisure power save mode.*/ @@ -470,9 +415,8 @@ void rtl_lps_leave(struct ieee80211_hw *hw)  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));  	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -	unsigned long flag; -	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); +	spin_lock(&rtlpriv->locks.lps_lock);  	if (ppsc->fwctrl_lps) {  		if (ppsc->dot11_psmode != EACTIVE) { @@ -493,7 +437,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw)  			rtl_lps_set_psmode(hw, EACTIVE);  		}  	} -	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +	spin_unlock(&rtlpriv->locks.lps_lock);  }  /* For sw LPS*/ @@ -582,7 +526,6 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));  	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -	unsigned long flag;  	if (!rtlpriv->psc.swctrl_lps)  		return; @@ -595,9 +538,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)  		RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);  	} -	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); -	rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false); -	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +	spin_lock(&rtlpriv->locks.lps_lock); +	rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS); +	spin_unlock(&rtlpriv->locks.lps_lock);  }  void rtl_swlps_rfon_wq_callback(void *data) @@ -614,7 +557,6 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));  	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); -	unsigned long flag;  	u8 sleep_intv;  	if (!rtlpriv->psc.sw_ps_enabled) @@ -631,16 +573,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)  	if (rtlpriv->link_info.busytraffic)  		return; -	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); -	if (rtlpriv->psc.rfchange_inprogress) { -		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); -		return; -	} -	spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); - -	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag); -	rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false); -	spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag); +	spin_lock(&rtlpriv->locks.lps_lock); +	rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS); +	spin_unlock(&rtlpriv->locks.lps_lock);  	if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&  		!RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) { diff --git a/drivers/net/wireless/rtlwifi/ps.h b/drivers/net/wireless/rtlwifi/ps.h index e3bf8984037..84628e6041c 100644 --- a/drivers/net/wireless/rtlwifi/ps.h +++ b/drivers/net/wireless/rtlwifi/ps.h @@ -33,8 +33,7 @@  #define MAX_SW_LPS_SLEEP_INTV	5  bool rtl_ps_set_rf_state(struct ieee80211_hw *hw, -			 enum rf_pwrstate state_toset, u32 changesource, -			 bool protect_or_not); +			 enum rf_pwrstate state_toset, u32 changesource);  bool rtl_ps_enable_nic(struct ieee80211_hw *hw);  bool rtl_ps_disable_nic(struct ieee80211_hw *hw);  void rtl_ips_nic_off(struct ieee80211_hw *hw); diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c index 30da68a7778..539df66dce0 100644 --- a/drivers/net/wireless/rtlwifi/rc.c +++ b/drivers/net/wireless/rtlwifi/rc.c @@ -200,7 +200,7 @@ static void rtl_tx_status(void *ppriv,  	if (sta) {  		/* Check if aggregation has to be enabled for this tid */  		sta_entry = (struct rtl_sta_info *) sta->drv_priv; -		if ((sta->ht_cap.ht_supported == true) && +		if ((sta->ht_cap.ht_supported) &&  				!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {  			if (ieee80211_is_data_qos(fc)) {  				u8 tid = rtl_get_tid(skb); diff --git a/drivers/net/wireless/rtlwifi/regd.c b/drivers/net/wireless/rtlwifi/regd.c index 8f6718f163e..9fedb1f7091 100644 --- a/drivers/net/wireless/rtlwifi/regd.c +++ b/drivers/net/wireless/rtlwifi/regd.c @@ -303,22 +303,6 @@ static void _rtl_reg_apply_world_flags(struct wiphy *wiphy,  	return;  } -static void _rtl_dump_channel_map(struct wiphy *wiphy) -{ -	enum ieee80211_band band; -	struct ieee80211_supported_band *sband; -	struct ieee80211_channel *ch; -	unsigned int i; - -	for (band = 0; band < IEEE80211_NUM_BANDS; band++) { -		if (!wiphy->bands[band]) -			continue; -		sband = wiphy->bands[band]; -		for (i = 0; i < sband->n_channels; i++) -			ch = &sband->channels[i]; -	} -} -  static int _rtl_reg_notifier_apply(struct wiphy *wiphy,  				   struct regulatory_request *request,  				   struct rtl_regulatory *reg) @@ -336,8 +320,6 @@ static int _rtl_reg_notifier_apply(struct wiphy *wiphy,  		break;  	} -	_rtl_dump_channel_map(wiphy); -  	return 0;  } diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index 97183829b9b..a00774e7090 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -474,7 +474,7 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)  {  	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); -	if (mac->act_scanning == true) +	if (mac->act_scanning)  		return;  	if (mac->link_state >= MAC80211_LINKED) @@ -670,7 +670,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw  	u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0;  	int i;  	bool is2t = IS_92C_SERIAL(rtlhal->version); -	u8 txpwr_level[2] = {0, 0}; +	s8 txpwr_level[2] = {0, 0};  	u8 ofdm_min_index = 6, rf;  	rtlpriv->dm.txpower_trackinginit = true; diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 50303e1adff..f9f2370e925 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -546,7 +546,6 @@ static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));  	struct rtl8192_tx_ring *ring;  	struct rtl_tx_desc *pdesc; -	u8 own;  	unsigned long flags;  	struct sk_buff *pskb = NULL; @@ -559,7 +558,6 @@ static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,  	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);  	pdesc = &ring->desc[0]; -	own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);  	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index d2cc81586a6..3b11642d3f7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -1253,10 +1253,9 @@ static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,  	const u32 retrycount = 2; -	u32 bbvalue; -  	if (t == 0) { -		bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD); +		/* dummy read */ +		rtl_get_bbreg(hw, 0x800, MASKDWORD);  		_rtl92c_phy_save_adda_registers(hw, adda_reg,  						rtlphy->adda_backup, 16); @@ -1762,8 +1761,7 @@ void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)  	long result[4][8];  	u8 i, final_candidate;  	bool patha_ok, pathb_ok; -	long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, -	    reg_ecc, reg_tmp = 0; +	long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4, reg_tmp = 0;  	bool is12simular, is13simular, is23simular;  	bool start_conttx = false, singletone = false;  	u32 iqk_bb_reg[10] = { @@ -1841,21 +1839,17 @@ void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)  		reg_e94 = result[i][0];  		reg_e9c = result[i][1];  		reg_ea4 = result[i][2]; -		reg_eac = result[i][3];  		reg_eb4 = result[i][4];  		reg_ebc = result[i][5];  		reg_ec4 = result[i][6]; -		reg_ecc = result[i][7];  	}  	if (final_candidate != 0xff) {  		rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];  		rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];  		reg_ea4 = result[final_candidate][2]; -		reg_eac = result[final_candidate][3];  		rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];  		rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];  		reg_ec4 = result[final_candidate][6]; -		reg_ecc = result[final_candidate][7];  		patha_ok = pathb_ok = true;  	} else {  		rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index defb4370cf7..9e2a9e34a69 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -488,7 +488,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)  	case HW_VAR_CORRECT_TSF:{  			u8 btype_ibss = ((u8 *) (val))[0]; -			if (btype_ibss == true) +			if (btype_ibss)  				_rtl92ce_stop_tx_beacon(hw);  			_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3)); @@ -500,7 +500,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)  			_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); -			if (btype_ibss == true) +			if (btype_ibss)  				_rtl92ce_resume_tx_beacon(hw);  			break; @@ -763,11 +763,9 @@ static void _rtl92ce_hw_configure(struct ieee80211_hw *hw)  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);  	u8 reg_bw_opmode; -	u32 reg_ratr, reg_prsr; +	u32 reg_prsr;  	reg_bw_opmode = BW_OPMODE_20MHZ; -	reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | -	    RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;  	reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;  	rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); @@ -1123,7 +1121,7 @@ void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)  	if (rtlpriv->psc.rfpwr_state != ERFON)  		return; -	if (check_bssid == true) { +	if (check_bssid) {  		reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);  		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,  					      (u8 *) (®_rcr)); @@ -1185,7 +1183,6 @@ void rtl92ce_enable_interrupt(struct ieee80211_hw *hw)  	rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);  	rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); -	rtlpci->irq_enabled = true;  }  void rtl92ce_disable_interrupt(struct ieee80211_hw *hw) @@ -1195,7 +1192,7 @@ void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)  	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);  	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); -	rtlpci->irq_enabled = false; +	synchronize_irq(rtlpci->pdev->irq);  }  static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) @@ -1586,7 +1583,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw)  		rtlefuse->autoload_failflag = false;  	} -	if (rtlefuse->autoload_failflag == true) +	if (rtlefuse->autoload_failflag)  		return;  	for (i = 0; i < 6; i += 2) { @@ -1969,7 +1966,7 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -	enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; +	enum rf_pwrstate e_rfpowerstate_toset;  	u8 u1tmp;  	bool actuallyset = false;  	unsigned long flag; @@ -1989,15 +1986,13 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)  		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);  	} -	cur_rfstate = ppsc->rfpwr_state; -  	rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv,  		       REG_MAC_PINMUX_CFG)&~(BIT(3)));  	u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);  	e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF; -	if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) { +	if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) {  		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,  			 ("GPIOChangeRF  - HW Radio ON, RF ON\n")); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c index 9dd1ed7b642..28a1a707d09 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c @@ -84,7 +84,7 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)  		break;  	case LED_PIN_LED0:  		ledcfg &= 0xf0; -		if (pcipriv->ledctl.led_opendrain == true) +		if (pcipriv->ledctl.led_opendrain)  			rtl_write_byte(rtlpriv, REG_LEDCFG2,  				       (ledcfg | BIT(1) | BIT(5) | BIT(6)));  		else diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index abe0fcc7536..592a10ac592 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -46,13 +46,12 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	u32 original_value, readback_value, bitshift;  	struct rtl_phy *rtlphy = &(rtlpriv->phy); -	unsigned long flags;  	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "  					       "rfpath(%#x), bitmask(%#x)\n",  					       regaddr, rfpath, bitmask)); -	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); +	spin_lock(&rtlpriv->locks.rf_lock);  	if (rtlphy->rf_mode != RF_OP_BY_FW) {  		original_value = _rtl92c_phy_rf_serial_read(hw, @@ -65,7 +64,7 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,  	bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);  	readback_value = (original_value & bitmask) >> bitshift; -	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); +	spin_unlock(&rtlpriv->locks.rf_lock);  	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,  		 ("regaddr(%#x), rfpath(%#x), " @@ -120,13 +119,12 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_phy *rtlphy = &(rtlpriv->phy);  	u32 original_value, bitshift; -	unsigned long flags;  	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,  		 ("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",  		  regaddr, bitmask, data, rfpath)); -	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); +	spin_lock(&rtlpriv->locks.rf_lock);  	if (rtlphy->rf_mode != RF_OP_BY_FW) {  		if (bitmask != RFREG_OFFSET_MASK) { @@ -153,7 +151,7 @@ void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,  		_rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);  	} -	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); +	spin_unlock(&rtlpriv->locks.rf_lock);  	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "  					       "bitmask(%#x), data(%#x), " @@ -281,7 +279,6 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,  {  	int i; -	bool rtstatus = true;  	u32 *radioa_array_table;  	u32 *radiob_array_table;  	u16 radioa_arraylen, radiob_arraylen; @@ -308,7 +305,6 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,  			 ("Radio_B:RTL8192CE_RADIOB_1TARRAY\n"));  	}  	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath)); -	rtstatus = true;  	switch (rfpath) {  	case RF90_PATH_A:  		for (i = 0; i < radioa_arraylen; i = i + 2) { @@ -521,7 +517,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,  	u8 i, queue_id;  	struct rtl8192_tx_ring *ring = NULL; -	ppsc->set_rfpowerstate_inprogress = true;  	switch (rfpwr_state) {  	case ERFON:{  			if ((ppsc->rfpwr_state == ERFOFF) && @@ -617,7 +612,6 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,  	}  	if (bresult)  		ppsc->rfpwr_state = rfpwr_state; -	ppsc->set_rfpowerstate_inprogress = false;  	return bresult;  } diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h index 598cecc63f4..72a3d549754 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h @@ -1203,7 +1203,9 @@  #define EPROM_CMD_CONFIG			0x3  #define EPROM_CMD_LOAD				1 +#define HWSET_MAX_SIZE				128  #define	HWSET_MAX_SIZE_92S			HWSET_MAX_SIZE +#define EFUSE_MAX_SECTION			16  #define	WL_HWPDN_EN				BIT(0) diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c index 90d0f2cf3b2..d3b01e6023b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c @@ -76,7 +76,7 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,  	if (rtlefuse->eeprom_regulatory != 0)  		turbo_scanoff = true; -	if (mac->act_scanning == true) { +	if (mac->act_scanning) {  		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;  		tx_agc[RF90_PATH_B] = 0x3f3f3f3f; diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 54b2bd53d36..230bbe900d8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -225,7 +225,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,  {  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct phy_sts_cck_8192s_t *cck_buf; -	s8 rx_pwr_all, rx_pwr[4]; +	s8 rx_pwr_all = 0, rx_pwr[4];  	u8 evm, pwdb_all, rf_rx_num = 0;  	u8 i, max_spatial_stream;  	u32 rssi, total_rssi = 0; @@ -592,7 +592,6 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,  	struct ieee80211_hdr *hdr;  	u8 *tmp_buf;  	u8 *praddr; -	u8 *psaddr;  	__le16 fc;  	u16 type, c_fc;  	bool packet_matchbssid, packet_toself, packet_beacon; @@ -604,7 +603,6 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,  	c_fc = le16_to_cpu(fc);  	type = WLAN_FC_GET_TYPE(fc);  	praddr = hdr->addr1; -	psaddr = hdr->addr2;  	packet_matchbssid =  	    ((IEEE80211_FTYPE_CTL != type) && @@ -680,7 +678,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,  						    GET_RX_DESC_PAGGR(pdesc));  	rx_status->mactime = GET_RX_DESC_TSFL(pdesc); -	if (phystatus == true) { +	if (phystatus) {  		p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +  						     stats->rx_bufshift); @@ -929,9 +927,10 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,  void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)  { -	if (istx == true) { +	if (istx) {  		switch (desc_name) {  		case HW_DESC_OWN: +			wmb();  			SET_TX_DESC_OWN(pdesc, 1);  			break;  		case HW_DESC_TX_NEXTDESC_ADDR: @@ -945,6 +944,7 @@ void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)  	} else {  		switch (desc_name) {  		case HW_DESC_RXOWN: +			wmb();  			SET_RX_DESC_OWN(pdesc, 1);  			break;  		case HW_DESC_RXBUFF_ADDR: @@ -968,7 +968,7 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name)  {  	u32 ret = 0; -	if (istx == true) { +	if (istx) {  		switch (desc_name) {  		case HW_DESC_OWN:  			ret = GET_TX_DESC_OWN(p_desc); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 52e2af58c1e..2b34764fbf7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -520,7 +520,7 @@ static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw)  		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));  		rtlefuse->autoload_failflag = false;  	} -	if (rtlefuse->autoload_failflag == true) +	if (rtlefuse->autoload_failflag)  		return;  	for (i = 0; i < 6; i += 2) {  		usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; @@ -1594,7 +1594,7 @@ static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,  	default:  		break;  	} -	if (filterout_non_associated_bssid == true) { +	if (filterout_non_associated_bssid) {  		if (IS_NORMAL_CHIP(rtlhal->version)) {  			switch (rtlphy->current_io_type) {  			case IO_CMD_RESUME_DM_BY_SCAN: @@ -2155,7 +2155,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)  	case HW_VAR_CORRECT_TSF:{  			u8 btype_ibss = ((u8 *) (val))[0]; -			if (btype_ibss == true) +			if (btype_ibss)  				_rtl92cu_stop_tx_beacon(hw);  			_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3));  			rtl_write_dword(rtlpriv, REG_TSFTR, (u32)(mac->tsf & @@ -2163,7 +2163,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)  			rtl_write_dword(rtlpriv, REG_TSFTR + 4,  					(u32)((mac->tsf >> 32) & 0xffffffff));  			_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0); -			if (btype_ibss == true) +			if (btype_ibss)  				_rtl92cu_resume_tx_beacon(hw);  			break;  		} diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c index 332c74348a6..2ff9d8314e7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c @@ -82,7 +82,7 @@ void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)  		break;  	case LED_PIN_LED0:  		ledcfg &= 0xf0; -		if (usbpriv->ledctl.led_opendrain == true) +		if (usbpriv->ledctl.led_opendrain)  			rtl_write_byte(rtlpriv, REG_LEDCFG2,  				       (ledcfg | BIT(1) | BIT(5) | BIT(6)));  		else diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index f8514cba17b..a90c09b4239 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c @@ -380,13 +380,11 @@ void rtl92c_enable_interrupt(struct ieee80211_hw *hw)  				0xFFFFFFFF);  		rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] &  				0xFFFFFFFF); -		rtlpci->irq_enabled = true;  	} else {  		rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &  				0xFFFFFFFF);  		rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &  				0xFFFFFFFF); -		rtlusb->irq_enabled = true;  	}  } @@ -398,16 +396,9 @@ void rtl92c_init_interrupt(struct ieee80211_hw *hw)  void rtl92c_disable_interrupt(struct ieee80211_hw *hw)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw); -	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); -	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));  	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);  	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); -	if (IS_HARDWARE_TYPE_8192CE(rtlhal)) -		rtlpci->irq_enabled = false; -	else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) -		rtlusb->irq_enabled = false;  }  void rtl92c_set_qos(struct ieee80211_hw *hw, int aci) @@ -1113,7 +1104,6 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,  	struct ieee80211_hdr *hdr;  	u8 *tmp_buf;  	u8 *praddr; -	u8 *psaddr;  	__le16 fc;  	u16 type, cpu_fc;  	bool packet_matchbssid, packet_toself, packet_beacon; @@ -1124,7 +1114,6 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,  	cpu_fc = le16_to_cpu(fc);  	type = WLAN_FC_GET_TYPE(fc);  	praddr = hdr->addr1; -	psaddr = hdr->addr2;  	packet_matchbssid =  	    ((IEEE80211_FTYPE_CTL != type) &&  	     (!compare_ether_addr(mac->bssid, diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c index 9a3d0239e27..72852900df8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c @@ -470,7 +470,6 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,  	u8 i, queue_id;  	struct rtl8192_tx_ring *ring = NULL; -	ppsc->set_rfpowerstate_inprogress = true;  	switch (rfpwr_state) {  	case ERFON:  		if ((ppsc->rfpwr_state == ERFOFF) && @@ -590,7 +589,6 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,  	}  	if (bresult)  		ppsc->rfpwr_state = rfpwr_state; -	ppsc->set_rfpowerstate_inprogress = false;  	return bresult;  } diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index c7576ec4744..17a8e962851 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -82,7 +82,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,  		    (rtlefuse->external_pa))  			turbo_scanoff = true;  	} -	if (mac->act_scanning == true) { +	if (mac->act_scanning) {  		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;  		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;  		if (turbo_scanoff) { @@ -104,7 +104,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,  			tx_agc[RF90_PATH_A] = 0x10101010;  			tx_agc[RF90_PATH_B] = 0x10101010;  		} else if (rtlpriv->dm.dynamic_txhighpower_lvl == -			   TXHIGHPWRLEVEL_LEVEL1) { +			   TXHIGHPWRLEVEL_LEVEL2) {  			tx_agc[RF90_PATH_A] = 0x00000000;  			tx_agc[RF90_PATH_B] = 0x00000000;  		} else{ diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index bee7c1480f6..942f7a3969a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -53,6 +53,8 @@ MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin");  static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw); +	const struct firmware *firmware; +	int err;  	rtlpriv->dm.dm_initialgain_enable = 1;  	rtlpriv->dm.dm_flag = 0; @@ -64,6 +66,24 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)  			 ("Can't alloc buffer for fw.\n"));  		return 1;  	} +	/* request fw */ +	err = request_firmware(&firmware, rtlpriv->cfg->fw_name, +			rtlpriv->io.dev); +	if (err) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("Failed to request firmware!\n")); +		return 1; +	} +	if (firmware->size > 0x4000) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("Firmware is too big!\n")); +		release_firmware(firmware); +		return 1; +	} +	memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); +	rtlpriv->rtlhal.fwsize = firmware->size; +	release_firmware(firmware); +  	return 0;  } @@ -278,6 +298,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {  	{RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/  	{RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/  	{RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ +	{RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/  	{RTL_USB_DEVICE(0x0Df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/  	{RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/  	/* HP - Lite-On ,8188CUS Slim Combo */ diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 3a92ba3c4a1..906e7aa55bc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -342,7 +342,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,  						(u8)GET_RX_DESC_RX_MCS(pdesc),  						(bool)GET_RX_DESC_PAGGR(pdesc));  	rx_status->mactime = GET_RX_DESC_TSFL(pdesc); -	if (phystatus == true) { +	if (phystatus) {  		p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE);  		rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc,  						 p_drvinfo); diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/Makefile b/drivers/net/wireless/rtlwifi/rtl8192de/Makefile new file mode 100644 index 00000000000..e3213c8264b --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/Makefile @@ -0,0 +1,14 @@ +rtl8192de-objs :=		\ +		dm.o		\ +		fw.o		\ +		hw.o		\ +		led.o		\ +		phy.o		\ +		rf.o		\ +		sw.o		\ +		table.o		\ +		trx.o + +obj-$(CONFIG_RTL8192DE) += rtl8192de.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/rtlwifi/rtl8192de/def.h new file mode 100644 index 00000000000..f0f5f9bfbb7 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/def.h @@ -0,0 +1,269 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92D_DEF_H__ +#define __RTL92D_DEF_H__ + +/* Min Spacing related settings. */ +#define	MAX_MSS_DENSITY_2T				0x13 +#define	MAX_MSS_DENSITY_1T				0x0A + +#define RF6052_MAX_TX_PWR				0x3F +#define RF6052_MAX_REG					0x3F +#define RF6052_MAX_PATH					2 + +#define HAL_RETRY_LIMIT_INFRA				48 +#define HAL_RETRY_LIMIT_AP_ADHOC			7 + +#define	PHY_RSSI_SLID_WIN_MAX				100 +#define	PHY_LINKQUALITY_SLID_WIN_MAX			20 +#define	PHY_BEACON_RSSI_SLID_WIN_MAX			10 + +#define RESET_DELAY_8185				20 + +#define RT_IBSS_INT_MASKS	(IMR_BCNINT | IMR_TBDOK | IMR_TBDER) +#define RT_AC_INT_MASKS		(IMR_VIDOK | IMR_VODOK | IMR_BEDOK|IMR_BKDOK) + +#define NUM_OF_FIRMWARE_QUEUE				10 +#define NUM_OF_PAGES_IN_FW				0x100 +#define NUM_OF_PAGE_IN_FW_QUEUE_BK			0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_BE			0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_VI			0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_VO			0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA			0x0 +#define NUM_OF_PAGE_IN_FW_QUEUE_CMD			0x0 +#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT			0x02 +#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH			0x02 +#define NUM_OF_PAGE_IN_FW_QUEUE_BCN			0x2 +#define NUM_OF_PAGE_IN_FW_QUEUE_PUB			0xA1 + +#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM			0x026 +#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM			0x048 +#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM			0x048 +#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM			0x026 +#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM			0x00 + +#define MAX_LINES_HWCONFIG_TXT				1000 +#define MAX_BYTES_LINE_HWCONFIG_TXT			256 + +#define SW_THREE_WIRE					0 +#define HW_THREE_WIRE					2 + +#define BT_DEMO_BOARD					0 +#define BT_QA_BOARD					1 +#define BT_FPGA						2 + +#define RX_SMOOTH_FACTOR				20 + +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE			0 +#define HAL_PRIME_CHNL_OFFSET_LOWER			1 +#define HAL_PRIME_CHNL_OFFSET_UPPER			2 + +#define MAX_H2C_QUEUE_NUM				10 + +#define RX_MPDU_QUEUE					0 +#define RX_CMD_QUEUE					1 +#define RX_MAX_QUEUE					2 + +#define	C2H_RX_CMD_HDR_LEN				8 +#define	GET_C2H_CMD_CMD_LEN(__prxhdr)			\ +	LE_BITS_TO_4BYTE((__prxhdr), 0, 16) +#define	GET_C2H_CMD_ELEMENT_ID(__prxhdr)		\ +	LE_BITS_TO_4BYTE((__prxhdr), 16, 8) +#define	GET_C2H_CMD_CMD_SEQ(__prxhdr)			\ +	LE_BITS_TO_4BYTE((__prxhdr), 24, 7) +#define	GET_C2H_CMD_CONTINUE(__prxhdr)			\ +	LE_BITS_TO_4BYTE((__prxhdr), 31, 1) +#define	GET_C2H_CMD_CONTENT(__prxhdr)			\ +	((u8 *)(__prxhdr) + C2H_RX_CMD_HDR_LEN) + +#define	GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pcmdfbhdr)	\ +	LE_BITS_TO_4BYTE((__pcmdfbhdr), 0, 8) +#define	GET_C2H_CMD_FEEDBACK_CCX_LEN(__pcmdfbhdr)	\ +	LE_BITS_TO_4BYTE((__pcmdfbhdr), 8, 8) +#define	GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pcmdfbhdr)	\ +	LE_BITS_TO_4BYTE((__pcmdfbhdr), 16, 16) +#define	GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pcmdfbhdr)	\ +	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 0, 5) +#define	GET_C2H_CMD_FEEDBACK_CCX_VALID(__pcmdfbhdr)	\ +	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 7, 1) +#define	GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pcmdfbhdr)	\ +	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 8, 5) +#define	GET_C2H_CMD_FEEDBACK_CCX_TOK(__pcmdfbhdr)	\ +	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 15, 1) +#define	GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pcmdfbhdr)	\ +	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) +#define	GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr)	\ +	LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) + +/* + * 92D chip ver: + * BIT8: IS 92D + * BIT9: single phy + * BIT10: C-cut + * BIT11: D-cut + */ + +/* Chip specific */ +#define CHIP_92C			BIT(0) +#define CHIP_92C_1T2R			BIT(1) +#define CHIP_8723			BIT(2) /* RTL8723 With BT feature */ +#define CHIP_8723_DRV_REV		BIT(3) /* RTL8723 Driver Revised */ +#define NORMAL_CHIP			BIT(4) +#define CHIP_VENDOR_UMC			BIT(5) +#define CHIP_VENDOR_UMC_B_CUT		BIT(6) /* Chip version for ECO */ + +/* for 92D */ +#define CHIP_92D			BIT(8) +#define CHIP_92D_SINGLEPHY		BIT(9) +#define CHIP_92D_C_CUT			BIT(10) +#define CHIP_92D_D_CUT			BIT(11) + +enum version_8192d { +	VERSION_TEST_CHIP_88C = 0x00, +	VERSION_TEST_CHIP_92C = 0x01, +	VERSION_NORMAL_TSMC_CHIP_88C = 0x10, +	VERSION_NORMAL_TSMC_CHIP_92C = 0x11, +	VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x13, +	VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x30, +	VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x31, +	VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x33, +	VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT = 0x34, +	VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT = 0x3c, +	VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x70, +	VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x71, +	VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x73, +	VERSION_TEST_CHIP_92D_SINGLEPHY = 0x300, +	VERSION_TEST_CHIP_92D_DUALPHY = 0x100, +	VERSION_NORMAL_CHIP_92D_SINGLEPHY = 0x310, +	VERSION_NORMAL_CHIP_92D_DUALPHY = 0x110, +	VERSION_NORMAL_CHIP_92D_C_CUT_SINGLEPHY = 0x710, +	VERSION_NORMAL_CHIP_92D_C_CUT_DUALPHY = 0x510, +	VERSION_NORMAL_CHIP_92D_D_CUT_SINGLEPHY = 0xB10, +	VERSION_NORMAL_CHIP_92D_D_CUT_DUALPHY = 0x910, +}; + +#define IS_92D_SINGLEPHY(version)		\ +	((version & CHIP_92D_SINGLEPHY) ? true : false) +#define IS_92D_C_CUT(version)			\ +	((version & CHIP_92D_C_CUT) ? true : false) +#define IS_92D_D_CUT(version)			\ +	((version & CHIP_92D_D_CUT) ? true : false) + +enum rf_optype { +	RF_OP_BY_SW_3WIRE = 0, +	RF_OP_BY_FW, +	RF_OP_MAX +}; + +enum rtl_desc_qsel { +	QSLT_BK = 0x2, +	QSLT_BE = 0x0, +	QSLT_VI = 0x5, +	QSLT_VO = 0x7, +	QSLT_BEACON = 0x10, +	QSLT_HIGH = 0x11, +	QSLT_MGNT = 0x12, +	QSLT_CMD = 0x13, +}; + +enum rtl_desc92d_rate { +	DESC92D_RATE1M = 0x00, +	DESC92D_RATE2M = 0x01, +	DESC92D_RATE5_5M = 0x02, +	DESC92D_RATE11M = 0x03, + +	DESC92D_RATE6M = 0x04, +	DESC92D_RATE9M = 0x05, +	DESC92D_RATE12M = 0x06, +	DESC92D_RATE18M = 0x07, +	DESC92D_RATE24M = 0x08, +	DESC92D_RATE36M = 0x09, +	DESC92D_RATE48M = 0x0a, +	DESC92D_RATE54M = 0x0b, + +	DESC92D_RATEMCS0 = 0x0c, +	DESC92D_RATEMCS1 = 0x0d, +	DESC92D_RATEMCS2 = 0x0e, +	DESC92D_RATEMCS3 = 0x0f, +	DESC92D_RATEMCS4 = 0x10, +	DESC92D_RATEMCS5 = 0x11, +	DESC92D_RATEMCS6 = 0x12, +	DESC92D_RATEMCS7 = 0x13, +	DESC92D_RATEMCS8 = 0x14, +	DESC92D_RATEMCS9 = 0x15, +	DESC92D_RATEMCS10 = 0x16, +	DESC92D_RATEMCS11 = 0x17, +	DESC92D_RATEMCS12 = 0x18, +	DESC92D_RATEMCS13 = 0x19, +	DESC92D_RATEMCS14 = 0x1a, +	DESC92D_RATEMCS15 = 0x1b, +	DESC92D_RATEMCS15_SG = 0x1c, +	DESC92D_RATEMCS32 = 0x20, +}; + +enum channel_plan { +	CHPL_FCC	= 0, +	CHPL_IC		= 1, +	CHPL_ETSI	= 2, +	CHPL_SPAIN	= 3, +	CHPL_FRANCE	= 4, +	CHPL_MKK	= 5, +	CHPL_MKK1	= 6, +	CHPL_ISRAEL	= 7, +	CHPL_TELEC	= 8, +	CHPL_GLOBAL	= 9, +	CHPL_WORLD	= 10, +}; + +struct phy_sts_cck_8192d { +	u8 adc_pwdb_X[4]; +	u8 sq_rpt; +	u8 cck_agc_rpt; +}; + +struct h2c_cmd_8192c { +	u8 element_id; +	u32 cmd_len; +	u8 *p_cmdbuffer; +}; + +struct txpower_info { +	u8 cck_index[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; +	u8 ht40_1sindex[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; +	u8 ht40_2sindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; +	u8 ht20indexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; +	u8 ofdmindexdiff[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; +	u8 ht40maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; +	u8 ht20maxoffset[RF6052_MAX_PATH][CHANNEL_GROUP_MAX]; +	u8 tssi_a[3];		/* 5GL/5GM/5GH */ +	u8 tssi_b[3]; +}; + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c new file mode 100644 index 00000000000..3cd0736fe8e --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.c @@ -0,0 +1,1355 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" + +#define UNDEC_SM_PWDB	entry_min_undecoratedsmoothed_pwdb + +struct dig_t de_digtable; + +static const u32 ofdmswing_table[OFDM_TABLE_SIZE_92D] = { +	0x7f8001fe,		/* 0, +6.0dB */ +	0x788001e2,		/* 1, +5.5dB */ +	0x71c001c7,		/* 2, +5.0dB */ +	0x6b8001ae,		/* 3, +4.5dB */ +	0x65400195,		/* 4, +4.0dB */ +	0x5fc0017f,		/* 5, +3.5dB */ +	0x5a400169,		/* 6, +3.0dB */ +	0x55400155,		/* 7, +2.5dB */ +	0x50800142,		/* 8, +2.0dB */ +	0x4c000130,		/* 9, +1.5dB */ +	0x47c0011f,		/* 10, +1.0dB */ +	0x43c0010f,		/* 11, +0.5dB */ +	0x40000100,		/* 12, +0dB */ +	0x3c8000f2,		/* 13, -0.5dB */ +	0x390000e4,		/* 14, -1.0dB */ +	0x35c000d7,		/* 15, -1.5dB */ +	0x32c000cb,		/* 16, -2.0dB */ +	0x300000c0,		/* 17, -2.5dB */ +	0x2d4000b5,		/* 18, -3.0dB */ +	0x2ac000ab,		/* 19, -3.5dB */ +	0x288000a2,		/* 20, -4.0dB */ +	0x26000098,		/* 21, -4.5dB */ +	0x24000090,		/* 22, -5.0dB */ +	0x22000088,		/* 23, -5.5dB */ +	0x20000080,		/* 24, -6.0dB */ +	0x1e400079,		/* 25, -6.5dB */ +	0x1c800072,		/* 26, -7.0dB */ +	0x1b00006c,		/* 27. -7.5dB */ +	0x19800066,		/* 28, -8.0dB */ +	0x18000060,		/* 29, -8.5dB */ +	0x16c0005b,		/* 30, -9.0dB */ +	0x15800056,		/* 31, -9.5dB */ +	0x14400051,		/* 32, -10.0dB */ +	0x1300004c,		/* 33, -10.5dB */ +	0x12000048,		/* 34, -11.0dB */ +	0x11000044,		/* 35, -11.5dB */ +	0x10000040,		/* 36, -12.0dB */ +	0x0f00003c,		/* 37, -12.5dB */ +	0x0e400039,		/* 38, -13.0dB */ +	0x0d800036,		/* 39, -13.5dB */ +	0x0cc00033,		/* 40, -14.0dB */ +	0x0c000030,		/* 41, -14.5dB */ +	0x0b40002d,		/* 42, -15.0dB */ +}; + +static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { +	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},    /* 0, +0dB */ +	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},    /* 1, -0.5dB */ +	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},    /* 2, -1.0dB */ +	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},    /* 3, -1.5dB */ +	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},    /* 4, -2.0dB */ +	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},    /* 5, -2.5dB */ +	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},    /* 6, -3.0dB */ +	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},    /* 7, -3.5dB */ +	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},    /* 8, -4.0dB */ +	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},    /* 9, -4.5dB */ +	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},    /* 10, -5.0dB */ +	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},    /* 11, -5.5dB */ +	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},    /* 12, -6.0dB */ +	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},    /* 13, -6.5dB */ +	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},    /* 14, -7.0dB */ +	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},    /* 15, -7.5dB */ +	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},    /* 16, -8.0dB */ +	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},    /* 17, -8.5dB */ +	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},    /* 18, -9.0dB */ +	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},    /* 19, -9.5dB */ +	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},    /* 20, -10.0dB */ +	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},    /* 21, -10.5dB */ +	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},    /* 22, -11.0dB */ +	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},    /* 23, -11.5dB */ +	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},    /* 24, -12.0dB */ +	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},    /* 25, -12.5dB */ +	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},    /* 26, -13.0dB */ +	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},    /* 27, -13.5dB */ +	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},    /* 28, -14.0dB */ +	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},    /* 29, -14.5dB */ +	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},    /* 30, -15.0dB */ +	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},    /* 31, -15.5dB */ +	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}     /* 32, -16.0dB */ +}; + +static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { +	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},    /* 0, +0dB */ +	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},    /* 1, -0.5dB */ +	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},    /* 2, -1.0dB */ +	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},    /* 3, -1.5dB */ +	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},    /* 4, -2.0dB */ +	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},    /* 5, -2.5dB */ +	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},    /* 6, -3.0dB */ +	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},    /* 7, -3.5dB */ +	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},    /* 8, -4.0dB */ +	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},    /* 9, -4.5dB */ +	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},    /* 10, -5.0dB */ +	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},    /* 11, -5.5dB */ +	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},    /* 12, -6.0dB */ +	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},    /* 13, -6.5dB */ +	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},    /* 14, -7.0dB */ +	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},    /* 15, -7.5dB */ +	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},    /* 16, -8.0dB */ +	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},    /* 17, -8.5dB */ +	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},    /* 18, -9.0dB */ +	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},    /* 19, -9.5dB */ +	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},    /* 20, -10.0dB */ +	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},    /* 21, -10.5dB */ +	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},    /* 22, -11.0dB */ +	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},    /* 23, -11.5dB */ +	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},    /* 24, -12.0dB */ +	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},    /* 25, -12.5dB */ +	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},    /* 26, -13.0dB */ +	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},    /* 27, -13.5dB */ +	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 28, -14.0dB */ +	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 29, -14.5dB */ +	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 30, -15.0dB */ +	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},    /* 31, -15.5dB */ +	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}     /* 32, -16.0dB */ +}; + +static void rtl92d_dm_diginit(struct ieee80211_hw *hw) +{ +	de_digtable.dig_enable_flag = true; +	de_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; +	de_digtable.cur_igvalue = 0x20; +	de_digtable.pre_igvalue = 0x0; +	de_digtable.cursta_connectctate = DIG_STA_DISCONNECT; +	de_digtable.presta_connectstate = DIG_STA_DISCONNECT; +	de_digtable.curmultista_connectstate = DIG_MULTISTA_DISCONNECT; +	de_digtable.rssi_lowthresh = DM_DIG_THRESH_LOW; +	de_digtable.rssi_highthresh = DM_DIG_THRESH_HIGH; +	de_digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW; +	de_digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH; +	de_digtable.rx_gain_range_max = DM_DIG_FA_UPPER; +	de_digtable.rx_gain_range_min = DM_DIG_FA_LOWER; +	de_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT; +	de_digtable.backoff_val_range_max = DM_DIG_BACKOFF_MAX; +	de_digtable.backoff_val_range_min = DM_DIG_BACKOFF_MIN; +	de_digtable.pre_cck_pd_state = CCK_PD_STAGE_LOWRSSI; +	de_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX; +	de_digtable.large_fa_hit = 0; +	de_digtable.recover_cnt = 0; +	de_digtable.forbidden_igi = DM_DIG_FA_LOWER; +} + +static void rtl92d_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) +{ +	u32 ret_value; +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); +	unsigned long flag = 0; + +	/* hold ofdm counter */ +	rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 1); /* hold page C counter */ +	rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 1); /*hold page D counter */ + +	ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, BMASKDWORD); +	falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff); +	falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16); +	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, BMASKDWORD); +	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); +	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, BMASKDWORD); +	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); +	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); +	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, BMASKDWORD); +	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); +	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + +				      falsealm_cnt->cnt_rate_illegal + +				      falsealm_cnt->cnt_crc8_fail + +				      falsealm_cnt->cnt_mcs_fail + +				      falsealm_cnt->cnt_fast_fsync_fail + +				      falsealm_cnt->cnt_sb_search_fail; + +	if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) { +		/* hold cck counter */ +		rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); +		ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, BMASKBYTE0); +		falsealm_cnt->cnt_cck_fail = ret_value; +		ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, BMASKBYTE3); +		falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; +		rtl92d_release_cckandrw_pagea_ctl(hw, &flag); +	} else { +		falsealm_cnt->cnt_cck_fail = 0; +	} + +	/* reset false alarm counter registers */ +	falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail + +				falsealm_cnt->cnt_sb_search_fail + +				falsealm_cnt->cnt_parity_fail + +				falsealm_cnt->cnt_rate_illegal + +				falsealm_cnt->cnt_crc8_fail + +				falsealm_cnt->cnt_mcs_fail + +				falsealm_cnt->cnt_cck_fail; + +	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1); +	/* update ofdm counter */ +	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0); +	/* update page C counter */ +	rtl_set_bbreg(hw, ROFDM0_LSTF, BIT(31), 0); +	/* update page D counter */ +	rtl_set_bbreg(hw, ROFDM1_LSTF, BIT(31), 0); +	if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) { +		/* reset cck counter */ +		rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); +		rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0); +		/* enable cck counter */ +		rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2); +		rtl92d_release_cckandrw_pagea_ctl(hw, &flag); +	} +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Cnt_Fast_Fsync_fail = %x, " +		 "Cnt_SB_Search_fail = %x\n", +		 falsealm_cnt->cnt_fast_fsync_fail, +		 falsealm_cnt->cnt_sb_search_fail)); +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Cnt_Parity_Fail = %x, " +		 "Cnt_Rate_Illegal = %x, Cnt_Crc8_fail = %x, " +		 "Cnt_Mcs_fail = %x\n", +		 falsealm_cnt->cnt_parity_fail, +		 falsealm_cnt->cnt_rate_illegal, +		 falsealm_cnt->cnt_crc8_fail, +		 falsealm_cnt->cnt_mcs_fail)); +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, +		 ("Cnt_Ofdm_fail = %x, " "Cnt_Cck_fail = %x, " +		 "Cnt_all = %x\n", +		 falsealm_cnt->cnt_ofdm_fail, +		 falsealm_cnt->cnt_cck_fail, +		 falsealm_cnt->cnt_all)); +} + +static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_mac *mac = rtl_mac(rtlpriv); + +	/* Determine the minimum RSSI  */ +	if ((mac->link_state < MAC80211_LINKED) && +	    (rtlpriv->dm.UNDEC_SM_PWDB == 0)) { +		de_digtable.min_undecorated_pwdb_for_dm = 0; +		RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, +			 ("Not connected to any\n")); +	} +	if (mac->link_state >= MAC80211_LINKED) { +		if (mac->opmode == NL80211_IFTYPE_AP || +		    mac->opmode == NL80211_IFTYPE_ADHOC) { +			de_digtable.min_undecorated_pwdb_for_dm = +			    rtlpriv->dm.UNDEC_SM_PWDB; +			RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, +				 ("AP Client PWDB = 0x%lx\n", +				  rtlpriv->dm.UNDEC_SM_PWDB)); +		} else { +			de_digtable.min_undecorated_pwdb_for_dm = +			    rtlpriv->dm.undecorated_smoothed_pwdb; +			RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, +				 ("STA Default Port PWDB = 0x%x\n", +				  de_digtable.min_undecorated_pwdb_for_dm)); +		} +	} else { +		de_digtable.min_undecorated_pwdb_for_dm = +		    rtlpriv->dm.UNDEC_SM_PWDB; +		RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, +			 ("AP Ext Port or disconnet PWDB = 0x%x\n", +			  de_digtable.min_undecorated_pwdb_for_dm)); +	} + +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("MinUndecoratedPWDBForDM =%d\n", +			de_digtable.min_undecorated_pwdb_for_dm)); +} + +static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	unsigned long flag = 0; + +	if (de_digtable.cursta_connectctate == DIG_STA_CONNECT) { +		if (de_digtable.pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { +			if (de_digtable.min_undecorated_pwdb_for_dm <= 25) +				de_digtable.cur_cck_pd_state = +							 CCK_PD_STAGE_LOWRSSI; +			else +				de_digtable.cur_cck_pd_state = +							 CCK_PD_STAGE_HIGHRSSI; +		} else { +			if (de_digtable.min_undecorated_pwdb_for_dm <= 20) +				de_digtable.cur_cck_pd_state = +							 CCK_PD_STAGE_LOWRSSI; +			else +				de_digtable.cur_cck_pd_state = +							 CCK_PD_STAGE_HIGHRSSI; +		} +	} else { +		de_digtable.cur_cck_pd_state = CCK_PD_STAGE_LOWRSSI; +	} +	if (de_digtable.pre_cck_pd_state != de_digtable.cur_cck_pd_state) { +		if (de_digtable.cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { +			rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); +			rtl_set_bbreg(hw, RCCK0_CCA, BMASKBYTE2, 0x83); +			rtl92d_release_cckandrw_pagea_ctl(hw, &flag); +		} else { +			rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); +			rtl_set_bbreg(hw, RCCK0_CCA, BMASKBYTE2, 0xcd); +			rtl92d_release_cckandrw_pagea_ctl(hw, &flag); +		} +		de_digtable.pre_cck_pd_state = de_digtable.cur_cck_pd_state; +	} +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("CurSTAConnectState=%s\n", +		 (de_digtable.cursta_connectctate == DIG_STA_CONNECT ? +		 "DIG_STA_CONNECT " : "DIG_STA_DISCONNECT"))); +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("CCKPDStage=%s\n", +		 (de_digtable.cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ? +		 "Low RSSI " : "High RSSI "))); +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("is92d single phy =%x\n", +		 IS_92D_SINGLEPHY(rtlpriv->rtlhal.version))); + +} + +void rtl92d_dm_write_dig(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("cur_igvalue = 0x%x, " +		 "pre_igvalue = 0x%x, backoff_val = %d\n", +		 de_digtable.cur_igvalue, de_digtable.pre_igvalue, +		 de_digtable.backoff_val)); +	if (de_digtable.dig_enable_flag == false) { +		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("DIG is disabled\n")); +		de_digtable.pre_igvalue = 0x17; +		return; +	} +	if (de_digtable.pre_igvalue != de_digtable.cur_igvalue) { +		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, +			      de_digtable.cur_igvalue); +		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, +			      de_digtable.cur_igvalue); +		de_digtable.pre_igvalue = de_digtable.cur_igvalue; +	} +} + +static void rtl92d_early_mode_enabled(struct rtl_priv *rtlpriv) +{ +	if ((rtlpriv->mac80211.link_state >= MAC80211_LINKED) && +	    (rtlpriv->mac80211.vendor == PEER_CISCO)) { +		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, +			 ("IOT_PEER = CISCO\n")); +		if (de_digtable.last_min_undecorated_pwdb_for_dm >= 50 +		    && de_digtable.min_undecorated_pwdb_for_dm < 50) { +			rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x00); +			RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, +				 ("Early Mode Off\n")); +		} else if (de_digtable.last_min_undecorated_pwdb_for_dm <= 55 && +			   de_digtable.min_undecorated_pwdb_for_dm > 55) { +			rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f); +			RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, +				 ("Early Mode On\n")); +		} +	} else if (!(rtl_read_byte(rtlpriv, REG_EARLY_MODE_CONTROL) & 0xf)) { +		rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f); +		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("Early Mode On\n")); +	} +} + +static void rtl92d_dm_dig(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 value_igi = de_digtable.cur_igvalue; +	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); + +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("==>\n")); +	if (rtlpriv->rtlhal.earlymode_enable) { +		rtl92d_early_mode_enabled(rtlpriv); +		de_digtable.last_min_undecorated_pwdb_for_dm = +				 de_digtable.min_undecorated_pwdb_for_dm; +	} +	if (rtlpriv->dm.dm_initialgain_enable == false) +		return; + +	/* because we will send data pkt when scanning +	 * this will cause some ap like gear-3700 wep TP +	 * lower if we retrun here, this is the diff of +	 * mac80211 driver vs ieee80211 driver */ +	/* if (rtlpriv->mac80211.act_scanning) +	 *      return; */ + +	/* Not STA mode return tmp */ +	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) +		return; +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("progress\n")); +	/* Decide the current status and if modify initial gain or not */ +	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) +		de_digtable.cursta_connectctate = DIG_STA_CONNECT; +	else +		de_digtable.cursta_connectctate = DIG_STA_DISCONNECT; + +	/* adjust initial gain according to false alarm counter */ +	if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0) +		value_igi--; +	else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH1) +		value_igi += 0; +	else if (falsealm_cnt->cnt_all < DM_DIG_FA_TH2) +		value_igi++; +	else if (falsealm_cnt->cnt_all >= DM_DIG_FA_TH2) +		value_igi += 2; +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, +		 ("dm_DIG() Before: large_fa_hit=%d, forbidden_igi=%x\n", +		 de_digtable.large_fa_hit, de_digtable.forbidden_igi)); +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, +		 ("dm_DIG() Before: Recover_cnt=%d, rx_gain_range_min=%x\n", +		 de_digtable.recover_cnt, de_digtable.rx_gain_range_min)); + +	/* deal with abnorally large false alarm */ +	if (falsealm_cnt->cnt_all > 10000) { +		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, +			 ("dm_DIG(): Abnornally false alarm case.\n")); + +		de_digtable.large_fa_hit++; +		if (de_digtable.forbidden_igi < de_digtable.cur_igvalue) { +			de_digtable.forbidden_igi = de_digtable.cur_igvalue; +			de_digtable.large_fa_hit = 1; +		} +		if (de_digtable.large_fa_hit >= 3) { +			if ((de_digtable.forbidden_igi + 1) > DM_DIG_MAX) +				de_digtable.rx_gain_range_min = DM_DIG_MAX; +			else +				de_digtable.rx_gain_range_min = +				    (de_digtable.forbidden_igi + 1); +			de_digtable.recover_cnt = 3600;	/* 3600=2hr */ +		} +	} else { +		/* Recovery mechanism for IGI lower bound */ +		if (de_digtable.recover_cnt != 0) { +			de_digtable.recover_cnt--; +		} else { +			if (de_digtable.large_fa_hit == 0) { +				if ((de_digtable.forbidden_igi - 1) < +				    DM_DIG_FA_LOWER) { +					de_digtable.forbidden_igi = +							 DM_DIG_FA_LOWER; +					de_digtable.rx_gain_range_min = +							 DM_DIG_FA_LOWER; + +				} else { +					de_digtable.forbidden_igi--; +					de_digtable.rx_gain_range_min = +					    (de_digtable.forbidden_igi + 1); +				} +			} else if (de_digtable.large_fa_hit == 3) { +				de_digtable.large_fa_hit = 0; +			} +		} +	} +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, +		 ("dm_DIG() After: large_fa_hit=%d, forbidden_igi=%x\n", +		  de_digtable.large_fa_hit, de_digtable.forbidden_igi)); +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, +		 ("dm_DIG() After: recover_cnt=%d, rx_gain_range_min=%x\n", +		  de_digtable.recover_cnt, de_digtable.rx_gain_range_min)); + +	if (value_igi > DM_DIG_MAX) +		value_igi = DM_DIG_MAX; +	else if (value_igi < de_digtable.rx_gain_range_min) +		value_igi = de_digtable.rx_gain_range_min; +	de_digtable.cur_igvalue = value_igi; +	rtl92d_dm_write_dig(hw); +	if (rtlpriv->rtlhal.current_bandtype != BAND_ON_5G) +		rtl92d_dm_cck_packet_detection_thresh(hw); +	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, ("<<==\n")); +} + +static void rtl92d_dm_init_dynamic_txpower(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	rtlpriv->dm.dynamic_txpower_enable = true; +	rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; +	rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; +} + +static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_hal *rtlhal = rtl_hal(rtlpriv); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	long undecorated_smoothed_pwdb; + +	if ((!rtlpriv->dm.dynamic_txpower_enable) +	    || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { +		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; +		return; +	} +	if ((mac->link_state < MAC80211_LINKED) && +	    (rtlpriv->dm.UNDEC_SM_PWDB == 0)) { +		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, +			 ("Not connected to any\n")); +		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; +		rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; +		return; +	} +	if (mac->link_state >= MAC80211_LINKED) { +		if (mac->opmode == NL80211_IFTYPE_ADHOC) { +			undecorated_smoothed_pwdb = +			    rtlpriv->dm.UNDEC_SM_PWDB; +			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, +				 ("IBSS Client PWDB = 0x%lx\n", +				  undecorated_smoothed_pwdb)); +		} else { +			undecorated_smoothed_pwdb = +			    rtlpriv->dm.undecorated_smoothed_pwdb; +			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, +				 ("STA Default Port PWDB = 0x%lx\n", +				  undecorated_smoothed_pwdb)); +		} +	} else { +		undecorated_smoothed_pwdb = +		    rtlpriv->dm.UNDEC_SM_PWDB; + +		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, +			 ("AP Ext Port PWDB = 0x%lx\n", +			  undecorated_smoothed_pwdb)); +	} +	if (rtlhal->current_bandtype == BAND_ON_5G) { +		if (undecorated_smoothed_pwdb >= 0x33) { +			rtlpriv->dm.dynamic_txhighpower_lvl = +						 TXHIGHPWRLEVEL_LEVEL2; +			RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, +				 ("5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n")); +		} else if ((undecorated_smoothed_pwdb < 0x33) +			   && (undecorated_smoothed_pwdb >= 0x2b)) { +			rtlpriv->dm.dynamic_txhighpower_lvl = +						 TXHIGHPWRLEVEL_LEVEL1; +			RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, +				 ("5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n")); +		} else if (undecorated_smoothed_pwdb < 0x2b) { +			rtlpriv->dm.dynamic_txhighpower_lvl = +						 TXHIGHPWRLEVEL_NORMAL; +			RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, +				 ("5G:TxHighPwrLevel_Normal\n")); +		} +	} else { +		if (undecorated_smoothed_pwdb >= +		    TX_POWER_NEAR_FIELD_THRESH_LVL2) { +			rtlpriv->dm.dynamic_txhighpower_lvl = +						 TXHIGHPWRLEVEL_LEVEL2; +			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, +				 ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n")); +		} else +		    if ((undecorated_smoothed_pwdb < +			 (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) +			&& (undecorated_smoothed_pwdb >= +			    TX_POWER_NEAR_FIELD_THRESH_LVL1)) { + +			rtlpriv->dm.dynamic_txhighpower_lvl = +						 TXHIGHPWRLEVEL_LEVEL1; +			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, +				 ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n")); +		} else if (undecorated_smoothed_pwdb < +			   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { +			rtlpriv->dm.dynamic_txhighpower_lvl = +						 TXHIGHPWRLEVEL_NORMAL; +			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, +				 ("TXHIGHPWRLEVEL_NORMAL\n")); +		} +	} +	if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { +		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, +			 ("PHY_SetTxPowerLevel8192S() Channel = %d\n", +			  rtlphy->current_channel)); +		rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); +	} +	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; +} + +static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	/* AP & ADHOC & MESH will return tmp */ +	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) +		return; +	/* Indicate Rx signal strength to FW. */ +	if (rtlpriv->dm.useramask) { +		u32 temp = rtlpriv->dm.undecorated_smoothed_pwdb; + +		temp <<= 16; +		temp |= 0x100; +		/* fw v12 cmdid 5:use max macid ,for nic , +		 * default macid is 0 ,max macid is 1 */ +		rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp)); +	} else { +		rtl_write_byte(rtlpriv, 0x4fe, +			       (u8) rtlpriv->dm.undecorated_smoothed_pwdb); +	} +} + +void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	rtlpriv->dm.current_turbo_edca = false; +	rtlpriv->dm.is_any_nonbepkts = false; +	rtlpriv->dm.is_cur_rdlstate = false; +} + +static void rtl92d_dm_check_edca_turbo(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	static u64 last_txok_cnt; +	static u64 last_rxok_cnt; +	u64 cur_txok_cnt; +	u64 cur_rxok_cnt; +	u32 edca_be_ul = 0x5ea42b; +	u32 edca_be_dl = 0x5ea42b; + +	if (mac->link_state != MAC80211_LINKED) { +		rtlpriv->dm.current_turbo_edca = false; +		goto exit; +	} + +	/* Enable BEQ TxOP limit configuration in wireless G-mode. */ +	/* To check whether we shall force turn on TXOP configuration. */ +	if ((!rtlpriv->dm.disable_framebursting) && +	    (rtlpriv->sec.pairwise_enc_algorithm == WEP40_ENCRYPTION || +	    rtlpriv->sec.pairwise_enc_algorithm == WEP104_ENCRYPTION || +	    rtlpriv->sec.pairwise_enc_algorithm == TKIP_ENCRYPTION)) { +		/* Force TxOP limit to 0x005e for UL. */ +		if (!(edca_be_ul & 0xffff0000)) +			edca_be_ul |= 0x005e0000; +		/* Force TxOP limit to 0x005e for DL. */ +		if (!(edca_be_dl & 0xffff0000)) +			edca_be_dl |= 0x005e0000; +	} + +	if ((!rtlpriv->dm.is_any_nonbepkts) && +	    (!rtlpriv->dm.disable_framebursting)) { +		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; +		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; +		if (cur_rxok_cnt > 4 * cur_txok_cnt) { +			if (!rtlpriv->dm.is_cur_rdlstate || +			    !rtlpriv->dm.current_turbo_edca) { +				rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, +						edca_be_dl); +				rtlpriv->dm.is_cur_rdlstate = true; +			} +		} else { +			if (rtlpriv->dm.is_cur_rdlstate || +			    !rtlpriv->dm.current_turbo_edca) { +				rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, +						edca_be_ul); +				rtlpriv->dm.is_cur_rdlstate = false; +			} +		} +		rtlpriv->dm.current_turbo_edca = true; +	} else { +		if (rtlpriv->dm.current_turbo_edca) { +			u8 tmp = AC0_BE; +			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, +						      (u8 *) (&tmp)); +			rtlpriv->dm.current_turbo_edca = false; +		} +	} + +exit: +	rtlpriv->dm.is_any_nonbepkts = false; +	last_txok_cnt = rtlpriv->stats.txbytesunicast; +	last_rxok_cnt = rtlpriv->stats.rxbytesunicast; +} + +static void rtl92d_dm_rxgain_tracking_thermalmeter(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 index_mapping[RX_INDEX_MAPPING_NUM] = { +		0x0f, 0x0f, 0x0d, 0x0c, 0x0b, +		0x0a, 0x09, 0x08, 0x07, 0x06, +		0x05, 0x04, 0x04, 0x03, 0x02 +	}; +	int i; +	u32 u4tmp; + +	u4tmp = (index_mapping[(rtlpriv->efuse.eeprom_thermalmeter - +				rtlpriv->dm.thermalvalue_rxgain)]) << 12; +	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +		 ("===> Rx Gain %x\n", u4tmp)); +	for (i = RF90_PATH_A; i < rtlpriv->phy.num_total_rfpath; i++) +		rtl_set_rfreg(hw, i, 0x3C, BRFREGOFFSETMASK, +			      (rtlpriv->phy.reg_rf3c[i] & (~(0xF000))) | u4tmp); +} + +static void rtl92d_bandtype_2_4G(struct ieee80211_hw *hw, long *temp_cckg, +				 u8 *cck_index_old) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	int i; +	unsigned long flag = 0; +	long temp_cck; + +	/* Query CCK default setting From 0xa24 */ +	rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); +	temp_cck = rtl_get_bbreg(hw, RCCK0_TXFILTER2, +				 BMASKDWORD) & BMASKCCK; +	rtl92d_release_cckandrw_pagea_ctl(hw, &flag); +	for (i = 0; i < CCK_TABLE_LENGTH; i++) { +		if (rtlpriv->dm.cck_inch14) { +			if (!memcmp((void *)&temp_cck, +			    (void *)&cckswing_table_ch14[i][2], 4)) { +				*cck_index_old = (u8) i; +				RT_TRACE(rtlpriv, +					 COMP_POWER_TRACKING, +					 DBG_LOUD, +					 ("Initial reg0x%x = 0x%lx, " +					  "cck_index=0x%x, ch 14 %d\n", +					  RCCK0_TXFILTER2, +					  temp_cck, *cck_index_old, +					  rtlpriv->dm.cck_inch14)); +				break; +			} +		} else { +			if (!memcmp((void *) &temp_cck, +			    &cckswing_table_ch1ch13[i][2], 4)) { +				*cck_index_old = (u8) i; +				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, +					 DBG_LOUD, +					 ("Initial reg0x%x = 0x%lx, " +					 "cck_index = 0x%x, ch14 %d\n", +					 RCCK0_TXFILTER2, +					 temp_cck, *cck_index_old, +					 rtlpriv->dm.cck_inch14)); +				break; +			} +		} +	} +	*temp_cckg = temp_cck; +} + +static void rtl92d_bandtype_5G(struct rtl_hal *rtlhal, u8 *ofdm_index, +			       bool *internal_pa, u8 thermalvalue, u8 delta, +			       u8 rf, struct rtl_efuse *rtlefuse, +			       struct rtl_priv *rtlpriv, struct rtl_phy *rtlphy, +			       u8 index_mapping[5][INDEX_MAPPING_NUM], +			       u8 index_mapping_pa[8][INDEX_MAPPING_NUM]) +{ +	int i; +	u8 index; +	u8 offset = 0; + +	for (i = 0; i < rf; i++) { +		if (rtlhal->macphymode == DUALMAC_DUALPHY && +		    rtlhal->interfaceindex == 1)	/* MAC 1 5G */ +			*internal_pa = rtlefuse->internal_pa_5g[1]; +		else +			*internal_pa = rtlefuse->internal_pa_5g[i]; +		if (*internal_pa) { +			if (rtlhal->interfaceindex == 1 || i == rf) +				offset = 4; +			else +				offset = 0; +			if (rtlphy->current_channel >= 100 && +				rtlphy->current_channel <= 165) +				offset += 2; +		} else { +			if (rtlhal->interfaceindex == 1 || i == rf) +				offset = 2; +			else +				offset = 0; +		} +		if (thermalvalue > rtlefuse->eeprom_thermalmeter) +			offset++; +		if (*internal_pa) { +			if (delta > INDEX_MAPPING_NUM - 1) +				index = index_mapping_pa[offset] +						    [INDEX_MAPPING_NUM - 1]; +			else +				index = +				     index_mapping_pa[offset][delta]; +		} else { +			if (delta > INDEX_MAPPING_NUM - 1) +				index = +				   index_mapping[offset][INDEX_MAPPING_NUM - 1]; +			else +				index = index_mapping[offset][delta]; +		} +		if (thermalvalue > rtlefuse->eeprom_thermalmeter) { +			if (*internal_pa && thermalvalue > 0x12) { +				ofdm_index[i] = rtlpriv->dm.ofdm_index[i] - +						((delta / 2) * 3 + (delta % 2)); +			} else { +				ofdm_index[i] -= index; +			} +		} else { +			ofdm_index[i] += index; +		} +	} +} + +static void rtl92d_dm_txpower_tracking_callback_thermalmeter( +			struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	u8 thermalvalue, delta, delta_lck, delta_iqk, delta_rxgain; +	u8 offset, thermalvalue_avg_count = 0; +	u32 thermalvalue_avg = 0; +	bool internal_pa = false; +	long ele_a = 0, ele_d, temp_cck, val_x, value32; +	long val_y, ele_c = 0; +	u8 ofdm_index[2]; +	u8 cck_index = 0; +	u8 ofdm_index_old[2]; +	u8 cck_index_old = 0; +	u8 index; +	int i; +	bool is2t = IS_92D_SINGLEPHY(rtlhal->version); +	u8 ofdm_min_index = 6, ofdm_min_index_internal_pa = 3, rf; +	u8 indexforchannel = +	    rtl92d_get_rightchnlplace_for_iqk(rtlphy->current_channel); +	u8 index_mapping[5][INDEX_MAPPING_NUM] = { +		/* 5G, path A/MAC 0, decrease power  */ +		{0, 1, 3, 6, 8, 9,	11, 13, 14, 16, 17, 18, 18}, +		/* 5G, path A/MAC 0, increase power  */ +		{0, 2, 4, 5, 7, 10,	12, 14, 16, 18, 18, 18, 18}, +		/* 5G, path B/MAC 1, decrease power */ +		{0, 2, 3, 6, 8, 9,	11, 13, 14, 16, 17, 18, 18}, +		/* 5G, path B/MAC 1, increase power */ +		{0, 2, 4, 5, 7, 10,	13, 16, 16, 18, 18, 18, 18}, +		/* 2.4G, for decreas power */ +		{0, 1, 2, 3, 4, 5,	6, 7, 7, 8, 9, 10, 10}, +	}; +	u8 index_mapping_internal_pa[8][INDEX_MAPPING_NUM] = { +		/* 5G, path A/MAC 0, ch36-64, decrease power  */ +		{0, 1, 2, 4, 6, 7,	9, 11, 12, 14, 15, 16, 16}, +		/* 5G, path A/MAC 0, ch36-64, increase power  */ +		{0, 2, 4, 5, 7, 10,	12, 14, 16, 18, 18, 18, 18}, +		/* 5G, path A/MAC 0, ch100-165, decrease power  */ +		{0, 1, 2, 3, 5, 6,	8, 10, 11, 13, 14, 15, 15}, +		/* 5G, path A/MAC 0, ch100-165, increase power  */ +		{0, 2, 4, 5, 7, 10,	12, 14, 16, 18, 18, 18, 18}, +		/* 5G, path B/MAC 1, ch36-64, decrease power */ +		{0, 1, 2, 4, 6, 7,	9, 11, 12, 14, 15, 16, 16}, +		/* 5G, path B/MAC 1, ch36-64, increase power */ +		{0, 2, 4, 5, 7, 10,	13, 16, 16, 18, 18, 18, 18}, +		/* 5G, path B/MAC 1, ch100-165, decrease power */ +		{0, 1, 2, 3, 5, 6,	8, 9, 10, 12, 13, 14, 14}, +		/* 5G, path B/MAC 1, ch100-165, increase power */ +		{0, 2, 4, 5, 7, 10,	13, 16, 16, 18, 18, 18, 18}, +	}; + +	rtlpriv->dm.txpower_trackinginit = true; +	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("\n")); +	thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xf800); +	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +		 ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x " +		 "eeprom_thermalmeter 0x%x\n", thermalvalue, +		 rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter)); +	rtl92d_phy_ap_calibrate(hw, (thermalvalue - +				     rtlefuse->eeprom_thermalmeter)); +	if (is2t) +		rf = 2; +	else +		rf = 1; +	if (thermalvalue) { +		ele_d = rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, +				      BMASKDWORD) & BMASKOFDM_D; +		for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { +			if (ele_d == (ofdmswing_table[i] & BMASKOFDM_D)) { +				ofdm_index_old[0] = (u8) i; + +				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +					 ("Initial pathA ele_d reg0x%x = 0x%lx," +					 " ofdm_index=0x%x\n", +					 ROFDM0_XATxIQIMBALANCE, +					 ele_d, ofdm_index_old[0])); +				break; +			} +		} +		if (is2t) { +			ele_d = rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, +					      BMASKDWORD) & BMASKOFDM_D; +			for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) { +				if (ele_d == +				    (ofdmswing_table[i] & BMASKOFDM_D)) { +					ofdm_index_old[1] = (u8) i; +					RT_TRACE(rtlpriv, COMP_POWER_TRACKING, +						 DBG_LOUD, +						 ("Initial pathB ele_d reg " +						 "0x%x = 0x%lx, ofdm_index " +						 "= 0x%x\n", +						 ROFDM0_XBTxIQIMBALANCE, ele_d, +						 ofdm_index_old[1])); +					break; +				} +			} +		} +		if (rtlhal->current_bandtype == BAND_ON_2_4G) { +			rtl92d_bandtype_2_4G(hw, &temp_cck, &cck_index_old); +		} else { +			temp_cck = 0x090e1317; +			cck_index_old = 12; +		} + +		if (!rtlpriv->dm.thermalvalue) { +			rtlpriv->dm.thermalvalue = +				 rtlefuse->eeprom_thermalmeter; +			rtlpriv->dm.thermalvalue_lck = thermalvalue; +			rtlpriv->dm.thermalvalue_iqk = thermalvalue; +			rtlpriv->dm.thermalvalue_rxgain = +					 rtlefuse->eeprom_thermalmeter; +			for (i = 0; i < rf; i++) +				rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; +			rtlpriv->dm.cck_index = cck_index_old; +		} +		if (rtlhal->reloadtxpowerindex) { +			for (i = 0; i < rf; i++) +				rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i]; +			rtlpriv->dm.cck_index = cck_index_old; +			RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +				 ("reload ofdm index for band switch\n")); +		} +		rtlpriv->dm.thermalvalue_avg +			    [rtlpriv->dm.thermalvalue_avg_index] = thermalvalue; +		rtlpriv->dm.thermalvalue_avg_index++; +		if (rtlpriv->dm.thermalvalue_avg_index == AVG_THERMAL_NUM) +			rtlpriv->dm.thermalvalue_avg_index = 0; +		for (i = 0; i < AVG_THERMAL_NUM; i++) { +			if (rtlpriv->dm.thermalvalue_avg[i]) { +				thermalvalue_avg += +					 rtlpriv->dm.thermalvalue_avg[i]; +				thermalvalue_avg_count++; +			} +		} +		if (thermalvalue_avg_count) +			thermalvalue = (u8) (thermalvalue_avg / +					thermalvalue_avg_count); +		if (rtlhal->reloadtxpowerindex) { +			delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? +			    (thermalvalue - rtlefuse->eeprom_thermalmeter) : +			    (rtlefuse->eeprom_thermalmeter - thermalvalue); +			rtlhal->reloadtxpowerindex = false; +			rtlpriv->dm.done_txpower = false; +		} else if (rtlpriv->dm.done_txpower) { +			delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? +			    (thermalvalue - rtlpriv->dm.thermalvalue) : +			    (rtlpriv->dm.thermalvalue - thermalvalue); +		} else { +			delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? +			    (thermalvalue - rtlefuse->eeprom_thermalmeter) : +			    (rtlefuse->eeprom_thermalmeter - thermalvalue); +		} +		delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? +		    (thermalvalue - rtlpriv->dm.thermalvalue_lck) : +		    (rtlpriv->dm.thermalvalue_lck - thermalvalue); +		delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? +		    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : +		    (rtlpriv->dm.thermalvalue_iqk - thermalvalue); +		delta_rxgain = +			(thermalvalue > rtlpriv->dm.thermalvalue_rxgain) ? +			(thermalvalue - rtlpriv->dm.thermalvalue_rxgain) : +			(rtlpriv->dm.thermalvalue_rxgain - thermalvalue); +		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +			 ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x" +			  " eeprom_thermalmeter 0x%x delta 0x%x " +			  "delta_lck 0x%x delta_iqk 0x%x\n", +			  thermalvalue, rtlpriv->dm.thermalvalue, +			  rtlefuse->eeprom_thermalmeter, delta, delta_lck, +			  delta_iqk)); +		if ((delta_lck > rtlefuse->delta_lck) && +		    (rtlefuse->delta_lck != 0)) { +			rtlpriv->dm.thermalvalue_lck = thermalvalue; +			rtl92d_phy_lc_calibrate(hw); +		} +		if (delta > 0 && rtlpriv->dm.txpower_track_control) { +			rtlpriv->dm.done_txpower = true; +			delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? +			    (thermalvalue - rtlefuse->eeprom_thermalmeter) : +			    (rtlefuse->eeprom_thermalmeter - thermalvalue); +			if (rtlhal->current_bandtype == BAND_ON_2_4G) { +				offset = 4; +				if (delta > INDEX_MAPPING_NUM - 1) +					index = index_mapping[offset] +						[INDEX_MAPPING_NUM - 1]; +				else +					index = index_mapping[offset][delta]; +				if (thermalvalue > rtlpriv->dm.thermalvalue) { +					for (i = 0; i < rf; i++) +						ofdm_index[i] -= delta; +					cck_index -= delta; +				} else { +					for (i = 0; i < rf; i++) +						ofdm_index[i] += index; +					cck_index += index; +				} +			} else if (rtlhal->current_bandtype == BAND_ON_5G) { +				rtl92d_bandtype_5G(rtlhal, ofdm_index, +						   &internal_pa, thermalvalue, +						   delta, rf, rtlefuse, rtlpriv, +						   rtlphy, index_mapping, +						   index_mapping_internal_pa); +			} +			if (is2t) { +				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +					 ("temp OFDM_A_index=0x%x, OFDM_B_index" +					 " = 0x%x,cck_index=0x%x\n", +					  rtlpriv->dm.ofdm_index[0], +					  rtlpriv->dm.ofdm_index[1], +					  rtlpriv->dm.cck_index)); +			} else { +				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +					 ("temp OFDM_A_index=0x%x,cck_index = " +					 "0x%x\n", +					  rtlpriv->dm.ofdm_index[0], +							rtlpriv->dm.cck_index)); +			} +			for (i = 0; i < rf; i++) { +				if (ofdm_index[i] > OFDM_TABLE_SIZE_92D - 1) +					ofdm_index[i] = OFDM_TABLE_SIZE_92D - 1; +				else if (ofdm_index[i] < ofdm_min_index) +					ofdm_index[i] = ofdm_min_index; +			} +			if (rtlhal->current_bandtype == BAND_ON_2_4G) { +				if (cck_index > CCK_TABLE_SIZE - 1) { +					cck_index = CCK_TABLE_SIZE - 1; +				} else if (internal_pa || +					   rtlhal->current_bandtype == +					   BAND_ON_2_4G) { +					if (ofdm_index[i] < +					    ofdm_min_index_internal_pa) +						ofdm_index[i] = +						     ofdm_min_index_internal_pa; +				} else if (cck_index < 0) { +					cck_index = 0; +				} +			} +			if (is2t) { +				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +					 ("new OFDM_A_index=0x%x, OFDM_B_index " +					 "= 0x%x, cck_index=0x%x\n", +					 ofdm_index[0], ofdm_index[1], +					 cck_index)); +			} else { +				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +					 ("new OFDM_A_index=0x%x,cck_index = " +					 "0x%x\n", +					  ofdm_index[0], cck_index)); +			} +			ele_d = (ofdmswing_table[(u8) ofdm_index[0]] & +						 0xFFC00000) >> 22; +			val_x = rtlphy->iqk_matrix_regsetting +						[indexforchannel].value[0][0]; +			val_y = rtlphy->iqk_matrix_regsetting +						[indexforchannel].value[0][1]; +			if (val_x != 0) { +				if ((val_x & 0x00000200) != 0) +					val_x = val_x | 0xFFFFFC00; +				ele_a = +				    ((val_x * ele_d) >> 8) & 0x000003FF; + +				/* new element C = element D x Y */ +				if ((val_y & 0x00000200) != 0) +					val_y = val_y | 0xFFFFFC00; +				ele_c = ((val_y * ele_d) >> 8) & 0x000003FF; + +				/* wirte new elements A, C, D to regC80 and +				 * regC94, element B is always 0 */ +				value32 = (ele_d << 22) | ((ele_c & 0x3F) << +					  16) | ele_a; +				rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, +					      BMASKDWORD, value32); + +				value32 = (ele_c & 0x000003C0) >> 6; +				rtl_set_bbreg(hw, ROFDM0_XCTxAFE, BMASKH4BITS, +					      value32); + +				value32 = ((val_x * ele_d) >> 7) & 0x01; +				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), +					      value32); + +			} else { +				rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, +					      BMASKDWORD, +					      ofdmswing_table +					      [(u8)ofdm_index[0]]); +				rtl_set_bbreg(hw, ROFDM0_XCTxAFE, BMASKH4BITS, +					      0x00); +				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, +					      BIT(24), 0x00); +			} + +			RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +				 ("TxPwrTracking for interface %d path A: X =" +				 " 0x%lx, Y = 0x%lx ele_A = 0x%lx ele_C = " +				 "0x%lx ele_D = 0x%lx 0xe94 = 0x%lx 0xe9c = " +				 "0x%lx\n", rtlhal->interfaceindex, +				 val_x, val_y, ele_a, ele_c, ele_d, +				 val_x, val_y)); + +			if (rtlhal->current_bandtype == BAND_ON_2_4G) { +				/* Adjust CCK according to IQK result */ +				if (!rtlpriv->dm.cck_inch14) { +					rtl_write_byte(rtlpriv, 0xa22, +						       cckswing_table_ch1ch13 +						       [(u8)cck_index][0]); +					rtl_write_byte(rtlpriv, 0xa23, +						       cckswing_table_ch1ch13 +						       [(u8)cck_index][1]); +					rtl_write_byte(rtlpriv, 0xa24, +						       cckswing_table_ch1ch13 +						       [(u8)cck_index][2]); +					rtl_write_byte(rtlpriv, 0xa25, +						       cckswing_table_ch1ch13 +						       [(u8)cck_index][3]); +					rtl_write_byte(rtlpriv, 0xa26, +						       cckswing_table_ch1ch13 +						       [(u8)cck_index][4]); +					rtl_write_byte(rtlpriv, 0xa27, +						       cckswing_table_ch1ch13 +						       [(u8)cck_index][5]); +					rtl_write_byte(rtlpriv, 0xa28, +						       cckswing_table_ch1ch13 +						       [(u8)cck_index][6]); +					rtl_write_byte(rtlpriv, 0xa29, +						       cckswing_table_ch1ch13 +						       [(u8)cck_index][7]); +				} else { +					rtl_write_byte(rtlpriv, 0xa22, +						       cckswing_table_ch14 +						       [(u8)cck_index][0]); +					rtl_write_byte(rtlpriv, 0xa23, +						       cckswing_table_ch14 +						       [(u8)cck_index][1]); +					rtl_write_byte(rtlpriv, 0xa24, +						       cckswing_table_ch14 +						       [(u8)cck_index][2]); +					rtl_write_byte(rtlpriv, 0xa25, +						       cckswing_table_ch14 +						       [(u8)cck_index][3]); +					rtl_write_byte(rtlpriv, 0xa26, +						       cckswing_table_ch14 +						       [(u8)cck_index][4]); +					rtl_write_byte(rtlpriv, 0xa27, +						       cckswing_table_ch14 +						       [(u8)cck_index][5]); +					rtl_write_byte(rtlpriv, 0xa28, +						       cckswing_table_ch14 +						       [(u8)cck_index][6]); +					rtl_write_byte(rtlpriv, 0xa29, +						       cckswing_table_ch14 +						       [(u8)cck_index][7]); +				} +			} +			if (is2t) { +				ele_d = (ofdmswing_table[(u8) ofdm_index[1]] & +						0xFFC00000) >> 22; +				val_x = rtlphy->iqk_matrix_regsetting +						[indexforchannel].value[0][4]; +				val_y = rtlphy->iqk_matrix_regsetting +						[indexforchannel].value[0][5]; +				if (val_x != 0) { +					if ((val_x & 0x00000200) != 0) +						/* consider minus */ +						val_x = val_x | 0xFFFFFC00; +					ele_a = ((val_x * ele_d) >> 8) & +						0x000003FF; +					/* new element C = element D x Y */ +					if ((val_y & 0x00000200) != 0) +						val_y = +						    val_y | 0xFFFFFC00; +					ele_c = +					    ((val_y * +					      ele_d) >> 8) & 0x00003FF; +					/* write new elements A, C, D to regC88 +					 * and regC9C, element B is always 0 +					 */ +					value32 = (ele_d << 22) | +						  ((ele_c & 0x3F) << 16) | +						  ele_a; +					rtl_set_bbreg(hw, +						      ROFDM0_XBTxIQIMBALANCE, +						      BMASKDWORD, value32); +					value32 = (ele_c & 0x000003C0) >> 6; +					rtl_set_bbreg(hw, ROFDM0_XDTxAFE, +						      BMASKH4BITS, value32); +					value32 = ((val_x * ele_d) >> 7) & 0x01; +					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, +						      BIT(28), value32); +				} else { +					rtl_set_bbreg(hw, +						      ROFDM0_XBTxIQIMBALANCE, +						      BMASKDWORD, +						      ofdmswing_table +						      [(u8) ofdm_index[1]]); +					rtl_set_bbreg(hw, ROFDM0_XDTxAFE, +						      BMASKH4BITS, 0x00); +					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, +						      BIT(28), 0x00); +				} +				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +					 ("TxPwrTracking path B: X = 0x%lx, " +					 "Y = 0x%lx ele_A = 0x%lx ele_C = 0x" +					 "%lx ele_D = 0x%lx 0xeb4 = 0x%lx " +					 "0xebc = 0x%lx\n", +					  val_x, val_y, ele_a, ele_c, +					  ele_d, val_x, val_y)); +			} +			RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +				 ("TxPwrTracking 0xc80 = 0x%x, 0xc94 = " +				 "0x%x RF 0x24 = 0x%x\n", +				 rtl_get_bbreg(hw, 0xc80, BMASKDWORD), +				 rtl_get_bbreg(hw, 0xc94, BMASKDWORD), +				 rtl_get_rfreg(hw, RF90_PATH_A, 0x24, +				 BRFREGOFFSETMASK))); +		} +		if ((delta_iqk > rtlefuse->delta_iqk) && +		    (rtlefuse->delta_iqk != 0)) { +			rtl92d_phy_reset_iqk_result(hw); +			rtlpriv->dm.thermalvalue_iqk = thermalvalue; +			rtl92d_phy_iq_calibrate(hw); +		} +		if (delta_rxgain > 0 && rtlhal->current_bandtype == BAND_ON_5G +		    && thermalvalue <= rtlefuse->eeprom_thermalmeter) { +			rtlpriv->dm.thermalvalue_rxgain = thermalvalue; +			rtl92d_dm_rxgain_tracking_thermalmeter(hw); +		} +		if (rtlpriv->dm.txpower_track_control) +			rtlpriv->dm.thermalvalue = thermalvalue; +	} + +	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("<===\n")); +} + +static void rtl92d_dm_initialize_txpower_tracking(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	rtlpriv->dm.txpower_tracking = true; +	rtlpriv->dm.txpower_trackinginit = false; +	rtlpriv->dm.txpower_track_control = true; +	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +		 ("pMgntInfo->txpower_tracking = %d\n", +		 rtlpriv->dm.txpower_tracking)); +} + +void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	static u8 tm_trigger; + +	if (!rtlpriv->dm.txpower_tracking) +		return; + +	if (!tm_trigger) { +		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | +			      BIT(16), 0x03); +		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +			 ("Trigger 92S Thermal Meter!!\n")); +		tm_trigger = 1; +		return; +	} else { +		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, +			 ("Schedule TxPowerTracking direct call!!\n")); +		rtl92d_dm_txpower_tracking_callback_thermalmeter(hw); +		tm_trigger = 0; +	} +} + +void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rate_adaptive *ra = &(rtlpriv->ra); + +	ra->ratr_state = DM_RATR_STA_INIT; +	ra->pre_ratr_state = DM_RATR_STA_INIT; +	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) +		rtlpriv->dm.useramask = true; +	else +		rtlpriv->dm.useramask = false; +} + +void rtl92d_dm_init(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; +	rtl92d_dm_diginit(hw); +	rtl92d_dm_init_dynamic_txpower(hw); +	rtl92d_dm_init_edca_turbo(hw); +	rtl92d_dm_init_rate_adaptive_mask(hw); +	rtl92d_dm_initialize_txpower_tracking(hw); +} + +void rtl92d_dm_watchdog(struct ieee80211_hw *hw) +{ +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); +	bool fw_current_inpsmode = false; +	bool fwps_awake = true; + +	/* 1. RF is OFF. (No need to do DM.) +	 * 2. Fw is under power saving mode for FwLPS. +	 *    (Prevent from SW/FW I/O racing.) +	 * 3. IPS workitem is scheduled. (Prevent from IPS sequence +	 *    to be swapped with DM. +	 * 4. RFChangeInProgress is TRUE. +	 *    (Prevent from broken by IPS/HW/SW Rf off.) */ + +	if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && +	    fwps_awake) && (!ppsc->rfchange_inprogress)) { +		rtl92d_dm_pwdb_monitor(hw); +		rtl92d_dm_false_alarm_counter_statistics(hw); +		rtl92d_dm_find_minimum_rssi(hw); +		rtl92d_dm_dig(hw); +		/* rtl92d_dm_dynamic_bb_powersaving(hw); */ +		rtl92d_dm_dynamic_txpower(hw); +		/* rtl92d_dm_check_txpower_tracking_thermal_meter(hw); */ +		/* rtl92d_dm_refresh_rate_adaptive_mask(hw); */ +		/* rtl92d_dm_interrupt_migration(hw); */ +		rtl92d_dm_check_edca_turbo(hw); +	} +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/dm.h b/drivers/net/wireless/rtlwifi/rtl8192de/dm.h new file mode 100644 index 00000000000..69354657f0f --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/dm.h @@ -0,0 +1,212 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef	__RTL92C_DM_H__ +#define __RTL92C_DM_H__ + +#define HAL_DM_DIG_DISABLE			BIT(0) +#define HAL_DM_HIPWR_DISABLE			BIT(1) + +#define OFDM_TABLE_LENGTH			37 +#define OFDM_TABLE_SIZE_92D			43 +#define CCK_TABLE_LENGTH			33 + +#define CCK_TABLE_SIZE				33 + +#define BW_AUTO_SWITCH_HIGH_LOW			25 +#define BW_AUTO_SWITCH_LOW_HIGH			30 + +#define DM_DIG_THRESH_HIGH			40 +#define DM_DIG_THRESH_LOW			35 + +#define DM_FALSEALARM_THRESH_LOW		400 +#define DM_FALSEALARM_THRESH_HIGH		1000 + +#define DM_DIG_MAX				0x3e +#define DM_DIG_MIN				0x1c + +#define DM_DIG_FA_UPPER				0x32 +#define DM_DIG_FA_LOWER				0x20 +#define DM_DIG_FA_TH0				0x100 +#define DM_DIG_FA_TH1				0x400 +#define DM_DIG_FA_TH2				0x600 + +#define DM_DIG_BACKOFF_MAX			12 +#define DM_DIG_BACKOFF_MIN			-4 +#define DM_DIG_BACKOFF_DEFAULT			10 + +#define RXPATHSELECTION_SS_TH_lOW		30 +#define RXPATHSELECTION_DIFF_TH			18 + +#define DM_RATR_STA_INIT			0 +#define DM_RATR_STA_HIGH			1 +#define DM_RATR_STA_MIDDLE			2 +#define DM_RATR_STA_LOW				3 + +#define CTS2SELF_THVAL				30 +#define REGC38_TH				20 + +#define WAIOTTHVAL				25 + +#define TXHIGHPWRLEVEL_NORMAL			0 +#define TXHIGHPWRLEVEL_LEVEL1			1 +#define TXHIGHPWRLEVEL_LEVEL2			2 +#define TXHIGHPWRLEVEL_BT1			3 +#define TXHIGHPWRLEVEL_BT2			4 + +#define DM_TYPE_BYFW				0 +#define DM_TYPE_BYDRIVER			1 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2		74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1		67 +#define INDEX_MAPPING_NUM			13 + +struct ps_t { +	u8 pre_ccastate; +	u8 cur_ccasate; + +	u8 pre_rfstate; +	u8 cur_rfstate; + +	long rssi_val_min; +}; + +struct dig_t { +	u8 dig_enable_flag; +	u8 dig_ext_port_stage; + +	u32 rssi_lowthresh; +	u32 rssi_highthresh; + +	u32 fa_lowthresh; +	u32 fa_highthresh; + +	u8 cursta_connectctate; +	u8 presta_connectstate; +	u8 curmultista_connectstate; + +	u8 pre_igvalue; +	u8 cur_igvalue; + +	char backoff_val; +	char backoff_val_range_max; +	char backoff_val_range_min; +	u8 rx_gain_range_max; +	u8 rx_gain_range_min; +	u8 min_undecorated_pwdb_for_dm; +	long last_min_undecorated_pwdb_for_dm; + +	u8 pre_cck_pd_state; +	u8 cur_cck_pd_state; + +	u8 pre_cck_fa_state; +	u8 cur_cck_fa_state; + +	u8 pre_ccastate; +	u8 cur_ccasate; + +	u8 large_fa_hit; +	u8 forbidden_igi; +	u32 recover_cnt; +}; + +struct swat { +	u8 failure_cnt; +	u8 try_flag; +	u8 stop_trying; +	long pre_rssi; +	long trying_threshold; +	u8 cur_antenna; +	u8 pre_antenna; +}; + +enum tag_dynamic_init_gain_operation_type_definition { +	DIG_TYPE_THRESH_HIGH = 0, +	DIG_TYPE_THRESH_LOW = 1, +	DIG_TYPE_BACKOFF = 2, +	DIG_TYPE_RX_GAIN_MIN = 3, +	DIG_TYPE_RX_GAIN_MAX = 4, +	DIG_TYPE_ENABLE = 5, +	DIG_TYPE_DISABLE = 6, +	DIG_OP_TYPE_MAX +}; + +enum tag_cck_packet_detection_threshold_type_definition { +	CCK_PD_STAGE_LOWRSSI = 0, +	CCK_PD_STAGE_HIGHRSSI = 1, +	CCK_FA_STAGE_LOW = 2, +	CCK_FA_STAGE_HIGH = 3, +	CCK_PD_STAGE_MAX = 4, +}; + +enum dm_1r_cca { +	CCA_1R = 0, +	CCA_2R = 1, +	CCA_MAX = 2, +}; + +enum dm_rf { +	RF_SAVE = 0, +	RF_NORMAL = 1, +	RF_MAX = 2, +}; + +enum dm_sw_ant_switch { +	ANS_ANTENNA_B = 1, +	ANS_ANTENNA_A = 2, +	ANS_ANTENNA_MAX = 3, +}; + +enum dm_dig_ext_port_alg { +	DIG_EXT_PORT_STAGE_0 = 0, +	DIG_EXT_PORT_STAGE_1 = 1, +	DIG_EXT_PORT_STAGE_2 = 2, +	DIG_EXT_PORT_STAGE_3 = 3, +	DIG_EXT_PORT_STAGE_MAX = 4, +}; + +enum dm_dig_connect { +	DIG_STA_DISCONNECT = 0, +	DIG_STA_CONNECT = 1, +	DIG_STA_BEFORE_CONNECT = 2, +	DIG_MULTISTA_DISCONNECT = 3, +	DIG_MULTISTA_CONNECT = 4, +	DIG_CONNECT_MAX +}; + +extern struct dig_t de_digtable; + +void rtl92d_dm_init(struct ieee80211_hw *hw); +void rtl92d_dm_watchdog(struct ieee80211_hw *hw); +void rtl92d_dm_init_edca_turbo(struct ieee80211_hw *hw); +void rtl92d_dm_write_dig(struct ieee80211_hw *hw); +void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw); +void rtl92d_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c new file mode 100644 index 00000000000..82f060bdbc0 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c @@ -0,0 +1,790 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "fw.h" +#include "sw.h" + +static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv) +{ +	return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ? +		true : false; +} + +static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 tmp; + +	if (enable) { +		tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); +		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04); +		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); +		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); +		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); +		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); +	} else { +		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); +		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); +		/* Reserved for fw extension. +		 * 0x81[7] is used for mac0 status , +		 * so don't write this reg here +		 * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/ +	} +} + +static void _rtl92d_fw_block_write(struct ieee80211_hw *hw, +				   const u8 *buffer, u32 size) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 blocksize = sizeof(u32); +	u8 *bufferptr = (u8 *) buffer; +	u32 *pu4BytePtr = (u32 *) buffer; +	u32 i, offset, blockCount, remainSize; + +	blockCount = size / blocksize; +	remainSize = size % blocksize; +	for (i = 0; i < blockCount; i++) { +		offset = i * blocksize; +		rtl_write_dword(rtlpriv, (FW_8192D_START_ADDRESS + offset), +				*(pu4BytePtr + i)); +	} +	if (remainSize) { +		offset = blockCount * blocksize; +		bufferptr += offset; +		for (i = 0; i < remainSize; i++) { +			rtl_write_byte(rtlpriv, (FW_8192D_START_ADDRESS + +						 offset + i), *(bufferptr + i)); +		} +	} +} + +static void _rtl92d_fw_page_write(struct ieee80211_hw *hw, +				  u32 page, const u8 *buffer, u32 size) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 value8; +	u8 u8page = (u8) (page & 0x07); + +	value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page; +	rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8); +	_rtl92d_fw_block_write(hw, buffer, size); +} + +static void _rtl92d_fill_dummy(u8 *pfwbuf, u32 *pfwlen) +{ +	u32 fwlen = *pfwlen; +	u8 remain = (u8) (fwlen % 4); + +	remain = (remain == 0) ? 0 : (4 - remain); +	while (remain > 0) { +		pfwbuf[fwlen] = 0; +		fwlen++; +		remain--; +	} +	*pfwlen = fwlen; +} + +static void _rtl92d_write_fw(struct ieee80211_hw *hw, +			     enum version_8192d version, u8 *buffer, u32 size) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u8 *bufferPtr = (u8 *) buffer; +	u32 pagenums, remainSize; +	u32 page, offset; + +	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size)); +	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) +		_rtl92d_fill_dummy(bufferPtr, &size); +	pagenums = size / FW_8192D_PAGE_SIZE; +	remainSize = size % FW_8192D_PAGE_SIZE; +	if (pagenums > 8) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("Page numbers should not greater then 8\n")); +	} +	for (page = 0; page < pagenums; page++) { +		offset = page * FW_8192D_PAGE_SIZE; +		_rtl92d_fw_page_write(hw, page, (bufferPtr + offset), +				      FW_8192D_PAGE_SIZE); +	} +	if (remainSize) { +		offset = pagenums * FW_8192D_PAGE_SIZE; +		page = pagenums; +		_rtl92d_fw_page_write(hw, page, (bufferPtr + offset), +				      remainSize); +	} +} + +static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 counter = 0; +	u32 value32; + +	do { +		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); +	} while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) && +		 (!(value32 & FWDL_ChkSum_rpt))); +	if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("chksum report faill ! REG_MCUFWDL:0x%08x .\n", +			 value32)); +		return -EIO; +	} +	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, +		 ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32)); +	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); +	value32 |= MCUFWDL_RDY; +	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); +	return 0; +} + +void rtl92d_firmware_selfreset(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 u1b_tmp; +	u8 delay = 100; + +	/* Set (REG_HMETFR + 3) to  0x20 is reset 8051 */ +	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); +	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); +	while (u1b_tmp & BIT(2)) { +		delay--; +		if (delay == 0) +			break; +		udelay(50); +		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); +	} +	RT_ASSERT((delay > 0), ("8051 reset failed!\n")); +	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, +		 ("=====> 8051 reset success (%d) .\n", delay)); +} + +static int _rtl92d_fw_init(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u32 counter; + +	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, ("FW already have download\n")); +	/* polling for FW ready */ +	counter = 0; +	do { +		if (rtlhal->interfaceindex == 0) { +			if (rtl_read_byte(rtlpriv, FW_MAC0_READY) & +			    MAC0_READY) { +				RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, +					 ("Polling FW ready success!! " +					 "REG_MCUFWDL: 0x%x .\n", +					 rtl_read_byte(rtlpriv, +					 FW_MAC0_READY))); +				return 0; +			} +			udelay(5); +		} else { +			if (rtl_read_byte(rtlpriv, FW_MAC1_READY) & +			    MAC1_READY) { +				RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, +					 ("Polling FW ready success!! " +					 "REG_MCUFWDL: 0x%x .\n", +					 rtl_read_byte(rtlpriv, +						       FW_MAC1_READY))); +				return 0; +			} +			udelay(5); +		} +	} while (counter++ < POLLING_READY_TIMEOUT_COUNT); + +	if (rtlhal->interfaceindex == 0) { +		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, +			 ("Polling FW ready fail!! MAC0 FW init not ready: " +			 "0x%x .\n", +			 rtl_read_byte(rtlpriv, FW_MAC0_READY))); +	} else { +		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, +			 ("Polling FW ready fail!! MAC1 FW init not ready: " +			 "0x%x .\n", +			 rtl_read_byte(rtlpriv, FW_MAC1_READY))); +	} +	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, +		 ("Polling FW ready fail!! REG_MCUFWDL:0x%08ul .\n", +		 rtl_read_dword(rtlpriv, REG_MCUFWDL))); +	return -1; +} + +int rtl92d_download_fw(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u8 *pfwheader; +	u8 *pfwdata; +	u32 fwsize; +	int err; +	enum version_8192d version = rtlhal->version; +	u8 value; +	u32 count; +	bool fw_downloaded = false, fwdl_in_process = false; +	unsigned long flags; + +	if (!rtlhal->pfirmware) +		return 1; +	fwsize = rtlhal->fwsize; +	pfwheader = (u8 *) rtlhal->pfirmware; +	pfwdata = (u8 *) rtlhal->pfirmware; +	rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader); +	rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, (" FirmwareVersion(%d)," +		 "FirmwareSubVersion(%d), Signature(%#x)\n", +		 rtlhal->fw_version,	rtlhal->fw_subversion, +		 GET_FIRMWARE_HDR_SIGNATURE(pfwheader))); +	if (IS_FW_HEADER_EXIST(pfwheader)) { +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +			 ("Shift 32 bytes for FW header!!\n")); +		pfwdata = pfwdata + 32; +		fwsize = fwsize - 32; +	} + +	spin_lock_irqsave(&globalmutex_for_fwdownload, flags); +	fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv); +	if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5)) +		fwdl_in_process = true; +	else +		fwdl_in_process = false; +	if (fw_downloaded) { +		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); +		goto exit; +	} else if (fwdl_in_process) { +		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); +		for (count = 0; count < 5000; count++) { +			udelay(500); +			spin_lock_irqsave(&globalmutex_for_fwdownload, flags); +			fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv); +			if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5)) +				fwdl_in_process = true; +			else +				fwdl_in_process = false; +			spin_unlock_irqrestore(&globalmutex_for_fwdownload, +					       flags); +			if (fw_downloaded) +				goto exit; +			else if (!fwdl_in_process) +				break; +			else +				RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, +					 ("Wait for another mac " +					 "download fw\n")); +		} +		spin_lock_irqsave(&globalmutex_for_fwdownload, flags); +		value = rtl_read_byte(rtlpriv, 0x1f); +		value |= BIT(5); +		rtl_write_byte(rtlpriv, 0x1f, value); +		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); +	} else { +		value = rtl_read_byte(rtlpriv, 0x1f); +		value |= BIT(5); +		rtl_write_byte(rtlpriv, 0x1f, value); +		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); +	} + +	/* If 8051 is running in RAM code, driver should +	 * inform Fw to reset by itself, or it will cause +	 * download Fw fail.*/ +	/* 8051 RAM code */ +	if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) { +		rtl92d_firmware_selfreset(hw); +		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); +	} +	_rtl92d_enable_fw_download(hw, true); +	_rtl92d_write_fw(hw, version, pfwdata, fwsize); +	_rtl92d_enable_fw_download(hw, false); +	spin_lock_irqsave(&globalmutex_for_fwdownload, flags); +	err = _rtl92d_fw_free_to_go(hw); +	/* download fw over,clear 0x1f[5] */ +	value = rtl_read_byte(rtlpriv, 0x1f); +	value &= (~BIT(5)); +	rtl_write_byte(rtlpriv, 0x1f, value); +	spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags); +	if (err) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("fw is not ready to run!\n")); +		goto exit; +	} else { +		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, +			 ("fw is ready to run!\n")); +	} +exit: +	err = _rtl92d_fw_init(hw); +	return err; +} + +static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 val_hmetfr; +	bool result = false; + +	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR); +	if (((val_hmetfr >> boxnum) & BIT(0)) == 0) +		result = true; +	return result; +} + +static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw, +			      u8 element_id, u32 cmd_len, u8 *cmdbuffer) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); +	u8 boxnum; +	u16 box_reg = 0, box_extreg = 0; +	u8 u1b_tmp; +	bool isfw_read = false; +	u8 buf_index = 0; +	bool bwrite_sucess = false; +	u8 wait_h2c_limmit = 100; +	u8 wait_writeh2c_limmit = 100; +	u8 boxcontent[4], boxextcontent[2]; +	u32 h2c_waitcounter = 0; +	unsigned long flag; +	u8 idx; + +	if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) { +		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, +			 ("Return as RF is off!!!\n")); +		return; +	} +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n")); +	while (true) { +		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); +		if (rtlhal->h2c_setinprogress) { +			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, +				 ("H2C set in progress! Wait to set.." +				 "element_id(%d).\n", element_id)); + +			while (rtlhal->h2c_setinprogress) { +				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, +						       flag); +				h2c_waitcounter++; +				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, +					 ("Wait 100 us (%d times)...\n", +					 h2c_waitcounter)); +				udelay(100); + +				if (h2c_waitcounter > 1000) +					return; + +				spin_lock_irqsave(&rtlpriv->locks.h2c_lock, +						  flag); +			} +			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); +		} else { +			rtlhal->h2c_setinprogress = true; +			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); +			break; +		} +	} +	while (!bwrite_sucess) { +		wait_writeh2c_limmit--; +		if (wait_writeh2c_limmit == 0) { +			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +				 ("Write H2C fail because no trigger " +				 "for FW INT!\n")); +			break; +		} +		boxnum = rtlhal->last_hmeboxnum; +		switch (boxnum) { +		case 0: +			box_reg = REG_HMEBOX_0; +			box_extreg = REG_HMEBOX_EXT_0; +			break; +		case 1: +			box_reg = REG_HMEBOX_1; +			box_extreg = REG_HMEBOX_EXT_1; +			break; +		case 2: +			box_reg = REG_HMEBOX_2; +			box_extreg = REG_HMEBOX_EXT_2; +			break; +		case 3: +			box_reg = REG_HMEBOX_3; +			box_extreg = REG_HMEBOX_EXT_3; +			break; +		default: +			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +				 ("switch case not process\n")); +			break; +		} +		isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum); +		while (!isfw_read) { +			wait_h2c_limmit--; +			if (wait_h2c_limmit == 0) { +				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, +					 ("Wating too long for FW read " +					 "clear HMEBox(%d)!\n", boxnum)); +				break; +			} +			udelay(10); +			isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum); +			u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF); +			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, +				 ("Wating for FW read clear HMEBox(%d)!!! " +				 "0x1BF = %2x\n", boxnum, u1b_tmp)); +		} +		if (!isfw_read) { +			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, +				 ("Write H2C register BOX[%d] fail!!!!! " +				 "Fw do not read.\n", boxnum)); +			break; +		} +		memset(boxcontent, 0, sizeof(boxcontent)); +		memset(boxextcontent, 0, sizeof(boxextcontent)); +		boxcontent[0] = element_id; +		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, +			 ("Write element_id box_reg(%4x) = %2x\n", +			 box_reg, element_id)); +		switch (cmd_len) { +		case 1: +			boxcontent[0] &= ~(BIT(7)); +			memcpy(boxcontent + 1, cmdbuffer + buf_index, 1); +			for (idx = 0; idx < 4; idx++) +				rtl_write_byte(rtlpriv, box_reg + idx, +					       boxcontent[idx]); +			break; +		case 2: +			boxcontent[0] &= ~(BIT(7)); +			memcpy(boxcontent + 1, cmdbuffer + buf_index, 2); +			for (idx = 0; idx < 4; idx++) +				rtl_write_byte(rtlpriv, box_reg + idx, +					       boxcontent[idx]); +			break; +		case 3: +			boxcontent[0] &= ~(BIT(7)); +			memcpy(boxcontent + 1, cmdbuffer + buf_index, 3); +			for (idx = 0; idx < 4; idx++) +				rtl_write_byte(rtlpriv, box_reg + idx, +					       boxcontent[idx]); +			break; +		case 4: +			boxcontent[0] |= (BIT(7)); +			memcpy(boxextcontent, cmdbuffer + buf_index, 2); +			memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2); +			for (idx = 0; idx < 2; idx++) +				rtl_write_byte(rtlpriv, box_extreg + idx, +					       boxextcontent[idx]); +			for (idx = 0; idx < 4; idx++) +				rtl_write_byte(rtlpriv, box_reg + idx, +					       boxcontent[idx]); +			break; +		case 5: +			boxcontent[0] |= (BIT(7)); +			memcpy(boxextcontent, cmdbuffer + buf_index, 2); +			memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3); +			for (idx = 0; idx < 2; idx++) +				rtl_write_byte(rtlpriv, box_extreg + idx, +					       boxextcontent[idx]); +			for (idx = 0; idx < 4; idx++) +				rtl_write_byte(rtlpriv, box_reg + idx, +					       boxcontent[idx]); +			break; +		default: +			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +				("switch case not process\n")); +			break; +		} +		bwrite_sucess = true; +		rtlhal->last_hmeboxnum = boxnum + 1; +		if (rtlhal->last_hmeboxnum == 4) +			rtlhal->last_hmeboxnum = 0; +		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, +			 ("pHalData->last_hmeboxnum  = %d\n", +			  rtlhal->last_hmeboxnum)); +	} +	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag); +	rtlhal->h2c_setinprogress = false; +	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag); +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n")); +} + +void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, +			 u8 element_id, u32 cmd_len, u8 *cmdbuffer) +{ +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u32 tmp_cmdbuf[2]; + +	if (rtlhal->fw_ready == false) { +		RT_ASSERT(false, ("return H2C cmd because of Fw " +				  "download fail!!!\n")); +		return; +	} +	memset(tmp_cmdbuf, 0, 8); +	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); +	_rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); +	return; +} + +void rtl92d_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 u1_h2c_set_pwrmode[3] = { 0 }; +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + +	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode)); +	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode); +	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1); +	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode, +					      ppsc->reg_max_lps_awakeintvl); +	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, +		      "rtl92d_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n", +		      u1_h2c_set_pwrmode, 3); +	rtl92d_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode); +} + +static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw, +				    struct sk_buff *skb) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct rtl8192_tx_ring *ring; +	struct rtl_tx_desc *pdesc; +	u8 idx = 0; +	unsigned long flags; +	struct sk_buff *pskb; + +	ring = &rtlpci->tx_ring[BEACON_QUEUE]; +	pskb = __skb_dequeue(&ring->queue); +	if (pskb) +		kfree_skb(pskb); +	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); +	pdesc = &ring->desc[idx]; +	/* discard output from call below */ +	rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); +	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); +	__skb_queue_tail(&ring->queue, skb); +	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); +	rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); +	return true; +} + +#define BEACON_PG		0	/*->1 */ +#define PSPOLL_PG		2 +#define NULL_PG			3 +#define PROBERSP_PG		4	/*->5 */ +#define TOTAL_RESERVED_PKT_LEN	768 + +static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { +	/* page 0 beacon */ +	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, +	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, +	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, +	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, +	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, +	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, +	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, +	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, +	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +	/* page 1 beacon */ +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +	/* page 2  ps-poll */ +	0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10, +	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +	/* page 3  null */ +	0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, +	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, +	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +	/* page 4  probe_resp */ +	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10, +	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42, +	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, +	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00, +	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69, +	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C, +	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96, +	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A, +	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C, +	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18, +	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02, +	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +	/* page 5  probe_resp */ +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct sk_buff *skb = NULL; +	u32 totalpacketlen; +	bool rtstatus; +	u8 u1RsvdPageLoc[3] = { 0 }; +	bool dlok = false; +	u8 *beacon; +	u8 *p_pspoll; +	u8 *nullfunc; +	u8 *p_probersp; +	/*--------------------------------------------------------- +						(1) beacon +	---------------------------------------------------------*/ +	beacon = &reserved_page_packet[BEACON_PG * 128]; +	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr); +	SET_80211_HDR_ADDRESS3(beacon, mac->bssid); +	/*------------------------------------------------------- +						(2) ps-poll +	--------------------------------------------------------*/ +	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128]; +	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000)); +	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid); +	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr); +	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG); +	/*-------------------------------------------------------- +						(3) null data +	---------------------------------------------------------*/ +	nullfunc = &reserved_page_packet[NULL_PG * 128]; +	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid); +	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr); +	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid); +	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG); +	/*--------------------------------------------------------- +						(4) probe response +	----------------------------------------------------------*/ +	p_probersp = &reserved_page_packet[PROBERSP_PG * 128]; +	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid); +	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr); +	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid); +	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG); +	totalpacketlen = TOTAL_RESERVED_PKT_LEN; +	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, +		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", +		      &reserved_page_packet[0], totalpacketlen); +	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, +		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", +		      u1RsvdPageLoc, 3); +	skb = dev_alloc_skb(totalpacketlen); +	memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet, +		totalpacketlen); +	rtstatus = _rtl92d_cmd_send_packet(hw, skb); + +	if (rtstatus) +		dlok = true; +	if (dlok) { +		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, +			("Set RSVD page location to Fw.\n")); +		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG, +			      "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3); +		rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE, +			sizeof(u1RsvdPageLoc), u1RsvdPageLoc); +	} else +		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, +			("Set RSVD page location to Fw FAIL!!!!!!.\n")); +} + +void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus) +{ +	u8 u1_joinbssrpt_parm[1] = {0}; + +	SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus); +	rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.h b/drivers/net/wireless/rtlwifi/rtl8192de/fw.h new file mode 100644 index 00000000000..0c4d489eaa4 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.h @@ -0,0 +1,155 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92D__FW__H__ +#define __RTL92D__FW__H__ + +#define FW_8192D_START_ADDRESS			0x1000 +#define FW_8192D_PAGE_SIZE				4096 +#define FW_8192D_POLLING_TIMEOUT_COUNT	1000 + +#define IS_FW_HEADER_EXIST(_pfwhdr)	\ +		((GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x92C0 || \ +		(GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFF0) == 0x88C0 ||  \ +		(GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D0 ||  \ +		(GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D1 ||  \ +		(GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D2 ||  \ +		(GET_FIRMWARE_HDR_SIGNATURE(_pfwhdr) & 0xFFFF) == 0x92D3) + +/* Define a macro that takes an le32 word, converts it to host ordering, + * right shifts by a specified count, creates a mask of the specified + * bit count, and extracts that number of bits. + */ + +#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask)		\ +	((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) &	\ +	BIT_LEN_MASK_32(__mask)) + +/* Firmware Header(8-byte alinment required) */ +/* --- LONG WORD 0 ---- */ +#define GET_FIRMWARE_HDR_SIGNATURE(__fwhdr)		\ +	SHIFT_AND_MASK_LE(__fwhdr, 0, 16) +#define GET_FIRMWARE_HDR_CATEGORY(__fwhdr)		\ +	SHIFT_AND_MASK_LE(__fwhdr, 16, 8) +#define GET_FIRMWARE_HDR_FUNCTION(__fwhdr)		\ +	SHIFT_AND_MASK_LE(__fwhdr, 24, 8) +#define GET_FIRMWARE_HDR_VERSION(__fwhdr)		\ +	SHIFT_AND_MASK_LE(__fwhdr + 4, 0, 16) +#define GET_FIRMWARE_HDR_SUB_VER(__fwhdr)		\ +	SHIFT_AND_MASK_LE(__fwhdr + 4, 16, 8) +#define GET_FIRMWARE_HDR_RSVD1(__fwhdr)			\ +	SHIFT_AND_MASK_LE(__fwhdr + 4, 24, 8) + +/* --- LONG WORD 1 ---- */ +#define GET_FIRMWARE_HDR_MONTH(__fwhdr)			\ +	SHIFT_AND_MASK_LE(__fwhdr + 8, 0, 8) +#define GET_FIRMWARE_HDR_DATE(__fwhdr)			\ +	SHIFT_AND_MASK_LE(__fwhdr + 8, 8, 8) +#define GET_FIRMWARE_HDR_HOUR(__fwhdr)			\ +	SHIFT_AND_MASK_LE(__fwhdr + 8, 16, 8) +#define GET_FIRMWARE_HDR_MINUTE(__fwhdr)		\ +	SHIFT_AND_MASK_LE(__fwhdr + 8, 24, 8) +#define GET_FIRMWARE_HDR_ROMCODE_SIZE(__fwhdr)		\ +	SHIFT_AND_MASK_LE(__fwhdr + 12, 0, 16) +#define GET_FIRMWARE_HDR_RSVD2(__fwhdr)			\ +	SHIFT_AND_MASK_LE(__fwhdr + 12, 16, 16) + +/* --- LONG WORD 2 ---- */ +#define GET_FIRMWARE_HDR_SVN_IDX(__fwhdr)		\ +	SHIFT_AND_MASK_LE(__fwhdr + 16, 0, 32) +#define GET_FIRMWARE_HDR_RSVD3(__fwhdr)			\ +	SHIFT_AND_MASK_LE(__fwhdr + 20, 0, 32) + +/* --- LONG WORD 3 ---- */ +#define GET_FIRMWARE_HDR_RSVD4(__fwhdr)			\ +	SHIFT_AND_MASK_LE(__fwhdr + 24, 0, 32) +#define GET_FIRMWARE_HDR_RSVD5(__fwhdr)			\ +	SHIFT_AND_MASK_LE(__fwhdr + 28, 0, 32) + +#define pagenum_128(_len) \ +	(u32)(((_len) >> 7) + ((_len) & 0x7F ? 1 : 0)) + +#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val)		\ +	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val)	\ +	SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val) +#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val)	\ +	SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val) +#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val)	\ +	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val)	\ +	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val)	\ +	SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 1, 0, 8, __val) +#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val)	\ +	SET_BITS_TO_LE_1BYTE((__ph2ccmd) + 2, 0, 8, __val) + +struct rtl92d_firmware_header { +	u16 signature; +	u8 category; +	u8 function; +	u16 version; +	u8 subversion; +	u8 rsvd1; + +	u8 month; +	u8 date; +	u8 hour; +	u8 minute; +	u16 ramcodeSize; +	u16 rsvd2; + +	u32 svnindex; +	u32 rsvd3; + +	u32 rsvd4; +	u32 rsvd5; +}; + +enum rtl8192d_h2c_cmd { +	H2C_AP_OFFLOAD = 0, +	H2C_SETPWRMODE = 1, +	H2C_JOINBSSRPT = 2, +	H2C_RSVDPAGE = 3, +	H2C_RSSI_REPORT = 5, +	H2C_RA_MASK = 6, +	H2C_MAC_MODE_SEL = 9, +	H2C_PWRM = 15, +	MAX_H2CCMD +}; + +int rtl92d_download_fw(struct ieee80211_hw *hw); +void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, +			 u32 cmd_len, u8 *p_cmdbuffer); +void rtl92d_firmware_selfreset(struct ieee80211_hw *hw); +void rtl92d_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); +void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); +void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c new file mode 100644 index 00000000000..5a65bea4cb8 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c @@ -0,0 +1,2329 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../efuse.h" +#include "../base.h" +#include "../regd.h" +#include "../cam.h" +#include "../ps.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "fw.h" +#include "led.h" +#include "sw.h" +#include "hw.h" + +u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 value; + +	rtl_write_word(rtlpriv, REG_DBI_CTRL, (offset & 0xFFC)); +	rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(1) | direct); +	udelay(10); +	value = rtl_read_dword(rtlpriv, REG_DBI_RDATA); +	return value; +} + +void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, +			     u16 offset, u32 value, u8 direct) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	rtl_write_word(rtlpriv, REG_DBI_CTRL, ((offset & 0xFFC) | 0xF000)); +	rtl_write_dword(rtlpriv, REG_DBI_WDATA, value); +	rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(0) | direct); +} + +static void _rtl92de_set_bcn_ctrl_reg(struct ieee80211_hw *hw, +				      u8 set_bits, u8 clear_bits) +{ +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	rtlpci->reg_bcn_ctrl_val |= set_bits; +	rtlpci->reg_bcn_ctrl_val &= ~clear_bits; +	rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); +} + +static void _rtl92de_stop_tx_beacon(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 tmp1byte; + +	tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); +	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte & (~BIT(6))); +	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xff); +	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64); +	tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); +	tmp1byte &= ~(BIT(0)); +	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl92de_resume_tx_beacon(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 tmp1byte; + +	tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); +	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp1byte | BIT(6)); +	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a); +	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); +	tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); +	tmp1byte |= BIT(0); +	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte); +} + +static void _rtl92de_enable_bcn_sub_func(struct ieee80211_hw *hw) +{ +	_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(1)); +} + +static void _rtl92de_disable_bcn_sub_func(struct ieee80211_hw *hw) +{ +	_rtl92de_set_bcn_ctrl_reg(hw, BIT(1), 0); +} + +void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + +	switch (variable) { +	case HW_VAR_RCR: +		*((u32 *) (val)) = rtlpci->receive_config; +		break; +	case HW_VAR_RF_STATE: +		*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; +		break; +	case HW_VAR_FWLPS_RF_ON:{ +		enum rf_pwrstate rfState; +		u32 val_rcr; + +		rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, +					      (u8 *) (&rfState)); +		if (rfState == ERFOFF) { +			*((bool *) (val)) = true; +		} else { +			val_rcr = rtl_read_dword(rtlpriv, REG_RCR); +			val_rcr &= 0x00070000; +			if (val_rcr) +				*((bool *) (val)) = false; +			else +				*((bool *) (val)) = true; +		} +		break; +	} +	case HW_VAR_FW_PSMODE_STATUS: +		*((bool *) (val)) = ppsc->fw_current_inpsmode; +		break; +	case HW_VAR_CORRECT_TSF:{ +		u64 tsf; +		u32 *ptsf_low = (u32 *)&tsf; +		u32 *ptsf_high = ((u32 *)&tsf) + 1; + +		*ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4)); +		*ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); +		*((u64 *) (val)) = tsf; +		break; +	} +	case HW_VAR_INT_MIGRATION: +		*((bool *)(val)) = rtlpriv->dm.interrupt_migration; +		break; +	case HW_VAR_INT_AC: +		*((bool *)(val)) = rtlpriv->dm.disable_tx_int; +		break; +	default: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("switch case not process\n")); +		break; +	} +} + +void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); +	u8 idx; + +	switch (variable) { +	case HW_VAR_ETHER_ADDR: +		for (idx = 0; idx < ETH_ALEN; idx++) { +			rtl_write_byte(rtlpriv, (REG_MACID + idx), +				       val[idx]); +		} +		break; +	case HW_VAR_BASIC_RATE: { +		u16 rate_cfg = ((u16 *) val)[0]; +		u8 rate_index = 0; + +		rate_cfg = rate_cfg & 0x15f; +		if (mac->vendor == PEER_CISCO && +		    ((rate_cfg & 0x150) == 0)) +			rate_cfg |= 0x01; +		rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff); +		rtl_write_byte(rtlpriv, REG_RRSR + 1, +			       (rate_cfg >> 8) & 0xff); +		while (rate_cfg > 0x1) { +			rate_cfg = (rate_cfg >> 1); +			rate_index++; +		} +		if (rtlhal->fw_version > 0xe) +			rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, +				       rate_index); +		break; +	} +	case HW_VAR_BSSID: +		for (idx = 0; idx < ETH_ALEN; idx++) { +			rtl_write_byte(rtlpriv, (REG_BSSID + idx), +				       val[idx]); +		} +		break; +	case HW_VAR_SIFS: +		rtl_write_byte(rtlpriv, REG_SIFS_CTX + 1, val[0]); +		rtl_write_byte(rtlpriv, REG_SIFS_TRX + 1, val[1]); +		rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]); +		rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]); +		if (!mac->ht_enable) +			rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, +				       0x0e0e); +		else +			rtl_write_word(rtlpriv, REG_RESP_SIFS_OFDM, +				       *((u16 *) val)); +		break; +	case HW_VAR_SLOT_TIME: { +		u8 e_aci; + +		RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, +			 ("HW_VAR_SLOT_TIME %x\n", val[0])); +		rtl_write_byte(rtlpriv, REG_SLOT, val[0]); +		for (e_aci = 0; e_aci < AC_MAX; e_aci++) +			rtlpriv->cfg->ops->set_hw_reg(hw, +						      HW_VAR_AC_PARAM, +						      (u8 *) (&e_aci)); +		break; +	} +	case HW_VAR_ACK_PREAMBLE: { +		u8 reg_tmp; +		u8 short_preamble = (bool) (*(u8 *) val); + +		reg_tmp = (mac->cur_40_prime_sc) << 5; +		if (short_preamble) +			reg_tmp |= 0x80; +		rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp); +		break; +	} +	case HW_VAR_AMPDU_MIN_SPACE: { +		u8 min_spacing_to_set; +		u8 sec_min_space; + +		min_spacing_to_set = *((u8 *) val); +		if (min_spacing_to_set <= 7) { +			sec_min_space = 0; +			if (min_spacing_to_set < sec_min_space) +				min_spacing_to_set = sec_min_space; +			mac->min_space_cfg = ((mac->min_space_cfg & 0xf8) | +					      min_spacing_to_set); +			*val = min_spacing_to_set; +			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, +				 ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", +				 mac->min_space_cfg)); +			rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, +				       mac->min_space_cfg); +		} +		break; +	} +	case HW_VAR_SHORTGI_DENSITY: { +		u8 density_to_set; + +		density_to_set = *((u8 *) val); +		mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg; +		mac->min_space_cfg |= (density_to_set << 3); +		RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, +			 ("Set HW_VAR_SHORTGI_DENSITY: %#x\n", +			 mac->min_space_cfg)); +		rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, +			       mac->min_space_cfg); +		break; +	} +	case HW_VAR_AMPDU_FACTOR: { +		u8 factor_toset; +		u32 regtoSet; +		u8 *ptmp_byte = NULL; +		u8 index; + +		if (rtlhal->macphymode == DUALMAC_DUALPHY) +			regtoSet = 0xb9726641; +		else if (rtlhal->macphymode == DUALMAC_SINGLEPHY) +			regtoSet = 0x66626641; +		else +			regtoSet = 0xb972a841; +		factor_toset = *((u8 *) val); +		if (factor_toset <= 3) { +			factor_toset = (1 << (factor_toset + 2)); +			if (factor_toset > 0xf) +				factor_toset = 0xf; +			for (index = 0; index < 4; index++) { +				ptmp_byte = (u8 *) (®toSet) + index; +				if ((*ptmp_byte & 0xf0) > +				    (factor_toset << 4)) +					*ptmp_byte = (*ptmp_byte & 0x0f) +						 | (factor_toset << 4); +				if ((*ptmp_byte & 0x0f) > factor_toset) +					*ptmp_byte = (*ptmp_byte & 0xf0) +						     | (factor_toset); +			} +			rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, regtoSet); +			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, +				 ("Set HW_VAR_AMPDU_FACTOR: %#x\n", +				 factor_toset)); +		} +		break; +	} +	case HW_VAR_AC_PARAM: { +		u8 e_aci = *((u8 *) val); +		rtl92d_dm_init_edca_turbo(hw); +		if (rtlpci->acm_method != eAcmWay2_SW) +			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, +						      (u8 *) (&e_aci)); +		break; +	} +	case HW_VAR_ACM_CTRL: { +		u8 e_aci = *((u8 *) val); +		union aci_aifsn *p_aci_aifsn = +		    (union aci_aifsn *)(&(mac->ac[0].aifs)); +		u8 acm = p_aci_aifsn->f.acm; +		u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); + +		acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ?  0x0 : 0x1); +		if (acm) { +			switch (e_aci) { +			case AC0_BE: +				acm_ctrl |= ACMHW_BEQEN; +				break; +			case AC2_VI: +				acm_ctrl |= ACMHW_VIQEN; +				break; +			case AC3_VO: +				acm_ctrl |= ACMHW_VOQEN; +				break; +			default: +				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, +					 ("HW_VAR_ACM_CTRL acm set " +					 "failed: eACI is %d\n", acm)); +				break; +			} +		} else { +			switch (e_aci) { +			case AC0_BE: +				acm_ctrl &= (~ACMHW_BEQEN); +				break; +			case AC2_VI: +				acm_ctrl &= (~ACMHW_VIQEN); +				break; +			case AC3_VO: +				acm_ctrl &= (~ACMHW_VOQEN); +				break; +			default: +				RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +					 ("switch case not process\n")); +				break; +			} +		} +		RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, +			 ("SetHwReg8190pci(): [HW_VAR_ACM_CTRL] " +			 "Write 0x%X\n", acm_ctrl)); +		rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); +		break; +	} +	case HW_VAR_RCR: +		rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]); +		rtlpci->receive_config = ((u32 *) (val))[0]; +		break; +	case HW_VAR_RETRY_LIMIT: { +		u8 retry_limit = ((u8 *) (val))[0]; + +		rtl_write_word(rtlpriv, REG_RL, +			       retry_limit << RETRY_LIMIT_SHORT_SHIFT | +			       retry_limit << RETRY_LIMIT_LONG_SHIFT); +		break; +	} +	case HW_VAR_DUAL_TSF_RST: +		rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1))); +		break; +	case HW_VAR_EFUSE_BYTES: +		rtlefuse->efuse_usedbytes = *((u16 *) val); +		break; +	case HW_VAR_EFUSE_USAGE: +		rtlefuse->efuse_usedpercentage = *((u8 *) val); +		break; +	case HW_VAR_IO_CMD: +		rtl92d_phy_set_io_cmd(hw, (*(enum io_type *)val)); +		break; +	case HW_VAR_WPA_CONFIG: +		rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *) val)); +		break; +	case HW_VAR_SET_RPWM: +		rtl92d_fill_h2c_cmd(hw, H2C_PWRM, 1, (u8 *) (val)); +		break; +	case HW_VAR_H2C_FW_PWRMODE: +		break; +	case HW_VAR_FW_PSMODE_STATUS: +		ppsc->fw_current_inpsmode = *((bool *) val); +		break; +	case HW_VAR_H2C_FW_JOINBSSRPT: { +		u8 mstatus = (*(u8 *) val); +		u8 tmp_regcr, tmp_reg422; +		bool recover = false; + +		if (mstatus == RT_MEDIA_CONNECT) { +			rtlpriv->cfg->ops->set_hw_reg(hw, +						      HW_VAR_AID, NULL); +			tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); +			rtl_write_byte(rtlpriv, REG_CR + 1, +				       (tmp_regcr | BIT(0))); +			_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3)); +			_rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0); +			tmp_reg422 = rtl_read_byte(rtlpriv, +						 REG_FWHW_TXQ_CTRL + 2); +			if (tmp_reg422 & BIT(6)) +				recover = true; +			rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, +				       tmp_reg422 & (~BIT(6))); +			rtl92d_set_fw_rsvdpagepkt(hw, 0); +			_rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0); +			_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4)); +			if (recover) +				rtl_write_byte(rtlpriv, +					       REG_FWHW_TXQ_CTRL + 2, +					       tmp_reg422); +			rtl_write_byte(rtlpriv, REG_CR + 1, +				       (tmp_regcr & ~(BIT(0)))); +		} +		rtl92d_set_fw_joinbss_report_cmd(hw, (*(u8 *) val)); +		break; +	} +	case HW_VAR_AID: { +		u16 u2btmp; +		u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); +		u2btmp &= 0xC000; +		rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, (u2btmp | +			       mac->assoc_id)); +		break; +	} +	case HW_VAR_CORRECT_TSF: { +		u8 btype_ibss = ((u8 *) (val))[0]; + +		if (btype_ibss) +			_rtl92de_stop_tx_beacon(hw); +		_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3)); +		rtl_write_dword(rtlpriv, REG_TSFTR, +				(u32) (mac->tsf & 0xffffffff)); +		rtl_write_dword(rtlpriv, REG_TSFTR + 4, +				(u32) ((mac->tsf >> 32) & 0xffffffff)); +		_rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0); +		if (btype_ibss) +			_rtl92de_resume_tx_beacon(hw); + +		break; +	} +	case HW_VAR_INT_MIGRATION: { +		bool int_migration = *(bool *) (val); + +		if (int_migration) { +			/* Set interrrupt migration timer and +			 * corresponging Tx/Rx counter. +			 * timer 25ns*0xfa0=100us for 0xf packets. +			 * 0x306:Rx, 0x307:Tx */ +			rtl_write_dword(rtlpriv, REG_INT_MIG, 0xfe000fa0); +			rtlpriv->dm.interrupt_migration = int_migration; +		} else { +			/* Reset all interrupt migration settings. */ +			rtl_write_dword(rtlpriv, REG_INT_MIG, 0); +			rtlpriv->dm.interrupt_migration = int_migration; +		} +		break; +	} +	case HW_VAR_INT_AC: { +		bool disable_ac_int = *((bool *) val); + +		/* Disable four ACs interrupts. */ +		if (disable_ac_int) { +			/* Disable VO, VI, BE and BK four AC interrupts +			 * to gain more efficient CPU utilization. +			 * When extremely highly Rx OK occurs, +			 * we will disable Tx interrupts. +			 */ +			rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, +						 RT_AC_INT_MASKS); +			rtlpriv->dm.disable_tx_int = disable_ac_int; +		/* Enable four ACs interrupts. */ +		} else { +			rtlpriv->cfg->ops->update_interrupt_mask(hw, +						 RT_AC_INT_MASKS, 0); +			rtlpriv->dm.disable_tx_int = disable_ac_int; +		} +		break; +	} +	default: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("switch case not process\n")); +		break; +	} +} + +static bool _rtl92de_llt_write(struct ieee80211_hw *hw, u32 address, u32 data) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	bool status = true; +	long count = 0; +	u32 value = _LLT_INIT_ADDR(address) | +	    _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS); + +	rtl_write_dword(rtlpriv, REG_LLT_INIT, value); +	do { +		value = rtl_read_dword(rtlpriv, REG_LLT_INIT); +		if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) +			break; +		if (count > POLLING_LLT_THRESHOLD) { +			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +				 ("Failed to polling write LLT done at " +				  "address %d!\n", address)); +			status = false; +			break; +		} +	} while (++count); +	return status; +} + +static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	unsigned short i; +	u8 txpktbuf_bndy; +	u8 maxPage; +	bool status; +	u32 value32; /* High+low page number */ +	u8 value8;	 /* normal page number */ + +	if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) { +		maxPage = 255; +		txpktbuf_bndy = 246; +		value8 = 0; +		value32 = 0x80bf0d29; +	} else if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) { +		maxPage = 127; +		txpktbuf_bndy = 123; +		value8 = 0; +		value32 = 0x80750005; +	} + +	/* Set reserved page for each queue */ +	/* 11.  RQPN 0x200[31:0] = 0x80BD1C1C */ +	/* load RQPN */ +	rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8); +	rtl_write_dword(rtlpriv, REG_RQPN, value32); + +	/* 12.  TXRKTBUG_PG_BNDY 0x114[31:0] = 0x27FF00F6 */ +	/* TXRKTBUG_PG_BNDY */ +	rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, +			(rtl_read_word(rtlpriv, REG_TRXFF_BNDY + 2) << 16 | +			txpktbuf_bndy)); + +	/* 13.  TDECTRL[15:8] 0x209[7:0] = 0xF6 */ +	/* Beacon Head for TXDMA */ +	rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); + +	/* 14.  BCNQ_PGBNDY 0x424[7:0] =  0xF6 */ +	/* BCNQ_PGBNDY */ +	rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); +	rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); + +	/* 15.  WMAC_LBK_BF_HD 0x45D[7:0] =  0xF6 */ +	/* WMAC_LBK_BF_HD */ +	rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); + +	/* Set Tx/Rx page size (Tx must be 128 Bytes, */ +	/* Rx can be 64,128,256,512,1024 bytes) */ +	/* 16.  PBP [7:0] = 0x11 */ +	/* TRX page size */ +	rtl_write_byte(rtlpriv, REG_PBP, 0x11); + +	/* 17.  DRV_INFO_SZ = 0x04 */ +	rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); + +	/* 18.  LLT_table_init(Adapter);  */ +	for (i = 0; i < (txpktbuf_bndy - 1); i++) { +		status = _rtl92de_llt_write(hw, i, i + 1); +		if (true != status) +			return status; +	} + +	/* end of list */ +	status = _rtl92de_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); +	if (true != status) +		return status; + +	/* Make the other pages as ring buffer */ +	/* This ring buffer is used as beacon buffer if we */ +	/* config this MAC as two MAC transfer. */ +	/* Otherwise used as local loopback buffer.  */ +	for (i = txpktbuf_bndy; i < maxPage; i++) { +		status = _rtl92de_llt_write(hw, i, (i + 1)); +		if (true != status) +			return status; +	} + +	/* Let last entry point to the start entry of ring buffer */ +	status = _rtl92de_llt_write(hw, maxPage, txpktbuf_bndy); +	if (true != status) +		return status; + +	return true; +} + +static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw) +{ +	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); +	struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); + +	if (rtlpci->up_first_time) +		return; +	if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) +		rtl92de_sw_led_on(hw, pLed0); +	else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) +		rtl92de_sw_led_on(hw, pLed0); +	else +		rtl92de_sw_led_off(hw, pLed0); +} + +static bool _rtl92de_init_mac(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	unsigned char bytetmp; +	unsigned short wordtmp; +	u16 retry; + +	rtl92d_phy_set_poweron(hw); +	/* Add for resume sequence of power domain according +	 * to power document V11. Chapter V.11....  */ +	/* 0.   RSV_CTRL 0x1C[7:0] = 0x00  */ +	/* unlock ISO/CLK/Power control register */ +	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); +	rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x05); + +	/* 1.   AFE_XTAL_CTRL [7:0] = 0x0F  enable XTAL */ +	/* 2.   SPS0_CTRL 0x11[7:0] = 0x2b  enable SPS into PWM mode  */ +	/* 3.   delay (1ms) this is not necessary when initially power on */ + +	/* C.   Resume Sequence */ +	/* a.   SPS0_CTRL 0x11[7:0] = 0x2b */ +	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); + +	/* b.   AFE_XTAL_CTRL [7:0] = 0x0F */ +	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); + +	/* c.   DRV runs power on init flow */ + +	/* auto enable WLAN */ +	/* 4.   APS_FSMCO 0x04[8] = 1; wait till 0x04[8] = 0   */ +	/* Power On Reset for MAC Block */ +	bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); +	udelay(2); +	rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); +	udelay(2); + +	/* 5.   Wait while 0x04[8] == 0 goto 2, otherwise goto 1 */ +	bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); +	udelay(50); +	retry = 0; +	while ((bytetmp & BIT(0)) && retry < 1000) { +		retry++; +		bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); +		udelay(50); +	} + +	/* Enable Radio off, GPIO, and LED function */ +	/* 6.   APS_FSMCO 0x04[15:0] = 0x0012  when enable HWPDN */ +	rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x1012); + +	/* release RF digital isolation  */ +	/* 7.  SYS_ISO_CTRL 0x01[1]    = 0x0;  */ +	/*Set REG_SYS_ISO_CTRL 0x1=0x82 to prevent wake# problem. */ +	rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); +	udelay(2); + +	/* make sure that BB reset OK. */ +	/* rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); */ + +	/* Disable REG_CR before enable it to assure reset */ +	rtl_write_word(rtlpriv, REG_CR, 0x0); + +	/* Release MAC IO register reset */ +	rtl_write_word(rtlpriv, REG_CR, 0x2ff); + +	/* clear stopping tx/rx dma   */ +	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x0); + +	/* rtl_write_word(rtlpriv,REG_CR+2, 0x2); */ + +	/* System init */ +	/* 18.  LLT_table_init(Adapter);  */ +	if (_rtl92de_llt_table_init(hw) == false) +		return false; + +	/* Clear interrupt and enable interrupt */ +	/* 19.  HISR 0x124[31:0] = 0xffffffff;  */ +	/*      HISRE 0x12C[7:0] = 0xFF */ +	rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); +	rtl_write_byte(rtlpriv, REG_HISRE, 0xff); + +	/* 20.  HIMR 0x120[31:0] |= [enable INT mask bit map];  */ +	/* 21.  HIMRE 0x128[7:0] = [enable INT mask bit map] */ +	/* The IMR should be enabled later after all init sequence +	 * is finished. */ + +	/* 22.  PCIE configuration space configuration */ +	/* 23.  Ensure PCIe Device 0x80[15:0] = 0x0143 (ASPM+CLKREQ),  */ +	/*      and PCIe gated clock function is enabled.    */ +	/* PCIE configuration space will be written after +	 * all init sequence.(Or by BIOS) */ + +	rtl92d_phy_config_maccoexist_rfpage(hw); + +	/* THe below section is not related to power document Vxx . */ +	/* This is only useful for driver and OS setting. */ +	/* -------------------Software Relative Setting---------------------- */ +	wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); +	wordtmp &= 0xf; +	wordtmp |= 0xF771; +	rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); + +	/* Reported Tx status from HW for rate adaptive. */ +	/* This should be realtive to power on step 14. But in document V11  */ +	/* still not contain the description.!!! */ +	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); + +	/* Set Tx/Rx page size (Tx must be 128 Bytes, +	 * Rx can be 64,128,256,512,1024 bytes) */ +	/* rtl_write_byte(rtlpriv,REG_PBP, 0x11); */ + +	/* Set RCR register */ +	rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); +	/* rtl_write_byte(rtlpriv,REG_RX_DRVINFO_SZ, 4); */ + +	/*  Set TCR register */ +	rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); + +	/* disable earlymode */ +	rtl_write_byte(rtlpriv, 0x4d0, 0x0); + +	/* Set TX/RX descriptor physical address(from OS API). */ +	rtl_write_dword(rtlpriv, REG_BCNQ_DESA, +			rtlpci->tx_ring[BEACON_QUEUE].dma); +	rtl_write_dword(rtlpriv, REG_MGQ_DESA, rtlpci->tx_ring[MGNT_QUEUE].dma); +	rtl_write_dword(rtlpriv, REG_VOQ_DESA, rtlpci->tx_ring[VO_QUEUE].dma); +	rtl_write_dword(rtlpriv, REG_VIQ_DESA, rtlpci->tx_ring[VI_QUEUE].dma); +	rtl_write_dword(rtlpriv, REG_BEQ_DESA, rtlpci->tx_ring[BE_QUEUE].dma); +	rtl_write_dword(rtlpriv, REG_BKQ_DESA, rtlpci->tx_ring[BK_QUEUE].dma); +	rtl_write_dword(rtlpriv, REG_HQ_DESA, rtlpci->tx_ring[HIGH_QUEUE].dma); +	/* Set RX Desc Address */ +	rtl_write_dword(rtlpriv, REG_RX_DESA, +			rtlpci->rx_ring[RX_MPDU_QUEUE].dma); + +	/* if we want to support 64 bit DMA, we should set it here, +	 * but now we do not support 64 bit DMA*/ + +	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x33); + +	/* Reset interrupt migration setting when initialization */ +	rtl_write_dword(rtlpriv, REG_INT_MIG, 0); + +	/* Reconsider when to do this operation after asking HWSD. */ +	bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); +	rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6)); +	do { +		retry++; +		bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); +	} while ((retry < 200) && !(bytetmp & BIT(7))); + +	/* After MACIO reset,we must refresh LED state. */ +	_rtl92de_gen_refresh_led_state(hw); + +	/* Reset H2C protection register */ +	rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); + +	return true; +} + +static void _rtl92de_hw_configure(struct ieee80211_hw *hw) +{ +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u8 reg_bw_opmode = BW_OPMODE_20MHZ; +	u32 reg_rrsr; + +	reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; +	rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); +	rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); +	rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); +	rtl_write_byte(rtlpriv, REG_SLOT, 0x09); +	rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0); +	rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); +	rtl_write_word(rtlpriv, REG_RL, 0x0707); +	rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802); +	rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); +	rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); +	rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); +	rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); +	rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); +	/* Aggregation threshold */ +	if (rtlhal->macphymode == DUALMAC_DUALPHY) +		rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb9726641); +	else if (rtlhal->macphymode == DUALMAC_SINGLEPHY) +		rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x66626641); +	else +		rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); +	rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); +	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a); +	rtlpci->reg_bcn_ctrl_val = 0x1f; +	rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); +	rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); +	rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); +	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); +	rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); +	/* For throughput */ +	rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0x6666); +	/* ACKTO for IOT issue. */ +	rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); +	/* Set Spec SIFS (used in NAV) */ +	rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010); +	rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010); +	/* Set SIFS for CCK */ +	rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010); +	/* Set SIFS for OFDM */ +	rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010); +	/* Set Multicast Address. */ +	rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); +	rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); +	switch (rtlpriv->phy.rf_type) { +	case RF_1T2R: +	case RF_1T1R: +		rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3); +		break; +	case RF_2T2R: +	case RF_2T2R_GREEN: +		rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3); +		break; +	} +} + +static void _rtl92de_enable_aspm_back_door(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + +	rtl_write_byte(rtlpriv, 0x34b, 0x93); +	rtl_write_word(rtlpriv, 0x350, 0x870c); +	rtl_write_byte(rtlpriv, 0x352, 0x1); +	if (ppsc->support_backdoor) +		rtl_write_byte(rtlpriv, 0x349, 0x1b); +	else +		rtl_write_byte(rtlpriv, 0x349, 0x03); +	rtl_write_word(rtlpriv, 0x350, 0x2718); +	rtl_write_byte(rtlpriv, 0x352, 0x1); +} + +void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 sec_reg_value; + +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 ("PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n", +		  rtlpriv->sec.pairwise_enc_algorithm, +		  rtlpriv->sec.group_enc_algorithm)); +	if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { +		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, +			 ("not open hw encryption\n")); +		return; +	} +	sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE; +	if (rtlpriv->sec.use_defaultkey) { +		sec_reg_value |= SCR_TXUSEDK; +		sec_reg_value |= SCR_RXUSEDK; +	} +	sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); +	rtl_write_byte(rtlpriv, REG_CR + 1, 0x02); +	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, +		 ("The SECR-value %x\n", sec_reg_value)); +	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); +} + +int rtl92de_hw_init(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); +	bool rtstatus = true; +	u8 tmp_u1b; +	int i; +	int err; +	unsigned long flags; + +	rtlpci->being_init_adapter = true; +	rtlpci->init_ready = false; +	spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags); +	/* we should do iqk after disable/enable */ +	rtl92d_phy_reset_iqk_result(hw); +	/* rtlpriv->intf_ops->disable_aspm(hw); */ +	rtstatus = _rtl92de_init_mac(hw); +	if (rtstatus != true) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Init MAC failed\n")); +		err = 1; +		spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); +		return err; +	} +	err = rtl92d_download_fw(hw); +	spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); +	if (err) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, +			 ("Failed to download FW. Init HW " +			 "without FW..\n")); +		rtlhal->fw_ready = false; +		return 1; +	} else { +		rtlhal->fw_ready = true; +	} +	rtlhal->last_hmeboxnum = 0; +	rtlpriv->psc.fw_current_inpsmode = false; + +	tmp_u1b = rtl_read_byte(rtlpriv, 0x605); +	tmp_u1b = tmp_u1b | 0x30; +	rtl_write_byte(rtlpriv, 0x605, tmp_u1b); + +	if (rtlhal->earlymode_enable) { +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +			 ("EarlyMode Enabled!!!\n")); + +		tmp_u1b = rtl_read_byte(rtlpriv, 0x4d0); +		tmp_u1b = tmp_u1b | 0x1f; +		rtl_write_byte(rtlpriv, 0x4d0, tmp_u1b); + +		rtl_write_byte(rtlpriv, 0x4d3, 0x80); + +		tmp_u1b = rtl_read_byte(rtlpriv, 0x605); +		tmp_u1b = tmp_u1b | 0x40; +		rtl_write_byte(rtlpriv, 0x605, tmp_u1b); +	} + +	if (mac->rdg_en) { +		rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xff); +		rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200); +		rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05); +	} + +	rtl92d_phy_mac_config(hw); +	/* because last function modify RCR, so we update +	 * rcr var here, or TP will unstable for receive_config +	 * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx +	 * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/ +	rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); +	rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); + +	rtl92d_phy_bb_config(hw); + +	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; +	/* set before initialize RF */ +	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); + +	/* config RF */ +	rtl92d_phy_rf_config(hw); + +	/* After read predefined TXT, we must set BB/MAC/RF +	 * register as our requirement */ +	/* After load BB,RF params,we need do more for 92D. */ +	rtl92d_update_bbrf_configuration(hw); +	/* set default value after initialize RF,  */ +	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0); +	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, +			RF_CHNLBW, BRFREGOFFSETMASK); +	rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, +			RF_CHNLBW, BRFREGOFFSETMASK); + +	/*---- Set CCK and OFDM Block "ON"----*/ +	if (rtlhal->current_bandtype == BAND_ON_2_4G) +		rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); +	rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); +	if (rtlhal->interfaceindex == 0) { +		/* RFPGA0_ANALOGPARAMETER2: cck clock select, +		 *  set to 20MHz by default */ +		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) | +			      BIT(11), 3); +	} else { +		/* Mac1 */ +		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(11) | +			      BIT(10), 3); +	} + +	_rtl92de_hw_configure(hw); + +	/* reset hw sec */ +	rtl_cam_reset_all_entry(hw); +	rtl92de_enable_hw_security_config(hw); + +	/* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */ +	/* TX power index for different rate set. */ +	rtl92d_phy_get_hw_reg_originalvalue(hw); +	rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); + +	ppsc->rfpwr_state = ERFON; + +	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); + +	_rtl92de_enable_aspm_back_door(hw); +	/* rtlpriv->intf_ops->enable_aspm(hw); */ + +	rtl92d_dm_init(hw); +	rtlpci->being_init_adapter = false; + +	if (ppsc->rfpwr_state == ERFON) { +		rtl92d_phy_lc_calibrate(hw); +		/* 5G and 2.4G must wait sometime to let RF LO ready */ +		if (rtlhal->macphymode == DUALMAC_DUALPHY) { +			u32 tmp_rega; +			for (i = 0; i < 10000; i++) { +				udelay(MAX_STALL_TIME); + +				tmp_rega = rtl_get_rfreg(hw, +						  (enum radio_path)RF90_PATH_A, +						  0x2a, BMASKDWORD); + +				if (((tmp_rega & BIT(11)) == BIT(11))) +					break; +			} +			/* check that loop was successful. If not, exit now */ +			if (i == 10000) { +				rtlpci->init_ready = false; +				return 1; +			} +		} +	} +	rtlpci->init_ready = true; +	return err; +} + +static enum version_8192d _rtl92de_read_chip_version(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	enum version_8192d version = VERSION_NORMAL_CHIP_92D_SINGLEPHY; +	u32 value32; + +	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG); +	if (!(value32 & 0x000f0000)) { +		version = VERSION_TEST_CHIP_92D_SINGLEPHY; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("TEST CHIP!!!\n")); +	} else { +		version = VERSION_NORMAL_CHIP_92D_SINGLEPHY; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Normal CHIP!!!\n")); +	} +	return version; +} + +static int _rtl92de_set_media_status(struct ieee80211_hw *hw, +				     enum nl80211_iftype type) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 bt_msr = rtl_read_byte(rtlpriv, MSR); +	enum led_ctl_mode ledaction = LED_CTL_NO_LINK; +	u8 bcnfunc_enable; + +	bt_msr &= 0xfc; + +	if (type == NL80211_IFTYPE_UNSPECIFIED || +	    type == NL80211_IFTYPE_STATION) { +		_rtl92de_stop_tx_beacon(hw); +		_rtl92de_enable_bcn_sub_func(hw); +	} else if (type == NL80211_IFTYPE_ADHOC || +		type == NL80211_IFTYPE_AP) { +		_rtl92de_resume_tx_beacon(hw); +		_rtl92de_disable_bcn_sub_func(hw); +	} else { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, +			 ("Set HW_VAR_MEDIA_STATUS: No such media " +			 "status(%x).\n", type)); +	} +	bcnfunc_enable = rtl_read_byte(rtlpriv, REG_BCN_CTRL); +	switch (type) { +	case NL80211_IFTYPE_UNSPECIFIED: +		bt_msr |= MSR_NOLINK; +		ledaction = LED_CTL_LINK; +		bcnfunc_enable &= 0xF7; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("Set Network type to NO LINK!\n")); +		break; +	case NL80211_IFTYPE_ADHOC: +		bt_msr |= MSR_ADHOC; +		bcnfunc_enable |= 0x08; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("Set Network type to Ad Hoc!\n")); +		break; +	case NL80211_IFTYPE_STATION: +		bt_msr |= MSR_INFRA; +		ledaction = LED_CTL_LINK; +		bcnfunc_enable &= 0xF7; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("Set Network type to STA!\n")); +		break; +	case NL80211_IFTYPE_AP: +		bt_msr |= MSR_AP; +		bcnfunc_enable |= 0x08; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("Set Network type to AP!\n")); +		break; +	default: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("Network type %d not support!\n", type)); +		return 1; +		break; + +	} +	rtl_write_byte(rtlpriv, REG_CR + 2, bt_msr); +	rtlpriv->cfg->ops->led_control(hw, ledaction); +	if ((bt_msr & 0xfc) == MSR_AP) +		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); +	else +		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); +	return 0; +} + +void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	u32 reg_rcr = rtlpci->receive_config; + +	if (rtlpriv->psc.rfpwr_state != ERFON) +		return; +	if (check_bssid) { +		reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); +		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); +		_rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4)); +	} else if (check_bssid == false) { +		reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); +		_rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0); +		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); +	} +} + +int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	if (_rtl92de_set_media_status(hw, type)) +		return -EOPNOTSUPP; + +	/* check bssid */ +	if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { +		if (type != NL80211_IFTYPE_AP) +			rtl92de_set_check_bssid(hw, true); +	} else { +		rtl92de_set_check_bssid(hw, false); +	} +	return 0; +} + +/* do iqk or reload iqk */ +/* windows just rtl92d_phy_reload_iqk_setting in set channel, + * but it's very strict for time sequence so we add + * rtl92d_phy_reload_iqk_setting here */ +void rtl92d_linked_set_reg(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	u8 indexforchannel; +	u8 channel = rtlphy->current_channel; + +	indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); +	if (!rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done) { +		RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG, +				("Do IQK for channel:%d.\n", channel)); +		rtl92d_phy_iq_calibrate(hw); +	} +} + +/* don't set REG_EDCA_BE_PARAM here because + * mac80211 will send pkt when scan */ +void rtl92de_set_qos(struct ieee80211_hw *hw, int aci) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	rtl92d_dm_init_edca_turbo(hw); +	return; +	switch (aci) { +	case AC1_BK: +		rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0xa44f); +		break; +	case AC0_BE: +		break; +	case AC2_VI: +		rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x5e4322); +		break; +	case AC3_VO: +		rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x2f3222); +		break; +	default: +		RT_ASSERT(false, ("invalid aci: %d !\n", aci)); +		break; +	} +} + +void rtl92de_enable_interrupt(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + +	rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); +	rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); +} + +void rtl92de_disable_interrupt(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + +	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); +	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); +	synchronize_irq(rtlpci->pdev->irq); +} + +static void _rtl92de_poweroff_adapter(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 u1b_tmp; +	unsigned long flags; + +	rtlpriv->intf_ops->enable_aspm(hw); +	rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); +	rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(3), 0); +	rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(15), 0); + +	/* 0x20:value 05-->04 */ +	rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04); + +	/*  ==== Reset digital sequence   ====== */ +	rtl92d_firmware_selfreset(hw); + +	/* f.   SYS_FUNC_EN 0x03[7:0]=0x51 reset MCU, MAC register, DCORE */ +	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51); + +	/* g.   MCUFWDL 0x80[1:0]=0 reset MCU ready status */ +	rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); + +	/*  ==== Pull GPIO PIN to balance level and LED control ====== */ + +	/* h.     GPIO_PIN_CTRL 0x44[31:0]=0x000  */ +	rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); + +	/* i.    Value = GPIO_PIN_CTRL[7:0] */ +	u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); + +	/* j.    GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); */ +	/* write external PIN level  */ +	rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, +			0x00FF0000 | (u1b_tmp << 8)); + +	/* k.   GPIO_MUXCFG 0x42 [15:0] = 0x0780 */ +	rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); + +	/* l.   LEDCFG 0x4C[15:0] = 0x8080 */ +	rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); + +	/*  ==== Disable analog sequence === */ + +	/* m.   AFE_PLL_CTRL[7:0] = 0x80  disable PLL */ +	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); + +	/* n.   SPS0_CTRL 0x11[7:0] = 0x22  enter PFM mode */ +	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); + +	/* o.   AFE_XTAL_CTRL 0x24[7:0] = 0x0E  disable XTAL, if No BT COEX */ +	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); + +	/* p.   RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */ +	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); + +	/*  ==== interface into suspend === */ + +	/* q.   APS_FSMCO[15:8] = 0x58 PCIe suspend mode */ +	/* According to power document V11, we need to set this */ +	/* value as 0x18. Otherwise, we may not L0s sometimes. */ +	/* This indluences power consumption. Bases on SD1's test, */ +	/* set as 0x00 do not affect power current. And if it */ +	/* is set as 0x18, they had ever met auto load fail problem. */ +	rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); + +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 ("In PowerOff,reg0x%x=%X\n", REG_SPS0_CTRL, +		  rtl_read_byte(rtlpriv, REG_SPS0_CTRL))); +	/* r.   Note: for PCIe interface, PON will not turn */ +	/* off m-bias and BandGap in PCIe suspend mode.  */ + +	/* 0x17[7] 1b': power off in process  0b' : power off over */ +	if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) { +		spin_lock_irqsave(&globalmutex_power, flags); +		u1b_tmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS); +		u1b_tmp &= (~BIT(7)); +		rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1b_tmp); +		spin_unlock_irqrestore(&globalmutex_power, flags); +	} + +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<=======\n")); +} + +void rtl92de_card_disable(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	enum nl80211_iftype opmode; + +	mac->link_state = MAC80211_NOLINK; +	opmode = NL80211_IFTYPE_UNSPECIFIED; +	_rtl92de_set_media_status(hw, opmode); + +	if (rtlpci->driver_is_goingto_unload || +	    ppsc->rfoff_reason > RF_CHANGE_BY_PS) +		rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); +	RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); +	/* Power sequence for each MAC. */ +	/* a. stop tx DMA  */ +	/* b. close RF */ +	/* c. clear rx buf */ +	/* d. stop rx DMA */ +	/* e.  reset MAC */ + +	/* a. stop tx DMA */ +	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE); +	udelay(50); + +	/* b. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */ + +	/* c. ========RF OFF sequence==========  */ +	/* 0x88c[23:20] = 0xf. */ +	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); +	rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00); + +	/* APSD_CTRL 0x600[7:0] = 0x40 */ +	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); + +	/* Close antenna 0,0xc04,0xd04 */ +	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0); +	rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0); + +	/*  SYS_FUNC_EN 0x02[7:0] = 0xE2   reset BB state machine */ +	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); + +	/* Mac0 can not do Global reset. Mac1 can do. */ +	/* SYS_FUNC_EN 0x02[7:0] = 0xE0  reset BB state machine  */ +	if (rtlpriv->rtlhal.interfaceindex == 1) +		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0); +	udelay(50); + +	/* d.  stop tx/rx dma before disable REG_CR (0x100) to fix */ +	/* dma hang issue when disable/enable device.  */ +	rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xff); +	udelay(50); +	rtl_write_byte(rtlpriv, REG_CR, 0x0); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==> Do power off.......\n")); +	if (rtl92d_phy_check_poweroff(hw)) +		_rtl92de_poweroff_adapter(hw); +	return; +} + +void rtl92de_interrupt_recognized(struct ieee80211_hw *hw, +				  u32 *p_inta, u32 *p_intb) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + +	*p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; +	rtl_write_dword(rtlpriv, ISR, *p_inta); + +	/* +	 * *p_intb = rtl_read_dword(rtlpriv, REG_HISRE) & rtlpci->irq_mask[1]; +	 * rtl_write_dword(rtlpriv, ISR + 4, *p_intb); +	 */ +} + +void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	u16 bcn_interval, atim_window; + +	bcn_interval = mac->beacon_interval; +	atim_window = 2; +	/*rtl92de_disable_interrupt(hw);  */ +	rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); +	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); +	rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); +	rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x20); +	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) +		rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x30); +	else +		rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x20); +	rtl_write_byte(rtlpriv, 0x606, 0x30); +} + +void rtl92de_set_beacon_interval(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	u16 bcn_interval = mac->beacon_interval; + +	RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG, +		 ("beacon_interval:%d\n", bcn_interval)); +	/* rtl92de_disable_interrupt(hw); */ +	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); +	/* rtl92de_enable_interrupt(hw); */ +} + +void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw, +				   u32 add_msr, u32 rm_msr) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + +	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, +		 ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr)); +	if (add_msr) +		rtlpci->irq_mask[0] |= add_msr; +	if (rm_msr) +		rtlpci->irq_mask[0] &= (~rm_msr); +	rtl92de_disable_interrupt(hw); +	rtl92de_enable_interrupt(hw); +} + +static void _rtl92de_readpowervalue_fromprom(struct txpower_info *pwrinfo, +				 u8 *rom_content, bool autoLoadfail) +{ +	u32 rfpath, eeaddr, group, offset1, offset2; +	u8 i; + +	memset(pwrinfo, 0, sizeof(struct txpower_info)); +	if (autoLoadfail) { +		for (group = 0; group < CHANNEL_GROUP_MAX; group++) { +			for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { +				if (group < CHANNEL_GROUP_MAX_2G) { +					pwrinfo->cck_index[rfpath][group] = +					    EEPROM_DEFAULT_TXPOWERLEVEL_2G; +					pwrinfo->ht40_1sindex[rfpath][group] = +					    EEPROM_DEFAULT_TXPOWERLEVEL_2G; +				} else { +					pwrinfo->ht40_1sindex[rfpath][group] = +					    EEPROM_DEFAULT_TXPOWERLEVEL_5G; +				} +				pwrinfo->ht40_2sindexdiff[rfpath][group] = +				    EEPROM_DEFAULT_HT40_2SDIFF; +				pwrinfo->ht20indexdiff[rfpath][group] = +				    EEPROM_DEFAULT_HT20_DIFF; +				pwrinfo->ofdmindexdiff[rfpath][group] = +				    EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; +				pwrinfo->ht40maxoffset[rfpath][group] = +				    EEPROM_DEFAULT_HT40_PWRMAXOFFSET; +				pwrinfo->ht20maxoffset[rfpath][group] = +				    EEPROM_DEFAULT_HT20_PWRMAXOFFSET; +			} +		} +		for (i = 0; i < 3; i++) { +			pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI; +			pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI; +		} +		return; +	} + +	/* Maybe autoload OK,buf the tx power index value is not filled. +	 * If we find it, we set it to default value. */ +	for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { +		for (group = 0; group < CHANNEL_GROUP_MAX_2G; group++) { +			eeaddr = EEPROM_CCK_TX_PWR_INX_2G + (rfpath * 3) +				 + group; +			pwrinfo->cck_index[rfpath][group] = +					(rom_content[eeaddr] == 0xFF) ? +					     (eeaddr > 0x7B ? +					     EEPROM_DEFAULT_TXPOWERLEVEL_5G : +					     EEPROM_DEFAULT_TXPOWERLEVEL_2G) : +					     rom_content[eeaddr]; +		} +	} +	for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { +		for (group = 0; group < CHANNEL_GROUP_MAX; group++) { +			offset1 = group / 3; +			offset2 = group % 3; +			eeaddr = EEPROM_HT40_1S_TX_PWR_INX_2G + (rfpath * 3) + +			    offset2 + offset1 * 21; +			pwrinfo->ht40_1sindex[rfpath][group] = +			    (rom_content[eeaddr] == 0xFF) ? (eeaddr > 0x7B ? +					     EEPROM_DEFAULT_TXPOWERLEVEL_5G : +					     EEPROM_DEFAULT_TXPOWERLEVEL_2G) : +						 rom_content[eeaddr]; +		} +	} +	/* These just for 92D efuse offset. */ +	for (group = 0; group < CHANNEL_GROUP_MAX; group++) { +		for (rfpath = 0; rfpath < RF6052_MAX_PATH; rfpath++) { +			int base1 = EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G; + +			offset1 = group / 3; +			offset2 = group % 3; + +			if (rom_content[base1 + offset2 + offset1 * 21] != 0xFF) +				pwrinfo->ht40_2sindexdiff[rfpath][group] = +				    (rom_content[base1 + +				     offset2 + offset1 * 21] >> (rfpath * 4)) +				     & 0xF; +			else +				pwrinfo->ht40_2sindexdiff[rfpath][group] = +				    EEPROM_DEFAULT_HT40_2SDIFF; +			if (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G + offset2 +			    + offset1 * 21] != 0xFF) +				pwrinfo->ht20indexdiff[rfpath][group] = +				    (rom_content[EEPROM_HT20_TX_PWR_INX_DIFF_2G +				    + offset2 + offset1 * 21] >> (rfpath * 4)) +				    & 0xF; +			else +				pwrinfo->ht20indexdiff[rfpath][group] = +				    EEPROM_DEFAULT_HT20_DIFF; +			if (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G + offset2 +			    + offset1 * 21] != 0xFF) +				pwrinfo->ofdmindexdiff[rfpath][group] = +				    (rom_content[EEPROM_OFDM_TX_PWR_INX_DIFF_2G +				     + offset2 + offset1 * 21] >> (rfpath * 4)) +				     & 0xF; +			else +				pwrinfo->ofdmindexdiff[rfpath][group] = +				    EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; +			if (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G + offset2 +			    + offset1 * 21] != 0xFF) +				pwrinfo->ht40maxoffset[rfpath][group] = +				    (rom_content[EEPROM_HT40_MAX_PWR_OFFSET_2G +				    + offset2 + offset1 * 21] >> (rfpath * 4)) +				    & 0xF; +			else +				pwrinfo->ht40maxoffset[rfpath][group] = +				    EEPROM_DEFAULT_HT40_PWRMAXOFFSET; +			if (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G + offset2 +			    + offset1 * 21] != 0xFF) +				pwrinfo->ht20maxoffset[rfpath][group] = +				    (rom_content[EEPROM_HT20_MAX_PWR_OFFSET_2G + +				     offset2 + offset1 * 21] >> (rfpath * 4)) & +				     0xF; +			else +				pwrinfo->ht20maxoffset[rfpath][group] = +				    EEPROM_DEFAULT_HT20_PWRMAXOFFSET; +		} +	} +	if (rom_content[EEPROM_TSSI_A_5G] != 0xFF) { +		/* 5GL */ +		pwrinfo->tssi_a[0] = rom_content[EEPROM_TSSI_A_5G] & 0x3F; +		pwrinfo->tssi_b[0] = rom_content[EEPROM_TSSI_B_5G] & 0x3F; +		/* 5GM */ +		pwrinfo->tssi_a[1] = rom_content[EEPROM_TSSI_AB_5G] & 0x3F; +		pwrinfo->tssi_b[1] = +		    (rom_content[EEPROM_TSSI_AB_5G] & 0xC0) >> 6 | +		    (rom_content[EEPROM_TSSI_AB_5G + 1] & 0x0F) << 2; +		/* 5GH */ +		pwrinfo->tssi_a[2] = (rom_content[EEPROM_TSSI_AB_5G + 1] & +				      0xF0) >> 4 | +		    (rom_content[EEPROM_TSSI_AB_5G + 2] & 0x03) << 4; +		pwrinfo->tssi_b[2] = (rom_content[EEPROM_TSSI_AB_5G + 2] & +				      0xFC) >> 2; +	} else { +		for (i = 0; i < 3; i++) { +			pwrinfo->tssi_a[i] = EEPROM_DEFAULT_TSSI; +			pwrinfo->tssi_b[i] = EEPROM_DEFAULT_TSSI; +		} +	} +} + +static void _rtl92de_read_txpower_info(struct ieee80211_hw *hw, +				       bool autoload_fail, u8 *hwinfo) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	struct txpower_info pwrinfo; +	u8 tempval[2], i, pwr, diff; +	u32 ch, rfPath, group; + +	_rtl92de_readpowervalue_fromprom(&pwrinfo, hwinfo, autoload_fail); +	if (!autoload_fail) { +		/* bit0~2 */ +		rtlefuse->eeprom_regulatory = (hwinfo[EEPROM_RF_OPT1] & 0x7); +		rtlefuse->eeprom_thermalmeter = +			 hwinfo[EEPROM_THERMAL_METER] & 0x1f; +		rtlefuse->crystalcap = hwinfo[EEPROM_XTAL_K]; +		tempval[0] = hwinfo[EEPROM_IQK_DELTA] & 0x03; +		tempval[1] = (hwinfo[EEPROM_LCK_DELTA] & 0x0C) >> 2; +		rtlefuse->txpwr_fromeprom = true; +		if (IS_92D_D_CUT(rtlpriv->rtlhal.version)) { +			rtlefuse->internal_pa_5g[0] = +				 !((hwinfo[EEPROM_TSSI_A_5G] & +				 BIT(6)) >> 6); +			rtlefuse->internal_pa_5g[1] = +				 !((hwinfo[EEPROM_TSSI_B_5G] & +				 BIT(6)) >> 6); +			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +				 ("Is D cut,Internal PA0 %d Internal PA1 %d\n", +				  rtlefuse->internal_pa_5g[0], +				  rtlefuse->internal_pa_5g[1])) +		} +		rtlefuse->eeprom_c9 = hwinfo[EEPROM_RF_OPT6]; +		rtlefuse->eeprom_cc = hwinfo[EEPROM_RF_OPT7]; +	} else { +		rtlefuse->eeprom_regulatory = 0; +		rtlefuse->eeprom_thermalmeter = EEPROM_DEFAULT_THERMALMETER; +		rtlefuse->crystalcap = EEPROM_DEFAULT_CRYSTALCAP; +		tempval[0] = tempval[1] = 3; +	} + +	/* Use default value to fill parameters if +	 * efuse is not filled on some place. */ + +	/* ThermalMeter from EEPROM */ +	if (rtlefuse->eeprom_thermalmeter < 0x06 || +	    rtlefuse->eeprom_thermalmeter > 0x1c) +		rtlefuse->eeprom_thermalmeter = 0x12; +	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; + +	/* check XTAL_K */ +	if (rtlefuse->crystalcap == 0xFF) +		rtlefuse->crystalcap = 0; +	if (rtlefuse->eeprom_regulatory > 3) +		rtlefuse->eeprom_regulatory = 0; + +	for (i = 0; i < 2; i++) { +		switch (tempval[i]) { +		case 0: +			tempval[i] = 5; +			break; +		case 1: +			tempval[i] = 4; +			break; +		case 2: +			tempval[i] = 3; +			break; +		case 3: +		default: +			tempval[i] = 0; +			break; +		} +	} + +	rtlefuse->delta_iqk = tempval[0]; +	if (tempval[1] > 0) +		rtlefuse->delta_lck = tempval[1] - 1; +	if (rtlefuse->eeprom_c9 == 0xFF) +		rtlefuse->eeprom_c9 = 0x00; +	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, +		 ("EEPROMRegulatory = 0x%x\n", rtlefuse->eeprom_regulatory)); +	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, +		 ("ThermalMeter = 0x%x\n", rtlefuse->eeprom_thermalmeter)); +	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, +		 ("CrystalCap = 0x%x\n", rtlefuse->crystalcap)); +	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, +		 ("Delta_IQK = 0x%x Delta_LCK = 0x%x\n", rtlefuse->delta_iqk, +		 rtlefuse->delta_lck)); + +	for (rfPath = 0; rfPath < RF6052_MAX_PATH; rfPath++) { +		for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) { +			group = rtl92d_get_chnlgroup_fromarray((u8) ch); +			if (ch < CHANNEL_MAX_NUMBER_2G) +				rtlefuse->txpwrlevel_cck[rfPath][ch] = +				    pwrinfo.cck_index[rfPath][group]; +			rtlefuse->txpwrlevel_ht40_1s[rfPath][ch] = +				    pwrinfo.ht40_1sindex[rfPath][group]; +			rtlefuse->txpwr_ht20diff[rfPath][ch] = +				    pwrinfo.ht20indexdiff[rfPath][group]; +			rtlefuse->txpwr_legacyhtdiff[rfPath][ch] = +				    pwrinfo.ofdmindexdiff[rfPath][group]; +			rtlefuse->pwrgroup_ht20[rfPath][ch] = +				    pwrinfo.ht20maxoffset[rfPath][group]; +			rtlefuse->pwrgroup_ht40[rfPath][ch] = +				    pwrinfo.ht40maxoffset[rfPath][group]; +			pwr = pwrinfo.ht40_1sindex[rfPath][group]; +			diff = pwrinfo.ht40_2sindexdiff[rfPath][group]; +			rtlefuse->txpwrlevel_ht40_2s[rfPath][ch] = +				    (pwr > diff) ? (pwr - diff) : 0; +		} +	} +} + +static void _rtl92de_read_macphymode_from_prom(struct ieee80211_hw *hw, +					       u8 *content) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u8 macphy_crvalue = content[EEPROM_MAC_FUNCTION]; + +	if (macphy_crvalue & BIT(3)) { +		rtlhal->macphymode = SINGLEMAC_SINGLEPHY; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +			 ("MacPhyMode SINGLEMAC_SINGLEPHY\n")); +	} else { +		rtlhal->macphymode = DUALMAC_DUALPHY; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +			 ("MacPhyMode DUALMAC_DUALPHY\n")); +	} +} + +static void _rtl92de_read_macphymode_and_bandtype(struct ieee80211_hw *hw, +						  u8 *content) +{ +	_rtl92de_read_macphymode_from_prom(hw, content); +	rtl92d_phy_config_macphymode(hw); +	rtl92d_phy_config_macphymode_info(hw); +} + +static void _rtl92de_efuse_update_chip_version(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	enum version_8192d chipver = rtlpriv->rtlhal.version; +	u8 cutvalue[2]; +	u16 chipvalue; + +	rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_H, +					   &cutvalue[1]); +	rtlpriv->intf_ops->read_efuse_byte(hw, EEPROME_CHIP_VERSION_L, +					   &cutvalue[0]); +	chipvalue = (cutvalue[1] << 8) | cutvalue[0]; +	switch (chipvalue) { +	case 0xAA55: +		chipver |= CHIP_92D_C_CUT; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("C-CUT!!!\n")); +		break; +	case 0x9966: +		chipver |= CHIP_92D_D_CUT; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("D-CUT!!!\n")); +		break; +	default: +		chipver |= CHIP_92D_D_CUT; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, ("Unkown CUT!\n")); +		break; +	} +	rtlpriv->rtlhal.version = chipver; +} + +static void _rtl92de_read_adapter_info(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u16 i, usvalue; +	u8 hwinfo[HWSET_MAX_SIZE]; +	u16 eeprom_id; +	unsigned long flags; + +	if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { +		spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags); +		rtl_efuse_shadow_map_update(hw); +		_rtl92de_efuse_update_chip_version(hw); +		spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); +		memcpy((void *)hwinfo, (void *)&rtlefuse->efuse_map +		       [EFUSE_INIT_MAP][0], +		       HWSET_MAX_SIZE); +	} else if (rtlefuse->epromtype == EEPROM_93C46) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("RTL819X Not boot from eeprom, check it !!")); +	} +	RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), +		      hwinfo, HWSET_MAX_SIZE); + +	eeprom_id = *((u16 *)&hwinfo[0]); +	if (eeprom_id != RTL8190_EEPROM_ID) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, +			 ("EEPROM ID(%#x) is invalid!!\n", eeprom_id)); +		rtlefuse->autoload_failflag = true; +	} else { +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n")); +		rtlefuse->autoload_failflag = false; +	} +	if (rtlefuse->autoload_failflag) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("RTL819X Not boot from eeprom, check it !!")); +		return; +	} +	rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID]; +	_rtl92de_read_macphymode_and_bandtype(hw, hwinfo); + +	/* VID, DID  SE     0xA-D */ +	rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; +	rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; +	rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; +	rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 ("EEPROMId = 0x%4x\n", eeprom_id)); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 ("EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid)); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 ("EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did)); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 ("EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid)); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 ("EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid)); + +	/* Read Permanent MAC address */ +	if (rtlhal->interfaceindex == 0) { +		for (i = 0; i < 6; i += 2) { +			usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC0_92D + i]; +			*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; +		} +	} else { +		for (i = 0; i < 6; i += 2) { +			usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR_MAC1_92D + i]; +			*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; +		} +	} +	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, +				      rtlefuse->dev_addr); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, +		 (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr))); +	_rtl92de_read_txpower_info(hw, rtlefuse->autoload_failflag, hwinfo); + +	/* Read Channel Plan */ +	switch (rtlhal->bandset) { +	case BAND_ON_2_4G: +		rtlefuse->channel_plan = COUNTRY_CODE_TELEC; +		break; +	case BAND_ON_5G: +		rtlefuse->channel_plan = COUNTRY_CODE_FCC; +		break; +	case BAND_ON_BOTH: +		rtlefuse->channel_plan = COUNTRY_CODE_FCC; +		break; +	default: +		rtlefuse->channel_plan = COUNTRY_CODE_FCC; +		break; +	} +	rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; +	rtlefuse->txpwr_fromeprom = true; +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid)); +} + +void rtl92de_read_eeprom_info(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u8 tmp_u1b; + +	rtlhal->version = _rtl92de_read_chip_version(hw); +	tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); +	rtlefuse->autoload_status = tmp_u1b; +	if (tmp_u1b & BIT(4)) { +		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EEPROM\n")); +		rtlefuse->epromtype = EEPROM_93C46; +	} else { +		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EFUSE\n")); +		rtlefuse->epromtype = EEPROM_BOOT_EFUSE; +	} +	if (tmp_u1b & BIT(5)) { +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n")); + +		rtlefuse->autoload_failflag = false; +		_rtl92de_read_adapter_info(hw); +	} else { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n")); +	} +	return; +} + +static void rtl92de_update_hal_rate_table(struct ieee80211_hw *hw, +					  struct ieee80211_sta *sta) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u32 ratr_value; +	u8 ratr_index = 0; +	u8 nmode = mac->ht_enable; +	u8 mimo_ps = IEEE80211_SMPS_OFF; +	u16 shortgi_rate; +	u32 tmp_ratr_value; +	u8 curtxbw_40mhz = mac->bw_40; +	u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? +							1 : 0; +	u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? +							1 : 0; +	enum wireless_mode wirelessmode = mac->mode; + +	if (rtlhal->current_bandtype == BAND_ON_5G) +		ratr_value = sta->supp_rates[1] << 4; +	else +		ratr_value = sta->supp_rates[0]; +	ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | +		       sta->ht_cap.mcs.rx_mask[0] << 12); +	switch (wirelessmode) { +	case WIRELESS_MODE_A: +		ratr_value &= 0x00000FF0; +		break; +	case WIRELESS_MODE_B: +		if (ratr_value & 0x0000000c) +			ratr_value &= 0x0000000d; +		else +			ratr_value &= 0x0000000f; +		break; +	case WIRELESS_MODE_G: +		ratr_value &= 0x00000FF5; +		break; +	case WIRELESS_MODE_N_24G: +	case WIRELESS_MODE_N_5G: +		nmode = 1; +		if (mimo_ps == IEEE80211_SMPS_STATIC) { +			ratr_value &= 0x0007F005; +		} else { +			u32 ratr_mask; + +			if (get_rf_type(rtlphy) == RF_1T2R || +			    get_rf_type(rtlphy) == RF_1T1R) { +				ratr_mask = 0x000ff005; +			} else { +				ratr_mask = 0x0f0ff005; +			} + +			ratr_value &= ratr_mask; +		} +		break; +	default: +		if (rtlphy->rf_type == RF_1T2R) +			ratr_value &= 0x000ff0ff; +		else +			ratr_value &= 0x0f0ff0ff; + +		break; +	} +	ratr_value &= 0x0FFFFFFF; +	if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) || +	    (!curtxbw_40mhz && curshortgi_20mhz))) { +		ratr_value |= 0x10000000; +		tmp_ratr_value = (ratr_value >> 12); +		for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { +			if ((1 << shortgi_rate) & tmp_ratr_value) +				break; +		} +		shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | +		    (shortgi_rate << 4) | (shortgi_rate); +	} +	rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); +	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, +		 ("%x\n", rtl_read_dword(rtlpriv, REG_ARFR0))); +} + +static void rtl92de_update_hal_rate_mask(struct ieee80211_hw *hw, +		struct ieee80211_sta *sta, u8 rssi_level) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	struct rtl_sta_info *sta_entry = NULL; +	u32 ratr_bitmap; +	u8 ratr_index; +	u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) +							? 1 : 0; +	u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? +							1 : 0; +	u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? +							1 : 0; +	enum wireless_mode wirelessmode = 0; +	bool shortgi = false; +	u32 value[2]; +	u8 macid = 0; +	u8 mimo_ps = IEEE80211_SMPS_OFF; + +	sta_entry = (struct rtl_sta_info *) sta->drv_priv; +	mimo_ps = sta_entry->mimo_ps; +	wirelessmode = sta_entry->wireless_mode; +	if (mac->opmode == NL80211_IFTYPE_STATION) +		curtxbw_40mhz = mac->bw_40; +	else if (mac->opmode == NL80211_IFTYPE_AP || +		mac->opmode == NL80211_IFTYPE_ADHOC) +		macid = sta->aid + 1; + +	if (rtlhal->current_bandtype == BAND_ON_5G) +		ratr_bitmap = sta->supp_rates[1] << 4; +	else +		ratr_bitmap = sta->supp_rates[0]; +	ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | +			sta->ht_cap.mcs.rx_mask[0] << 12); +	switch (wirelessmode) { +	case WIRELESS_MODE_B: +		ratr_index = RATR_INX_WIRELESS_B; +		if (ratr_bitmap & 0x0000000c) +			ratr_bitmap &= 0x0000000d; +		else +			ratr_bitmap &= 0x0000000f; +		break; +	case WIRELESS_MODE_G: +		ratr_index = RATR_INX_WIRELESS_GB; + +		if (rssi_level == 1) +			ratr_bitmap &= 0x00000f00; +		else if (rssi_level == 2) +			ratr_bitmap &= 0x00000ff0; +		else +			ratr_bitmap &= 0x00000ff5; +		break; +	case WIRELESS_MODE_A: +		ratr_index = RATR_INX_WIRELESS_G; +		ratr_bitmap &= 0x00000ff0; +		break; +	case WIRELESS_MODE_N_24G: +	case WIRELESS_MODE_N_5G: +		if (wirelessmode == WIRELESS_MODE_N_24G) +			ratr_index = RATR_INX_WIRELESS_NGB; +		else +			ratr_index = RATR_INX_WIRELESS_NG; +		if (mimo_ps == IEEE80211_SMPS_STATIC) { +			if (rssi_level == 1) +				ratr_bitmap &= 0x00070000; +			else if (rssi_level == 2) +				ratr_bitmap &= 0x0007f000; +			else +				ratr_bitmap &= 0x0007f005; +		} else { +			if (rtlphy->rf_type == RF_1T2R || +			    rtlphy->rf_type == RF_1T1R) { +				if (curtxbw_40mhz) { +					if (rssi_level == 1) +						ratr_bitmap &= 0x000f0000; +					else if (rssi_level == 2) +						ratr_bitmap &= 0x000ff000; +					else +						ratr_bitmap &= 0x000ff015; +				} else { +					if (rssi_level == 1) +						ratr_bitmap &= 0x000f0000; +					else if (rssi_level == 2) +						ratr_bitmap &= 0x000ff000; +					else +						ratr_bitmap &= 0x000ff005; +				} +			} else { +				if (curtxbw_40mhz) { +					if (rssi_level == 1) +						ratr_bitmap &= 0x0f0f0000; +					else if (rssi_level == 2) +						ratr_bitmap &= 0x0f0ff000; +					else +						ratr_bitmap &= 0x0f0ff015; +				} else { +					if (rssi_level == 1) +						ratr_bitmap &= 0x0f0f0000; +					else if (rssi_level == 2) +						ratr_bitmap &= 0x0f0ff000; +					else +						ratr_bitmap &= 0x0f0ff005; +				} +			} +		} +		if ((curtxbw_40mhz && curshortgi_40mhz) || +		    (!curtxbw_40mhz && curshortgi_20mhz)) { + +			if (macid == 0) +				shortgi = true; +			else if (macid == 1) +				shortgi = false; +		} +		break; +	default: +		ratr_index = RATR_INX_WIRELESS_NGB; + +		if (rtlphy->rf_type == RF_1T2R) +			ratr_bitmap &= 0x000ff0ff; +		else +			ratr_bitmap &= 0x0f0ff0ff; +		break; +	} + +	value[0] = (ratr_bitmap & 0x0fffffff) | (ratr_index << 28); +	value[1] = macid | (shortgi ? 0x20 : 0x00) | 0x80; +	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, +		 ("ratr_bitmap :%x value0:%x value1:%x\n", +		  ratr_bitmap, value[0], value[1])); +	rtl92d_fill_h2c_cmd(hw, H2C_RA_MASK, 5, (u8 *) value); +	if (macid != 0) +		sta_entry->ratr_index = ratr_index; +} + +void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw, +		struct ieee80211_sta *sta, u8 rssi_level) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	if (rtlpriv->dm.useramask) +		rtl92de_update_hal_rate_mask(hw, sta, rssi_level); +	else +		rtl92de_update_hal_rate_table(hw, sta); +} + +void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	u16 sifs_timer; + +	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, +				      (u8 *)&mac->slot_time); +	if (!mac->ht_enable) +		sifs_timer = 0x0a0a; +	else +		sifs_timer = 0x1010; +	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); +} + +bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	enum rf_pwrstate e_rfpowerstate_toset; +	u8 u1tmp; +	bool actuallyset = false; +	unsigned long flag; + +	if (rtlpci->being_init_adapter) +		return false; +	if (ppsc->swrf_processing) +		return false; +	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); +	if (ppsc->rfchange_inprogress) { +		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); +		return false; +	} else { +		ppsc->rfchange_inprogress = true; +		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); +	} +	rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, rtl_read_byte(rtlpriv, +			  REG_MAC_PINMUX_CFG) & ~(BIT(3))); +	u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); +	e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF; +	if (ppsc->hwradiooff && (e_rfpowerstate_toset == ERFON)) { +		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, +			 ("GPIOChangeRF  - HW Radio ON, RF ON\n")); +		e_rfpowerstate_toset = ERFON; +		ppsc->hwradiooff = false; +		actuallyset = true; +	} else if ((ppsc->hwradiooff == false) +		&& (e_rfpowerstate_toset == ERFOFF)) { +		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, +			 ("GPIOChangeRF  - HW Radio OFF, RF OFF\n")); +		e_rfpowerstate_toset = ERFOFF; +		ppsc->hwradiooff = true; +		actuallyset = true; +	} +	if (actuallyset) { +		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); +		ppsc->rfchange_inprogress = false; +		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); +	} else { +		if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) +			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); +		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); +		ppsc->rfchange_inprogress = false; +		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); +	} +	*valid = 1; +	return !ppsc->hwradiooff; +} + +void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index, +		     u8 *p_macaddr, bool is_group, u8 enc_algo, +		     bool is_wepkey, bool clear_all) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	u8 *macaddr = p_macaddr; +	u32 entry_id; +	bool is_pairwise = false; +	static u8 cam_const_addr[4][6] = { +		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, +		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, +		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, +		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03} +	}; +	static u8 cam_const_broad[] = { +		0xff, 0xff, 0xff, 0xff, 0xff, 0xff +	}; + +	if (clear_all) { +		u8 idx; +		u8 cam_offset = 0; +		u8 clear_number = 5; +		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n")); +		for (idx = 0; idx < clear_number; idx++) { +			rtl_cam_mark_invalid(hw, cam_offset + idx); +			rtl_cam_empty_entry(hw, cam_offset + idx); + +			if (idx < 5) { +				memset(rtlpriv->sec.key_buf[idx], 0, +				       MAX_KEY_LEN); +				rtlpriv->sec.key_len[idx] = 0; +			} +		} +	} else { +		switch (enc_algo) { +		case WEP40_ENCRYPTION: +			enc_algo = CAM_WEP40; +			break; +		case WEP104_ENCRYPTION: +			enc_algo = CAM_WEP104; +			break; +		case TKIP_ENCRYPTION: +			enc_algo = CAM_TKIP; +			break; +		case AESCCMP_ENCRYPTION: +			enc_algo = CAM_AES; +			break; +		default: +			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case " +						"not process\n")); +			enc_algo = CAM_TKIP; +			break; +		} +		if (is_wepkey || rtlpriv->sec.use_defaultkey) { +			macaddr = cam_const_addr[key_index]; +			entry_id = key_index; +		} else { +			if (is_group) { +				macaddr = cam_const_broad; +				entry_id = key_index; +			} else { +				if (mac->opmode == NL80211_IFTYPE_AP) { +					entry_id = rtl_cam_get_free_entry(hw, +								 p_macaddr); +					if (entry_id >=  TOTAL_CAM_ENTRY) { +						RT_TRACE(rtlpriv, COMP_SEC, +							 DBG_EMERG, ("Can not " +							 "find free hw security" +							 " cam entry\n")); +						return; +					} +				} else { +					entry_id = CAM_PAIRWISE_KEY_POSITION; +				} +				key_index = PAIRWISE_KEYIDX; +				is_pairwise = true; +			} +		} +		if (rtlpriv->sec.key_len[key_index] == 0) { +			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, +				 ("delete one entry, entry_id is %d\n", +				 entry_id)); +			if (mac->opmode == NL80211_IFTYPE_AP) +				rtl_cam_del_entry(hw, p_macaddr); +			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); +		} else { +			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, +				 ("The insert KEY length is %d\n", +				  rtlpriv->sec.key_len[PAIRWISE_KEYIDX])); +			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, +				 ("The insert KEY  is %x %x\n", +				  rtlpriv->sec.key_buf[0][0], +				  rtlpriv->sec.key_buf[0][1])); +			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, +				 ("add one entry\n")); +			if (is_pairwise) { +				RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, +					      "Pairwiase Key content :", +					      rtlpriv->sec.pairwise_key, +					      rtlpriv-> +					      sec.key_len[PAIRWISE_KEYIDX]); +				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, +					 ("set Pairwiase key\n")); +				rtl_cam_add_one_entry(hw, macaddr, key_index, +						      entry_id, enc_algo, +						      CAM_CONFIG_NO_USEDK, +						      rtlpriv-> +						      sec.key_buf[key_index]); +			} else { +				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, +					 ("set group key\n")); +				if (mac->opmode == NL80211_IFTYPE_ADHOC) { +					rtl_cam_add_one_entry(hw, +						rtlefuse->dev_addr, +						PAIRWISE_KEYIDX, +						CAM_PAIRWISE_KEY_POSITION, +						enc_algo, CAM_CONFIG_NO_USEDK, +						rtlpriv->sec.key_buf[entry_id]); +				} +				rtl_cam_add_one_entry(hw, macaddr, key_index, +						entry_id, enc_algo, +						CAM_CONFIG_NO_USEDK, +						rtlpriv->sec.key_buf +						[entry_id]); +			} +		} +	} +} + +void rtl92de_suspend(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	rtlpriv->rtlhal.macphyctl_reg = rtl_read_byte(rtlpriv, +		REG_MAC_PHY_CTRL_NORMAL); +} + +void rtl92de_resume(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL, +		       rtlpriv->rtlhal.macphyctl_reg); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.h b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h new file mode 100644 index 00000000000..ad44ffa520e --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92DE_HW_H__ +#define __RTL92DE_HW_H__ + +void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92de_read_eeprom_info(struct ieee80211_hw *hw); +void rtl92de_interrupt_recognized(struct ieee80211_hw *hw, +				  u32 *p_inta, u32 *p_intb); +int rtl92de_hw_init(struct ieee80211_hw *hw); +void rtl92de_card_disable(struct ieee80211_hw *hw); +void rtl92de_enable_interrupt(struct ieee80211_hw *hw); +void rtl92de_disable_interrupt(struct ieee80211_hw *hw); +int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type); +void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); +void rtl92de_set_qos(struct ieee80211_hw *hw, int aci); +void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw); +void rtl92de_set_beacon_interval(struct ieee80211_hw *hw); +void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw, +				   u32 add_msr, u32 rm_msr); +void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val); +void rtl92de_update_hal_rate_tbl(struct ieee80211_hw *hw, +				 struct ieee80211_sta *sta, u8 rssi_level); +void rtl92de_update_channel_access_setting(struct ieee80211_hw *hw); +bool rtl92de_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid); +void rtl92de_enable_hw_security_config(struct ieee80211_hw *hw); +void rtl92de_set_key(struct ieee80211_hw *hw, u32 key_index, +		     u8 *p_macaddr, bool is_group, u8 enc_algo, +		     bool is_wepkey, bool clear_all); + +extern void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset, +				    u32 value, u8 direct); +extern u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, +				  u8 direct); +void rtl92de_suspend(struct ieee80211_hw *hw); +void rtl92de_resume(struct ieee80211_hw *hw); +void rtl92d_linked_set_reg(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.c b/drivers/net/wireless/rtlwifi/rtl8192de/led.c new file mode 100644 index 00000000000..f1552f4df65 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/led.c @@ -0,0 +1,159 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "reg.h" +#include "led.h" + +static void _rtl92ce_init_led(struct ieee80211_hw *hw, +			      struct rtl_led *pled, enum rtl_led_pin ledpin) +{ +	pled->hw = hw; +	pled->ledpin = ledpin; +	pled->ledon = false; +} + +void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) +{ +	u8 ledcfg; +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, +		 ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin)); + +	switch (pled->ledpin) { +	case LED_PIN_GPIO0: +		break; +	case LED_PIN_LED0: +		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + +		if ((rtlpriv->efuse.eeprom_did == 0x8176) || +			(rtlpriv->efuse.eeprom_did == 0x8193)) +			/* BIT7 of REG_LEDCFG2 should be set to +			 * make sure we could emit the led2. */ +			rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) | +				       BIT(7) | BIT(5) | BIT(6)); +		else +			rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0xf0) | +				       BIT(7) | BIT(5)); +		break; +	case LED_PIN_LED1: +		ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG1); + +		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5)); +		break; +	default: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("switch case not process\n")); +		break; +	} +	pled->ledon = true; +} + +void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); +	u8 ledcfg; + +	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, +		 ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin)); + +	ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2); + +	switch (pled->ledpin) { +	case LED_PIN_GPIO0: +		break; +	case LED_PIN_LED0: +		ledcfg &= 0xf0; +		if (pcipriv->ledctl.led_opendrain) +			rtl_write_byte(rtlpriv, REG_LEDCFG2, +				       (ledcfg | BIT(1) | BIT(5) | BIT(6))); +		else +			rtl_write_byte(rtlpriv, REG_LEDCFG2, +				       (ledcfg | BIT(3) | BIT(5) | BIT(6))); +		break; +	case LED_PIN_LED1: +		ledcfg &= 0x0f; +		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3))); +		break; +	default: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("switch case not process\n")); +		break; +	} +	pled->ledon = false; +} + +void rtl92de_init_sw_leds(struct ieee80211_hw *hw) +{ +	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); +	_rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); +	_rtl92ce_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); +} + +static void _rtl92ce_sw_led_control(struct ieee80211_hw *hw, +				    enum led_ctl_mode ledaction) +{ +	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); +	struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); +	switch (ledaction) { +	case LED_CTL_POWER_ON: +	case LED_CTL_LINK: +	case LED_CTL_NO_LINK: +		rtl92de_sw_led_on(hw, pLed0); +		break; +	case LED_CTL_POWER_OFF: +		rtl92de_sw_led_off(hw, pLed0); +		break; +	default: +		break; +	} +} + +void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); + +	if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && +	    (ledaction == LED_CTL_TX || +	     ledaction == LED_CTL_RX || +	     ledaction == LED_CTL_SITE_SURVEY || +	     ledaction == LED_CTL_LINK || +	     ledaction == LED_CTL_NO_LINK || +	     ledaction == LED_CTL_START_TO_LINK || +	     ledaction == LED_CTL_POWER_ON)) { +		return; +	} +	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", ledaction)); + +	_rtl92ce_sw_led_control(hw, ledaction); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/led.h b/drivers/net/wireless/rtlwifi/rtl8192de/led.h new file mode 100644 index 00000000000..57f4a3c583d --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/led.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92CE_LED_H__ +#define __RTL92CE_LED_H__ + +void rtl92de_init_sw_leds(struct ieee80211_hw *hw); +void rtl92de_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92de_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); +void rtl92de_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c new file mode 100644 index 00000000000..3ac7af1c550 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c @@ -0,0 +1,3831 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../ps.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "table.h" +#include "sw.h" +#include "hw.h" + +#define MAX_RF_IMR_INDEX			12 +#define MAX_RF_IMR_INDEX_NORMAL			13 +#define RF_REG_NUM_FOR_C_CUT_5G			6 +#define RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA	7 +#define RF_REG_NUM_FOR_C_CUT_2G			5 +#define RF_CHNL_NUM_5G				19 +#define RF_CHNL_NUM_5G_40M			17 +#define TARGET_CHNL_NUM_5G			221 +#define TARGET_CHNL_NUM_2G			14 +#define CV_CURVE_CNT				64 + +static u32 rf_reg_for_5g_swchnl_normal[MAX_RF_IMR_INDEX_NORMAL] = { +	0, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x0 +}; + +static u8 rf_reg_for_c_cut_5g[RF_REG_NUM_FOR_C_CUT_5G] = { +	RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G4, RF_SYN_G5, RF_SYN_G6 +}; + +static u8 rf_reg_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = { +	RF_SYN_G1, RF_SYN_G2, RF_SYN_G3, RF_SYN_G7, RF_SYN_G8 +}; + +static u8 rf_for_c_cut_5g_internal_pa[RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = { +	0x0B, 0x48, 0x49, 0x4B, 0x03, 0x04, 0x0E +}; + +static u32 rf_reg_mask_for_c_cut_2g[RF_REG_NUM_FOR_C_CUT_2G] = { +	BIT(19) | BIT(18) | BIT(17) | BIT(14) | BIT(1), +	BIT(10) | BIT(9), +	BIT(18) | BIT(17) | BIT(16) | BIT(1), +	BIT(2) | BIT(1), +	BIT(15) | BIT(14) | BIT(13) | BIT(12) | BIT(11) +}; + +static u8 rf_chnl_5g[RF_CHNL_NUM_5G] = { +	36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, +	112, 116, 120, 124, 128, 132, 136, 140 +}; + +static u8 rf_chnl_5g_40m[RF_CHNL_NUM_5G_40M] = { +	38, 42, 46, 50, 54, 58, 62, 102, 106, 110, 114, +	118, 122, 126, 130, 134, 138 +}; +static u32 rf_reg_pram_c_5g[5][RF_REG_NUM_FOR_C_CUT_5G] = { +	{0xE43BE, 0xFC638, 0x77C0A, 0xDE471, 0xd7110, 0x8EB04}, +	{0xE43BE, 0xFC078, 0xF7C1A, 0xE0C71, 0xD7550, 0xAEB04}, +	{0xE43BF, 0xFF038, 0xF7C0A, 0xDE471, 0xE5550, 0xAEB04}, +	{0xE43BF, 0xFF079, 0xF7C1A, 0xDE471, 0xE5550, 0xAEB04}, +	{0xE43BF, 0xFF038, 0xF7C1A, 0xDE471, 0xd7550, 0xAEB04} +}; + +static u32 rf_reg_param_for_c_cut_2g[3][RF_REG_NUM_FOR_C_CUT_2G] = { +	{0x643BC, 0xFC038, 0x77C1A, 0x41289, 0x01840}, +	{0x643BC, 0xFC038, 0x07C1A, 0x41289, 0x01840}, +	{0x243BC, 0xFC438, 0x07C1A, 0x4128B, 0x0FC41} +}; + +static u32 rf_syn_g4_for_c_cut_2g = 0xD1C31 & 0x7FF; + +static u32 rf_pram_c_5g_int_pa[3][RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA] = { +	{0x01a00, 0x40443, 0x00eb5, 0x89bec, 0x94a12, 0x94a12, 0x94a12}, +	{0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a52, 0x94a52, 0x94a52}, +	{0x01800, 0xc0443, 0x00730, 0x896ee, 0x94a12, 0x94a12, 0x94a12} +}; + +/* [mode][patha+b][reg] */ +static u32 rf_imr_param_normal[1][3][MAX_RF_IMR_INDEX_NORMAL] = { +	{ +		/* channel 1-14. */ +		{ +			0x70000, 0x00ff0, 0x4400f, 0x00ff0, 0x0, 0x0, 0x0, +			0x0, 0x0, 0x64888, 0xe266c, 0x00090, 0x22fff +		}, +		/* path 36-64 */ +		{ +			0x70000, 0x22880, 0x4470f, 0x55880, 0x00070, 0x88000, +			0x0, 0x88080, 0x70000, 0x64a82, 0xe466c, 0x00090, +			0x32c9a +		}, +		/* 100 -165 */ +		{ +			0x70000, 0x44880, 0x4477f, 0x77880, 0x00070, 0x88000, +			0x0, 0x880b0, 0x0, 0x64b82, 0xe466c, 0x00090, 0x32c9a +		} +	} +}; + +static u32 curveindex_5g[TARGET_CHNL_NUM_5G] = {0}; + +static u32 curveindex_2g[TARGET_CHNL_NUM_2G] = {0}; + +static u32 targetchnl_5g[TARGET_CHNL_NUM_5G] = { +	25141, 25116, 25091, 25066, 25041, +	25016, 24991, 24966, 24941, 24917, +	24892, 24867, 24843, 24818, 24794, +	24770, 24765, 24721, 24697, 24672, +	24648, 24624, 24600, 24576, 24552, +	24528, 24504, 24480, 24457, 24433, +	24409, 24385, 24362, 24338, 24315, +	24291, 24268, 24245, 24221, 24198, +	24175, 24151, 24128, 24105, 24082, +	24059, 24036, 24013, 23990, 23967, +	23945, 23922, 23899, 23876, 23854, +	23831, 23809, 23786, 23764, 23741, +	23719, 23697, 23674, 23652, 23630, +	23608, 23586, 23564, 23541, 23519, +	23498, 23476, 23454, 23432, 23410, +	23388, 23367, 23345, 23323, 23302, +	23280, 23259, 23237, 23216, 23194, +	23173, 23152, 23130, 23109, 23088, +	23067, 23046, 23025, 23003, 22982, +	22962, 22941, 22920, 22899, 22878, +	22857, 22837, 22816, 22795, 22775, +	22754, 22733, 22713, 22692, 22672, +	22652, 22631, 22611, 22591, 22570, +	22550, 22530, 22510, 22490, 22469, +	22449, 22429, 22409, 22390, 22370, +	22350, 22336, 22310, 22290, 22271, +	22251, 22231, 22212, 22192, 22173, +	22153, 22134, 22114, 22095, 22075, +	22056, 22037, 22017, 21998, 21979, +	21960, 21941, 21921, 21902, 21883, +	21864, 21845, 21826, 21807, 21789, +	21770, 21751, 21732, 21713, 21695, +	21676, 21657, 21639, 21620, 21602, +	21583, 21565, 21546, 21528, 21509, +	21491, 21473, 21454, 21436, 21418, +	21400, 21381, 21363, 21345, 21327, +	21309, 21291, 21273, 21255, 21237, +	21219, 21201, 21183, 21166, 21148, +	21130, 21112, 21095, 21077, 21059, +	21042, 21024, 21007, 20989, 20972, +	25679, 25653, 25627, 25601, 25575, +	25549, 25523, 25497, 25471, 25446, +	25420, 25394, 25369, 25343, 25318, +	25292, 25267, 25242, 25216, 25191, +	25166 +}; + +/* channel 1~14 */ +static u32 targetchnl_2g[TARGET_CHNL_NUM_2G] = { +	26084, 26030, 25976, 25923, 25869, 25816, 25764, +	25711, 25658, 25606, 25554, 25502, 25451, 25328 +}; + +static u32 _rtl92d_phy_calculate_bit_shift(u32 bitmask) +{ +	u32 i; + +	for (i = 0; i <= 31; i++) { +		if (((bitmask >> i) & 0x1) == 1) +			break; +	} + +	return i; +} + +u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtlpriv); +	u32 returnvalue, originalvalue, bitshift; +	u8 dbi_direct; + +	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), " +		"bitmask(%#x)\n", regaddr, bitmask)); +	if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) { +		/* mac1 use phy0 read radio_b. */ +		/* mac0 use phy1 read radio_b. */ +		if (rtlhal->during_mac1init_radioa) +			dbi_direct = BIT(3); +		else if (rtlhal->during_mac0init_radiob) +			dbi_direct = BIT(3) | BIT(2); +		originalvalue = rtl92de_read_dword_dbi(hw, (u16)regaddr, +			dbi_direct); +	} else { +		originalvalue = rtl_read_dword(rtlpriv, regaddr); +	} +	bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); +	returnvalue = (originalvalue & bitmask) >> bitshift; +	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("BBR MASK=0x%x " +		"Addr[0x%x]=0x%x\n", bitmask, regaddr, originalvalue)); +	return returnvalue; +} + +void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw, +			   u32 regaddr, u32 bitmask, u32 data) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtlpriv); +	u8 dbi_direct = 0; +	u32 originalvalue, bitshift; + +	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," +		" data(%#x)\n", regaddr, bitmask, data)); +	if (rtlhal->during_mac1init_radioa) +		dbi_direct = BIT(3); +	else if (rtlhal->during_mac0init_radiob) +		/* mac0 use phy1 write radio_b. */ +		dbi_direct = BIT(3) | BIT(2); +	if (bitmask != BMASKDWORD) { +		if (rtlhal->during_mac1init_radioa || +		    rtlhal->during_mac0init_radiob) +			originalvalue = rtl92de_read_dword_dbi(hw, +					(u16) regaddr, +					dbi_direct); +		else +			originalvalue = rtl_read_dword(rtlpriv, regaddr); +		bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); +		data = ((originalvalue & (~bitmask)) | (data << bitshift)); +	} +	if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob) +		rtl92de_write_dword_dbi(hw, (u16) regaddr, data, dbi_direct); +	else +		rtl_write_dword(rtlpriv, regaddr, data); +	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," +		 " data(%#x)\n", regaddr, bitmask, data)); +} + +static u32 _rtl92d_phy_rf_serial_read(struct ieee80211_hw *hw, +				      enum radio_path rfpath, u32 offset) +{ + +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; +	u32 newoffset; +	u32 tmplong, tmplong2; +	u8 rfpi_enable = 0; +	u32 retvalue; + +	newoffset = offset; +	tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD); +	if (rfpath == RF90_PATH_A) +		tmplong2 = tmplong; +	else +		tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, BMASKDWORD); +	tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) | +		(newoffset << 23) | BLSSIREADEDGE; +	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD, +		tmplong & (~BLSSIREADEDGE)); +	udelay(10); +	rtl_set_bbreg(hw, pphyreg->rfhssi_para2, BMASKDWORD, tmplong2); +	udelay(50); +	udelay(50); +	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, BMASKDWORD, +		tmplong | BLSSIREADEDGE); +	udelay(10); +	if (rfpath == RF90_PATH_A) +		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, +			      BIT(8)); +	else if (rfpath == RF90_PATH_B) +		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, +			      BIT(8)); +	if (rfpi_enable) +		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi, +			BLSSIREADBACKDATA); +	else +		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, +			BLSSIREADBACKDATA); +	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x] = 0x%x\n", +		 rfpath, pphyreg->rflssi_readback, retvalue)); +	return retvalue; +} + +static void _rtl92d_phy_rf_serial_write(struct ieee80211_hw *hw, +					enum radio_path rfpath, +					u32 offset, u32 data) +{ +	u32 data_and_addr; +	u32 newoffset; +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + +	newoffset = offset; +	/* T65 RF */ +	data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; +	rtl_set_bbreg(hw, pphyreg->rf3wire_offset, BMASKDWORD, data_and_addr); +	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n", +		rfpath, pphyreg->rf3wire_offset, data_and_addr)); +} + +u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw, +			    enum radio_path rfpath, u32 regaddr, u32 bitmask) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 original_value, readback_value, bitshift; +	unsigned long flags; + +	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), " +		"rfpath(%#x), bitmask(%#x)\n", +		regaddr, rfpath, bitmask)); +	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); +	original_value = _rtl92d_phy_rf_serial_read(hw, rfpath, regaddr); +	bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); +	readback_value = (original_value & bitmask) >> bitshift; +	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); +	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), " +		"bitmask(%#x), original_value(%#x)\n", +		regaddr, rfpath, bitmask, original_value)); +	return readback_value; +} + +void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, +	u32 regaddr, u32 bitmask, u32 data) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	u32 original_value, bitshift; +	unsigned long flags; + +	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, +		("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", +		regaddr, bitmask, data, rfpath)); +	if (bitmask == 0) +		return; +	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); +	if (rtlphy->rf_mode != RF_OP_BY_FW) { +		if (bitmask != BRFREGOFFSETMASK) { +			original_value = _rtl92d_phy_rf_serial_read(hw, +				rfpath, regaddr); +			bitshift = _rtl92d_phy_calculate_bit_shift(bitmask); +			data = ((original_value & (~bitmask)) | +				(data << bitshift)); +		} +		_rtl92d_phy_rf_serial_write(hw, rfpath, regaddr, data); +	} +	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); +	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), " +		"bitmask(%#x), data(%#x), rfpath(%#x)\n", +		regaddr, bitmask, data, rfpath)); +} + +bool rtl92d_phy_mac_config(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 i; +	u32 arraylength; +	u32 *ptrarray; + +	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Read Rtl819XMACPHY_Array\n")); +	arraylength = MAC_2T_ARRAYLENGTH; +	ptrarray = rtl8192de_mac_2tarray; +	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Img:Rtl819XMAC_Array\n")); +	for (i = 0; i < arraylength; i = i + 2) +		rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); +	if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) { +		/* improve 2-stream TX EVM */ +		/* rtl_write_byte(rtlpriv, 0x14,0x71); */ +		/* AMPDU aggregation number 9 */ +		/* rtl_write_word(rtlpriv, REG_MAX_AGGR_NUM, MAX_AGGR_NUM); */ +		rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x0B); +	} else { +		/* 92D need to test to decide the num. */ +		rtl_write_byte(rtlpriv, REG_MAX_AGGR_NUM, 0x07); +	} +	return true; +} + +static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); + +	/* RF Interface Sowrtware Control */ +	/* 16 LSBs if read 32-bit from 0x870 */ +	rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; +	/* 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872) */ +	rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; +	/* 16 LSBs if read 32-bit from 0x874 */ +	rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; +	/* 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876) */ + +	rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; +	/* RF Interface Readback Value */ +	/* 16 LSBs if read 32-bit from 0x8E0 */ +	rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; +	/* 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2) */ +	rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; +	/* 16 LSBs if read 32-bit from 0x8E4 */ +	rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; +	/* 16 MSBs if read 32-bit from 0x8E4 (16-bit for 0x8E6) */ +	rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; + +	/* RF Interface Output (and Enable) */ +	/* 16 LSBs if read 32-bit from 0x860 */ +	rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; +	/* 16 LSBs if read 32-bit from 0x864 */ +	rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; + +	/* RF Interface (Output and)  Enable */ +	/* 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862) */ +	rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; +	/* 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866) */ +	rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; + +	/* Addr of LSSI. Wirte RF register by driver */ +	/* LSSI Parameter */ +	rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = +				 RFPGA0_XA_LSSIPARAMETER; +	rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = +				 RFPGA0_XB_LSSIPARAMETER; + +	/* RF parameter */ +	/* BB Band Select */ +	rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; +	rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; +	rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; +	rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; + +	/* Tx AGC Gain Stage (same for all path. Should we remove this?) */ +	/* Tx gain stage */ +	rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; +	/* Tx gain stage */ +	rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; +	/* Tx gain stage */ +	rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; +	/* Tx gain stage */ +	rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; + +	/* Tranceiver A~D HSSI Parameter-1 */ +	/* wire control parameter1 */ +	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; +	/* wire control parameter1 */ +	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; + +	/* Tranceiver A~D HSSI Parameter-2 */ +	/* wire control parameter2 */ +	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; +	/* wire control parameter2 */ +	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; + +	/* RF switch Control */ +	/* TR/Ant switch control */ +	rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control = +		RFPGA0_XAB_SWITCHCONTROL; +	rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control = +	    RFPGA0_XAB_SWITCHCONTROL; +	rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control = +	    RFPGA0_XCD_SWITCHCONTROL; +	rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control = +	    RFPGA0_XCD_SWITCHCONTROL; + +	/* AGC control 1 */ +	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; +	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; +	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; +	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; + +	/* AGC control 2  */ +	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; +	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; +	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; +	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; + +	/* RX AFE control 1 */ +	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance = +	    ROFDM0_XARXIQIMBALANCE; +	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance = +	    ROFDM0_XBRXIQIMBALANCE; +	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance = +	    ROFDM0_XCRXIQIMBALANCE; +	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance = +	    ROFDM0_XDRXIQIMBALANCE; + +	/*RX AFE control 1 */ +	rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; +	rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; +	rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; +	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; + +	/* Tx AFE control 1 */ +	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance = +	    ROFDM0_XATxIQIMBALANCE; +	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance = +	    ROFDM0_XBTxIQIMBALANCE; +	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance = +	    ROFDM0_XCTxIQIMBALANCE; +	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance = +	    ROFDM0_XDTxIQIMBALANCE; + +	/* Tx AFE control 2 */ +	rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE; +	rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTxAFE; +	rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTxAFE; +	rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE; + +	/* Tranceiver LSSI Readback SI mode */ +	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback = +	    RFPGA0_XA_LSSIREADBACK; +	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback = +	    RFPGA0_XB_LSSIREADBACK; +	rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback = +	    RFPGA0_XC_LSSIREADBACK; +	rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback = +	    RFPGA0_XD_LSSIREADBACK; + +	/* Tranceiver LSSI Readback PI mode */ +	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi = +	    TRANSCEIVERA_HSPI_READBACK; +	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi = +	    TRANSCEIVERB_HSPI_READBACK; +} + +static bool _rtl92d_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, +	u8 configtype) +{ +	int i; +	u32 *phy_regarray_table; +	u32 *agctab_array_table = NULL; +	u32 *agctab_5garray_table; +	u16 phy_reg_arraylen, agctab_arraylen = 0, agctab_5garraylen; +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); + +	/* Normal chip,Mac0 use AGC_TAB.txt for 2G and 5G band. */ +	if (rtlhal->interfaceindex == 0) { +		agctab_arraylen = AGCTAB_ARRAYLENGTH; +		agctab_array_table = rtl8192de_agctab_array; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +			 (" ===> phy:MAC0, Rtl819XAGCTAB_Array\n")); +	} else { +		if (rtlhal->current_bandtype == BAND_ON_2_4G) { +			agctab_arraylen = AGCTAB_2G_ARRAYLENGTH; +			agctab_array_table = rtl8192de_agctab_2garray; +			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +				 (" ===> phy:MAC1, Rtl819XAGCTAB_2GArray\n")); +		} else { +			agctab_5garraylen = AGCTAB_5G_ARRAYLENGTH; +			agctab_5garray_table = rtl8192de_agctab_5garray; +			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +				 (" ===> phy:MAC1, Rtl819XAGCTAB_5GArray\n")); + +		} +	} +	phy_reg_arraylen = PHY_REG_2T_ARRAYLENGTH; +	phy_regarray_table = rtl8192de_phy_reg_2tarray; +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 (" ===> phy:Rtl819XPHY_REG_Array_PG\n")); +	if (configtype == BASEBAND_CONFIG_PHY_REG) { +		for (i = 0; i < phy_reg_arraylen; i = i + 2) { +			if (phy_regarray_table[i] == 0xfe) +				mdelay(50); +			else if (phy_regarray_table[i] == 0xfd) +				mdelay(5); +			else if (phy_regarray_table[i] == 0xfc) +				mdelay(1); +			else if (phy_regarray_table[i] == 0xfb) +				udelay(50); +			else if (phy_regarray_table[i] == 0xfa) +				udelay(5); +			else if (phy_regarray_table[i] == 0xf9) +				udelay(1); +			rtl_set_bbreg(hw, phy_regarray_table[i], BMASKDWORD, +				      phy_regarray_table[i + 1]); +			udelay(1); +			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +				 ("The phy_regarray_table[0] is %x" +				  " Rtl819XPHY_REGArray[1] is %x\n", +				  phy_regarray_table[i], +				  phy_regarray_table[i + 1])); +		} +	} else if (configtype == BASEBAND_CONFIG_AGC_TAB) { +		if (rtlhal->interfaceindex == 0) { +			for (i = 0; i < agctab_arraylen; i = i + 2) { +				rtl_set_bbreg(hw, agctab_array_table[i], +					BMASKDWORD, +					agctab_array_table[i + 1]); +				/* Add 1us delay between BB/RF register +				 * setting. */ +				udelay(1); +				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +					 ("The Rtl819XAGCTAB_Array_" +					 "Table[0] is %ul " +					 "Rtl819XPHY_REGArray[1] is %ul\n", +					 agctab_array_table[i], +					 agctab_array_table[i + 1])); +			} +			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +				 ("Normal Chip, MAC0, load " +				 "Rtl819XAGCTAB_Array\n")); +		} else { +			if (rtlhal->current_bandtype == BAND_ON_2_4G) { +				for (i = 0; i < agctab_arraylen; i = i + 2) { +					rtl_set_bbreg(hw, agctab_array_table[i], +						BMASKDWORD, +						agctab_array_table[i + 1]); +					/* Add 1us delay between BB/RF register +					 * setting. */ +					udelay(1); +					RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +						 ("The Rtl819XAGCTAB_Array_" +						 "Table[0] is %ul Rtl819XPHY_" +						 "REGArray[1] is %ul\n", +						 agctab_array_table[i], +						 agctab_array_table[i + 1])); +				} +				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +					 ("Load Rtl819XAGCTAB_2GArray\n")); +			} else { +				for (i = 0; i < agctab_5garraylen; i = i + 2) { +					rtl_set_bbreg(hw, +						agctab_5garray_table[i], +						BMASKDWORD, +						agctab_5garray_table[i + 1]); +					/* Add 1us delay between BB/RF registeri +					 * setting. */ +					udelay(1); +					RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +						 ("The Rtl819XAGCTAB_5GArray_" +						 "Table[0] is %ul Rtl819XPHY_" +						 "REGArray[1] is %ul\n", +						 agctab_5garray_table[i], +						 agctab_5garray_table[i + 1])); +				} +				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +					("Load Rtl819XAGCTAB_5GArray\n")); +			} +		} +	} +	return true; +} + +static void _rtl92d_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, +						   u32 regaddr, u32 bitmask, +						   u32 data) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); + +	if (regaddr == RTXAGC_A_RATE18_06) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][0])); +	} +	if (regaddr == RTXAGC_A_RATE54_24) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][1])); +	} +	if (regaddr == RTXAGC_A_CCK1_MCS32) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][6])); +	} +	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][7])); +	} +	if (regaddr == RTXAGC_A_MCS03_MCS00) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][2])); +	} +	if (regaddr == RTXAGC_A_MCS07_MCS04) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][3])); +	} +	if (regaddr == RTXAGC_A_MCS11_MCS08) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][4])); +	} +	if (regaddr == RTXAGC_A_MCS15_MCS12) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][5])); +	} +	if (regaddr == RTXAGC_B_RATE18_06) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][8])); +	} +	if (regaddr == RTXAGC_B_RATE54_24) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][9])); +	} +	if (regaddr == RTXAGC_B_CCK1_55_MCS32) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][14])); +	} +	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][15])); +	} +	if (regaddr == RTXAGC_B_MCS03_MCS00) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][10])); +	} +	if (regaddr == RTXAGC_B_MCS07_MCS04) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%ulx\n", +			 rtlphy->pwrgroup_cnt, +			 rtlphy->mcs_txpwrlevel_origoffset +			 [rtlphy->pwrgroup_cnt][11])); +	} +	if (regaddr == RTXAGC_B_MCS11_MCS08) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%ulx\n", +			  rtlphy->pwrgroup_cnt, +			  rtlphy->mcs_txpwrlevel_origoffset +					[rtlphy->pwrgroup_cnt][12])); +	} +	if (regaddr == RTXAGC_B_MCS15_MCS12) { +		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] = +									 data; +		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +			 ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%ulx\n", +			  rtlphy->pwrgroup_cnt, +			  rtlphy->mcs_txpwrlevel_origoffset +					[rtlphy->pwrgroup_cnt][13])); +		rtlphy->pwrgroup_cnt++; +	} +} + +static bool _rtl92d_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, +	u8 configtype) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	int i; +	u32 *phy_regarray_table_pg; +	u16 phy_regarray_pg_len; + +	phy_regarray_pg_len = PHY_REG_ARRAY_PG_LENGTH; +	phy_regarray_table_pg = rtl8192de_phy_reg_array_pg; +	if (configtype == BASEBAND_CONFIG_PHY_REG) { +		for (i = 0; i < phy_regarray_pg_len; i = i + 3) { +			if (phy_regarray_table_pg[i] == 0xfe) +				mdelay(50); +			else if (phy_regarray_table_pg[i] == 0xfd) +				mdelay(5); +			else if (phy_regarray_table_pg[i] == 0xfc) +				mdelay(1); +			else if (phy_regarray_table_pg[i] == 0xfb) +				udelay(50); +			else if (phy_regarray_table_pg[i] == 0xfa) +				udelay(5); +			else if (phy_regarray_table_pg[i] == 0xf9) +				udelay(1); +			_rtl92d_store_pwrindex_diffrate_offset(hw, +				phy_regarray_table_pg[i], +				phy_regarray_table_pg[i + 1], +				phy_regarray_table_pg[i + 2]); +		} +	} else { +		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, +			 ("configtype != BaseBand_Config_PHY_REG\n")); +	} +	return true; +} + +static bool _rtl92d_phy_bb_config(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	bool rtstatus = true; + +	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("==>\n")); +	rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw, +		BASEBAND_CONFIG_PHY_REG); +	if (rtstatus != true) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Write BB Reg Fail!!")); +		return false; +	} + +	/* if (rtlphy->rf_type == RF_1T2R) { +	 *      _rtl92c_phy_bb_config_1t(hw); +	 *     RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Config to 1T!!\n")); +	 *} */ + +	if (rtlefuse->autoload_failflag == false) { +		rtlphy->pwrgroup_cnt = 0; +		rtstatus = _rtl92d_phy_config_bb_with_pgheaderfile(hw, +			BASEBAND_CONFIG_PHY_REG); +	} +	if (rtstatus != true) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("BB_PG Reg Fail!!")); +		return false; +	} +	rtstatus = _rtl92d_phy_config_bb_with_headerfile(hw, +		BASEBAND_CONFIG_AGC_TAB); +	if (rtstatus != true) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("AGC Table Fail\n")); +		return false; +	} +	rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, +		RFPGA0_XA_HSSIPARAMETER2, 0x200)); + +	return true; +} + +bool rtl92d_phy_bb_config(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u16 regval; +	u32 regvaldw; +	u8 value; + +	_rtl92d_phy_init_bb_rf_register_definition(hw); +	regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); +	rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, +		       regval | BIT(13) | BIT(0) | BIT(1)); +	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); +	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); +	/* 0x1f bit7 bit6 represent for mac0/mac1 driver ready */ +	value = rtl_read_byte(rtlpriv, REG_RF_CTRL); +	rtl_write_byte(rtlpriv, REG_RF_CTRL, value | RF_EN | RF_RSTB | +		RF_SDMRSTB); +	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA | +		FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB); +	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); +	if (!(IS_92D_SINGLEPHY(rtlpriv->rtlhal.version))) { +		regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); +		rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); +	} + +	return _rtl92d_phy_bb_config(hw); +} + +bool rtl92d_phy_rf_config(struct ieee80211_hw *hw) +{ +	return rtl92d_phy_rf6052_config(hw); +} + +bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, +					  enum rf_content content, +					  enum radio_path rfpath) +{ +	int i; +	u32 *radioa_array_table; +	u32 *radiob_array_table; +	u16 radioa_arraylen, radiob_arraylen; +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	radioa_arraylen = RADIOA_2T_ARRAYLENGTH; +	radioa_array_table = rtl8192de_radioa_2tarray; +	radiob_arraylen = RADIOB_2T_ARRAYLENGTH; +	radiob_array_table = rtl8192de_radiob_2tarray; +	if (rtlpriv->efuse.internal_pa_5g[0]) { +		radioa_arraylen = RADIOA_2T_INT_PA_ARRAYLENGTH; +		radioa_array_table = rtl8192de_radioa_2t_int_paarray; +	} +	if (rtlpriv->efuse.internal_pa_5g[1]) { +		radiob_arraylen = RADIOB_2T_INT_PA_ARRAYLENGTH; +		radiob_array_table = rtl8192de_radiob_2t_int_paarray; +	} +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 ("PHY_ConfigRFWithHeaderFile() " +		 "Radio_A:Rtl819XRadioA_1TArray\n")); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +		 ("PHY_ConfigRFWithHeaderFile() " +		 "Radio_B:Rtl819XRadioB_1TArray\n")); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath)); + +	/* this only happens when DMDP, mac0 start on 2.4G, +	 * mac1 start on 5G, mac 0 has to set phy0&phy1 +	 * pathA or mac1 has to set phy0&phy1 pathA */ +	if ((content == radiob_txt) && (rfpath == RF90_PATH_A)) { +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +			 (" ===> althougth Path A, we load radiob.txt\n")); +		radioa_arraylen = radiob_arraylen; +		radioa_array_table = radiob_array_table; +	} +	switch (rfpath) { +	case RF90_PATH_A: +		for (i = 0; i < radioa_arraylen; i = i + 2) { +			if (radioa_array_table[i] == 0xfe) { +				mdelay(50); +			} else if (radioa_array_table[i] == 0xfd) { +				/* delay_ms(5); */ +				mdelay(5); +			} else if (radioa_array_table[i] == 0xfc) { +				/* delay_ms(1); */ +				mdelay(1); +			} else if (radioa_array_table[i] == 0xfb) { +				udelay(50); +			} else if (radioa_array_table[i] == 0xfa) { +				udelay(5); +			} else if (radioa_array_table[i] == 0xf9) { +				udelay(1); +			} else { +				rtl_set_rfreg(hw, rfpath, radioa_array_table[i], +					      BRFREGOFFSETMASK, +					      radioa_array_table[i + 1]); +				/*  Add 1us delay between BB/RF register set. */ +				udelay(1); +			} +		} +		break; +	case RF90_PATH_B: +		for (i = 0; i < radiob_arraylen; i = i + 2) { +			if (radiob_array_table[i] == 0xfe) { +				/* Delay specific ms. Only RF configuration +				 * requires delay. */ +				mdelay(50); +			} else if (radiob_array_table[i] == 0xfd) { +				/* delay_ms(5); */ +				mdelay(5); +			} else if (radiob_array_table[i] == 0xfc) { +				/* delay_ms(1); */ +				mdelay(1); +			} else if (radiob_array_table[i] == 0xfb) { +				udelay(50); +			} else if (radiob_array_table[i] == 0xfa) { +				udelay(5); +			} else if (radiob_array_table[i] == 0xf9) { +				udelay(1); +			} else { +				rtl_set_rfreg(hw, rfpath, radiob_array_table[i], +					      BRFREGOFFSETMASK, +					      radiob_array_table[i + 1]); +				/*  Add 1us delay between BB/RF register set. */ +				udelay(1); +			} +		} +		break; +	case RF90_PATH_C: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("switch case not process\n")); +		break; +	case RF90_PATH_D: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("switch case not process\n")); +		break; +	} +	return true; +} + +void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); + +	rtlphy->default_initialgain[0] = +	    (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, BMASKBYTE0); +	rtlphy->default_initialgain[1] = +	    (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, BMASKBYTE0); +	rtlphy->default_initialgain[2] = +	    (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, BMASKBYTE0); +	rtlphy->default_initialgain[3] = +	    (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, BMASKBYTE0); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +		 ("Default initial gain (c50=0x%x, " +		  "c58=0x%x, c60=0x%x, c68=0x%x\n", +		  rtlphy->default_initialgain[0], +		  rtlphy->default_initialgain[1], +		  rtlphy->default_initialgain[2], +		  rtlphy->default_initialgain[3])); +	rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, +					      BMASKBYTE0); +	rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, +					      BMASKDWORD); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +		 ("Default framesync (0x%x) = 0x%x\n", +		  ROFDM0_RXDETECTOR3, rtlphy->framesync)); +} + +static void _rtl92d_get_txpower_index(struct ieee80211_hw *hw, u8 channel, +	u8 *cckpowerlevel, u8 *ofdmpowerlevel) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	u8 index = (channel - 1); + +	/* 1. CCK */ +	if (rtlhal->current_bandtype == BAND_ON_2_4G) { +		/* RF-A */ +		cckpowerlevel[RF90_PATH_A] = +				 rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; +		/* RF-B */ +		cckpowerlevel[RF90_PATH_B] = +				 rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; +	} else { +		cckpowerlevel[RF90_PATH_A] = 0; +		cckpowerlevel[RF90_PATH_B] = 0; +	} +	/* 2. OFDM for 1S or 2S */ +	if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) { +		/*  Read HT 40 OFDM TX power */ +		ofdmpowerlevel[RF90_PATH_A] = +		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; +		ofdmpowerlevel[RF90_PATH_B] = +		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; +	} else if (rtlphy->rf_type == RF_2T2R) { +		/* Read HT 40 OFDM TX power */ +		ofdmpowerlevel[RF90_PATH_A] = +		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index]; +		ofdmpowerlevel[RF90_PATH_B] = +		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index]; +	} +} + +static void _rtl92d_ccxpower_index_check(struct ieee80211_hw *hw, +	u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); + +	rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; +	rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; +} + +static u8 _rtl92c_phy_get_rightchnlplace(u8 chnl) +{ +	u8 channel_5g[59] = { +		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, +		60, 62, 64, 100, 102, 104, 106, 108, 110, 112, +		114, 116, 118, 120, 122, 124, 126, 128, +		130, 132, 134, 136, 138, 140, 149, 151, +		153, 155, 157, 159, 161, 163, 165 +	}; +	u8 place = chnl; + +	if (chnl > 14) { +		for (place = 14; place < sizeof(channel_5g); place++) { +			if (channel_5g[place] == chnl) { +				place++; +				break; +			} +		} +	} +	return place; +} + +void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) +{ +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 cckpowerlevel[2], ofdmpowerlevel[2]; + +	if (rtlefuse->txpwr_fromeprom == false) +		return; +	channel = _rtl92c_phy_get_rightchnlplace(channel); +	_rtl92d_get_txpower_index(hw, channel, &cckpowerlevel[0], +		&ofdmpowerlevel[0]); +	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) +		_rtl92d_ccxpower_index_check(hw, channel, &cckpowerlevel[0], +				&ofdmpowerlevel[0]); +	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) +		rtl92d_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); +	rtl92d_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel); +} + +void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	enum io_type iotype; + +	if (!is_hal_stop(rtlhal)) { +		switch (operation) { +		case SCAN_OPT_BACKUP: +			rtlhal->current_bandtypebackup = +						 rtlhal->current_bandtype; +			iotype = IO_CMD_PAUSE_DM_BY_SCAN; +			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, +						      (u8 *)&iotype); +			break; +		case SCAN_OPT_RESTORE: +			iotype = IO_CMD_RESUME_DM_BY_SCAN; +			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, +						      (u8 *)&iotype); +			break; +		default: +			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +				 ("Unknown Scan Backup operation.\n")); +			break; +		} +	} +} + +void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw, +			    enum nl80211_channel_type ch_type) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	unsigned long flag = 0; +	u8 reg_prsr_rsc; +	u8 reg_bw_opmode; + +	if (rtlphy->set_bwmode_inprogress) +		return; +	if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, +			 ("FALSE driver sleep or unload\n")); +		return; +	} +	rtlphy->set_bwmode_inprogress = true; +	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, +		 ("Switch to %s bandwidth\n", +		  rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? +		  "20MHz" : "40MHz")); +	reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); +	reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); +	switch (rtlphy->current_chan_bw) { +	case HT_CHANNEL_WIDTH_20: +		reg_bw_opmode |= BW_OPMODE_20MHZ; +		rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); +		break; +	case HT_CHANNEL_WIDTH_20_40: +		reg_bw_opmode &= ~BW_OPMODE_20MHZ; +		rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); + +		reg_prsr_rsc = (reg_prsr_rsc & 0x90) | +			(mac->cur_40_prime_sc << 5); +		rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); +		break; +	default: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); +		break; +	} +	switch (rtlphy->current_chan_bw) { +	case HT_CHANNEL_WIDTH_20: +		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); +		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); +		/* SET BIT10 BIT11  for receive cck */ +		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) | +			      BIT(11), 3); +		break; +	case HT_CHANNEL_WIDTH_20_40: +		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); +		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); +		/* Set Control channel to upper or lower. +		 * These settings are required only for 40MHz */ +		if (rtlhal->current_bandtype == BAND_ON_2_4G) { +			rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); +			rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCKSIDEBAND, +				(mac->cur_40_prime_sc >> 1)); +			rtl92d_release_cckandrw_pagea_ctl(hw, &flag); +		} +		rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); +		/* SET BIT10 BIT11  for receive cck */ +		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) | +			      BIT(11), 0); +		rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), +			(mac->cur_40_prime_sc == +			HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); +		break; +	default: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); +		break; + +	} +	rtl92d_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); +	rtlphy->set_bwmode_inprogress = false; +	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); +} + +static void _rtl92d_phy_stop_trx_before_changeband(struct ieee80211_hw *hw) +{ +	rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0); +	rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0); +	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x00); +	rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x0); +} + +static void rtl92d_phy_switch_wirelessband(struct ieee80211_hw *hw, u8 band) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u8 value8; + +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==>\n")); +	rtlhal->bandset = band; +	rtlhal->current_bandtype = band; +	if (IS_92D_SINGLEPHY(rtlhal->version)) +		rtlhal->bandset = BAND_ON_BOTH; +	/* stop RX/Tx */ +	_rtl92d_phy_stop_trx_before_changeband(hw); +	/* reconfig BB/RF according to wireless mode */ +	if (rtlhal->current_bandtype == BAND_ON_2_4G) { +		/* BB & RF Config */ +		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("====>2.4G\n")); +		if (rtlhal->interfaceindex == 1) +			_rtl92d_phy_config_bb_with_headerfile(hw, +				BASEBAND_CONFIG_AGC_TAB); +	} else { +		/* 5G band */ +		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("====>5G\n")); +		if (rtlhal->interfaceindex == 1) +			_rtl92d_phy_config_bb_with_headerfile(hw, +				BASEBAND_CONFIG_AGC_TAB); +	} +	rtl92d_update_bbrf_configuration(hw); +	if (rtlhal->current_bandtype == BAND_ON_2_4G) +		rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); +	rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); + +	/* 20M BW. */ +	/* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); */ +	rtlhal->reloadtxpowerindex = true; +	/* notice fw know band status  0x81[1]/0x53[1] = 0: 5G, 1: 2G */ +	if (rtlhal->current_bandtype == BAND_ON_2_4G) { +		value8 = rtl_read_byte(rtlpriv,	(rtlhal->interfaceindex == +			0 ? REG_MAC0 : REG_MAC1)); +		value8 |= BIT(1); +		rtl_write_byte(rtlpriv, (rtlhal->interfaceindex == +			0 ? REG_MAC0 : REG_MAC1), value8); +	} else { +		value8 = rtl_read_byte(rtlpriv, (rtlhal->interfaceindex == +			0 ? REG_MAC0 : REG_MAC1)); +		value8 &= (~BIT(1)); +		rtl_write_byte(rtlpriv, (rtlhal->interfaceindex == +			0 ? REG_MAC0 : REG_MAC1), value8); +	} +	mdelay(1); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<==Switch Band OK.\n")); +} + +static void _rtl92d_phy_reload_imr_setting(struct ieee80211_hw *hw, +	u8 channel, u8 rfpath) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 imr_num = MAX_RF_IMR_INDEX; +	u32 rfmask = BRFREGOFFSETMASK; +	u8 group, i; +	unsigned long flag = 0; + +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>path %d\n", rfpath)); +	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) { +		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>5G\n")); +		rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0); +		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); +		/* fc area 0xd2c */ +		if (channel > 99) +			rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) | +				      BIT(14), 2); +		else +			rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(13) | +				      BIT(14), 1); +		/* leave 0 for channel1-14. */ +		group = channel <= 64 ? 1 : 2; +		imr_num = MAX_RF_IMR_INDEX_NORMAL; +		for (i = 0; i < imr_num; i++) +			rtl_set_rfreg(hw, (enum radio_path)rfpath, +				      rf_reg_for_5g_swchnl_normal[i], rfmask, +				      rf_imr_param_normal[0][group][i]); +		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0); +		rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 1); +	} else { +		/* G band. */ +		RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, +			 ("Load RF IMR parameters for G band. IMR already " +			 "setting %d\n", +			  rtlpriv->rtlhal.load_imrandiqk_setting_for2g)); +		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>2.4G\n")); +		if (!rtlpriv->rtlhal.load_imrandiqk_setting_for2g) { +			RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, +				("Load RF IMR parameters " +				"for G band. %d\n", rfpath)); +			rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); +			rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(25) | BIT(24), 0); +			rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, +				      0x00f00000, 0xf); +			imr_num = MAX_RF_IMR_INDEX_NORMAL; +			for (i = 0; i < imr_num; i++) { +				rtl_set_rfreg(hw, (enum radio_path)rfpath, +					      rf_reg_for_5g_swchnl_normal[i], +					      BRFREGOFFSETMASK, +					      rf_imr_param_normal[0][0][i]); +			} +			rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, +				      0x00f00000, 0); +			rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN | BCCKEN, 3); +			rtl92d_release_cckandrw_pagea_ctl(hw, &flag); +		} +	} +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n")); +} + +static void _rtl92d_phy_enable_rf_env(struct ieee80211_hw *hw, +	u8 rfpath, u32 *pu4_regval) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + +	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("====>\n")); +	/*----Store original RFENV control type----*/ +	switch (rfpath) { +	case RF90_PATH_A: +	case RF90_PATH_C: +		*pu4_regval = rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV); +		break; +	case RF90_PATH_B: +	case RF90_PATH_D: +		*pu4_regval = +		    rtl_get_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16); +		break; +	} +	/*----Set RF_ENV enable----*/ +	rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); +	udelay(1); +	/*----Set RF_ENV output high----*/ +	rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); +	udelay(1); +	/* Set bit number of Address and Data for RF register */ +	/* Set 1 to 4 bits for 8255 */ +	rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREADDRESSLENGTH, 0x0); +	udelay(1); +	/*Set 0 to 12 bits for 8255 */ +	rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); +	udelay(1); +	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<====\n")); +} + +static void _rtl92d_phy_restore_rf_env(struct ieee80211_hw *hw, u8 rfpath, +				       u32 *pu4_regval) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; + +	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("=====>\n")); +	/*----Restore RFENV control type----*/ ; +	switch (rfpath) { +	case RF90_PATH_A: +	case RF90_PATH_C: +		rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, *pu4_regval); +		break; +	case RF90_PATH_B: +	case RF90_PATH_D: +		rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16, +			      *pu4_regval); +		break; +	} +	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<=====\n")); +} + +static void _rtl92d_phy_switch_rf_setting(struct ieee80211_hw *hw, u8 channel) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	u8 path = rtlhal->current_bandtype == +	    BAND_ON_5G ? RF90_PATH_A : RF90_PATH_B; +	u8 index = 0, i = 0, rfpath = RF90_PATH_A; +	bool need_pwr_down = false, internal_pa = false; +	u32 u4regvalue, mask = 0x1C000, value = 0, u4tmp, u4tmp2; + +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>\n")); +	/* config path A for 5G */ +	if (rtlhal->current_bandtype == BAND_ON_5G) { +		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>5G\n")); +		u4tmp = curveindex_5g[channel - 1]; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ver 1 set RF-A, 5G, " +			"0x28 = 0x%x !!\n", u4tmp)); +		for (i = 0; i < RF_CHNL_NUM_5G; i++) { +			if (channel == rf_chnl_5g[i] && channel <= 140) +				index = 0; +		} +		for (i = 0; i < RF_CHNL_NUM_5G_40M; i++) { +			if (channel == rf_chnl_5g_40m[i] && channel <= 140) +				index = 1; +		} +		if (channel == 149 || channel == 155 || channel == 161) +			index = 2; +		else if (channel == 151 || channel == 153 || channel == 163 +			 || channel == 165) +			index = 3; +		else if (channel == 157 || channel == 159) +			index = 4; + +		if (rtlhal->macphymode == DUALMAC_DUALPHY +		    && rtlhal->interfaceindex == 1) { +			need_pwr_down = rtl92d_phy_enable_anotherphy(hw, false); +			rtlhal->during_mac1init_radioa = true; +			/* asume no this case */ +			if (need_pwr_down) +				_rtl92d_phy_enable_rf_env(hw, path, +							  &u4regvalue); +		} +		for (i = 0; i < RF_REG_NUM_FOR_C_CUT_5G; i++) { +			if (i == 0 && (rtlhal->macphymode == DUALMAC_DUALPHY)) { +				rtl_set_rfreg(hw, (enum radio_path)path, +					      rf_reg_for_c_cut_5g[i], +					      BRFREGOFFSETMASK, 0xE439D); +			} else if (rf_reg_for_c_cut_5g[i] == RF_SYN_G4) { +				u4tmp2 = (rf_reg_pram_c_5g[index][i] & +				     0x7FF) | (u4tmp << 11); +				if (channel == 36) +					u4tmp2 &= ~(BIT(7) | BIT(6)); +				rtl_set_rfreg(hw, (enum radio_path)path, +					      rf_reg_for_c_cut_5g[i], +					      BRFREGOFFSETMASK, u4tmp2); +			} else { +				rtl_set_rfreg(hw, (enum radio_path)path, +					      rf_reg_for_c_cut_5g[i], +					      BRFREGOFFSETMASK, +					      rf_reg_pram_c_5g[index][i]); +			} +			RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, +				("offset 0x%x value 0x%x " +				"path %d index %d readback 0x%x\n", +				rf_reg_for_c_cut_5g[i], +				rf_reg_pram_c_5g[index][i], path, +				index, rtl_get_rfreg(hw, (enum radio_path)path, +				rf_reg_for_c_cut_5g[i], BRFREGOFFSETMASK))); +		} +		if (need_pwr_down) +			_rtl92d_phy_restore_rf_env(hw, path, &u4regvalue); +		if (rtlhal->during_mac1init_radioa) +			rtl92d_phy_powerdown_anotherphy(hw, false); +		if (channel < 149) +			value = 0x07; +		else if (channel >= 149) +			value = 0x02; +		if (channel >= 36 && channel <= 64) +			index = 0; +		else if (channel >= 100 && channel <= 140) +			index = 1; +		else +			index = 2; +		for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; +			rfpath++) { +			if (rtlhal->macphymode == DUALMAC_DUALPHY && +				rtlhal->interfaceindex == 1)	/* MAC 1 5G */ +				internal_pa = rtlpriv->efuse.internal_pa_5g[1]; +			else +				internal_pa = +					 rtlpriv->efuse.internal_pa_5g[rfpath]; +			if (internal_pa) { +				for (i = 0; +				     i < RF_REG_NUM_FOR_C_CUT_5G_INTERNALPA; +				     i++) { +					rtl_set_rfreg(hw, rfpath, +						rf_for_c_cut_5g_internal_pa[i], +						BRFREGOFFSETMASK, +						rf_pram_c_5g_int_pa[index][i]); +					RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, +						 ("offset 0x%x value 0x%x " +						 "path %d index %d\n", +						 rf_for_c_cut_5g_internal_pa[i], +						 rf_pram_c_5g_int_pa[index][i], +						 rfpath, index)); +				} +			} else { +				rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B, +					      mask, value); +			} +		} +	} else if (rtlhal->current_bandtype == BAND_ON_2_4G) { +		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("====>2.4G\n")); +		u4tmp = curveindex_2g[channel - 1]; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ver 3 set RF-B, 2G, " +			"0x28 = 0x%x !!\n", u4tmp)); +		if (channel == 1 || channel == 2 || channel == 4 || channel == 9 +		    || channel == 10 || channel == 11 || channel == 12) +			index = 0; +		else if (channel == 3 || channel == 13 || channel == 14) +			index = 1; +		else if (channel >= 5 && channel <= 8) +			index = 2; +		if (rtlhal->macphymode == DUALMAC_DUALPHY) { +			path = RF90_PATH_A; +			if (rtlhal->interfaceindex == 0) { +				need_pwr_down = +					 rtl92d_phy_enable_anotherphy(hw, true); +				rtlhal->during_mac0init_radiob = true; + +				if (need_pwr_down) +					_rtl92d_phy_enable_rf_env(hw, path, +								  &u4regvalue); +			} +		} +		for (i = 0; i < RF_REG_NUM_FOR_C_CUT_2G; i++) { +			if (rf_reg_for_c_cut_2g[i] == RF_SYN_G7) +				rtl_set_rfreg(hw, (enum radio_path)path, +					rf_reg_for_c_cut_2g[i], +					BRFREGOFFSETMASK, +					(rf_reg_param_for_c_cut_2g[index][i] | +					BIT(17))); +			else +				rtl_set_rfreg(hw, (enum radio_path)path, +					      rf_reg_for_c_cut_2g[i], +					      BRFREGOFFSETMASK, +					      rf_reg_param_for_c_cut_2g +					      [index][i]); +			RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, +				("offset 0x%x value 0x%x mak 0x%x path %d " +				"index %d readback 0x%x\n", +				rf_reg_for_c_cut_2g[i], +				rf_reg_param_for_c_cut_2g[index][i], +				rf_reg_mask_for_c_cut_2g[i], path, index, +				rtl_get_rfreg(hw, (enum radio_path)path, +				rf_reg_for_c_cut_2g[i], +				BRFREGOFFSETMASK))); +		} +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("cosa ver 3 set RF-B, 2G, 0x28 = 0x%x !!\n", +			rf_syn_g4_for_c_cut_2g | (u4tmp << 11))); + +		rtl_set_rfreg(hw, (enum radio_path)path, RF_SYN_G4, +			      BRFREGOFFSETMASK, +			      rf_syn_g4_for_c_cut_2g | (u4tmp << 11)); +		if (need_pwr_down) +			_rtl92d_phy_restore_rf_env(hw, path, &u4regvalue); +		if (rtlhal->during_mac0init_radiob) +			rtl92d_phy_powerdown_anotherphy(hw, true); +	} +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n")); +} + +u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl) +{ +	u8 channel_all[59] = { +		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, +		60, 62, 64, 100, 102, 104, 106, 108, 110, 112, +		114, 116, 118, 120, 122, 124, 126, 128,	130, +		132, 134, 136, 138, 140, 149, 151, 153, 155, +		157, 159, 161, 163, 165 +	}; +	u8 place = chnl; + +	if (chnl > 14) { +		for (place = 14; place < sizeof(channel_all); place++) { +			if (channel_all[place] == chnl) +				return place - 13; +		} +	} + +	return 0; +} + +#define MAX_TOLERANCE		5 +#define IQK_DELAY_TIME		1	/* ms */ +#define MAX_TOLERANCE_92D	3 + +/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +static u8 _rtl92d_phy_patha_iqk(struct ieee80211_hw *hw, bool configpathb) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u32 regeac, rege94, rege9c, regea4; +	u8 result = 0; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK!\n")); +	/* path-A IQK setting */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n")); +	if (rtlhal->interfaceindex == 0) { +		rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x10008c1f); +		rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x10008c1f); +	} else { +		rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x10008c22); +		rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x10008c22); +	} +	rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82140102); +	rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x28160206); +	/* path-B IQK setting */ +	if (configpathb) { +		rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x10008c22); +		rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x10008c22); +		rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82140102); +		rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x28160206); +	} +	/* LO calibration setting */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n")); +	rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911); +	/* One shot, path A LOK & IQK */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("One shot, path A LOK & IQK!\n")); +	rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf9000000); +	rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000); +	/* delay x ms */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, +		("Delay %d ms for One shot, path A LOK & IQK.\n", +		IQK_DELAY_TIME)); +	mdelay(IQK_DELAY_TIME); +	/* Check failed */ +	regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac)); +	rege94 = rtl_get_bbreg(hw, 0xe94, BMASKDWORD); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe94 = 0x%x\n", rege94)); +	rege9c = rtl_get_bbreg(hw, 0xe9c, BMASKDWORD); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe9c = 0x%x\n", rege9c)); +	regea4 = rtl_get_bbreg(hw, 0xea4, BMASKDWORD); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xea4 = 0x%x\n", regea4)); +	if (!(regeac & BIT(28)) && (((rege94 & 0x03FF0000) >> 16) != 0x142) && +	    (((rege9c & 0x03FF0000) >> 16) != 0x42)) +		result |= 0x01; +	else			/* if Tx not OK, ignore Rx */ +		return result; +	/* if Tx is OK, check whether Rx is OK */ +	if (!(regeac & BIT(27)) && (((regea4 & 0x03FF0000) >> 16) != 0x132) && +	    (((regeac & 0x03FF0000) >> 16) != 0x36)) +		result |= 0x02; +	else +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A Rx IQK fail!!\n")); +	return result; +} + +/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +static u8 _rtl92d_phy_patha_iqk_5g_normal(struct ieee80211_hw *hw, +					  bool configpathb) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	u32 regeac, rege94, rege9c, regea4; +	u8 result = 0; +	u8 i; +	u8 retrycount = 2; +	u32 TxOKBit = BIT(28), RxOKBit = BIT(27); + +	if (rtlhal->interfaceindex == 1) {	/* PHY1 */ +		TxOKBit = BIT(31); +		RxOKBit = BIT(30); +	} +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK!\n")); +	/* path-A IQK setting */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n")); +	rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x18008c1f); +	rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x18008c1f); +	rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82140307); +	rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x68160960); +	/* path-B IQK setting */ +	if (configpathb) { +		rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x18008c2f); +		rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x18008c2f); +		rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82110000); +		rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x68110000); +	} +	/* LO calibration setting */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n")); +	rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911); +	/* path-A PA on */ +	rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD, 0x07000f60); +	rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BMASKDWORD, 0x66e60e30); +	for (i = 0; i < retrycount; i++) { +		/* One shot, path A LOK & IQK */ +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("One shot, path A LOK & IQK!\n")); +		rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf9000000); +		rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000); +		/* delay x ms */ +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("Delay %d ms for One shot, path A LOK & IQK.\n", +			IQK_DELAY_TIME)); +		mdelay(IQK_DELAY_TIME * 10); +		/* Check failed */ +		regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac)); +		rege94 = rtl_get_bbreg(hw, 0xe94, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe94 = 0x%x\n", rege94)); +		rege9c = rtl_get_bbreg(hw, 0xe9c, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xe9c = 0x%x\n", rege9c)); +		regea4 = rtl_get_bbreg(hw, 0xea4, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xea4 = 0x%x\n", regea4)); +		if (!(regeac & TxOKBit) && +		     (((rege94 & 0x03FF0000) >> 16) != 0x142)) { +			result |= 0x01; +		} else { /* if Tx not OK, ignore Rx */ +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("Path A Tx IQK fail!!\n")); +			continue; +		} + +		/* if Tx is OK, check whether Rx is OK */ +		if (!(regeac & RxOKBit) && +		    (((regea4 & 0x03FF0000) >> 16) != 0x132)) { +			result |= 0x02; +			break; +		} else { +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("Path A Rx IQK fail!!\n")); +		} +	} +	/* path A PA off */ +	rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD, +		      rtlphy->iqk_bb_backup[0]); +	rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BMASKDWORD, +		      rtlphy->iqk_bb_backup[1]); +	return result; +} + +/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +static u8 _rtl92d_phy_pathb_iqk(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 regeac, regeb4, regebc, regec4, regecc; +	u8 result = 0; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQK!\n")); +	/* One shot, path B LOK & IQK */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("One shot, path A LOK & IQK!\n")); +	rtl_set_bbreg(hw, 0xe60, BMASKDWORD, 0x00000002); +	rtl_set_bbreg(hw, 0xe60, BMASKDWORD, 0x00000000); +	/* delay x ms  */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, +		("Delay %d ms for One shot, path B LOK & IQK.\n", +		IQK_DELAY_TIME)); +	mdelay(IQK_DELAY_TIME); +	/* Check failed */ +	regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac)); +	regeb4 = rtl_get_bbreg(hw, 0xeb4, BMASKDWORD); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeb4 = 0x%x\n", regeb4)); +	regebc = rtl_get_bbreg(hw, 0xebc, BMASKDWORD); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xebc = 0x%x\n", regebc)); +	regec4 = rtl_get_bbreg(hw, 0xec4, BMASKDWORD); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xec4 = 0x%x\n", regec4)); +	regecc = rtl_get_bbreg(hw, 0xecc, BMASKDWORD); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xecc = 0x%x\n", regecc)); +	if (!(regeac & BIT(31)) && (((regeb4 & 0x03FF0000) >> 16) != 0x142) && +	    (((regebc & 0x03FF0000) >> 16) != 0x42)) +		result |= 0x01; +	else +		return result; +	if (!(regeac & BIT(30)) && (((regec4 & 0x03FF0000) >> 16) != 0x132) && +	    (((regecc & 0x03FF0000) >> 16) != 0x36)) +		result |= 0x02; +	else +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B Rx IQK fail!!\n")); +	return result; +} + +/* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */ +static u8 _rtl92d_phy_pathb_iqk_5g_normal(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	u32 regeac, regeb4, regebc, regec4, regecc; +	u8 result = 0; +	u8 i; +	u8 retrycount = 2; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQK!\n")); +	/* path-A IQK setting */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A IQK setting!\n")); +	rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x18008c1f); +	rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x18008c1f); +	rtl_set_bbreg(hw, 0xe38, BMASKDWORD, 0x82110000); +	rtl_set_bbreg(hw, 0xe3c, BMASKDWORD, 0x68110000); + +	/* path-B IQK setting */ +	rtl_set_bbreg(hw, 0xe50, BMASKDWORD, 0x18008c2f); +	rtl_set_bbreg(hw, 0xe54, BMASKDWORD, 0x18008c2f); +	rtl_set_bbreg(hw, 0xe58, BMASKDWORD, 0x82140307); +	rtl_set_bbreg(hw, 0xe5c, BMASKDWORD, 0x68160960); + +	/* LO calibration setting */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LO calibration setting!\n")); +	rtl_set_bbreg(hw, 0xe4c, BMASKDWORD, 0x00462911); + +	/* path-B PA on */ +	rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD, 0x0f600700); +	rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BMASKDWORD, 0x061f0d30); + +	for (i = 0; i < retrycount; i++) { +		/* One shot, path B LOK & IQK */ +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("One shot, path A LOK & IQK!\n")); +		rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xfa000000); +		rtl_set_bbreg(hw, 0xe48, BMASKDWORD, 0xf8000000); + +		/* delay x ms */ +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("Delay %d ms for One shot, path B LOK & IQK.\n", 10)); +		mdelay(IQK_DELAY_TIME * 10); + +		/* Check failed */ +		regeac = rtl_get_bbreg(hw, 0xeac, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeac = 0x%x\n", regeac)); +		regeb4 = rtl_get_bbreg(hw, 0xeb4, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xeb4 = 0x%x\n", regeb4)); +		regebc = rtl_get_bbreg(hw, 0xebc, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xebc = 0x%x\n", regebc)); +		regec4 = rtl_get_bbreg(hw, 0xec4, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xec4 = 0x%x\n", regec4)); +		regecc = rtl_get_bbreg(hw, 0xecc, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xecc = 0x%x\n", regecc)); +		if (!(regeac & BIT(31)) && +		    (((regeb4 & 0x03FF0000) >> 16) != 0x142)) +			result |= 0x01; +		else +			continue; +		if (!(regeac & BIT(30)) && +		    (((regec4 & 0x03FF0000) >> 16) != 0x132)) { +			result |= 0x02; +			break; +		} else { +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("Path B Rx IQK fail!!\n")); +		} +	} + +	/* path B PA off */ +	rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BMASKDWORD, +		      rtlphy->iqk_bb_backup[0]); +	rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BMASKDWORD, +		      rtlphy->iqk_bb_backup[2]); +	return result; +} + +static void _rtl92d_phy_save_adda_registers(struct ieee80211_hw *hw, +					    u32 *adda_reg, u32 *adda_backup, +					    u32 regnum) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 i; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Save ADDA parameters.\n")); +	for (i = 0; i < regnum; i++) +		adda_backup[i] = rtl_get_bbreg(hw, adda_reg[i], BMASKDWORD); +} + +static void _rtl92d_phy_save_mac_registers(struct ieee80211_hw *hw, +	u32 *macreg, u32 *macbackup) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 i; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Save MAC parameters.\n")); +	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) +		macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]); +	macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]); +} + +static void _rtl92d_phy_reload_adda_registers(struct ieee80211_hw *hw, +					      u32 *adda_reg, u32 *adda_backup, +					      u32 regnum) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 i; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, +		("Reload ADDA power saving parameters !\n")); +	for (i = 0; i < regnum; i++) +		rtl_set_bbreg(hw, adda_reg[i], BMASKDWORD, adda_backup[i]); +} + +static void _rtl92d_phy_reload_mac_registers(struct ieee80211_hw *hw, +					     u32 *macreg, u32 *macbackup) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 i; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Reload MAC parameters !\n")); +	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) +		rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]); +	rtl_write_byte(rtlpriv, macreg[i], macbackup[i]); +} + +static void _rtl92d_phy_path_adda_on(struct ieee80211_hw *hw, +		u32 *adda_reg, bool patha_on, bool is2t) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 pathon; +	u32 i; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("ADDA ON.\n")); +	pathon = patha_on ? 0x04db25a4 : 0x0b1b25a4; +	if (patha_on) +		pathon = rtlpriv->rtlhal.interfaceindex == 0 ? +		    0x04db25a4 : 0x0b1b25a4; +	for (i = 0; i < IQK_ADDA_REG_NUM; i++) +		rtl_set_bbreg(hw, adda_reg[i], BMASKDWORD, pathon); +} + +static void _rtl92d_phy_mac_setting_calibration(struct ieee80211_hw *hw, +						u32 *macreg, u32 *macbackup) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 i; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("MAC settings for Calibration.\n")); +	rtl_write_byte(rtlpriv, macreg[0], 0x3F); + +	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) +		rtl_write_byte(rtlpriv, macreg[i], (u8)(macbackup[i] & +			       (~BIT(3)))); +	rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5)))); +} + +static void _rtl92d_phy_patha_standby(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path-A standby mode!\n")); + +	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x0); +	rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, BMASKDWORD, 0x00010000); +	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000); +} + +static void _rtl92d_phy_pimode_switch(struct ieee80211_hw *hw, bool pi_mode) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 mode; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, +		("BB Switch to %s mode!\n", (pi_mode ? "PI" : "SI"))); +	mode = pi_mode ? 0x01000100 : 0x01000000; +	rtl_set_bbreg(hw, 0x820, BMASKDWORD, mode); +	rtl_set_bbreg(hw, 0x828, BMASKDWORD, mode); +} + +static void _rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw, long result[][8], +				     u8 t, bool is2t) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	u32 i; +	u8 patha_ok, pathb_ok; +	static u32 adda_reg[IQK_ADDA_REG_NUM] = { +		RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74, +		0xe78, 0xe7c, 0xe80, 0xe84, +		0xe88, 0xe8c, 0xed0, 0xed4, +		0xed8, 0xedc, 0xee0, 0xeec +	}; +	static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { +		0x522, 0x550, 0x551, 0x040 +	}; +	static u32 iqk_bb_reg[IQK_BB_REG_NUM] = { +		RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE, +		RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR, +		RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE, +		RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4, +		ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1 +	}; +	const u32 retrycount = 2; +	u32 bbvalue; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK for 2.4G :Start!!!\n")); +	if (t == 0) { +		bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("==>0x%08x\n", bbvalue)); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQ Calibration for %s\n", +			(is2t ? "2T2R" : "1T1R"))); + +		/*  Save ADDA parameters, turn Path A ADDA on */ +		_rtl92d_phy_save_adda_registers(hw, adda_reg, +			rtlphy->adda_backup, IQK_ADDA_REG_NUM); +		_rtl92d_phy_save_mac_registers(hw, iqk_mac_reg, +			rtlphy->iqk_mac_backup); +		_rtl92d_phy_save_adda_registers(hw, iqk_bb_reg, +			rtlphy->iqk_bb_backup, IQK_BB_REG_NUM); +	} +	_rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t); +	if (t == 0) +		rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, +				RFPGA0_XA_HSSIPARAMETER1, BIT(8)); + +	/*  Switch BB to PI mode to do IQ Calibration. */ +	if (!rtlphy->rfpi_enable) +		_rtl92d_phy_pimode_switch(hw, true); + +	rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00); +	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKDWORD, 0x03a05600); +	rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, BMASKDWORD, 0x000800e4); +	rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, BMASKDWORD, 0x22204000); +	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f); +	if (is2t) { +		rtl_set_bbreg(hw, RFPGA0_XA_LSSIPARAMETER, BMASKDWORD, +			      0x00010000); +		rtl_set_bbreg(hw, RFPGA0_XB_LSSIPARAMETER, BMASKDWORD, +			      0x00010000); +	} +	/* MAC settings */ +	_rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg, +					    rtlphy->iqk_mac_backup); +	/* Page B init */ +	rtl_set_bbreg(hw, 0xb68, BMASKDWORD, 0x0f600000); +	if (is2t) +		rtl_set_bbreg(hw, 0xb6c, BMASKDWORD, 0x0f600000); +	/* IQ calibration setting */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK setting!\n")); +	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000); +	rtl_set_bbreg(hw, 0xe40, BMASKDWORD, 0x01007c00); +	rtl_set_bbreg(hw, 0xe44, BMASKDWORD, 0x01004800); +	for (i = 0; i < retrycount; i++) { +		patha_ok = _rtl92d_phy_patha_iqk(hw, is2t); +		if (patha_ok == 0x03) { +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("Path A IQK Success!!\n")); +			result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) & +					0x3FF0000) >> 16; +			result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) & +					0x3FF0000) >> 16; +			result[t][2] = (rtl_get_bbreg(hw, 0xea4, BMASKDWORD) & +					0x3FF0000) >> 16; +			result[t][3] = (rtl_get_bbreg(hw, 0xeac, BMASKDWORD) & +					0x3FF0000) >> 16; +			break; +		} else if (i == (retrycount - 1) && patha_ok == 0x01) { +			/* Tx IQK OK */ +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("Path A IQK Only  Tx Success!!\n")); + +			result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) & +					0x3FF0000) >> 16; +			result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) & +					0x3FF0000) >> 16; +		} +	} +	if (0x00 == patha_ok) +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK failed!!\n")); +	if (is2t) { +		_rtl92d_phy_patha_standby(hw); +		/* Turn Path B ADDA on */ +		_rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t); +		for (i = 0; i < retrycount; i++) { +			pathb_ok = _rtl92d_phy_pathb_iqk(hw); +			if (pathb_ok == 0x03) { +				RTPRINT(rtlpriv, FINIT, INIT_IQK, +					("Path B IQK Success!!\n")); +				result[t][4] = (rtl_get_bbreg(hw, 0xeb4, +					       BMASKDWORD) & 0x3FF0000) >> 16; +				result[t][5] = (rtl_get_bbreg(hw, 0xebc, +					       BMASKDWORD) & 0x3FF0000) >> 16; +				result[t][6] = (rtl_get_bbreg(hw, 0xec4, +					       BMASKDWORD) & 0x3FF0000) >> 16; +				result[t][7] = (rtl_get_bbreg(hw, 0xecc, +					       BMASKDWORD) & 0x3FF0000) >> 16; +				break; +			} else if (i == (retrycount - 1) && pathb_ok == 0x01) { +				/* Tx IQK OK */ +				RTPRINT(rtlpriv, FINIT, INIT_IQK, +					("Path B Only Tx IQK Success!!\n")); +				result[t][4] = (rtl_get_bbreg(hw, 0xeb4, +					       BMASKDWORD) & 0x3FF0000) >> 16; +				result[t][5] = (rtl_get_bbreg(hw, 0xebc, +					       BMASKDWORD) & 0x3FF0000) >> 16; +			} +		} +		if (0x00 == pathb_ok) +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("Path B IQK failed!!\n")); +	} + +	/* Back to BB mode, load original value */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, +		("IQK:Back to BB mode, load original value!\n")); + +	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0); +	if (t != 0) { +		/* Switch back BB to SI mode after finish IQ Calibration. */ +		if (!rtlphy->rfpi_enable) +			_rtl92d_phy_pimode_switch(hw, false); +		/* Reload ADDA power saving parameters */ +		_rtl92d_phy_reload_adda_registers(hw, adda_reg, +				rtlphy->adda_backup, IQK_ADDA_REG_NUM); +		/* Reload MAC parameters */ +		_rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg, +					rtlphy->iqk_mac_backup); +		if (is2t) +			_rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, +							  rtlphy->iqk_bb_backup, +							  IQK_BB_REG_NUM); +		else +			_rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, +							  rtlphy->iqk_bb_backup, +							  IQK_BB_REG_NUM - 1); +		/* load 0xe30 IQC default value */ +		rtl_set_bbreg(hw, 0xe30, BMASKDWORD, 0x01008c00); +		rtl_set_bbreg(hw, 0xe34, BMASKDWORD, 0x01008c00); +	} +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("<==\n")); +} + +static void _rtl92d_phy_iq_calibrate_5g_normal(struct ieee80211_hw *hw, +					       long result[][8], u8 t) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	u8 patha_ok, pathb_ok; +	static u32 adda_reg[IQK_ADDA_REG_NUM] = { +		RFPGA0_XCD_SWITCHCONTROL, 0xe6c, 0xe70, 0xe74, +		0xe78, 0xe7c, 0xe80, 0xe84, +		0xe88, 0xe8c, 0xed0, 0xed4, +		0xed8, 0xedc, 0xee0, 0xeec +	}; +	static u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { +		0x522, 0x550, 0x551, 0x040 +	}; +	static u32 iqk_bb_reg[IQK_BB_REG_NUM] = { +		RFPGA0_XAB_RFINTERFACESW, RFPGA0_XA_RFINTERFACEOE, +		RFPGA0_XB_RFINTERFACEOE, ROFDM0_TRMUXPAR, +		RFPGA0_XCD_RFINTERFACESW, ROFDM0_TRXPATHENABLE, +		RFPGA0_RFMOD, RFPGA0_ANALOGPARAMETER4, +		ROFDM0_XAAGCCORE1, ROFDM0_XBAGCCORE1 +	}; +	u32 bbvalue; +	bool is2t = IS_92D_SINGLEPHY(rtlhal->version); + +	/* Note: IQ calibration must be performed after loading +	 * PHY_REG.txt , and radio_a, radio_b.txt */ + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK for 5G NORMAL:Start!!!\n")); +	mdelay(IQK_DELAY_TIME * 20); +	if (t == 0) { +		bbvalue = rtl_get_bbreg(hw, RFPGA0_RFMOD, BMASKDWORD); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("==>0x%08x\n", bbvalue)); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQ Calibration for %s\n", +			(is2t ? "2T2R" : "1T1R"))); +		/* Save ADDA parameters, turn Path A ADDA on */ +		_rtl92d_phy_save_adda_registers(hw, adda_reg, +						rtlphy->adda_backup, +						IQK_ADDA_REG_NUM); +		_rtl92d_phy_save_mac_registers(hw, iqk_mac_reg, +					       rtlphy->iqk_mac_backup); +		if (is2t) +			_rtl92d_phy_save_adda_registers(hw, iqk_bb_reg, +							rtlphy->iqk_bb_backup, +							IQK_BB_REG_NUM); +		else +			_rtl92d_phy_save_adda_registers(hw, iqk_bb_reg, +							rtlphy->iqk_bb_backup, +							IQK_BB_REG_NUM - 1); +	} +	_rtl92d_phy_path_adda_on(hw, adda_reg, true, is2t); +	/* MAC settings */ +	_rtl92d_phy_mac_setting_calibration(hw, iqk_mac_reg, +			rtlphy->iqk_mac_backup); +	if (t == 0) +		rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, +			RFPGA0_XA_HSSIPARAMETER1, BIT(8)); +	/*  Switch BB to PI mode to do IQ Calibration. */ +	if (!rtlphy->rfpi_enable) +		_rtl92d_phy_pimode_switch(hw, true); +	rtl_set_bbreg(hw, RFPGA0_RFMOD, BIT(24), 0x00); +	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKDWORD, 0x03a05600); +	rtl_set_bbreg(hw, ROFDM0_TRMUXPAR, BMASKDWORD, 0x000800e4); +	rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW, BMASKDWORD, 0x22208000); +	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xf00000, 0x0f); + +	/* Page B init */ +	rtl_set_bbreg(hw, 0xb68, BMASKDWORD, 0x0f600000); +	if (is2t) +		rtl_set_bbreg(hw, 0xb6c, BMASKDWORD, 0x0f600000); +	/* IQ calibration setting  */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("IQK setting!\n")); +	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0x80800000); +	rtl_set_bbreg(hw, 0xe40, BMASKDWORD, 0x10007c00); +	rtl_set_bbreg(hw, 0xe44, BMASKDWORD, 0x01004800); +	patha_ok = _rtl92d_phy_patha_iqk_5g_normal(hw, is2t); +	if (patha_ok == 0x03) { +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK Success!!\n")); +		result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) & +				0x3FF0000) >> 16; +		result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) & +				0x3FF0000) >> 16; +		result[t][2] = (rtl_get_bbreg(hw, 0xea4, BMASKDWORD) & +				0x3FF0000) >> 16; +		result[t][3] = (rtl_get_bbreg(hw, 0xeac, BMASKDWORD) & +				0x3FF0000) >> 16; +	} else if (patha_ok == 0x01) {	/* Tx IQK OK */ +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("Path A IQK Only  Tx Success!!\n")); + +		result[t][0] = (rtl_get_bbreg(hw, 0xe94, BMASKDWORD) & +				0x3FF0000) >> 16; +		result[t][1] = (rtl_get_bbreg(hw, 0xe9c, BMASKDWORD) & +				0x3FF0000) >> 16; +	} else { +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path A IQK Fail!!\n")); +	} +	if (is2t) { +		/* _rtl92d_phy_patha_standby(hw); */ +		/* Turn Path B ADDA on  */ +		_rtl92d_phy_path_adda_on(hw, adda_reg, false, is2t); +		pathb_ok = _rtl92d_phy_pathb_iqk_5g_normal(hw); +		if (pathb_ok == 0x03) { +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("Path B IQK Success!!\n")); +			result[t][4] = (rtl_get_bbreg(hw, 0xeb4, BMASKDWORD) & +			     0x3FF0000) >> 16; +			result[t][5] = (rtl_get_bbreg(hw, 0xebc, BMASKDWORD) & +			     0x3FF0000) >> 16; +			result[t][6] = (rtl_get_bbreg(hw, 0xec4, BMASKDWORD) & +			     0x3FF0000) >> 16; +			result[t][7] = (rtl_get_bbreg(hw, 0xecc, BMASKDWORD) & +			     0x3FF0000) >> 16; +		} else if (pathb_ok == 0x01) { /* Tx IQK OK */ +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("Path B Only Tx IQK Success!!\n")); +			result[t][4] = (rtl_get_bbreg(hw, 0xeb4, BMASKDWORD) & +			     0x3FF0000) >> 16; +			result[t][5] = (rtl_get_bbreg(hw, 0xebc, BMASKDWORD) & +			     0x3FF0000) >> 16; +		} else { +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("Path B IQK failed!!\n")); +		} +	} + +	/* Back to BB mode, load original value */ +	RTPRINT(rtlpriv, FINIT, INIT_IQK, +		("IQK:Back to BB mode, load original value!\n")); +	rtl_set_bbreg(hw, 0xe28, BMASKDWORD, 0); +	if (t != 0) { +		if (is2t) +			_rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, +							  rtlphy->iqk_bb_backup, +							  IQK_BB_REG_NUM); +		else +			_rtl92d_phy_reload_adda_registers(hw, iqk_bb_reg, +							  rtlphy->iqk_bb_backup, +							  IQK_BB_REG_NUM - 1); +		/* Reload MAC parameters */ +		_rtl92d_phy_reload_mac_registers(hw, iqk_mac_reg, +				rtlphy->iqk_mac_backup); +		/*  Switch back BB to SI mode after finish IQ Calibration. */ +		if (!rtlphy->rfpi_enable) +			_rtl92d_phy_pimode_switch(hw, false); +		/* Reload ADDA power saving parameters */ +		_rtl92d_phy_reload_adda_registers(hw, adda_reg, +						  rtlphy->adda_backup, +						  IQK_ADDA_REG_NUM); +	} +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("<==\n")); +} + +static bool _rtl92d_phy_simularity_compare(struct ieee80211_hw *hw, +	long result[][8], u8 c1, u8 c2) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	u32 i, j, diff, sim_bitmap, bound; +	u8 final_candidate[2] = {0xFF, 0xFF};	/* for path A and path B */ +	bool bresult = true; +	bool is2t = IS_92D_SINGLEPHY(rtlhal->version); + +	if (is2t) +		bound = 8; +	else +		bound = 4; +	sim_bitmap = 0; +	for (i = 0; i < bound; i++) { +		diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - +		       result[c2][i]) : (result[c2][i] - result[c1][i]); +		if (diff > MAX_TOLERANCE_92D) { +			if ((i == 2 || i == 6) && !sim_bitmap) { +				if (result[c1][i] + result[c1][i + 1] == 0) +					final_candidate[(i / 4)] = c2; +				else if (result[c2][i] + result[c2][i + 1] == 0) +					final_candidate[(i / 4)] = c1; +				else +					sim_bitmap = sim_bitmap | (1 << i); +			} else { +				sim_bitmap = sim_bitmap | (1 << i); +			} +		} +	} +	if (sim_bitmap == 0) { +		for (i = 0; i < (bound / 4); i++) { +			if (final_candidate[i] != 0xFF) { +				for (j = i * 4; j < (i + 1) * 4 - 2; j++) +					result[3][j] = +						 result[final_candidate[i]][j]; +				bresult = false; +			} +		} +		return bresult; +	} +	if (!(sim_bitmap & 0x0F)) { /* path A OK */ +		for (i = 0; i < 4; i++) +			result[3][i] = result[c1][i]; +	} else if (!(sim_bitmap & 0x03)) { /* path A, Tx OK */ +		for (i = 0; i < 2; i++) +			result[3][i] = result[c1][i]; +	} +	if (!(sim_bitmap & 0xF0) && is2t) { /* path B OK */ +		for (i = 4; i < 8; i++) +			result[3][i] = result[c1][i]; +	} else if (!(sim_bitmap & 0x30)) { /* path B, Tx OK */ +		for (i = 4; i < 6; i++) +			result[3][i] = result[c1][i]; +	} +	return false; +} + +static void _rtl92d_phy_patha_fill_iqk_matrix(struct ieee80211_hw *hw, +					      bool iqk_ok, long result[][8], +					      u8 final_candidate, bool txonly) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	u32 oldval_0, val_x, tx0_a, reg; +	long val_y, tx0_c; +	bool is2t = IS_92D_SINGLEPHY(rtlhal->version) || +	    rtlhal->macphymode == DUALMAC_DUALPHY; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, +		("Path A IQ Calibration %s !\n", +		(iqk_ok) ? "Success" : "Failed")); +	if (final_candidate == 0xFF) { +		return; +	} else if (iqk_ok) { +		oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, +			BMASKDWORD) >> 22) & 0x3FF;	/* OFDM0_D */ +		val_x = result[final_candidate][0]; +		if ((val_x & 0x00000200) != 0) +			val_x = val_x | 0xFFFFFC00; +		tx0_a = (val_x * oldval_0) >> 8; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("X = 0x%x, tx0_a = 0x%x," +			" oldval_0 0x%x\n",	val_x, tx0_a, oldval_0)); +		rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x3FF, tx0_a); +		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), +			      ((val_x * oldval_0 >> 7) & 0x1)); +		val_y = result[final_candidate][1]; +		if ((val_y & 0x00000200) != 0) +			val_y = val_y | 0xFFFFFC00; +		/* path B IQK result + 3 */ +		if (rtlhal->interfaceindex == 1 && +			rtlhal->current_bandtype == BAND_ON_5G) +			val_y += 3; +		tx0_c = (val_y * oldval_0) >> 8; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Y = 0x%lx, tx0_c = 0x%lx\n", +			val_y, tx0_c)); +		rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, +			      ((tx0_c & 0x3C0) >> 6)); +		rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, 0x003F0000, +			      (tx0_c & 0x3F)); +		if (is2t) +			rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(26), +				      ((val_y * oldval_0 >> 7) & 0x1)); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("0xC80 = 0x%x\n", +			 rtl_get_bbreg(hw, ROFDM0_XATxIQIMBALANCE, +				       BMASKDWORD))); +		if (txonly) { +			RTPRINT(rtlpriv, FINIT, INIT_IQK, ("only Tx OK\n")); +			return; +		} +		reg = result[final_candidate][2]; +		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg); +		reg = result[final_candidate][3] & 0x3F; +		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg); +		reg = (result[final_candidate][3] >> 6) & 0xF; +		rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); +	} +} + +static void _rtl92d_phy_pathb_fill_iqk_matrix(struct ieee80211_hw *hw, +	bool iqk_ok, long result[][8], u8 final_candidate, bool txonly) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	u32 oldval_1, val_x, tx1_a, reg; +	long val_y, tx1_c; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Path B IQ Calibration %s !\n", +		 (iqk_ok) ? "Success" : "Failed")); +	if (final_candidate == 0xFF) { +		return; +	} else if (iqk_ok) { +		oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, +					  BMASKDWORD) >> 22) & 0x3FF; +		val_x = result[final_candidate][4]; +		if ((val_x & 0x00000200) != 0) +			val_x = val_x | 0xFFFFFC00; +		tx1_a = (val_x * oldval_1) >> 8; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("X = 0x%x, tx1_a = 0x%x\n", +			val_x, tx1_a)); +		rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x3FF, tx1_a); +		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(28), +			      ((val_x * oldval_1 >> 7) & 0x1)); +		val_y = result[final_candidate][5]; +		if ((val_y & 0x00000200) != 0) +			val_y = val_y | 0xFFFFFC00; +		if (rtlhal->current_bandtype == BAND_ON_5G) +			val_y += 3; +		tx1_c = (val_y * oldval_1) >> 8; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("Y = 0x%lx, tx1_c = 0x%lx\n", +			val_y, tx1_c)); +		rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, +			      ((tx1_c & 0x3C0) >> 6)); +		rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, 0x003F0000, +			      (tx1_c & 0x3F)); +		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30), +			      ((val_y * oldval_1 >> 7) & 0x1)); +		if (txonly) +			return; +		reg = result[final_candidate][6]; +		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg); +		reg = result[final_candidate][7] & 0x3F; +		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg); +		reg = (result[final_candidate][7] >> 6) & 0xF; +		rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg); +	} +} + +void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	long result[4][8]; +	u8 i, final_candidate, indexforchannel; +	bool patha_ok, pathb_ok; +	long rege94, rege9c, regea4, regeac, regeb4; +	long regebc, regec4, regecc, regtmp = 0; +	bool is12simular, is13simular, is23simular; +	unsigned long flag = 0; + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, +		("IQK:Start!!!channel %d\n", rtlphy->current_channel)); +	for (i = 0; i < 8; i++) { +		result[0][i] = 0; +		result[1][i] = 0; +		result[2][i] = 0; +		result[3][i] = 0; +	} +	final_candidate = 0xff; +	patha_ok = false; +	pathb_ok = false; +	is12simular = false; +	is23simular = false; +	is13simular = false; +	RTPRINT(rtlpriv, FINIT, INIT_IQK, +		("IQK !!!currentband %d\n", rtlhal->current_bandtype)); +	rtl92d_acquire_cckandrw_pagea_ctl(hw, &flag); +	for (i = 0; i < 3; i++) { +		if (rtlhal->current_bandtype == BAND_ON_5G) { +			_rtl92d_phy_iq_calibrate_5g_normal(hw, result, i); +		} else if (rtlhal->current_bandtype == BAND_ON_2_4G) { +			if (IS_92D_SINGLEPHY(rtlhal->version)) +				_rtl92d_phy_iq_calibrate(hw, result, i, true); +			else +				_rtl92d_phy_iq_calibrate(hw, result, i, false); +		} +		if (i == 1) { +			is12simular = _rtl92d_phy_simularity_compare(hw, result, +								     0, 1); +			if (is12simular) { +				final_candidate = 0; +				break; +			} +		} +		if (i == 2) { +			is13simular = _rtl92d_phy_simularity_compare(hw, result, +								     0, 2); +			if (is13simular) { +				final_candidate = 0; +				break; +			} +			is23simular = _rtl92d_phy_simularity_compare(hw, result, +								     1, 2); +			if (is23simular) { +				final_candidate = 1; +			} else { +				for (i = 0; i < 8; i++) +					regtmp += result[3][i]; + +				if (regtmp != 0) +					final_candidate = 3; +				else +					final_candidate = 0xFF; +			} +		} +	} +	rtl92d_release_cckandrw_pagea_ctl(hw, &flag); +	for (i = 0; i < 4; i++) { +		rege94 = result[i][0]; +		rege9c = result[i][1]; +		regea4 = result[i][2]; +		regeac = result[i][3]; +		regeb4 = result[i][4]; +		regebc = result[i][5]; +		regec4 = result[i][6]; +		regecc = result[i][7]; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx " +			"regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n ", +			rege94, rege9c, regea4, regeac, regeb4, regebc, regec4, +			regecc)); +	} +	if (final_candidate != 0xff) { +		rtlphy->reg_e94 = rege94 = result[final_candidate][0]; +		rtlphy->reg_e9c = rege9c = result[final_candidate][1]; +		regea4 = result[final_candidate][2]; +		regeac = result[final_candidate][3]; +		rtlphy->reg_eb4 = regeb4 = result[final_candidate][4]; +		rtlphy->reg_ebc = regebc = result[final_candidate][5]; +		regec4 = result[final_candidate][6]; +		regecc = result[final_candidate][7]; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("IQK: final_candidate is %x\n", final_candidate)); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("IQK: rege94=%lx rege9c=%lx regea4=%lx regeac=%lx " +			"regeb4=%lx regebc=%lx regec4=%lx regecc=%lx\n ", +			rege94, rege9c, regea4, regeac, regeb4, regebc, regec4, +			regecc)); +		patha_ok = pathb_ok = true; +	} else { +		rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; /* X default value */ +		rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0;   /* Y default value */ +	} +	if ((rege94 != 0) /*&&(regea4 != 0) */) +		_rtl92d_phy_patha_fill_iqk_matrix(hw, patha_ok, result, +				final_candidate, (regea4 == 0)); +	if (IS_92D_SINGLEPHY(rtlhal->version)) { +		if ((regeb4 != 0) /*&&(regec4 != 0) */) +			_rtl92d_phy_pathb_fill_iqk_matrix(hw, pathb_ok, result, +						final_candidate, (regec4 == 0)); +	} +	if (final_candidate != 0xFF) { +		indexforchannel = rtl92d_get_rightchnlplace_for_iqk( +				  rtlphy->current_channel); + +		for (i = 0; i < IQK_MATRIX_REG_NUM; i++) +			rtlphy->iqk_matrix_regsetting[indexforchannel]. +				value[0][i] = result[final_candidate][i]; +		rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done = +			true; + +		RT_TRACE(rtlpriv, COMP_SCAN | COMP_MLME, DBG_LOUD, +			 ("\nIQK OK indexforchannel %d.\n", indexforchannel)); +	} +} + +void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	u8 indexforchannel; + +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("channel %d\n", channel)); +	/*------Do IQK for normal chip and test chip 5G band------- */ +	indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, +		("indexforchannel %d done %d\n", indexforchannel, +		rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done)); +	if (0 && !rtlphy->iqk_matrix_regsetting[indexforchannel].iqk_done && +		rtlphy->need_iqk) { +		/* Re Do IQK. */ +		RT_TRACE(rtlpriv, COMP_SCAN | COMP_INIT, DBG_LOUD, +			 ("Do IQK Matrix reg for channel:%d....\n", channel)); +		rtl92d_phy_iq_calibrate(hw); +	} else { +		/* Just load the value. */ +		/* 2G band just load once. */ +		if (((!rtlhal->load_imrandiqk_setting_for2g) && +		    indexforchannel == 0) || indexforchannel > 0) { +			RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, +				 ("Just Read IQK Matrix reg for channel:%d" +				 "....\n", channel)); +			if ((rtlphy->iqk_matrix_regsetting[indexforchannel]. +			     value[0] != NULL) +				/*&&(regea4 != 0) */) +				_rtl92d_phy_patha_fill_iqk_matrix(hw, true, +					rtlphy->iqk_matrix_regsetting[ +					indexforchannel].value,	0, +					(rtlphy->iqk_matrix_regsetting[ +					indexforchannel].value[0][2] == 0)); +			if (IS_92D_SINGLEPHY(rtlhal->version)) { +				if ((rtlphy->iqk_matrix_regsetting[ +					indexforchannel].value[0][4] != 0) +					/*&&(regec4 != 0) */) +					_rtl92d_phy_pathb_fill_iqk_matrix(hw, +						true, +						rtlphy->iqk_matrix_regsetting[ +						indexforchannel].value, 0, +						(rtlphy->iqk_matrix_regsetting[ +						indexforchannel].value[0][6] +						== 0)); +			} +		} +	} +	rtlphy->need_iqk = false; +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n")); +} + +static u32 _rtl92d_phy_get_abs(u32 val1, u32 val2) +{ +	u32 ret; + +	if (val1 >= val2) +		ret = val1 - val2; +	else +		ret = val2 - val1; +	return ret; +} + +static bool _rtl92d_is_legal_5g_channel(struct ieee80211_hw *hw, u8 channel) +{ + +	int i; +	u8 channel_5g[45] = { +		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, +		60, 62, 64, 100, 102, 104, 106, 108, 110, 112, +		114, 116, 118, 120, 122, 124, 126, 128, 130, 132, +		134, 136, 138, 140, 149, 151, 153, 155, 157, 159, +		161, 163, 165 +	}; + +	for (i = 0; i < sizeof(channel_5g); i++) +		if (channel == channel_5g[i]) +			return true; +	return false; +} + +static void _rtl92d_phy_calc_curvindex(struct ieee80211_hw *hw, +				       u32 *targetchnl, u32 * curvecount_val, +				       bool is5g, u32 *curveindex) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 smallest_abs_val = 0xffffffff, u4tmp; +	u8 i, j; +	u8 chnl_num = is5g ? TARGET_CHNL_NUM_5G : TARGET_CHNL_NUM_2G; + +	for (i = 0; i < chnl_num; i++) { +		if (is5g && !_rtl92d_is_legal_5g_channel(hw, i + 1)) +			continue; +		curveindex[i] = 0; +		for (j = 0; j < (CV_CURVE_CNT * 2); j++) { +			u4tmp = _rtl92d_phy_get_abs(targetchnl[i], +				curvecount_val[j]); + +			if (u4tmp < smallest_abs_val) { +				curveindex[i] = j; +				smallest_abs_val = u4tmp; +			} +		} +		smallest_abs_val = 0xffffffff; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("curveindex[%d] = %x\n", i, +			curveindex[i])); +	} +} + +static void _rtl92d_phy_reload_lck_setting(struct ieee80211_hw *hw, +		u8 channel) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 erfpath = rtlpriv->rtlhal.current_bandtype == +		BAND_ON_5G ? RF90_PATH_A : +		IS_92D_SINGLEPHY(rtlpriv->rtlhal.version) ? +		RF90_PATH_B : RF90_PATH_A; +	u32 u4tmp = 0, u4regvalue = 0; +	bool bneed_powerdown_radio = false; + +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("path %d\n", erfpath)); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("band type = %d\n", +		rtlpriv->rtlhal.current_bandtype)); +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("channel = %d\n", channel)); +	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) {/* Path-A for 5G */ +		u4tmp = curveindex_5g[channel-1]; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("ver 1 set RF-A, 5G,	0x28 = 0x%ulx !!\n", u4tmp)); +		if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY && +			rtlpriv->rtlhal.interfaceindex == 1) { +			bneed_powerdown_radio = +				rtl92d_phy_enable_anotherphy(hw, false); +			rtlpriv->rtlhal.during_mac1init_radioa = true; +			/* asume no this case */ +			if (bneed_powerdown_radio) +				_rtl92d_phy_enable_rf_env(hw, erfpath, +							  &u4regvalue); +		} +		rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp); +		if (bneed_powerdown_radio) +			_rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue); +		if (rtlpriv->rtlhal.during_mac1init_radioa) +			rtl92d_phy_powerdown_anotherphy(hw, false); +	} else if (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) { +		u4tmp = curveindex_2g[channel-1]; +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("ver 3 set RF-B, 2G, 0x28 = 0x%ulx !!\n", u4tmp)); +		if (rtlpriv->rtlhal.macphymode == DUALMAC_DUALPHY && +			rtlpriv->rtlhal.interfaceindex == 0) { +			bneed_powerdown_radio = +				rtl92d_phy_enable_anotherphy(hw, true); +			rtlpriv->rtlhal.during_mac0init_radiob = true; +			if (bneed_powerdown_radio) +				_rtl92d_phy_enable_rf_env(hw, erfpath, +							  &u4regvalue); +		} +		rtl_set_rfreg(hw, erfpath, RF_SYN_G4, 0x3f800, u4tmp); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("ver 3 set RF-B, 2G, 0x28 = 0x%ulx !!\n", +			rtl_get_rfreg(hw,  erfpath, RF_SYN_G4, 0x3f800))); +		if (bneed_powerdown_radio) +			_rtl92d_phy_restore_rf_env(hw, erfpath, &u4regvalue); +		if (rtlpriv->rtlhal.during_mac0init_radiob) +			rtl92d_phy_powerdown_anotherphy(hw, true); +	} +	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("<====\n")); +} + +static void _rtl92d_phy_lc_calibrate_sw(struct ieee80211_hw *hw, bool is2t) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	u8 tmpreg, index, rf_mode[2]; +	u8 path = is2t ? 2 : 1; +	u8 i; +	u32 u4tmp, offset; +	u32 curvecount_val[CV_CURVE_CNT * 2] = {0}; +	u16 timeout = 800, timecount = 0; + +	/* Check continuous TX and Packet TX */ +	tmpreg = rtl_read_byte(rtlpriv, 0xd03); +	/* if Deal with contisuous TX case, disable all continuous TX */ +	/* if Deal with Packet TX case, block all queues */ +	if ((tmpreg & 0x70) != 0) +		rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); +	else +		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); +	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x0F); +	for (index = 0; index < path; index++) { +		/* 1. Read original RF mode */ +		offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1; +		rf_mode[index] = rtl_read_byte(rtlpriv, offset); +		/* 2. Set RF mode = standby mode */ +		rtl_set_rfreg(hw, (enum radio_path)index, RF_AC, +			      BRFREGOFFSETMASK, 0x010000); +		if (rtlpci->init_ready) { +			/* switch CV-curve control by LC-calibration */ +			rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7, +				      BIT(17), 0x0); +			/* 4. Set LC calibration begin */ +			rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW, +				      0x08000, 0x01); +		} +		u4tmp = rtl_get_rfreg(hw, (enum radio_path)index, RF_SYN_G6, +				  BRFREGOFFSETMASK); +		while ((!(u4tmp & BIT(11))) && timecount <= timeout) { +			mdelay(50); +			timecount += 50; +			u4tmp = rtl_get_rfreg(hw, (enum radio_path)index, +					      RF_SYN_G6, BRFREGOFFSETMASK); +		} +		RTPRINT(rtlpriv, FINIT, INIT_IQK, +			("PHY_LCK finish delay for %d ms=2\n", timecount)); +		u4tmp = rtl_get_rfreg(hw, index, RF_SYN_G4, BRFREGOFFSETMASK); +		if (index == 0 && rtlhal->interfaceindex == 0) { +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("path-A / 5G LCK\n")); +		} else { +			RTPRINT(rtlpriv, FINIT, INIT_IQK, +				("path-B / 2.4G LCK\n")); +		} +		memset(&curvecount_val[0], 0, CV_CURVE_CNT * 2); +		/* Set LC calibration off */ +		rtl_set_rfreg(hw, (enum radio_path)index, RF_CHNLBW, +			      0x08000, 0x0); +		RTPRINT(rtlpriv, FINIT, INIT_IQK, ("set RF 0x18[15] = 0\n")); +		/* save Curve-counting number */ +		for (i = 0; i < CV_CURVE_CNT; i++) { +			u32 readval = 0, readval2 = 0; +			rtl_set_rfreg(hw, (enum radio_path)index, 0x3F, +				      0x7f, i); + +			rtl_set_rfreg(hw, (enum radio_path)index, 0x4D, +				BRFREGOFFSETMASK, 0x0); +			readval = rtl_get_rfreg(hw, (enum radio_path)index, +					  0x4F, BRFREGOFFSETMASK); +			curvecount_val[2 * i + 1] = (readval & 0xfffe0) >> 5; +			/* reg 0x4f [4:0] */ +			/* reg 0x50 [19:10] */ +			readval2 = rtl_get_rfreg(hw, (enum radio_path)index, +						 0x50, 0xffc00); +			curvecount_val[2 * i] = (((readval & 0x1F) << 10) | +						 readval2); +		} +		if (index == 0 && rtlhal->interfaceindex == 0) +			_rtl92d_phy_calc_curvindex(hw, targetchnl_5g, +						   curvecount_val, +						   true, curveindex_5g); +		else +			_rtl92d_phy_calc_curvindex(hw, targetchnl_2g, +						   curvecount_val, +						   false, curveindex_2g); +		/* switch CV-curve control mode */ +		rtl_set_rfreg(hw, (enum radio_path)index, RF_SYN_G7, +			      BIT(17), 0x1); +	} + +	/* Restore original situation  */ +	for (index = 0; index < path; index++) { +		offset = index == 0 ? ROFDM0_XAAGCCORE1 : ROFDM0_XBAGCCORE1; +		rtl_write_byte(rtlpriv, offset, 0x50); +		rtl_write_byte(rtlpriv, offset, rf_mode[index]); +	} +	if ((tmpreg & 0x70) != 0) +		rtl_write_byte(rtlpriv, 0xd03, tmpreg); +	else /*Deal with Packet TX case */ +		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +	rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0xF00000, 0x00); +	_rtl92d_phy_reload_lck_setting(hw, rtlpriv->phy.current_channel); +} + +static void _rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("cosa PHY_LCK ver=2\n")); +	_rtl92d_phy_lc_calibrate_sw(hw, is2t); +} + +void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	u32 timeout = 2000, timecount = 0; + +	while (rtlpriv->mac80211.act_scanning && timecount < timeout) { +		udelay(50); +		timecount += 50; +	} + +	rtlphy->lck_inprogress = true; +	RTPRINT(rtlpriv, FINIT, INIT_IQK, +		("LCK:Start!!! currentband %x delay %d ms\n", +		 rtlhal->current_bandtype, timecount)); +	if (IS_92D_SINGLEPHY(rtlhal->version)) { +		_rtl92d_phy_lc_calibrate(hw, true); +	} else { +		/* For 1T1R */ +		_rtl92d_phy_lc_calibrate(hw, false); +	} +	rtlphy->lck_inprogress = false; +	RTPRINT(rtlpriv, FINIT, INIT_IQK, ("LCK:Finish!!!\n")); +} + +void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) +{ +	return; +} + +static bool _rtl92d_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, +		u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid, +		u32 para1, u32 para2, u32 msdelay) +{ +	struct swchnlcmd *pcmd; + +	if (cmdtable == NULL) { +		RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); +		return false; +	} +	if (cmdtableidx >= cmdtablesz) +		return false; + +	pcmd = cmdtable + cmdtableidx; +	pcmd->cmdid = cmdid; +	pcmd->para1 = para1; +	pcmd->para2 = para2; +	pcmd->msdelay = msdelay; +	return true; +} + +void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	u8 i; + +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +			("settings regs %d default regs %d\n", +			(int)(sizeof(rtlphy->iqk_matrix_regsetting) / +			sizeof(struct iqk_matrix_regs)), +			IQK_MATRIX_REG_NUM)); +	/* 0xe94, 0xe9c, 0xea4, 0xeac, 0xeb4, 0xebc, 0xec4, 0xecc */ +	for (i = 0; i < IQK_MATRIX_SETTINGS_NUM; i++) { +		rtlphy->iqk_matrix_regsetting[i].value[0][0] = 0x100; +		rtlphy->iqk_matrix_regsetting[i].value[0][2] = 0x100; +		rtlphy->iqk_matrix_regsetting[i].value[0][4] = 0x100; +		rtlphy->iqk_matrix_regsetting[i].value[0][6] = 0x100; +		rtlphy->iqk_matrix_regsetting[i].value[0][1] = 0x0; +		rtlphy->iqk_matrix_regsetting[i].value[0][3] = 0x0; +		rtlphy->iqk_matrix_regsetting[i].value[0][5] = 0x0; +		rtlphy->iqk_matrix_regsetting[i].value[0][7] = 0x0; +		rtlphy->iqk_matrix_regsetting[i].iqk_done = false; +	} +} + +static bool _rtl92d_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, +					     u8 channel, u8 *stage, u8 *step, +					     u32 *delay) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; +	u32 precommoncmdcnt; +	struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; +	u32 postcommoncmdcnt; +	struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; +	u32 rfdependcmdcnt; +	struct swchnlcmd *currentcmd = NULL; +	u8 rfpath; +	u8 num_total_rfpath = rtlphy->num_total_rfpath; + +	precommoncmdcnt = 0; +	_rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, +					 MAX_PRECMD_CNT, +					 CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); +	_rtl92d_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, +					 MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); +	postcommoncmdcnt = 0; +	_rtl92d_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, +					 MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); +	rfdependcmdcnt = 0; +	_rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, +					 MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, +					 RF_CHNLBW, channel, 0); +	_rtl92d_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, +					 MAX_RFDEPENDCMD_CNT, CMDID_END, +					 0, 0, 0); + +	do { +		switch (*stage) { +		case 0: +			currentcmd = &precommoncmd[*step]; +			break; +		case 1: +			currentcmd = &rfdependcmd[*step]; +			break; +		case 2: +			currentcmd = &postcommoncmd[*step]; +			break; +		} +		if (currentcmd->cmdid == CMDID_END) { +			if ((*stage) == 2) { +				return true; +			} else { +				(*stage)++; +				(*step) = 0; +				continue; +			} +		} +		switch (currentcmd->cmdid) { +		case CMDID_SET_TXPOWEROWER_LEVEL: +			rtl92d_phy_set_txpower_level(hw, channel); +			break; +		case CMDID_WRITEPORT_ULONG: +			rtl_write_dword(rtlpriv, currentcmd->para1, +					currentcmd->para2); +			break; +		case CMDID_WRITEPORT_USHORT: +			rtl_write_word(rtlpriv, currentcmd->para1, +				       (u16)currentcmd->para2); +			break; +		case CMDID_WRITEPORT_UCHAR: +			rtl_write_byte(rtlpriv, currentcmd->para1, +				       (u8)currentcmd->para2); +			break; +		case CMDID_RF_WRITEREG: +			for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { +				rtlphy->rfreg_chnlval[rfpath] = +					((rtlphy->rfreg_chnlval[rfpath] & +					0xffffff00) | currentcmd->para2); +				if (rtlpriv->rtlhal.current_bandtype == +				    BAND_ON_5G) { +					if (currentcmd->para2 > 99) +						rtlphy->rfreg_chnlval[rfpath] = +						    rtlphy->rfreg_chnlval +						    [rfpath] | (BIT(18)); +					else +						rtlphy->rfreg_chnlval[rfpath] = +						    rtlphy->rfreg_chnlval +						    [rfpath] & (~BIT(18)); +					rtlphy->rfreg_chnlval[rfpath] |= +						 (BIT(16) | BIT(8)); +				} else { +					rtlphy->rfreg_chnlval[rfpath] &= +						~(BIT(8) | BIT(16) | BIT(18)); +				} +				rtl_set_rfreg(hw, (enum radio_path)rfpath, +					      currentcmd->para1, +					      BRFREGOFFSETMASK, +					      rtlphy->rfreg_chnlval[rfpath]); +				_rtl92d_phy_reload_imr_setting(hw, channel, +							       rfpath); +			} +			_rtl92d_phy_switch_rf_setting(hw, channel); +			/* do IQK when all parameters are ready */ +			rtl92d_phy_reload_iqk_setting(hw, channel); +			break; +		default: +			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +				 ("switch case not process\n")); +			break; +		} +		break; +	} while (true); +	(*delay) = currentcmd->msdelay; +	(*step)++; +	return false; +} + +u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u32 delay; +	u32 timeout = 1000, timecount = 0; +	u8 channel = rtlphy->current_channel; +	u32 ret_value; + +	if (rtlphy->sw_chnl_inprogress) +		return 0; +	if (rtlphy->set_bwmode_inprogress) +		return 0; + +	if ((is_hal_stop(rtlhal)) || (RT_CANNOT_IO(hw))) { +		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, +			 ("sw_chnl_inprogress false driver sleep or unload\n")); +		return 0; +	} +	while (rtlphy->lck_inprogress && timecount < timeout) { +		mdelay(50); +		timecount += 50; +	} +	if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY && +	    rtlhal->bandset == BAND_ON_BOTH) { +		ret_value = rtl_get_bbreg(hw, RFPGA0_XAB_RFPARAMETER, +					  BMASKDWORD); +		if (rtlphy->current_channel > 14 && !(ret_value & BIT(0))) +			rtl92d_phy_switch_wirelessband(hw, BAND_ON_5G); +		else if (rtlphy->current_channel <= 14 && (ret_value & BIT(0))) +			rtl92d_phy_switch_wirelessband(hw, BAND_ON_2_4G); +	} +	switch (rtlhal->current_bandtype) { +	case BAND_ON_5G: +		/* Get first channel error when change between +		 * 5G and 2.4G band. */ +		if (channel <= 14) +			return 0; +		RT_ASSERT((channel > 14), ("5G but channel<=14")); +		break; +	case BAND_ON_2_4G: +		/* Get first channel error when change between +		 * 5G and 2.4G band. */ +		if (channel > 14) +			return 0; +		RT_ASSERT((channel <= 14), ("2G but channel>14")); +		break; +	default: +		RT_ASSERT(false, +			  ("Invalid WirelessMode(%#x)!!\n", +			   rtlpriv->mac80211.mode)); +		break; +	} +	rtlphy->sw_chnl_inprogress = true; +	if (channel == 0) +		channel = 1; +	rtlphy->sw_chnl_stage = 0; +	rtlphy->sw_chnl_step = 0; +	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, +		 ("switch to channel%d\n", rtlphy->current_channel)); + +	do { +		if (!rtlphy->sw_chnl_inprogress) +			break; +		if (!_rtl92d_phy_sw_chnl_step_by_step(hw, +						      rtlphy->current_channel, +		    &rtlphy->sw_chnl_stage, &rtlphy->sw_chnl_step, &delay)) { +			if (delay > 0) +				mdelay(delay); +			else +				continue; +		} else { +			rtlphy->sw_chnl_inprogress = false; +		} +		break; +	} while (true); +	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); +	rtlphy->sw_chnl_inprogress = false; +	return 1; +} + +static void rtl92d_phy_set_io(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); + +	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, +		 ("--->Cmd(%#x), set_io_inprogress(%d)\n", +		 rtlphy->current_io_type, rtlphy->set_io_inprogress)); +	switch (rtlphy->current_io_type) { +	case IO_CMD_RESUME_DM_BY_SCAN: +		de_digtable.cur_igvalue = rtlphy->initgain_backup.xaagccore1; +		rtl92d_dm_write_dig(hw); +		rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); +		break; +	case IO_CMD_PAUSE_DM_BY_SCAN: +		rtlphy->initgain_backup.xaagccore1 = de_digtable.cur_igvalue; +		de_digtable.cur_igvalue = 0x17; +		rtl92d_dm_write_dig(hw); +		break; +	default: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("switch case not process\n")); +		break; +	} +	rtlphy->set_io_inprogress = false; +	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, +		 ("<---(%#x)\n", rtlphy->current_io_type)); +} + +bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	bool postprocessing = false; + +	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, +		 ("-->IO Cmd(%#x), set_io_inprogress(%d)\n", +		 iotype, rtlphy->set_io_inprogress)); +	do { +		switch (iotype) { +		case IO_CMD_RESUME_DM_BY_SCAN: +			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, +				 ("[IO CMD] Resume DM after scan.\n")); +			postprocessing = true; +			break; +		case IO_CMD_PAUSE_DM_BY_SCAN: +			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, +				 ("[IO CMD] Pause DM before scan.\n")); +			postprocessing = true; +			break; +		default: +			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +				 ("switch case not process\n")); +			break; +		} +	} while (false); +	if (postprocessing && !rtlphy->set_io_inprogress) { +		rtlphy->set_io_inprogress = true; +		rtlphy->current_io_type = iotype; +	} else { +		return false; +	} +	rtl92d_phy_set_io(hw); +	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, ("<--IO Type(%#x)\n", iotype)); +	return true; +} + +static void _rtl92d_phy_set_rfon(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	/* a.  SYS_CLKR 0x08[11] = 1  restore MAC clock */ +	/* b.  SPS_CTRL 0x11[7:0] = 0x2b */ +	if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) +		rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); +	/* c.  For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE3 enable BB TRX function */ +	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); +	/* RF_ON_EXCEP(d~g): */ +	/* d.  APSD_CTRL 0x600[7:0] = 0x00 */ +	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); +	/* e.  SYS_FUNC_EN 0x02[7:0] = 0xE2  reset BB TRX function again */ +	/* f.  SYS_FUNC_EN 0x02[7:0] = 0xE3  enable BB TRX function*/ +	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); +	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); +	/* g.   txpause 0x522[7:0] = 0x00  enable mac tx queue */ +	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +} + +static void _rtl92d_phy_set_rfsleep(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 u4btmp; +	u8 delay = 5; + +	/* a.   TXPAUSE 0x522[7:0] = 0xFF  Pause MAC TX queue  */ +	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); +	/* b.   RF path 0 offset 0x00 = 0x00  disable RF  */ +	rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00); +	/* c.   APSD_CTRL 0x600[7:0] = 0x40 */ +	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); +	/* d. APSD_CTRL 0x600[7:0] = 0x00 +	 * APSD_CTRL 0x600[7:0] = 0x00 +	 * RF path 0 offset 0x00 = 0x00 +	 * APSD_CTRL 0x600[7:0] = 0x40 +	 * */ +	u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, BRFREGOFFSETMASK); +	while (u4btmp != 0 && delay > 0) { +		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); +		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, BRFREGOFFSETMASK, 0x00); +		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); +		u4btmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, BRFREGOFFSETMASK); +		delay--; +	} +	if (delay == 0) { +		/* Jump out the LPS turn off sequence to RF_ON_EXCEP */ +		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); + +		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); +		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); +		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); +		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, +			("Fail !!! Switch RF timeout.\n")); +		return; +	} +	/* e.   For PCIE: SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB TRX function */ +	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); +	/* f.   SPS_CTRL 0x11[7:0] = 0x22 */ +	if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) +		rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); +	/* g.    SYS_CLKR 0x08[11] = 0  gated MAC clock */ +} + +bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, +				   enum rf_pwrstate rfpwr_state) +{ + +	bool bresult = true; +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	u8 i, queue_id; +	struct rtl8192_tx_ring *ring = NULL; + +	if (rfpwr_state == ppsc->rfpwr_state) +		return false; +	switch (rfpwr_state) { +	case ERFON: +		if ((ppsc->rfpwr_state == ERFOFF) && +		    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { +			bool rtstatus; +			u32 InitializeCount = 0; +			do { +				InitializeCount++; +				RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, +					 ("IPS Set eRf nic enable\n")); +				rtstatus = rtl_ps_enable_nic(hw); +			} while ((rtstatus != true) && +				 (InitializeCount < 10)); + +			RT_CLEAR_PS_LEVEL(ppsc, +					  RT_RF_OFF_LEVL_HALT_NIC); +		} else { +			RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, +				 ("awake, sleeped:%d ms state_" +				 "inap:%x\n", +				 jiffies_to_msecs(jiffies - +				 ppsc->last_sleep_jiffies), +				 rtlpriv->psc.state_inap)); +			ppsc->last_awake_jiffies = jiffies; +			_rtl92d_phy_set_rfon(hw); +		} + +		if (mac->link_state == MAC80211_LINKED) +			rtlpriv->cfg->ops->led_control(hw, +					 LED_CTL_LINK); +		else +			rtlpriv->cfg->ops->led_control(hw, +					 LED_CTL_NO_LINK); +		break; +	case ERFOFF: +		if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { +			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, +				 ("IPS Set eRf nic disable\n")); +			rtl_ps_disable_nic(hw); +			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); +		} else { +			if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) +				rtlpriv->cfg->ops->led_control(hw, +						 LED_CTL_NO_LINK); +			else +				rtlpriv->cfg->ops->led_control(hw, +						 LED_CTL_POWER_OFF); +		} +		break; +	case ERFSLEEP: +		if (ppsc->rfpwr_state == ERFOFF) +			break; + +		for (queue_id = 0, i = 0; +		     queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { +			ring = &pcipriv->dev.tx_ring[queue_id]; +			if (skb_queue_len(&ring->queue) == 0 || +			    queue_id == BEACON_QUEUE) { +				queue_id++; +				continue; +			} else if (rtlpci->pdev->current_state != PCI_D0) { +				RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, +					 ("eRf Off/Sleep: %d times TcbBusyQueu" +					 "e[%d] !=0 but lower power state!\n", +					 (i + 1), queue_id)); +				break; +			} else { +				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, +					 ("eRf Off/Sleep: %d times TcbBusyQueu" +					 "e[%d] =%d " +					 "before doze!\n", (i + 1), queue_id, +					  skb_queue_len(&ring->queue))); +				udelay(10); +				i++; +			} + +			if (i >= MAX_DOZE_WAITING_TIMES_9x) { +				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, +					 ("\nERFOFF: %d times TcbBusyQueue[%d] " +					 "= %d !\n", +					  MAX_DOZE_WAITING_TIMES_9x, queue_id, +					  skb_queue_len(&ring->queue))); +				break; +			} +		} +		RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, +			 ("Set rfsleep awaked:%d ms\n", +			 jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies))); +		RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, ("sleep awaked:%d ms " +			 "state_inap:%x\n", jiffies_to_msecs(jiffies - +			 ppsc->last_awake_jiffies), rtlpriv->psc.state_inap)); +		ppsc->last_sleep_jiffies = jiffies; +		_rtl92d_phy_set_rfsleep(hw); +		break; +	default: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("switch case not process\n")); +		bresult = false; +		break; +	} +	if (bresult) +		ppsc->rfpwr_state = rfpwr_state; +	return bresult; +} + +void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u8 offset = REG_MAC_PHY_CTRL_NORMAL; + +	switch (rtlhal->macphymode) { +	case DUALMAC_DUALPHY: +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +			 ("MacPhyMode: DUALMAC_DUALPHY\n")); +		rtl_write_byte(rtlpriv, offset, 0xF3); +		break; +	case SINGLEMAC_SINGLEPHY: +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +			 ("MacPhyMode: SINGLEMAC_SINGLEPHY\n")); +		rtl_write_byte(rtlpriv, offset, 0xF4); +		break; +	case DUALMAC_SINGLEPHY: +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +			 ("MacPhyMode: DUALMAC_SINGLEPHY\n")); +		rtl_write_byte(rtlpriv, offset, 0xF1); +		break; +	} +} + +void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); + +	switch (rtlhal->macphymode) { +	case DUALMAC_SINGLEPHY: +		rtlphy->rf_type = RF_2T2R; +		rtlhal->version |= CHIP_92D_SINGLEPHY; +		rtlhal->bandset = BAND_ON_BOTH; +		rtlhal->current_bandtype = BAND_ON_2_4G; +		break; + +	case SINGLEMAC_SINGLEPHY: +		rtlphy->rf_type = RF_2T2R; +		rtlhal->version |= CHIP_92D_SINGLEPHY; +		rtlhal->bandset = BAND_ON_BOTH; +		rtlhal->current_bandtype = BAND_ON_2_4G; +		break; + +	case DUALMAC_DUALPHY: +		rtlphy->rf_type = RF_1T1R; +		rtlhal->version &= (~CHIP_92D_SINGLEPHY); +		/* Now we let MAC0 run on 5G band. */ +		if (rtlhal->interfaceindex == 0) { +			rtlhal->bandset = BAND_ON_5G; +			rtlhal->current_bandtype = BAND_ON_5G; +		} else { +			rtlhal->bandset = BAND_ON_2_4G; +			rtlhal->current_bandtype = BAND_ON_2_4G; +		} +		break; +	default: +		break; +	} +} + +u8 rtl92d_get_chnlgroup_fromarray(u8 chnl) +{ +	u8 group; +	u8 channel_info[59] = { +		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, +		58, 60, 62, 64, 100, 102, 104, 106, 108, +		110, 112, 114, 116, 118, 120, 122, 124, +		126, 128, 130, 132, 134, 136, 138, 140, +		149, 151, 153, 155, 157, 159, 161, 163, +		165 +	}; + +	if (channel_info[chnl] <= 3) +		group = 0; +	else if (channel_info[chnl] <= 9) +		group = 1; +	else if (channel_info[chnl] <= 14) +		group = 2; +	else if (channel_info[chnl] <= 44) +		group = 3; +	else if (channel_info[chnl] <= 54) +		group = 4; +	else if (channel_info[chnl] <= 64) +		group = 5; +	else if (channel_info[chnl] <= 112) +		group = 6; +	else if (channel_info[chnl] <= 126) +		group = 7; +	else if (channel_info[chnl] <= 140) +		group = 8; +	else if (channel_info[chnl] <= 153) +		group = 9; +	else if (channel_info[chnl] <= 159) +		group = 10; +	else +		group = 11; +	return group; +} + +void rtl92d_phy_set_poweron(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	unsigned long flags; +	u8 value8; +	u16 i; +	u32 mac_reg = (rtlhal->interfaceindex == 0 ? REG_MAC0 : REG_MAC1); + +	/* notice fw know band status  0x81[1]/0x53[1] = 0: 5G, 1: 2G */ +	if (rtlhal->current_bandtype == BAND_ON_2_4G) { +		value8 = rtl_read_byte(rtlpriv, mac_reg); +		value8 |= BIT(1); +		rtl_write_byte(rtlpriv, mac_reg, value8); +	} else { +		value8 = rtl_read_byte(rtlpriv, mac_reg); +		value8 &= (~BIT(1)); +		rtl_write_byte(rtlpriv, mac_reg, value8); +	} + +	if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) { +		value8 = rtl_read_byte(rtlpriv, REG_MAC0); +		rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON); +	} else { +		spin_lock_irqsave(&globalmutex_power, flags); +		if (rtlhal->interfaceindex == 0) { +			value8 = rtl_read_byte(rtlpriv, REG_MAC0); +			rtl_write_byte(rtlpriv, REG_MAC0, value8 | MAC0_ON); +		} else { +			value8 = rtl_read_byte(rtlpriv, REG_MAC1); +			rtl_write_byte(rtlpriv, REG_MAC1, value8 | MAC1_ON); +		} +		value8 = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS); +		spin_unlock_irqrestore(&globalmutex_power, flags); +		for (i = 0; i < 200; i++) { +			if ((value8 & BIT(7)) == 0) { +				break; +			} else { +				udelay(500); +				spin_lock_irqsave(&globalmutex_power, flags); +				value8 = rtl_read_byte(rtlpriv, +						    REG_POWER_OFF_IN_PROCESS); +				spin_unlock_irqrestore(&globalmutex_power, +						       flags); +			} +		} +		if (i == 200) +			RT_ASSERT(false, ("Another mac power off over time\n")); +	} +} + +void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	switch (rtlpriv->rtlhal.macphymode) { +	case DUALMAC_DUALPHY: +		rtl_write_byte(rtlpriv, REG_DMC, 0x0); +		rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08); +		rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff); +		break; +	case DUALMAC_SINGLEPHY: +		rtl_write_byte(rtlpriv, REG_DMC, 0xf8); +		rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x08); +		rtl_write_word(rtlpriv, REG_TRXFF_BNDY + 2, 0x13ff); +		break; +	case SINGLEMAC_SINGLEPHY: +		rtl_write_byte(rtlpriv, REG_DMC, 0x0); +		rtl_write_byte(rtlpriv, REG_RX_PKT_LIMIT, 0x10); +		rtl_write_word(rtlpriv, (REG_TRXFF_BNDY + 2), 0x27FF); +		break; +	default: +		break; +	} +} + +void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	u8 rfpath, i; + +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("==>\n")); +	/* r_select_5G for path_A/B 0 for 2.4G, 1 for 5G */ +	if (rtlhal->current_bandtype == BAND_ON_2_4G) { +		/* r_select_5G for path_A/B,0x878 */ +		rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x0); +		rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x0); +		if (rtlhal->macphymode != DUALMAC_DUALPHY) { +			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x0); +			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x0); +		} +		/* rssi_table_select:index 0 for 2.4G.1~3 for 5G,0xc78 */ +		rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x0); +		/* fc_area  0xd2c */ +		rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x0); +		/* 5G LAN ON */ +		rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0xa); +		/* TX BB gain shift*1,Just for testchip,0xc80,0xc88 */ +		rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD, +			      0x40000100); +		rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD, +			      0x40000100); +		if (rtlhal->macphymode == DUALMAC_DUALPHY) { +			rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, +				      BIT(10) | BIT(6) | BIT(5), +				      ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) | +				      (rtlefuse->eeprom_c9 & BIT(1)) | +				      ((rtlefuse->eeprom_cc & BIT(1)) << 4)); +			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, +				      BIT(10) | BIT(6) | BIT(5), +				      ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) | +				      ((rtlefuse->eeprom_c9 & BIT(0)) << 1) | +				      ((rtlefuse->eeprom_cc & BIT(0)) << 5)); +			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0); +		} else { +			rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, +				      BIT(26) | BIT(22) | BIT(21) | BIT(10) | +				      BIT(6) | BIT(5), +				      ((rtlefuse->eeprom_c9 & BIT(3)) >> 3) | +				      (rtlefuse->eeprom_c9 & BIT(1)) | +				      ((rtlefuse->eeprom_cc & BIT(1)) << 4) | +				      ((rtlefuse->eeprom_c9 & BIT(7)) << 9) | +				      ((rtlefuse->eeprom_c9 & BIT(5)) << 12) | +				      ((rtlefuse->eeprom_cc & BIT(3)) << 18)); +			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, +				      BIT(10) | BIT(6) | BIT(5), +				      ((rtlefuse->eeprom_c9 & BIT(2)) >> 2) | +				      ((rtlefuse->eeprom_c9 & BIT(0)) << 1) | +				      ((rtlefuse->eeprom_cc & BIT(0)) << 5)); +			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, +				      BIT(10) | BIT(6) | BIT(5), +				      ((rtlefuse->eeprom_c9 & BIT(6)) >> 6) | +				      ((rtlefuse->eeprom_c9 & BIT(4)) >> 3) | +				      ((rtlefuse->eeprom_cc & BIT(2)) << 3)); +			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, +				      BIT(31) | BIT(15), 0); +		} +		/* 1.5V_LDO */ +	} else { +		/* r_select_5G for path_A/B */ +		rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(0), 0x1); +		rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), 0x1); +		if (rtlhal->macphymode != DUALMAC_DUALPHY) { +			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(16), 0x1); +			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(31), 0x1); +		} +		/* rssi_table_select:index 0 for 2.4G.1~3 for 5G */ +		rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, BIT(6) | BIT(7), 0x1); +		/* fc_area */ +		rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(14) | BIT(13), 0x1); +		/* 5G LAN ON */ +		rtl_set_bbreg(hw, 0xB30, 0x00F00000, 0x0); +		/* TX BB gain shift,Just for testchip,0xc80,0xc88 */ +		if (rtlefuse->internal_pa_5g[0]) +			rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD, +				      0x2d4000b5); +		else +			rtl_set_bbreg(hw, ROFDM0_XATxIQIMBALANCE, BMASKDWORD, +				      0x20000080); +		if (rtlefuse->internal_pa_5g[1]) +			rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD, +				      0x2d4000b5); +		else +			rtl_set_bbreg(hw, ROFDM0_XBTxIQIMBALANCE, BMASKDWORD, +				      0x20000080); +		if (rtlhal->macphymode == DUALMAC_DUALPHY) { +			rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, +				      BIT(10) | BIT(6) | BIT(5), +				      (rtlefuse->eeprom_cc & BIT(5))); +			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10), +				      ((rtlefuse->eeprom_cc & BIT(4)) >> 4)); +			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(15), +				      (rtlefuse->eeprom_cc & BIT(4)) >> 4); +		} else { +			rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, +				      BIT(26) | BIT(22) | BIT(21) | BIT(10) | +				      BIT(6) | BIT(5), +				      (rtlefuse->eeprom_cc & BIT(5)) | +				      ((rtlefuse->eeprom_cc & BIT(7)) << 14)); +			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, BIT(10), +				      ((rtlefuse->eeprom_cc & BIT(4)) >> 4)); +			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, BIT(10), +				      ((rtlefuse->eeprom_cc & BIT(6)) >> 6)); +			rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, +				      BIT(31) | BIT(15), +				      ((rtlefuse->eeprom_cc & BIT(4)) >> 4) | +				      ((rtlefuse->eeprom_cc & BIT(6)) << 10)); +		} +	} +	/* update IQK related settings */ +	rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, BMASKDWORD, 0x40000100); +	rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, BMASKDWORD, 0x40000100); +	rtl_set_bbreg(hw, ROFDM0_XCTxAFE, 0xF0000000, 0x00); +	rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(30) | BIT(28) | +		      BIT(26) | BIT(24), 0x00); +	rtl_set_bbreg(hw, ROFDM0_XDTxAFE, 0xF0000000, 0x00); +	rtl_set_bbreg(hw, 0xca0, 0xF0000000, 0x00); +	rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, 0x00); + +	/* Update RF */ +	for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; +	     rfpath++) { +		if (rtlhal->current_bandtype == BAND_ON_2_4G) { +			/* MOD_AG for RF paht_A 0x18 BIT8,BIT16 */ +			rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) | BIT(16) | +				      BIT(18), 0); +			/* RF0x0b[16:14] =3b'111 */ +			rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B, +				      0x1c000, 0x07); +		} else { +			/* MOD_AG for RF paht_A 0x18 BIT8,BIT16 */ +			rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) | +				      BIT(16) | BIT(18), +				      (BIT(16) | BIT(8)) >> 8); +		} +	} +	/* Update for all band. */ +	/* DMDP */ +	if (rtlphy->rf_type == RF_1T1R) { +		/* Use antenna 0,0xc04,0xd04 */ +		rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x11); +		rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x1); + +		/* enable ad/da clock1 for dual-phy reg0x888 */ +		if (rtlhal->interfaceindex == 0) { +			rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) | +				      BIT(13), 0x3); +		} else { +			rtl92d_phy_enable_anotherphy(hw, false); +			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, +				 ("MAC1 use DBI to update 0x888")); +			/* 0x888 */ +			rtl92de_write_dword_dbi(hw, RFPGA0_ADDALLOCKEN, +						rtl92de_read_dword_dbi(hw, +						RFPGA0_ADDALLOCKEN, +						BIT(3)) | BIT(12) | BIT(13), +						BIT(3)); +			rtl92d_phy_powerdown_anotherphy(hw, false); +		} +	} else { +		/* Single PHY */ +		/* Use antenna 0 & 1,0xc04,0xd04 */ +		rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, BMASKBYTE0, 0x33); +		rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0x3); +		/* disable ad/da clock1,0x888 */ +		rtl_set_bbreg(hw, RFPGA0_ADDALLOCKEN, BIT(12) | BIT(13), 0); +	} +	for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; +	     rfpath++) { +		rtlphy->rfreg_chnlval[rfpath] = rtl_get_rfreg(hw, rfpath, +						RF_CHNLBW, BRFREGOFFSETMASK); +		rtlphy->reg_rf3c[rfpath] = rtl_get_rfreg(hw, rfpath, 0x3C, +			BRFREGOFFSETMASK); +	} +	for (i = 0; i < 2; i++) +		RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("RF 0x18 = 0x%x\n", +			  rtlphy->rfreg_chnlval[i])); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("<==\n")); + +} + +bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); +	u8 u1btmp; +	unsigned long flags; + +	if (rtlhal->macphymode == SINGLEMAC_SINGLEPHY) { +		u1btmp = rtl_read_byte(rtlpriv, REG_MAC0); +		rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON)); +		return true; +	} +	spin_lock_irqsave(&globalmutex_power, flags); +	if (rtlhal->interfaceindex == 0) { +		u1btmp = rtl_read_byte(rtlpriv, REG_MAC0); +		rtl_write_byte(rtlpriv, REG_MAC0, u1btmp & (~MAC0_ON)); +		u1btmp = rtl_read_byte(rtlpriv, REG_MAC1); +		u1btmp &= MAC1_ON; +	} else { +		u1btmp = rtl_read_byte(rtlpriv, REG_MAC1); +		rtl_write_byte(rtlpriv, REG_MAC1, u1btmp & (~MAC1_ON)); +		u1btmp = rtl_read_byte(rtlpriv, REG_MAC0); +		u1btmp &= MAC0_ON; +	} +	if (u1btmp) { +		spin_unlock_irqrestore(&globalmutex_power, flags); +		return false; +	} +	u1btmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS); +	u1btmp |= BIT(7); +	rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1btmp); +	spin_unlock_irqrestore(&globalmutex_power, flags); +	return true; +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.h b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h new file mode 100644 index 00000000000..a52c824b41e --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.h @@ -0,0 +1,178 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92D_PHY_H__ +#define __RTL92D_PHY_H__ + +#define MAX_PRECMD_CNT				16 +#define MAX_RFDEPENDCMD_CNT			16 +#define MAX_POSTCMD_CNT				16 + +#define MAX_DOZE_WAITING_TIMES_9x		64 + +#define RT_CANNOT_IO(hw)			false +#define HIGHPOWER_RADIOA_ARRAYLEN		22 + +#define IQK_ADDA_REG_NUM			16 +#define MAX_TOLERANCE				5 +#define	IQK_DELAY_TIME				1 + +#define	APK_BB_REG_NUM				5 +#define	APK_AFE_REG_NUM				16 +#define	APK_CURVE_REG_NUM			4 +#define	PATH_NUM				2 + +#define LOOP_LIMIT				5 +#define MAX_STALL_TIME				50 +#define ANTENNA_DIVERSITY_VALUE			0x80 +#define MAX_TXPWR_IDX_NMODE_92S			63 +#define RESET_CNT_LIMIT				3 + +#define IQK_ADDA_REG_NUM			16 +#define IQK_BB_REG_NUM				10 +#define IQK_BB_REG_NUM_test			6 +#define IQK_MAC_REG_NUM				4 +#define RX_INDEX_MAPPING_NUM			15 + +#define IQK_DELAY_TIME				1 + +#define CT_OFFSET_MAC_ADDR			0X16 + +#define CT_OFFSET_CCK_TX_PWR_IDX		0x5A +#define CT_OFFSET_HT401S_TX_PWR_IDX		0x60 +#define CT_OFFSET_HT402S_TX_PWR_IDX_DIFF	0x66 +#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF		0x69 +#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF		0x6C + +#define CT_OFFSET_HT40_MAX_PWR_OFFSET		0x6F +#define CT_OFFSET_HT20_MAX_PWR_OFFSET		0x72 + +#define CT_OFFSET_CHANNEL_PLAH			0x75 +#define CT_OFFSET_THERMAL_METER			0x78 +#define CT_OFFSET_RF_OPTION			0x79 +#define CT_OFFSET_VERSION			0x7E +#define CT_OFFSET_CUSTOMER_ID			0x7F + +enum swchnlcmd_id { +	CMDID_END, +	CMDID_SET_TXPOWEROWER_LEVEL, +	CMDID_BBREGWRITE10, +	CMDID_WRITEPORT_ULONG, +	CMDID_WRITEPORT_USHORT, +	CMDID_WRITEPORT_UCHAR, +	CMDID_RF_WRITEREG, +}; + +struct swchnlcmd { +	enum swchnlcmd_id cmdid; +	u32 para1; +	u32 para2; +	u32 msdelay; +}; + +enum baseband_config_type { +	BASEBAND_CONFIG_PHY_REG = 0, +	BASEBAND_CONFIG_AGC_TAB = 1, +}; + +enum rf_content { +	radioa_txt = 0, +	radiob_txt = 1, +	radioc_txt = 2, +	radiod_txt = 3 +}; + +static inline void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw, +						     unsigned long *flag) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	if (rtlpriv->rtlhal.interfaceindex == 1) +		spin_lock_irqsave(&rtlpriv->locks.cck_and_rw_pagea_lock, *flag); +} + +static inline void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw, +						     unsigned long *flag) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); + +	if (rtlpriv->rtlhal.interfaceindex == 1) +		spin_unlock_irqrestore(&rtlpriv->locks.cck_and_rw_pagea_lock, +			*flag); +} + +extern u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, +				   u32 regaddr, u32 bitmask); +extern void rtl92d_phy_set_bb_reg(struct ieee80211_hw *hw, +				  u32 regaddr, u32 bitmask, u32 data); +extern u32 rtl92d_phy_query_rf_reg(struct ieee80211_hw *hw, +				   enum radio_path rfpath, u32 regaddr, +				   u32 bitmask); +extern void rtl92d_phy_set_rf_reg(struct ieee80211_hw *hw, +				  enum radio_path rfpath, u32 regaddr, +				  u32 bitmask, u32 data); +extern bool rtl92d_phy_mac_config(struct ieee80211_hw *hw); +extern bool rtl92d_phy_bb_config(struct ieee80211_hw *hw); +extern bool rtl92d_phy_rf_config(struct ieee80211_hw *hw); +extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw, +						 enum radio_path rfpath); +extern void rtl92d_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); +extern void rtl92d_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel); +extern void rtl92d_phy_scan_operation_backup(struct ieee80211_hw *hw, +					     u8 operation); +extern void rtl92d_phy_set_bw_mode(struct ieee80211_hw *hw, +				   enum nl80211_channel_type ch_type); +extern u8 rtl92d_phy_sw_chnl(struct ieee80211_hw *hw); +bool rtl92d_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, +					  enum rf_content content, +					  enum radio_path rfpath); +bool rtl92d_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype); +extern bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, +					  enum rf_pwrstate rfpwr_state); + +void rtl92d_phy_config_macphymode(struct ieee80211_hw *hw); +void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw); +u8 rtl92d_get_chnlgroup_fromarray(u8 chnl); +void rtl92d_phy_set_poweron(struct ieee80211_hw *hw); +void rtl92d_phy_config_maccoexist_rfpage(struct ieee80211_hw *hw); +bool rtl92d_phy_check_poweroff(struct ieee80211_hw *hw); +void rtl92d_phy_lc_calibrate(struct ieee80211_hw *hw); +void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw); +void rtl92d_phy_ap_calibrate(struct ieee80211_hw *hw, char delta); +void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw); +void rtl92d_phy_reset_iqk_result(struct ieee80211_hw *hw); +void rtl92d_release_cckandrw_pagea_ctl(struct ieee80211_hw *hw, +				       unsigned long *flag); +void rtl92d_acquire_cckandrw_pagea_ctl(struct ieee80211_hw *hw, +				       unsigned long *flag); +u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl); +void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel); +void rtl92d_phy_iq_calibrate(struct ieee80211_hw *hw); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/reg.h b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h new file mode 100644 index 00000000000..131acc306fc --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/reg.h @@ -0,0 +1,1313 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92D_REG_H__ +#define __RTL92D_REG_H__ + +/* ----------------------------------------------------- */ +/* 0x0000h ~ 0x00FFh System Configuration */ +/* ----------------------------------------------------- */ +#define REG_SYS_ISO_CTRL		0x0000 +#define REG_SYS_FUNC_EN			0x0002 +#define REG_APS_FSMCO			0x0004 +#define REG_SYS_CLKR			0x0008 +#define REG_9346CR			0x000A +#define REG_EE_VPD			0x000C +#define REG_AFE_MISC			0x0010 +#define REG_SPS0_CTRL			0x0011 +#define REG_POWER_OFF_IN_PROCESS	0x0017 +#define REG_SPS_OCP_CFG			0x0018 +#define REG_RSV_CTRL			0x001C +#define REG_RF_CTRL			0x001F +#define REG_LDOA15_CTRL			0x0020 +#define REG_LDOV12D_CTRL		0x0021 +#define REG_LDOHCI12_CTRL		0x0022 +#define REG_LPLDO_CTRL			0x0023 +#define REG_AFE_XTAL_CTRL		0x0024 +#define REG_AFE_PLL_CTRL		0x0028 +/* for 92d, DMDP,SMSP,DMSP contrl */ +#define REG_MAC_PHY_CTRL		0x002c +#define REG_EFUSE_CTRL			0x0030 +#define REG_EFUSE_TEST			0x0034 +#define REG_PWR_DATA			0x0038 +#define REG_CAL_TIMER			0x003C +#define REG_ACLK_MON			0x003E +#define REG_GPIO_MUXCFG			0x0040 +#define REG_GPIO_IO_SEL			0x0042 +#define REG_MAC_PINMUX_CFG		0x0043 +#define REG_GPIO_PIN_CTRL		0x0044 +#define REG_GPIO_INTM			0x0048 +#define REG_LEDCFG0			0x004C +#define REG_LEDCFG1			0x004D +#define REG_LEDCFG2			0x004E +#define REG_LEDCFG3			0x004F +#define REG_FSIMR			0x0050 +#define REG_FSISR			0x0054 + +#define REG_MCUFWDL			0x0080 + +#define REG_HMEBOX_EXT_0		0x0088 +#define REG_HMEBOX_EXT_1		0x008A +#define REG_HMEBOX_EXT_2		0x008C +#define REG_HMEBOX_EXT_3		0x008E + +#define REG_BIST_SCAN			0x00D0 +#define REG_BIST_RPT			0x00D4 +#define REG_BIST_ROM_RPT		0x00D8 +#define REG_USB_SIE_INTF		0x00E0 +#define REG_PCIE_MIO_INTF		0x00E4 +#define REG_PCIE_MIO_INTD		0x00E8 +#define REG_HPON_FSM			0x00EC +#define REG_SYS_CFG			0x00F0 +#define REG_MAC_PHY_CTRL_NORMAL		0x00f8 + +#define  REG_MAC0			0x0081 +#define  REG_MAC1			0x0053 +#define  FW_MAC0_READY			0x18 +#define  FW_MAC1_READY			0x1A +#define  MAC0_ON			BIT(7) +#define  MAC1_ON			BIT(0) +#define  MAC0_READY			BIT(0) +#define  MAC1_READY			BIT(0) + +/* ----------------------------------------------------- */ +/* 0x0100h ~ 0x01FFh	MACTOP General Configuration */ +/* ----------------------------------------------------- */ +#define REG_CR				0x0100 +#define REG_PBP				0x0104 +#define REG_TRXDMA_CTRL			0x010C +#define REG_TRXFF_BNDY			0x0114 +#define REG_TRXFF_STATUS		0x0118 +#define REG_RXFF_PTR			0x011C +#define REG_HIMR			0x0120 +#define REG_HISR			0x0124 +#define REG_HIMRE			0x0128 +#define REG_HISRE			0x012C +#define REG_CPWM			0x012F +#define REG_FWIMR			0x0130 +#define REG_FWISR			0x0134 +#define REG_PKTBUF_DBG_CTRL		0x0140 +#define REG_PKTBUF_DBG_DATA_L		0x0144 +#define REG_PKTBUF_DBG_DATA_H		0x0148 + +#define REG_TC0_CTRL			0x0150 +#define REG_TC1_CTRL			0x0154 +#define REG_TC2_CTRL			0x0158 +#define REG_TC3_CTRL			0x015C +#define REG_TC4_CTRL			0x0160 +#define REG_TCUNIT_BASE			0x0164 +#define REG_MBIST_START			0x0174 +#define REG_MBIST_DONE			0x0178 +#define REG_MBIST_FAIL			0x017C +#define REG_C2HEVT_MSG_NORMAL		0x01A0 +#define REG_C2HEVT_MSG_TEST		0x01B8 +#define REG_C2HEVT_CLEAR		0x01BF +#define REG_MCUTST_1			0x01c0 +#define REG_FMETHR			0x01C8 +#define REG_HMETFR			0x01CC +#define REG_HMEBOX_0			0x01D0 +#define REG_HMEBOX_1			0x01D4 +#define REG_HMEBOX_2			0x01D8 +#define REG_HMEBOX_3			0x01DC + +#define REG_LLT_INIT			0x01E0 +#define REG_BB_ACCEESS_CTRL		0x01E8 +#define REG_BB_ACCESS_DATA		0x01EC + + +/* ----------------------------------------------------- */ +/*	0x0200h ~ 0x027Fh	TXDMA Configuration */ +/* ----------------------------------------------------- */ +#define REG_RQPN			0x0200 +#define REG_FIFOPAGE			0x0204 +#define REG_TDECTRL			0x0208 +#define REG_TXDMA_OFFSET_CHK		0x020C +#define REG_TXDMA_STATUS		0x0210 +#define REG_RQPN_NPQ			0x0214 + +/* ----------------------------------------------------- */ +/*	0x0280h ~ 0x02FFh	RXDMA Configuration */ +/* ----------------------------------------------------- */ +#define REG_RXDMA_AGG_PG_TH		0x0280 +#define REG_RXPKT_NUM			0x0284 +#define REG_RXDMA_STATUS		0x0288 + +/* ----------------------------------------------------- */ +/*	0x0300h ~ 0x03FFh	PCIe  */ +/* ----------------------------------------------------- */ +#define	REG_PCIE_CTRL_REG		0x0300 +#define	REG_INT_MIG			0x0304 +#define	REG_BCNQ_DESA			0x0308 +#define	REG_HQ_DESA			0x0310 +#define	REG_MGQ_DESA			0x0318 +#define	REG_VOQ_DESA			0x0320 +#define	REG_VIQ_DESA			0x0328 +#define	REG_BEQ_DESA			0x0330 +#define	REG_BKQ_DESA			0x0338 +#define	REG_RX_DESA			0x0340 +#define	REG_DBI				0x0348 +#define	REG_DBI_WDATA			0x0348 +#define REG_DBI_RDATA			0x034C +#define REG_DBI_CTRL			0x0350 +#define REG_DBI_FLAG			0x0352 +#define	REG_MDIO			0x0354 +#define	REG_DBG_SEL			0x0360 +#define	REG_PCIE_HRPWM			0x0361 +#define	REG_PCIE_HCPWM			0x0363 +#define	REG_UART_CTRL			0x0364 +#define	REG_UART_TX_DESA		0x0370 +#define	REG_UART_RX_DESA		0x0378 + +/* ----------------------------------------------------- */ +/*	0x0400h ~ 0x047Fh	Protocol Configuration  */ +/* ----------------------------------------------------- */ +#define REG_VOQ_INFORMATION		0x0400 +#define REG_VIQ_INFORMATION		0x0404 +#define REG_BEQ_INFORMATION		0x0408 +#define REG_BKQ_INFORMATION		0x040C +#define REG_MGQ_INFORMATION		0x0410 +#define REG_HGQ_INFORMATION		0x0414 +#define REG_BCNQ_INFORMATION		0x0418 + + +#define REG_CPU_MGQ_INFORMATION		0x041C +#define REG_FWHW_TXQ_CTRL		0x0420 +#define REG_HWSEQ_CTRL			0x0423 +#define REG_TXPKTBUF_BCNQ_BDNY		0x0424 +#define REG_TXPKTBUF_MGQ_BDNY		0x0425 +#define REG_MULTI_BCNQ_EN		0x0426 +#define REG_MULTI_BCNQ_OFFSET		0x0427 +#define REG_SPEC_SIFS			0x0428 +#define REG_RL				0x042A +#define REG_DARFRC			0x0430 +#define REG_RARFRC			0x0438 +#define REG_RRSR			0x0440 +#define REG_ARFR0			0x0444 +#define REG_ARFR1			0x0448 +#define REG_ARFR2			0x044C +#define REG_ARFR3			0x0450 +#define REG_AGGLEN_LMT			0x0458 +#define REG_AMPDU_MIN_SPACE		0x045C +#define REG_TXPKTBUF_WMAC_LBK_BF_HD	0x045D +#define REG_FAST_EDCA_CTRL		0x0460 +#define REG_RD_RESP_PKT_TH		0x0463 +#define REG_INIRTS_RATE_SEL		0x0480 +#define REG_INIDATA_RATE_SEL		0x0484 +#define REG_POWER_STATUS		0x04A4 +#define REG_POWER_STAGE1		0x04B4 +#define REG_POWER_STAGE2		0x04B8 +#define REG_PKT_LIFE_TIME		0x04C0 +#define REG_STBC_SETTING		0x04C4 +#define REG_PROT_MODE_CTRL		0x04C8 +#define REG_MAX_AGGR_NUM		0x04CA +#define REG_RTS_MAX_AGGR_NUM		0x04CB +#define REG_BAR_MODE_CTRL		0x04CC +#define REG_RA_TRY_RATE_AGG_LMT		0x04CF +#define REG_EARLY_MODE_CONTROL		0x4D0 +#define REG_NQOS_SEQ			0x04DC +#define REG_QOS_SEQ			0x04DE +#define REG_NEED_CPU_HANDLE		0x04E0 +#define REG_PKT_LOSE_RPT		0x04E1 +#define REG_PTCL_ERR_STATUS		0x04E2 +#define REG_DUMMY			0x04FC + +/* ----------------------------------------------------- */ +/*	0x0500h ~ 0x05FFh	EDCA Configuration   */ +/* ----------------------------------------------------- */ +#define REG_EDCA_VO_PARAM		0x0500 +#define REG_EDCA_VI_PARAM		0x0504 +#define REG_EDCA_BE_PARAM		0x0508 +#define REG_EDCA_BK_PARAM		0x050C +#define REG_BCNTCFG			0x0510 +#define REG_PIFS			0x0512 +#define REG_RDG_PIFS			0x0513 +#define REG_SIFS_CTX			0x0514 +#define REG_SIFS_TRX			0x0516 +#define REG_AGGR_BREAK_TIME		0x051A +#define REG_SLOT			0x051B +#define REG_TX_PTCL_CTRL		0x0520 +#define REG_TXPAUSE			0x0522 +#define REG_DIS_TXREQ_CLR		0x0523 +#define REG_RD_CTRL			0x0524 +#define REG_TBTT_PROHIBIT		0x0540 +#define REG_RD_NAV_NXT			0x0544 +#define REG_NAV_PROT_LEN		0x0546 +#define REG_BCN_CTRL			0x0550 +#define REG_USTIME_TSF			0x0551 +#define REG_MBID_NUM			0x0552 +#define REG_DUAL_TSF_RST		0x0553 +#define REG_BCN_INTERVAL		0x0554 +#define REG_MBSSID_BCN_SPACE		0x0554 +#define REG_DRVERLYINT			0x0558 +#define REG_BCNDMATIM			0x0559 +#define REG_ATIMWND			0x055A +#define REG_BCN_MAX_ERR			0x055D +#define REG_RXTSF_OFFSET_CCK		0x055E +#define REG_RXTSF_OFFSET_OFDM		0x055F +#define REG_TSFTR			0x0560 +#define REG_INIT_TSFTR			0x0564 +#define REG_PSTIMER			0x0580 +#define REG_TIMER0			0x0584 +#define REG_TIMER1			0x0588 +#define REG_ACMHWCTRL			0x05C0 +#define REG_ACMRSTCTRL			0x05C1 +#define REG_ACMAVG			0x05C2 +#define REG_VO_ADMTIME			0x05C4 +#define REG_VI_ADMTIME			0x05C6 +#define REG_BE_ADMTIME			0x05C8 +#define REG_EDCA_RANDOM_GEN		0x05CC +#define REG_SCH_TXCMD			0x05D0 + +/* Dual MAC Co-Existence Register  */ +#define REG_DMC				0x05F0 + +/* ----------------------------------------------------- */ +/*	0x0600h ~ 0x07FFh	WMAC Configuration */ +/* ----------------------------------------------------- */ +#define REG_APSD_CTRL			0x0600 +#define REG_BWOPMODE			0x0603 +#define REG_TCR				0x0604 +#define REG_RCR				0x0608 +#define REG_RX_PKT_LIMIT		0x060C +#define REG_RX_DLK_TIME			0x060D +#define REG_RX_DRVINFO_SZ		0x060F + +#define REG_MACID			0x0610 +#define REG_BSSID			0x0618 +#define REG_MAR				0x0620 +#define REG_MBIDCAMCFG			0x0628 + +#define REG_USTIME_EDCA			0x0638 +#define REG_MAC_SPEC_SIFS		0x063A +#define REG_RESP_SIFS_CCK		0x063C +#define REG_RESP_SIFS_OFDM		0x063E +#define REG_ACKTO			0x0640 +#define REG_CTS2TO			0x0641 +#define REG_EIFS			0x0642 + + +/* WMA, BA, CCX */ +#define REG_NAV_CTRL			0x0650 +#define REG_BACAMCMD			0x0654 +#define REG_BACAMCONTENT		0x0658 +#define REG_LBDLY			0x0660 +#define REG_FWDLY			0x0661 +#define REG_RXERR_RPT			0x0664 +#define REG_WMAC_TRXPTCL_CTL		0x0668 + + +/* Security  */ +#define REG_CAMCMD			0x0670 +#define REG_CAMWRITE			0x0674 +#define REG_CAMREAD			0x0678 +#define REG_CAMDBG			0x067C +#define REG_SECCFG			0x0680 + +/* Power  */ +#define REG_WOW_CTRL			0x0690 +#define REG_PSSTATUS			0x0691 +#define REG_PS_RX_INFO			0x0692 +#define REG_LPNAV_CTRL			0x0694 +#define REG_WKFMCAM_CMD			0x0698 +#define REG_WKFMCAM_RWD			0x069C +#define REG_RXFLTMAP0			0x06A0 +#define REG_RXFLTMAP1			0x06A2 +#define REG_RXFLTMAP2			0x06A4 +#define REG_BCN_PSR_RPT			0x06A8 +#define REG_CALB32K_CTRL		0x06AC +#define REG_PKT_MON_CTRL		0x06B4 +#define REG_BT_COEX_TABLE		0x06C0 +#define REG_WMAC_RESP_TXINFO		0x06D8 + + +/* ----------------------------------------------------- */ +/*	Redifine 8192C register definition for compatibility */ +/* ----------------------------------------------------- */ +#define	CR9346				REG_9346CR +#define	MSR				(REG_CR + 2) +#define	ISR				REG_HISR +#define	TSFR				REG_TSFTR + +#define	MACIDR0				REG_MACID +#define	MACIDR4				(REG_MACID + 4) + +#define PBP				REG_PBP + +#define	IDR0				MACIDR0 +#define	IDR4				MACIDR4 + +/* ----------------------------------------------------- */ +/* 8192C (MSR) Media Status Register(Offset 0x4C, 8 bits)*/ +/* ----------------------------------------------------- */ +#define	MSR_NOLINK			0x00 +#define	MSR_ADHOC			0x01 +#define	MSR_INFRA			0x02 +#define	MSR_AP				0x03 + +/* 6. Adaptive Control Registers  (Offset: 0x0160 - 0x01CF) */ +/* ----------------------------------------------------- */ +/* 8192C Response Rate Set Register(offset 0x181, 24bits)*/ +/* ----------------------------------------------------- */ +#define	RRSR_RSC_OFFSET			21 +#define	RRSR_SHORT_OFFSET		23 +#define	RRSR_RSC_BW_40M			0x600000 +#define	RRSR_RSC_UPSUBCHNL		0x400000 +#define	RRSR_RSC_LOWSUBCHNL		0x200000 +#define	RRSR_SHORT			0x800000 +#define	RRSR_1M				BIT0 +#define	RRSR_2M				BIT1 +#define	RRSR_5_5M			BIT2 +#define	RRSR_11M			BIT3 +#define	RRSR_6M				BIT4 +#define	RRSR_9M				BIT5 +#define	RRSR_12M			BIT6 +#define	RRSR_18M			BIT7 +#define	RRSR_24M			BIT8 +#define	RRSR_36M			BIT9 +#define	RRSR_48M			BIT10 +#define	RRSR_54M			BIT11 +#define	RRSR_MCS0			BIT12 +#define	RRSR_MCS1			BIT13 +#define	RRSR_MCS2			BIT14 +#define	RRSR_MCS3			BIT15 +#define	RRSR_MCS4			BIT16 +#define	RRSR_MCS5			BIT17 +#define	RRSR_MCS6			BIT18 +#define	RRSR_MCS7			BIT19 +#define	BRSR_ACKSHORTPMB		BIT23 + +/* ----------------------------------------------------- */ +/*       8192C Rate Definition  */ +/* ----------------------------------------------------- */ +/* CCK */ +#define	RATR_1M				0x00000001 +#define	RATR_2M				0x00000002 +#define	RATR_55M			0x00000004 +#define	RATR_11M			0x00000008 +/* OFDM */ +#define	RATR_6M				0x00000010 +#define	RATR_9M				0x00000020 +#define	RATR_12M			0x00000040 +#define	RATR_18M			0x00000080 +#define	RATR_24M			0x00000100 +#define	RATR_36M			0x00000200 +#define	RATR_48M			0x00000400 +#define	RATR_54M			0x00000800 +/* MCS 1 Spatial Stream	*/ +#define	RATR_MCS0			0x00001000 +#define	RATR_MCS1			0x00002000 +#define	RATR_MCS2			0x00004000 +#define	RATR_MCS3			0x00008000 +#define	RATR_MCS4			0x00010000 +#define	RATR_MCS5			0x00020000 +#define	RATR_MCS6			0x00040000 +#define	RATR_MCS7			0x00080000 +/* MCS 2 Spatial Stream */ +#define	RATR_MCS8			0x00100000 +#define	RATR_MCS9			0x00200000 +#define	RATR_MCS10			0x00400000 +#define	RATR_MCS11			0x00800000 +#define	RATR_MCS12			0x01000000 +#define	RATR_MCS13			0x02000000 +#define	RATR_MCS14			0x04000000 +#define	RATR_MCS15			0x08000000 + +/* CCK */ +#define RATE_1M				BIT(0) +#define RATE_2M				BIT(1) +#define RATE_5_5M			BIT(2) +#define RATE_11M			BIT(3) +/* OFDM  */ +#define RATE_6M				BIT(4) +#define RATE_9M				BIT(5) +#define RATE_12M			BIT(6) +#define RATE_18M			BIT(7) +#define RATE_24M			BIT(8) +#define RATE_36M			BIT(9) +#define RATE_48M			BIT(10) +#define RATE_54M			BIT(11) +/* MCS 1 Spatial Stream */ +#define RATE_MCS0			BIT(12) +#define RATE_MCS1			BIT(13) +#define RATE_MCS2			BIT(14) +#define RATE_MCS3			BIT(15) +#define RATE_MCS4			BIT(16) +#define RATE_MCS5			BIT(17) +#define RATE_MCS6			BIT(18) +#define RATE_MCS7			BIT(19) +/* MCS 2 Spatial Stream */ +#define RATE_MCS8			BIT(20) +#define RATE_MCS9			BIT(21) +#define RATE_MCS10			BIT(22) +#define RATE_MCS11			BIT(23) +#define RATE_MCS12			BIT(24) +#define RATE_MCS13			BIT(25) +#define RATE_MCS14			BIT(26) +#define RATE_MCS15			BIT(27) + +/* ALL CCK Rate */ +#define	RATE_ALL_CCK			(RATR_1M | RATR_2M | RATR_55M | \ +					RATR_11M) +#define	RATE_ALL_OFDM_AG		(RATR_6M | RATR_9M | RATR_12M | \ +					RATR_18M | RATR_24M | \ +					RATR_36M | RATR_48M | RATR_54M) +#define	RATE_ALL_OFDM_1SS		(RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \ +					RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \ +					RATR_MCS6 | RATR_MCS7) +#define	RATE_ALL_OFDM_2SS		(RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \ +					RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \ +					RATR_MCS14 | RATR_MCS15) + +/* ----------------------------------------------------- */ +/*    8192C BW_OPMODE bits		(Offset 0x203, 8bit)     */ +/* ----------------------------------------------------- */ +#define	BW_OPMODE_20MHZ			BIT(2) +#define	BW_OPMODE_5G			BIT(1) +#define	BW_OPMODE_11J			BIT(0) + + +/* ----------------------------------------------------- */ +/*     8192C CAM Config Setting (offset 0x250, 1 byte)   */ +/* ----------------------------------------------------- */ +#define	CAM_VALID			BIT(15) +#define	CAM_NOTVALID			0x0000 +#define	CAM_USEDK			BIT(5) + +#define	CAM_NONE			0x0 +#define	CAM_WEP40			0x01 +#define	CAM_TKIP			0x02 +#define	CAM_AES				0x04 +#define	CAM_WEP104			0x05 +#define	CAM_SMS4			0x6 + + +#define	TOTAL_CAM_ENTRY			32 +#define	HALF_CAM_ENTRY			16 + +#define	CAM_WRITE			BIT(16) +#define	CAM_READ			0x00000000 +#define	CAM_POLLINIG			BIT(31) + +/* 10. Power Save Control Registers	 (Offset: 0x0260 - 0x02DF) */ +#define	WOW_PMEN			BIT0 /* Power management Enable. */ +#define	WOW_WOMEN			BIT1 /* WoW function on or off. */ +#define	WOW_MAGIC			BIT2 /* Magic packet */ +#define	WOW_UWF				BIT3 /* Unicast Wakeup frame. */ + +/* 12. Host Interrupt Status Registers	 (Offset: 0x0300 - 0x030F) */ +/* ----------------------------------------------------- */ +/*      8190 IMR/ISR bits	(offset 0xfd,  8bits) */ +/* ----------------------------------------------------- */ +#define	IMR8190_DISABLED		0x0 +#define	IMR_BCNDMAINT6			BIT(31) +#define	IMR_BCNDMAINT5			BIT(30) +#define	IMR_BCNDMAINT4			BIT(29) +#define	IMR_BCNDMAINT3			BIT(28) +#define	IMR_BCNDMAINT2			BIT(27) +#define	IMR_BCNDMAINT1			BIT(26) +#define	IMR_BCNDOK8			BIT(25) +#define	IMR_BCNDOK7			BIT(24) +#define	IMR_BCNDOK6			BIT(23) +#define	IMR_BCNDOK5			BIT(22) +#define	IMR_BCNDOK4			BIT(21) +#define	IMR_BCNDOK3			BIT(20) +#define	IMR_BCNDOK2			BIT(19) +#define	IMR_BCNDOK1			BIT(18) +#define	IMR_TIMEOUT2			BIT(17) +#define	IMR_TIMEOUT1			BIT(16) +#define	IMR_TXFOVW			BIT(15) +#define	IMR_PSTIMEOUT			BIT(14) +#define	IMR_BcnInt			BIT(13) +#define	IMR_RXFOVW			BIT(12) +#define	IMR_RDU				BIT(11) +#define	IMR_ATIMEND			BIT(10) +#define	IMR_BDOK			BIT(9) +#define	IMR_HIGHDOK			BIT(8) +#define	IMR_TBDOK			BIT(7) +#define	IMR_MGNTDOK			BIT(6) +#define	IMR_TBDER			BIT(5) +#define	IMR_BKDOK			BIT(4) +#define	IMR_BEDOK			BIT(3) +#define	IMR_VIDOK			BIT(2) +#define	IMR_VODOK			BIT(1) +#define	IMR_ROK				BIT(0) + +#define	IMR_TXERR			BIT(11) +#define	IMR_RXERR			BIT(10) +#define	IMR_C2HCMD			BIT(9) +#define	IMR_CPWM			BIT(8) +#define	IMR_OCPINT			BIT(1) +#define	IMR_WLANOFF			BIT(0) + +/* ----------------------------------------------------- */ +/* 8192C EFUSE */ +/* ----------------------------------------------------- */ +#define	HWSET_MAX_SIZE			256 +#define EFUSE_MAX_SECTION		32 +#define EFUSE_REAL_CONTENT_LEN		512 + +/* ----------------------------------------------------- */ +/*     8192C EEPROM/EFUSE share register definition. */ +/* ----------------------------------------------------- */ +#define	EEPROM_DEFAULT_TSSI			0x0 +#define EEPROM_DEFAULT_CRYSTALCAP		0x0 +#define	EEPROM_DEFAULT_THERMALMETER		0x12 + +#define	EEPROM_DEFAULT_TXPOWERLEVEL_2G		0x2C +#define	EEPROM_DEFAULT_TXPOWERLEVEL_5G		0x22 + +#define	EEPROM_DEFAULT_HT40_2SDIFF		0x0 +/* HT20<->40 default Tx Power Index Difference */ +#define EEPROM_DEFAULT_HT20_DIFF		2 +/* OFDM Tx Power index diff */ +#define	EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF	0x4 +#define EEPROM_DEFAULT_HT40_PWRMAXOFFSET	0 +#define EEPROM_DEFAULT_HT20_PWRMAXOFFSET	0 + +#define	EEPROM_CHANNEL_PLAN_FCC			0x0 +#define	EEPROM_CHANNEL_PLAN_IC			0x1 +#define	EEPROM_CHANNEL_PLAN_ETSI		0x2 +#define	EEPROM_CHANNEL_PLAN_SPAIN		0x3 +#define	EEPROM_CHANNEL_PLAN_FRANCE		0x4 +#define	EEPROM_CHANNEL_PLAN_MKK			0x5 +#define	EEPROM_CHANNEL_PLAN_MKK1		0x6 +#define	EEPROM_CHANNEL_PLAN_ISRAEL		0x7 +#define	EEPROM_CHANNEL_PLAN_TELEC		0x8 +#define	EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN	0x9 +#define	EEPROM_CHANNEL_PLAN_WORLD_WIDE_13	0xA +#define	EEPROM_CHANNEL_PLAN_NCC			0xB +#define	EEPROM_CHANNEL_PLAN_BY_HW_MASK		0x80 + +#define EEPROM_CID_DEFAULT			0x0 +#define EEPROM_CID_TOSHIBA			0x4 +#define	EEPROM_CID_CCX				0x10 +#define	EEPROM_CID_QMI				0x0D +#define EEPROM_CID_WHQL				0xFE + + +#define	RTL8192_EEPROM_ID			0x8129 +#define	EEPROM_WAPI_SUPPORT			0x78 + + +#define RTL8190_EEPROM_ID		0x8129	/* 0-1 */ +#define EEPROM_HPON			0x02 /* LDO settings.2-5 */ +#define EEPROM_CLK			0x06 /* Clock settings.6-7 */ +#define EEPROM_MAC_FUNCTION		0x08 /* SE Test mode.8 */ + +#define EEPROM_VID			0x28 /* SE Vendor ID.A-B */ +#define EEPROM_DID			0x2A /* SE Device ID. C-D */ +#define EEPROM_SVID			0x2C /* SE Vendor ID.E-F */ +#define EEPROM_SMID			0x2E /* SE PCI Subsystem ID. 10-11 */ + +#define EEPROM_MAC_ADDR			0x16 /* SEMAC Address. 12-17 */ +#define EEPROM_MAC_ADDR_MAC0_92D	0x55 +#define EEPROM_MAC_ADDR_MAC1_92D	0x5B + +/* 2.4G band Tx power index setting */ +#define EEPROM_CCK_TX_PWR_INX_2G	0x61 +#define EEPROM_HT40_1S_TX_PWR_INX_2G	0x67 +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_2G	0x6D +#define EEPROM_HT20_TX_PWR_INX_DIFF_2G		0x70 +#define EEPROM_OFDM_TX_PWR_INX_DIFF_2G		0x73 +#define EEPROM_HT40_MAX_PWR_OFFSET_2G		0x76 +#define EEPROM_HT20_MAX_PWR_OFFSET_2G		0x79 + +/*5GL channel 32-64 */ +#define EEPROM_HT40_1S_TX_PWR_INX_5GL		0x7C +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GL	0x82 +#define EEPROM_HT20_TX_PWR_INX_DIFF_5GL		0x85 +#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GL		0x88 +#define EEPROM_HT40_MAX_PWR_OFFSET_5GL		0x8B +#define EEPROM_HT20_MAX_PWR_OFFSET_5GL		0x8E + +/* 5GM channel 100-140 */ +#define EEPROM_HT40_1S_TX_PWR_INX_5GM		0x91 +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GM	0x97 +#define EEPROM_HT20_TX_PWR_INX_DIFF_5GM		0x9A +#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GM		0x9D +#define EEPROM_HT40_MAX_PWR_OFFSET_5GM		0xA0 +#define EEPROM_HT20_MAX_PWR_OFFSET_5GM		0xA3 + +/* 5GH channel 149-165 */ +#define EEPROM_HT40_1S_TX_PWR_INX_5GH		0xA6 +#define EEPROM_HT40_2S_TX_PWR_INX_DIFF_5GH	0xAC +#define EEPROM_HT20_TX_PWR_INX_DIFF_5GH		0xAF +#define EEPROM_OFDM_TX_PWR_INX_DIFF_5GH		0xB2 +#define EEPROM_HT40_MAX_PWR_OFFSET_5GH		0xB5 +#define EEPROM_HT20_MAX_PWR_OFFSET_5GH		0xB8 + +/* Map of supported channels. */ +#define EEPROM_CHANNEL_PLAN			0xBB +#define EEPROM_IQK_DELTA			0xBC +#define EEPROM_LCK_DELTA			0xBC +#define EEPROM_XTAL_K				0xBD	/* [7:5] */ +#define EEPROM_TSSI_A_5G			0xBE +#define EEPROM_TSSI_B_5G			0xBF +#define EEPROM_TSSI_AB_5G			0xC0 +#define EEPROM_THERMAL_METER			0xC3	/* [4:0] */ +#define EEPROM_RF_OPT1				0xC4 +#define EEPROM_RF_OPT2				0xC5 +#define EEPROM_RF_OPT3				0xC6 +#define EEPROM_RF_OPT4				0xC7 +#define EEPROM_RF_OPT5				0xC8 +#define EEPROM_RF_OPT6				0xC9 +#define EEPROM_VERSION				0xCA +#define EEPROM_CUSTOMER_ID			0xCB +#define EEPROM_RF_OPT7				0xCC + +#define EEPROM_DEF_PART_NO			0x3FD    /* Byte */ +#define EEPROME_CHIP_VERSION_L			0x3FF +#define EEPROME_CHIP_VERSION_H			0x3FE + +/* + * Current IOREG MAP + * 0x0000h ~ 0x00FFh   System Configuration (256 Bytes) + * 0x0100h ~ 0x01FFh   MACTOP General Configuration (256 Bytes) + * 0x0200h ~ 0x027Fh   TXDMA Configuration (128 Bytes) + * 0x0280h ~ 0x02FFh   RXDMA Configuration (128 Bytes) + * 0x0300h ~ 0x03FFh   PCIE EMAC Reserved Region (256 Bytes) + * 0x0400h ~ 0x04FFh   Protocol Configuration (256 Bytes) + * 0x0500h ~ 0x05FFh   EDCA Configuration (256 Bytes) + * 0x0600h ~ 0x07FFh   WMAC Configuration (512 Bytes) + * 0x2000h ~ 0x3FFFh   8051 FW Download Region (8196 Bytes) + */ + +/* ----------------------------------------------------- */ +/* 8192C (RCR)	(Offset 0x608, 32 bits) */ +/* ----------------------------------------------------- */ +#define	RCR_APPFCS				BIT(31) +#define	RCR_APP_MIC				BIT(30) +#define	RCR_APP_ICV				BIT(29) +#define	RCR_APP_PHYST_RXFF			BIT(28) +#define	RCR_APP_BA_SSN				BIT(27) +#define	RCR_ENMBID				BIT(24) +#define	RCR_LSIGEN				BIT(23) +#define	RCR_MFBEN				BIT(22) +#define	RCR_HTC_LOC_CTRL			BIT(14) +#define	RCR_AMF					BIT(13) +#define	RCR_ACF					BIT(12) +#define	RCR_ADF					BIT(11) +#define	RCR_AICV				BIT(9) +#define	RCR_ACRC32				BIT(8) +#define	RCR_CBSSID_BCN				BIT(7) +#define	RCR_CBSSID_DATA				BIT(6) +#define	RCR_APWRMGT				BIT(5) +#define	RCR_ADD3				BIT(4) +#define	RCR_AB					BIT(3) +#define	RCR_AM					BIT(2) +#define	RCR_APM					BIT(1) +#define	RCR_AAP					BIT(0) +#define	RCR_MXDMA_OFFSET			8 +#define	RCR_FIFO_OFFSET				13 + +/* ----------------------------------------------------- */ +/*       8192C Regsiter Bit and Content definition	 */ +/* ----------------------------------------------------- */ +/* ----------------------------------------------------- */ +/*	0x0000h ~ 0x00FFh	System Configuration */ +/* ----------------------------------------------------- */ + +/* SPS0_CTRL */ +#define SW18_FPWM				BIT(3) + + +/* SYS_ISO_CTRL */ +#define ISO_MD2PP				BIT(0) +#define ISO_UA2USB				BIT(1) +#define ISO_UD2CORE				BIT(2) +#define ISO_PA2PCIE				BIT(3) +#define ISO_PD2CORE				BIT(4) +#define ISO_IP2MAC				BIT(5) +#define ISO_DIOP				BIT(6) +#define ISO_DIOE				BIT(7) +#define ISO_EB2CORE				BIT(8) +#define ISO_DIOR				BIT(9) + +#define PWC_EV25V				BIT(14) +#define PWC_EV12V				BIT(15) + + +/* SYS_FUNC_EN */ +#define FEN_BBRSTB				BIT(0) +#define FEN_BB_GLB_RSTn				BIT(1) +#define FEN_USBA				BIT(2) +#define FEN_UPLL				BIT(3) +#define FEN_USBD				BIT(4) +#define FEN_DIO_PCIE				BIT(5) +#define FEN_PCIEA				BIT(6) +#define FEN_PPLL				BIT(7) +#define FEN_PCIED				BIT(8) +#define FEN_DIOE				BIT(9) +#define FEN_CPUEN				BIT(10) +#define FEN_DCORE				BIT(11) +#define FEN_ELDR				BIT(12) +#define FEN_DIO_RF				BIT(13) +#define FEN_HWPDN				BIT(14) +#define FEN_MREGEN				BIT(15) + +/* APS_FSMCO */ +#define PFM_LDALL				BIT(0) +#define PFM_ALDN				BIT(1) +#define PFM_LDKP				BIT(2) +#define PFM_WOWL				BIT(3) +#define EnPDN					BIT(4) +#define PDN_PL					BIT(5) +#define APFM_ONMAC				BIT(8) +#define APFM_OFF				BIT(9) +#define APFM_RSM				BIT(10) +#define AFSM_HSUS				BIT(11) +#define AFSM_PCIE				BIT(12) +#define APDM_MAC				BIT(13) +#define APDM_HOST				BIT(14) +#define APDM_HPDN				BIT(15) +#define RDY_MACON				BIT(16) +#define SUS_HOST				BIT(17) +#define ROP_ALD					BIT(20) +#define ROP_PWR					BIT(21) +#define ROP_SPS					BIT(22) +#define SOP_MRST				BIT(25) +#define SOP_FUSE				BIT(26) +#define SOP_ABG					BIT(27) +#define SOP_AMB					BIT(28) +#define SOP_RCK					BIT(29) +#define SOP_A8M					BIT(30) +#define XOP_BTCK				BIT(31) + +/* SYS_CLKR */ +#define ANAD16V_EN				BIT(0) +#define ANA8M					BIT(1) +#define MACSLP					BIT(4) +#define LOADER_CLK_EN				BIT(5) +#define _80M_SSC_DIS				BIT(7) +#define _80M_SSC_EN_HO				BIT(8) +#define PHY_SSC_RSTB				BIT(9) +#define SEC_CLK_EN				BIT(10) +#define MAC_CLK_EN				BIT(11) +#define SYS_CLK_EN				BIT(12) +#define RING_CLK_EN				BIT(13) + + +/* 9346CR */ +#define	BOOT_FROM_EEPROM			BIT(4) +#define	EEPROM_EN				BIT(5) + +/* AFE_MISC */ +#define AFE_BGEN				BIT(0) +#define AFE_MBEN				BIT(1) +#define MAC_ID_EN				BIT(7) + +/* RSV_CTRL */ +#define WLOCK_ALL				BIT(0) +#define WLOCK_00				BIT(1) +#define WLOCK_04				BIT(2) +#define WLOCK_08				BIT(3) +#define WLOCK_40				BIT(4) +#define R_DIS_PRST_0				BIT(5) +#define R_DIS_PRST_1				BIT(6) +#define LOCK_ALL_EN				BIT(7) + +/* RF_CTRL */ +#define RF_EN					BIT(0) +#define RF_RSTB					BIT(1) +#define RF_SDMRSTB				BIT(2) + + + +/* LDOA15_CTRL */ +#define LDA15_EN				BIT(0) +#define LDA15_STBY				BIT(1) +#define LDA15_OBUF				BIT(2) +#define LDA15_REG_VOS				BIT(3) +#define _LDA15_VOADJ(x)				(((x) & 0x7) << 4) + + + +/* LDOV12D_CTRL */ +#define LDV12_EN				BIT(0) +#define LDV12_SDBY				BIT(1) +#define LPLDO_HSM				BIT(2) +#define LPLDO_LSM_DIS				BIT(3) +#define _LDV12_VADJ(x)				(((x) & 0xF) << 4) + + +/* AFE_XTAL_CTRL */ +#define XTAL_EN					BIT(0) +#define XTAL_BSEL				BIT(1) +#define _XTAL_BOSC(x)				(((x) & 0x3) << 2) +#define _XTAL_CADJ(x)				(((x) & 0xF) << 4) +#define XTAL_GATE_USB				BIT(8) +#define _XTAL_USB_DRV(x)			(((x) & 0x3) << 9) +#define XTAL_GATE_AFE				BIT(11) +#define _XTAL_AFE_DRV(x)			(((x) & 0x3) << 12) +#define XTAL_RF_GATE				BIT(14) +#define _XTAL_RF_DRV(x)				(((x) & 0x3) << 15) +#define XTAL_GATE_DIG				BIT(17) +#define _XTAL_DIG_DRV(x)			(((x) & 0x3) << 18) +#define XTAL_BT_GATE				BIT(20) +#define _XTAL_BT_DRV(x)				(((x) & 0x3) << 21) +#define _XTAL_GPIO(x)				(((x) & 0x7) << 23) + + +#define CKDLY_AFE				BIT(26) +#define CKDLY_USB				BIT(27) +#define CKDLY_DIG				BIT(28) +#define CKDLY_BT				BIT(29) + + +/* AFE_PLL_CTRL */ +#define APLL_EN					BIT(0) +#define APLL_320_EN				BIT(1) +#define APLL_FREF_SEL				BIT(2) +#define APLL_EDGE_SEL				BIT(3) +#define APLL_WDOGB				BIT(4) +#define APLL_LPFEN				BIT(5) + +#define APLL_REF_CLK_13MHZ			0x1 +#define APLL_REF_CLK_19_2MHZ			0x2 +#define APLL_REF_CLK_20MHZ			0x3 +#define APLL_REF_CLK_25MHZ			0x4 +#define APLL_REF_CLK_26MHZ			0x5 +#define APLL_REF_CLK_38_4MHZ			0x6 +#define APLL_REF_CLK_40MHZ			0x7 + +#define APLL_320EN				BIT(14) +#define APLL_80EN				BIT(15) +#define APLL_1MEN				BIT(24) + + +/* EFUSE_CTRL */ +#define ALD_EN					BIT(18) +#define EF_PD					BIT(19) +#define EF_FLAG					BIT(31) + +/* EFUSE_TEST  */ +#define EF_TRPT					BIT(7) +#define LDOE25_EN				BIT(31) + +/* MCUFWDL  */ +#define MCUFWDL_EN				BIT(0) +#define MCUFWDL_RDY				BIT(1) +#define FWDL_ChkSum_rpt				BIT(2) +#define MACINI_RDY				BIT(3) +#define BBINI_RDY				BIT(4) +#define RFINI_RDY				BIT(5) +#define WINTINI_RDY				BIT(6) +#define MAC1_WINTINI_RDY			BIT(11) +#define CPRST					BIT(23) + +/*  REG_SYS_CFG */ +#define XCLK_VLD				BIT(0) +#define ACLK_VLD				BIT(1) +#define UCLK_VLD				BIT(2) +#define PCLK_VLD				BIT(3) +#define PCIRSTB					BIT(4) +#define V15_VLD					BIT(5) +#define TRP_B15V_EN				BIT(7) +#define SIC_IDLE				BIT(8) +#define BD_MAC2					BIT(9) +#define BD_MAC1					BIT(10) +#define IC_MACPHY_MODE				BIT(11) +#define PAD_HWPD_IDN				BIT(22) +#define TRP_VAUX_EN				BIT(23) +#define TRP_BT_EN				BIT(24) +#define BD_PKG_SEL				BIT(25) +#define BD_HCI_SEL				BIT(26) +#define TYPE_ID					BIT(27) + +/* LLT_INIT */ +#define _LLT_NO_ACTIVE				0x0 +#define _LLT_WRITE_ACCESS			0x1 +#define _LLT_READ_ACCESS			0x2 + +#define _LLT_INIT_DATA(x)			((x) & 0xFF) +#define _LLT_INIT_ADDR(x)			(((x) & 0xFF) << 8) +#define _LLT_OP(x)				(((x) & 0x3) << 30) +#define _LLT_OP_VALUE(x)			(((x) >> 30) & 0x3) + + +/* ----------------------------------------------------- */ +/*	0x0400h ~ 0x047Fh	Protocol Configuration	 */ +/* ----------------------------------------------------- */ +#define	RETRY_LIMIT_SHORT_SHIFT			8 +#define	RETRY_LIMIT_LONG_SHIFT			0 + + +/* ----------------------------------------------------- */ +/*	0x0500h ~ 0x05FFh	EDCA Configuration */ +/* ----------------------------------------------------- */ +/* EDCA setting */ +#define AC_PARAM_TXOP_LIMIT_OFFSET		16 +#define AC_PARAM_ECW_MAX_OFFSET			12 +#define AC_PARAM_ECW_MIN_OFFSET			8 +#define AC_PARAM_AIFS_OFFSET			0 + +/* ACMHWCTRL */ +#define	ACMHW_HWEN				BIT(0) +#define	ACMHW_BEQEN				BIT(1) +#define	ACMHW_VIQEN				BIT(2) +#define	ACMHW_VOQEN				BIT(3) + +/* ----------------------------------------------------- */ +/*	0x0600h ~ 0x07FFh	WMAC Configuration */ +/* ----------------------------------------------------- */ + +/* TCR */ +#define TSFRST					BIT(0) +#define DIS_GCLK				BIT(1) +#define PAD_SEL					BIT(2) +#define PWR_ST					BIT(6) +#define PWRBIT_OW_EN				BIT(7) +#define ACRC					BIT(8) +#define CFENDFORM				BIT(9) +#define ICV					BIT(10) + +/* SECCFG */ +#define	SCR_TXUSEDK				BIT(0) +#define	SCR_RXUSEDK				BIT(1) +#define	SCR_TXENCENABLE				BIT(2) +#define	SCR_RXENCENABLE				BIT(3) +#define	SCR_SKBYA2				BIT(4) +#define	SCR_NOSKMC				BIT(5) +#define SCR_TXBCUSEDK				BIT(6) +#define SCR_RXBCUSEDK				BIT(7) + +/* General definitions */ +#define MAC_ADDR_LEN				6 +#define LAST_ENTRY_OF_TX_PKT_BUFFER		255 +#define LAST_ENTRY_OF_TX_PKT_BUFFER_DUAL_MAC	127 + +#define POLLING_LLT_THRESHOLD			20 +#define POLLING_READY_TIMEOUT_COUNT		1000 + +/* Min Spacing related settings. */ +#define	MAX_MSS_DENSITY_2T			0x13 +#define	MAX_MSS_DENSITY_1T			0x0A + + +/* BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF */ +/* 1. PMAC duplicate register due to connection: */ +/*    RF_Mode, TRxRN, NumOf L-STF */ +/* 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00 */ +/* 3. RF register 0x00-2E */ +/* 4. Bit Mask for BB/RF register */ +/* 5. Other defintion for BB/RF R/W */ + +/* 3. Page8(0x800) */ +#define	RFPGA0_RFMOD				0x800 + +#define	RFPGA0_TXINFO				0x804 +#define	RFPGA0_PSDFUNCTION			0x808 + +#define	RFPGA0_TXGAINSTAGE			0x80c + +#define	RFPGA0_RFTIMING1			0x810 +#define	RFPGA0_RFTIMING2			0x814 + +#define	RFPGA0_XA_HSSIPARAMETER1		0x820 +#define	RFPGA0_XA_HSSIPARAMETER2		0x824 +#define	RFPGA0_XB_HSSIPARAMETER1		0x828 +#define	RFPGA0_XB_HSSIPARAMETER2		0x82c + +#define	RFPGA0_XA_LSSIPARAMETER			0x840 +#define	RFPGA0_XB_LSSIPARAMETER			0x844 + +#define	RFPGA0_RFWAkEUPPARAMETER		0x850 +#define	RFPGA0_RFSLEEPUPPARAMETER		0x854 + +#define	RFPGA0_XAB_SWITCHCONTROL		0x858 +#define	RFPGA0_XCD_SWITCHCONTROL		0x85c + +#define	RFPGA0_XA_RFINTERFACEOE			0x860 +#define	RFPGA0_XB_RFINTERFACEOE			0x864 + +#define	RFPGA0_XAB_RFINTERFACESW		0x870 +#define	RFPGA0_XCD_RFINTERFACESW		0x874 + +#define	RFPGA0_XAB_RFPARAMETER			0x878 +#define	RFPGA0_XCD_RFPARAMETER			0x87c + +#define	RFPGA0_ANALOGPARAMETER1			0x880 +#define	RFPGA0_ANALOGPARAMETER2			0x884 +#define	RFPGA0_ANALOGPARAMETER3			0x888 +#define	RFPGA0_ADDALLOCKEN			0x888 +#define	RFPGA0_ANALOGPARAMETER4			0x88c + +#define	RFPGA0_XA_LSSIREADBACK			0x8a0 +#define	RFPGA0_XB_LSSIREADBACK			0x8a4 +#define	RFPGA0_XC_LSSIREADBACK			0x8a8 +#define	RFPGA0_XD_LSSIREADBACK			0x8ac + +#define	RFPGA0_PSDREPORT			0x8b4 +#define	TRANSCEIVERA_HSPI_READBACK		0x8b8 +#define	TRANSCEIVERB_HSPI_READBACK		0x8bc +#define	RFPGA0_XAB_RFINTERFACERB		0x8e0 +#define	RFPGA0_XCD_RFINTERFACERB		0x8e4 + +/* 4. Page9(0x900) */ +#define	RFPGA1_RFMOD				0x900 + +#define	RFPGA1_TXBLOCK				0x904 +#define	RFPGA1_DEBUGSELECT			0x908 +#define	RFPGA1_TXINFO				0x90c + +/* 5. PageA(0xA00)  */ +#define	RCCK0_SYSTEM				0xa00 + +#define	RCCK0_AFESSTTING			0xa04 +#define	RCCK0_CCA				0xa08 + +#define	RCCK0_RXAGC1				0xa0c +#define	RCCK0_RXAGC2				0xa10 + +#define	RCCK0_RXHP				0xa14 + +#define	RCCK0_DSPPARAMETER1			0xa18 +#define	RCCK0_DSPPARAMETER2			0xa1c + +#define	RCCK0_TXFILTER1				0xa20 +#define	RCCK0_TXFILTER2				0xa24 +#define	RCCK0_DEBUGPORT				0xa28 +#define	RCCK0_FALSEALARMREPORT			0xa2c +#define	RCCK0_TRSSIREPORT			0xa50 +#define	RCCK0_RXREPORT				0xa54 +#define	RCCK0_FACOUNTERLOWER			0xa5c +#define	RCCK0_FACOUNTERUPPER			0xa58 + +/* 6. PageC(0xC00) */ +#define	ROFDM0_LSTF				0xc00 + +#define	ROFDM0_TRXPATHENABLE			0xc04 +#define	ROFDM0_TRMUXPAR				0xc08 +#define	ROFDM0_TRSWISOLATION			0xc0c + +#define	ROFDM0_XARXAFE				0xc10 +#define	ROFDM0_XARXIQIMBALANCE			0xc14 +#define	ROFDM0_XBRXAFE				0xc18 +#define	ROFDM0_XBRXIQIMBALANCE			0xc1c +#define	ROFDM0_XCRXAFE				0xc20 +#define	ROFDM0_XCRXIQIMBALANCE			0xc24 +#define	ROFDM0_XDRXAFE				0xc28 +#define	ROFDM0_XDRXIQIMBALANCE			0xc2c + +#define	ROFDM0_RXDETECTOR1			0xc30 +#define	ROFDM0_RXDETECTOR2			0xc34 +#define	ROFDM0_RXDETECTOR3			0xc38 +#define	ROFDM0_RXDETECTOR4			0xc3c + +#define	ROFDM0_RXDSP				0xc40 +#define	ROFDM0_CFOANDDAGC			0xc44 +#define	ROFDM0_CCADROPTHRESHOLD			0xc48 +#define	ROFDM0_ECCATHRESHOLD			0xc4c + +#define	ROFDM0_XAAGCCORE1			0xc50 +#define	ROFDM0_XAAGCCORE2			0xc54 +#define	ROFDM0_XBAGCCORE1			0xc58 +#define	ROFDM0_XBAGCCORE2			0xc5c +#define	ROFDM0_XCAGCCORE1			0xc60 +#define	ROFDM0_XCAGCCORE2			0xc64 +#define	ROFDM0_XDAGCCORE1			0xc68 +#define	ROFDM0_XDAGCCORE2			0xc6c + +#define	ROFDM0_AGCPARAMETER1			0xc70 +#define	ROFDM0_AGCPARAMETER2			0xc74 +#define	ROFDM0_AGCRSSITABLE			0xc78 +#define	ROFDM0_HTSTFAGC				0xc7c + +#define	ROFDM0_XATxIQIMBALANCE			0xc80 +#define	ROFDM0_XATxAFE				0xc84 +#define	ROFDM0_XBTxIQIMBALANCE			0xc88 +#define	ROFDM0_XBTxAFE				0xc8c +#define	ROFDM0_XCTxIQIMBALANCE			0xc90 +#define	ROFDM0_XCTxAFE				0xc94 +#define	ROFDM0_XDTxIQIMBALANCE			0xc98 +#define	ROFDM0_XDTxAFE				0xc9c + +#define	ROFDM0_RXHPPARAMETER			0xce0 +#define	ROFDM0_TXPSEUDONOISEWGT			0xce4 +#define	ROFDM0_FRAMESYNC			0xcf0 +#define	ROFDM0_DFSREPORT			0xcf4 +#define	ROFDM0_TXCOEFF1				0xca4 +#define	ROFDM0_TXCOEFF2				0xca8 +#define	ROFDM0_TXCOEFF3				0xcac +#define	ROFDM0_TXCOEFF4				0xcb0 +#define	ROFDM0_TXCOEFF5				0xcb4 +#define	ROFDM0_TXCOEFF6				0xcb8 + +/* 7. PageD(0xD00) */ +#define	ROFDM1_LSTF				0xd00 +#define	ROFDM1_TRXPATHENABLE			0xd04 + +#define	ROFDM1_CFO				0xd08 +#define	ROFDM1_CSI1				0xd10 +#define	ROFDM1_SBD				0xd14 +#define	ROFDM1_CSI2				0xd18 +#define	ROFDM1_CFOTRACKING			0xd2c +#define	ROFDM1_TRXMESAURE1			0xd34 +#define	ROFDM1_INTFDET				0xd3c +#define	ROFDM1_PSEUDONOISESTATEAB		0xd50 +#define	ROFDM1_PSEUDONOISESTATECD		0xd54 +#define	ROFDM1_RXPSEUDONOISEWGT			0xd58 + +#define	ROFDM_PHYCOUNTER1			0xda0 +#define	ROFDM_PHYCOUNTER2			0xda4 +#define	ROFDM_PHYCOUNTER3			0xda8 + +#define	ROFDM_SHORTCFOAB			0xdac +#define	ROFDM_SHORTCFOCD			0xdb0 +#define	ROFDM_LONGCFOAB				0xdb4 +#define	ROFDM_LONGCFOCD				0xdb8 +#define	ROFDM_TAILCFOAB				0xdbc +#define	ROFDM_TAILCFOCD				0xdc0 +#define	ROFDM_PWMEASURE1			0xdc4 +#define	ROFDM_PWMEASURE2			0xdc8 +#define	ROFDM_BWREPORT				0xdcc +#define	ROFDM_AGCREPORT				0xdd0 +#define	ROFDM_RXSNR				0xdd4 +#define	ROFDM_RXEVMCSI				0xdd8 +#define	ROFDM_SIGReport				0xddc + +/* 8. PageE(0xE00) */ +#define	RTXAGC_A_RATE18_06			0xe00 +#define	RTXAGC_A_RATE54_24			0xe04 +#define	RTXAGC_A_CCK1_MCS32			0xe08 +#define	RTXAGC_A_MCS03_MCS00			0xe10 +#define	RTXAGC_A_MCS07_MCS04			0xe14 +#define	RTXAGC_A_MCS11_MCS08			0xe18 +#define	RTXAGC_A_MCS15_MCS12			0xe1c + +#define	RTXAGC_B_RATE18_06			0x830 +#define	RTXAGC_B_RATE54_24			0x834 +#define	RTXAGC_B_CCK1_55_MCS32			0x838 +#define	RTXAGC_B_MCS03_MCS00			0x83c +#define	RTXAGC_B_MCS07_MCS04			0x848 +#define	RTXAGC_B_MCS11_MCS08			0x84c +#define	RTXAGC_B_MCS15_MCS12			0x868 +#define	RTXAGC_B_CCK11_A_CCK2_11		0x86c + +/* RL6052 Register definition */ +#define	RF_AC					0x00 + +#define	RF_IQADJ_G1				0x01 +#define	RF_IQADJ_G2				0x02 +#define	RF_POW_TRSW				0x05 + +#define	RF_GAIN_RX				0x06 +#define	RF_GAIN_TX				0x07 + +#define	RF_TXM_IDAC				0x08 +#define	RF_BS_IQGEN				0x0F + +#define	RF_MODE1				0x10 +#define	RF_MODE2				0x11 + +#define	RF_RX_AGC_HP				0x12 +#define	RF_TX_AGC				0x13 +#define	RF_BIAS					0x14 +#define	RF_IPA					0x15 +#define	RF_POW_ABILITY				0x17 +#define	RF_MODE_AG				0x18 +#define	rRfChannel				0x18 +#define	RF_CHNLBW				0x18 +#define	RF_TOP					0x19 + +#define	RF_RX_G1				0x1A +#define	RF_RX_G2				0x1B + +#define	RF_RX_BB2				0x1C +#define	RF_RX_BB1				0x1D + +#define	RF_RCK1					0x1E +#define	RF_RCK2					0x1F + +#define	RF_TX_G1				0x20 +#define	RF_TX_G2				0x21 +#define	RF_TX_G3				0x22 + +#define	RF_TX_BB1				0x23 + +#define	RF_T_METER				0x42 + +#define	RF_SYN_G1				0x25 +#define	RF_SYN_G2				0x26 +#define	RF_SYN_G3				0x27 +#define	RF_SYN_G4				0x28 +#define	RF_SYN_G5				0x29 +#define	RF_SYN_G6				0x2A +#define	RF_SYN_G7				0x2B +#define	RF_SYN_G8				0x2C + +#define	RF_RCK_OS				0x30 + +#define	RF_TXPA_G1				0x31 +#define	RF_TXPA_G2				0x32 +#define	RF_TXPA_G3				0x33 + +/* Bit Mask */ + +/* 2. Page8(0x800) */ +#define	BRFMOD					0x1 +#define	BCCKTXSC				0x30 +#define	BCCKEN					0x1000000 +#define	BOFDMEN					0x2000000 + +#define	B3WIREDATALENGTH			0x800 +#define	B3WIREADDRESSLENGTH			0x400 + +#define	BRFSI_RFENV				0x10 + +#define	BLSSIREADADDRESS			0x7f800000 +#define	BLSSIREADEDGE				0x80000000 +#define	BLSSIREADBACKDATA			0xfffff +/* 4. PageA(0xA00) */ +#define BCCKSIDEBAND				0x10 + +/* Other Definition */ +#define	BBYTE0					0x1 +#define	BBYTE1					0x2 +#define	BBYTE2					0x4 +#define	BBYTE3					0x8 +#define	BWORD0					0x3 +#define	BWORD1					0xc +#define	BDWORD					0xf + +#define	BMASKBYTE0				0xff +#define	BMASKBYTE1				0xff00 +#define	BMASKBYTE2				0xff0000 +#define	BMASKBYTE3				0xff000000 +#define	BMASKHWORD				0xffff0000 +#define	BMASKLWORD				0x0000ffff +#define	BMASKDWORD				0xffffffff +#define	BMASK12BITS				0xfff +#define	BMASKH4BITS				0xf0000000 +#define BMASKOFDM_D				0xffc00000 +#define	BMASKCCK				0x3f3f3f3f + +#define BRFREGOFFSETMASK			0xfffff + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.c b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c new file mode 100644 index 00000000000..db27cebaac2 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.c @@ -0,0 +1,628 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "rf.h" +#include "dm.h" +#include "hw.h" + +void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	u8 rfpath; + +	switch (bandwidth) { +	case HT_CHANNEL_WIDTH_20: +		for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { +			rtlphy->rfreg_chnlval[rfpath] = ((rtlphy->rfreg_chnlval +					[rfpath] & 0xfffff3ff) | 0x0400); +			rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | +				      BIT(11), 0x01); + +			RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, +				 ("20M RF 0x18 = 0x%x\n", +				 rtlphy->rfreg_chnlval[rfpath])); +		} + +		break; +	case HT_CHANNEL_WIDTH_20_40: +		for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { +			rtlphy->rfreg_chnlval[rfpath] = +			    ((rtlphy->rfreg_chnlval[rfpath] & 0xfffff3ff)); +			rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(10) | BIT(11), +				      0x00); +			RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, +				 ("40M RF 0x18 = 0x%x\n", +				 rtlphy->rfreg_chnlval[rfpath])); +		} +		break; +	default: +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("unknown bandwidth: %#X\n", bandwidth)); +		break; +	} +} + +void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, +				       u8 *ppowerlevel) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	u32 tx_agc[2] = {0, 0}, tmpval; +	bool turbo_scanoff = false; +	u8 idx1, idx2; +	u8 *ptr; + +	if (rtlefuse->eeprom_regulatory != 0) +		turbo_scanoff = true; +	if (mac->act_scanning) { +		tx_agc[RF90_PATH_A] = 0x3f3f3f3f; +		tx_agc[RF90_PATH_B] = 0x3f3f3f3f; +		if (turbo_scanoff) { +			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { +				tx_agc[idx1] = ppowerlevel[idx1] | +				    (ppowerlevel[idx1] << 8) | +				    (ppowerlevel[idx1] << 16) | +				    (ppowerlevel[idx1] << 24); +			} +		} +	} else { +		for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { +			tx_agc[idx1] = ppowerlevel[idx1] | +			    (ppowerlevel[idx1] << 8) | +			    (ppowerlevel[idx1] << 16) | +			    (ppowerlevel[idx1] << 24); +		} +		if (rtlefuse->eeprom_regulatory == 0) { +			tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + +			    (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8); +			tx_agc[RF90_PATH_A] += tmpval; +			tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + +			    (rtlphy->mcs_txpwrlevel_origoffset[0][15] << 24); +			tx_agc[RF90_PATH_B] += tmpval; +		} +	} + +	for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { +		ptr = (u8 *) (&(tx_agc[idx1])); +		for (idx2 = 0; idx2 < 4; idx2++) { +			if (*ptr > RF6052_MAX_TX_PWR) +				*ptr = RF6052_MAX_TX_PWR; +			ptr++; +		} +	} + +	tmpval = tx_agc[RF90_PATH_A] & 0xff; +	rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, BMASKBYTE1, tmpval); +	RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +		("CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, +		RTXAGC_A_CCK1_MCS32)); +	tmpval = tx_agc[RF90_PATH_A] >> 8; +	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); +	RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +		("CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, +		RTXAGC_B_CCK11_A_CCK2_11)); +	tmpval = tx_agc[RF90_PATH_B] >> 24; +	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, BMASKBYTE0, tmpval); +	RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +		("CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, +		RTXAGC_B_CCK11_A_CCK2_11)); +	tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; +	rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); +	RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +		("CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, +		RTXAGC_B_CCK1_55_MCS32)); +} + +static void _rtl92d_phy_get_power_base(struct ieee80211_hw *hw, +				       u8 *ppowerlevel, u8 channel, +				       u32 *ofdmbase, u32 *mcsbase) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	u32 powerbase0, powerbase1; +	u8 legacy_pwrdiff, ht20_pwrdiff; +	u8 i, powerlevel[2]; + +	for (i = 0; i < 2; i++) { +		powerlevel[i] = ppowerlevel[i]; +		legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1]; +		powerbase0 = powerlevel[i] + legacy_pwrdiff; +		powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | +		    (powerbase0 << 8) | powerbase0; +		*(ofdmbase + i) = powerbase0; +		RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +			(" [OFDM power base index rf(%c) = 0x%x]\n", +			((i == 0) ? 'A' : 'B'), *(ofdmbase + i))); +	} + +	for (i = 0; i < 2; i++) { +		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { +			ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1]; +			powerlevel[i] += ht20_pwrdiff; +		} +		powerbase1 = powerlevel[i]; +		powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) | +			     (powerbase1 << 8) | powerbase1; +		*(mcsbase + i) = powerbase1; +		RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +			(" [MCS power base index rf(%c) = 0x%x]\n", +			((i == 0) ? 'A' : 'B'), *(mcsbase + i))); +	} +} + +static u8 _rtl92d_phy_get_chnlgroup_bypg(u8 chnlindex) +{ +	u8 group; +	u8 channel_info[59] = { +		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, +		60, 62, 64, 100, 102, 104, 106, 108, 110, 112, +		114, 116, 118, 120, 122, 124, 126, 128,	130, 132, +		134, 136, 138, 140, 149, 151, 153, 155, 157, 159, +		161, 163, 165 +	}; + +	if (channel_info[chnlindex] <= 3)	/* Chanel 1-3 */ +		group = 0; +	else if (channel_info[chnlindex] <= 9)	/* Channel 4-9 */ +		group = 1; +	else if (channel_info[chnlindex] <= 14)	/* Channel 10-14 */ +		group = 2; +	else if (channel_info[chnlindex] <= 64) +		group = 6; +	else if (channel_info[chnlindex] <= 140) +		group = 7; +	else +		group = 8; +	return group; +} + +static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, +						       u8 channel, u8 index, +						       u32 *powerbase0, +						       u32 *powerbase1, +						       u32 *p_outwriteval) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	u8 i, chnlgroup = 0, pwr_diff_limit[4]; +	u32 writeval = 0, customer_limit, rf; + +	for (rf = 0; rf < 2; rf++) { +		switch (rtlefuse->eeprom_regulatory) { +		case 0: +			chnlgroup = 0; +			writeval = rtlphy->mcs_txpwrlevel_origoffset +					[chnlgroup][index + +					(rf ? 8 : 0)] + ((index < 2) ? +					powerbase0[rf] : +					powerbase1[rf]); +			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("RTK better " +				"performance, writeval(%c) = 0x%x\n", +				((rf == 0) ? 'A' : 'B'), writeval)); +			break; +		case 1: +			if (rtlphy->pwrgroup_cnt == 1) +				chnlgroup = 0; +			if (rtlphy->pwrgroup_cnt >= MAX_PG_GROUP) { +				chnlgroup = _rtl92d_phy_get_chnlgroup_bypg( +								channel - 1); +				if (rtlphy->current_chan_bw == +				    HT_CHANNEL_WIDTH_20) +					chnlgroup++; +				else +					chnlgroup += 4; +				writeval = rtlphy->mcs_txpwrlevel_origoffset +						[chnlgroup][index + +						(rf ? 8 : 0)] + ((index < 2) ? +						powerbase0[rf] : +						powerbase1[rf]); +				RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +					("Realtek regulatory, " +					"20MHz, writeval(%c) = 0x%x\n", +					((rf == 0) ? 'A' : 'B'), +					writeval)); +			} +			break; +		case 2: +			writeval = ((index < 2) ? powerbase0[rf] : +				   powerbase1[rf]); +			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("Better regulatory, " +				"writeval(%c) = 0x%x\n", +				((rf == 0) ? 'A' : 'B'), writeval)); +			break; +		case 3: +			chnlgroup = 0; +			if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { +				RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +					("customer's limit, 40MHz rf(%c) = " +					"0x%x\n", ((rf == 0) ? 'A' : 'B'), +					rtlefuse->pwrgroup_ht40[rf] +					[channel - 1])); +			} else { +				RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +					("customer's limit, 20MHz rf(%c) = " +					"0x%x\n", ((rf == 0) ? 'A' : 'B'), +					rtlefuse->pwrgroup_ht20[rf] +					[channel - 1])); +			} +			for (i = 0; i < 4; i++) { +				pwr_diff_limit[i] = +					(u8)((rtlphy->mcs_txpwrlevel_origoffset +					[chnlgroup][index + (rf ? 8 : 0)] & +					(0x7f << (i * 8))) >> (i * 8)); +				if (rtlphy->current_chan_bw == +				    HT_CHANNEL_WIDTH_20_40) { +					if (pwr_diff_limit[i] > +					    rtlefuse->pwrgroup_ht40[rf] +					   [channel - 1]) +						pwr_diff_limit[i] = +							rtlefuse->pwrgroup_ht40 +							[rf][channel - 1]; +				} else { +					if (pwr_diff_limit[i] > +					    rtlefuse->pwrgroup_ht20[rf][ +						channel - 1]) +						pwr_diff_limit[i] = +						   rtlefuse->pwrgroup_ht20[rf] +						   [channel - 1]; +				} +			} +			customer_limit = (pwr_diff_limit[3] << 24) | +					 (pwr_diff_limit[2] << 16) | +					 (pwr_diff_limit[1] << 8) | +					 (pwr_diff_limit[0]); +			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +				("Customer's limit rf(%c) = 0x%x\n", +				((rf == 0) ? 'A' : 'B'), customer_limit)); +			writeval = customer_limit + ((index < 2) ? +				   powerbase0[rf] : powerbase1[rf]); +			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +				("Customer, writeval rf(%c)= 0x%x\n", +				((rf == 0) ? 'A' : 'B'), writeval)); +			break; +		default: +			chnlgroup = 0; +			writeval = rtlphy->mcs_txpwrlevel_origoffset +				   [chnlgroup][index + +				   (rf ? 8 : 0)] + ((index < 2) ? +				   powerbase0[rf] : powerbase1[rf]); +			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +				("RTK better performance, writeval " +				"rf(%c) = 0x%x\n", +				((rf == 0) ? 'A' : 'B'), writeval)); +			break; +		} +		*(p_outwriteval + rf) = writeval; +	} +} + +static void _rtl92d_write_ofdm_power_reg(struct ieee80211_hw *hw, +					 u8 index, u32 *pvalue) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	static u16 regoffset_a[6] = { +		RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, +		RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, +		RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 +	}; +	static u16 regoffset_b[6] = { +		RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, +		RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, +		RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 +	}; +	u8 i, rf, pwr_val[4]; +	u32 writeval; +	u16 regoffset; + +	for (rf = 0; rf < 2; rf++) { +		writeval = pvalue[rf]; +		for (i = 0; i < 4; i++) { +			pwr_val[i] = (u8) ((writeval & (0x7f << +				     (i * 8))) >> (i * 8)); +			if (pwr_val[i] > RF6052_MAX_TX_PWR) +				pwr_val[i] = RF6052_MAX_TX_PWR; +		} +		writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | +			   (pwr_val[1] << 8) | pwr_val[0]; +		if (rf == 0) +			regoffset = regoffset_a[index]; +		else +			regoffset = regoffset_b[index]; +		rtl_set_bbreg(hw, regoffset, BMASKDWORD, writeval); +		RTPRINT(rtlpriv, FPHY, PHY_TXPWR, +			("Set 0x%x = %08x\n", regoffset, writeval)); +		if (((get_rf_type(rtlphy) == RF_2T2R) && +		    (regoffset == RTXAGC_A_MCS15_MCS12 || +		    regoffset == RTXAGC_B_MCS15_MCS12)) || +		    ((get_rf_type(rtlphy) != RF_2T2R) && +		    (regoffset == RTXAGC_A_MCS07_MCS04 || +		    regoffset == RTXAGC_B_MCS07_MCS04))) { +			writeval = pwr_val[3]; +			if (regoffset == RTXAGC_A_MCS15_MCS12 || +			    regoffset == RTXAGC_A_MCS07_MCS04) +				regoffset = 0xc90; +			if (regoffset == RTXAGC_B_MCS15_MCS12 || +			    regoffset == RTXAGC_B_MCS07_MCS04) +				regoffset = 0xc98; +			for (i = 0; i < 3; i++) { +				if (i != 2) +					writeval = (writeval > 8) ? +						   (writeval - 8) : 0; +				else +					writeval = (writeval > 6) ? +						   (writeval - 6) : 0; +				rtl_write_byte(rtlpriv, (u32) (regoffset + i), +					       (u8) writeval); +			} +		} +	} +} + +void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, +					u8 *ppowerlevel, u8 channel) +{ +	u32 writeval[2], powerbase0[2], powerbase1[2]; +	u8 index; + +	_rtl92d_phy_get_power_base(hw, ppowerlevel, channel, +			&powerbase0[0],	&powerbase1[0]); +	for (index = 0; index < 6; index++) { +		_rtl92d_get_txpower_writeval_by_regulatory(hw, +				channel, index,	&powerbase0[0], +				&powerbase1[0],	&writeval[0]); +		_rtl92d_write_ofdm_power_reg(hw, index, &writeval[0]); +	} +} + +bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	u8 u1btmp; +	u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3); +	u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0; +	u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON; +	bool bresult = true; /* true: need to enable BB/RF power */ + +	rtlhal->during_mac0init_radiob = false; +	rtlhal->during_mac1init_radioa = false; +	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("===>\n")); +	/* MAC0 Need PHY1 load radio_b.txt . Driver use DBI to write. */ +	u1btmp = rtl_read_byte(rtlpriv, mac_reg); +	if (!(u1btmp & mac_on_bit)) { +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("enable BB & RF\n")); +		/* Enable BB and RF power */ +		rtl92de_write_dword_dbi(hw, REG_SYS_ISO_CTRL, +			rtl92de_read_dword_dbi(hw, REG_SYS_ISO_CTRL, direct) | +				BIT(29) | BIT(16) | BIT(17), direct); +	} else { +		/* We think if MAC1 is ON,then radio_a.txt +		 * and radio_b.txt has been load. */ +		bresult = false; +	} +	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<===\n")); +	return bresult; + +} + +void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, bool bmac0) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	u8 u1btmp; +	u8 direct = bmac0 ? BIT(3) | BIT(2) : BIT(3); +	u8 mac_reg = bmac0 ? REG_MAC1 : REG_MAC0; +	u8 mac_on_bit = bmac0 ? MAC1_ON : MAC0_ON; + +	rtlhal->during_mac0init_radiob = false; +	rtlhal->during_mac1init_radioa = false; +	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("====>\n")); +	/* check MAC0 enable or not again now, if +	 * enabled, not power down radio A. */ +	u1btmp = rtl_read_byte(rtlpriv, mac_reg); +	if (!(u1btmp & mac_on_bit)) { +		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("power down\n")); +		/* power down RF radio A according to YuNan's advice. */ +		rtl92de_write_dword_dbi(hw, RFPGA0_XA_LSSIPARAMETER, +					0x00000000, direct); +	} +	RT_TRACE(rtlpriv, COMP_RF, DBG_LOUD, ("<====\n")); +} + +bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	bool rtstatus = true; +	struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); +	u32 u4_regvalue = 0; +	u8 rfpath; +	struct bb_reg_def *pphyreg; +	bool mac1_initradioa_first = false, mac0_initradiob_first = false; +	bool need_pwrdown_radioa = false, need_pwrdown_radiob = false; +	bool true_bpath = false; + +	if (rtlphy->rf_type == RF_1T1R) +		rtlphy->num_total_rfpath = 1; +	else +		rtlphy->num_total_rfpath = 2; + +	/* Single phy mode: use radio_a radio_b config path_A path_B */ +	/* seperately by MAC0, and MAC1 needn't configure RF; */ +	/* Dual PHY mode:MAC0 use radio_a config 1st phy path_A, */ +	/* MAC1 use radio_b config 2nd PHY path_A. */ +	/* DMDP,MAC0 on G band,MAC1 on A band. */ +	if (rtlhal->macphymode == DUALMAC_DUALPHY) { +		if (rtlhal->current_bandtype == BAND_ON_2_4G && +		    rtlhal->interfaceindex == 0) { +			/* MAC0 needs PHY1 load radio_b.txt. +			 * Driver use DBI to write. */ +			if (rtl92d_phy_enable_anotherphy(hw, true)) { +				rtlphy->num_total_rfpath = 2; +				mac0_initradiob_first = true; +			} else { +				/* We think if MAC1 is ON,then radio_a.txt and +				 * radio_b.txt has been load. */ +				return rtstatus; +			} +		} else if (rtlhal->current_bandtype == BAND_ON_5G && +			   rtlhal->interfaceindex == 1) { +			/* MAC1 needs PHY0 load radio_a.txt. +			 * Driver use DBI to write. */ +			if (rtl92d_phy_enable_anotherphy(hw, false)) { +				rtlphy->num_total_rfpath = 2; +				mac1_initradioa_first = true; +			} else { +				/* We think if MAC0 is ON,then radio_a.txt and +				 * radio_b.txt has been load. */ +				return rtstatus; +			} +		} else if (rtlhal->interfaceindex == 1) { +			/* MAC0 enabled, only init radia B.   */ +			true_bpath = true; +		} +	} + +	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { +		/* Mac1 use PHY0 write */ +		if (mac1_initradioa_first) { +			if (rfpath == RF90_PATH_A) { +				rtlhal->during_mac1init_radioa = true; +				need_pwrdown_radioa = true; +			} else if (rfpath == RF90_PATH_B) { +				rtlhal->during_mac1init_radioa = false; +				mac1_initradioa_first = false; +				rfpath = RF90_PATH_A; +				true_bpath = true; +				rtlphy->num_total_rfpath = 1; +			} +		} else if (mac0_initradiob_first) { +			/* Mac0 use PHY1 write */ +			if (rfpath == RF90_PATH_A) +				rtlhal->during_mac0init_radiob = false; +			if (rfpath == RF90_PATH_B) { +				rtlhal->during_mac0init_radiob = true; +				mac0_initradiob_first = false; +				need_pwrdown_radiob = true; +				rfpath = RF90_PATH_A; +				true_bpath = true; +				rtlphy->num_total_rfpath = 1; +			} +		} +		pphyreg = &rtlphy->phyreg_def[rfpath]; +		switch (rfpath) { +		case RF90_PATH_A: +		case RF90_PATH_C: +			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, +						    BRFSI_RFENV); +			break; +		case RF90_PATH_B: +		case RF90_PATH_D: +			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, +				BRFSI_RFENV << 16); +			break; +		} +		rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); +		udelay(1); +		rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); +		udelay(1); +		/* Set bit number of Address and Data for RF register */ +		/* Set 1 to 4 bits for 8255 */ +		rtl_set_bbreg(hw, pphyreg->rfhssi_para2, +			      B3WIREADDRESSLENGTH, 0x0); +		udelay(1); +		/* Set 0 to 12  bits for 8255 */ +		rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); +		udelay(1); +		switch (rfpath) { +		case RF90_PATH_A: +			if (true_bpath) +				rtstatus = rtl92d_phy_config_rf_with_headerfile( +						hw, radiob_txt, +						(enum radio_path)rfpath); +			else +				rtstatus = rtl92d_phy_config_rf_with_headerfile( +					     hw, radioa_txt, +					     (enum radio_path)rfpath); +			break; +		case RF90_PATH_B: +			rtstatus = +			    rtl92d_phy_config_rf_with_headerfile(hw, radiob_txt, +						(enum radio_path) rfpath); +			break; +		case RF90_PATH_C: +			break; +		case RF90_PATH_D: +			break; +		} +		switch (rfpath) { +		case RF90_PATH_A: +		case RF90_PATH_C: +			rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV, +				      u4_regvalue); +			break; +		case RF90_PATH_B: +		case RF90_PATH_D: +			rtl_set_bbreg(hw, pphyreg->rfintfs, BRFSI_RFENV << 16, +				      u4_regvalue); +			break; +		} +		if (rtstatus != true) { +			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, +				("Radio[%d] Fail!!", rfpath)); +			goto phy_rf_cfg_fail; +		} + +	} + +	/* check MAC0 enable or not again, if enabled, +	 * not power down radio A. */ +	/* check MAC1 enable or not again, if enabled, +	 * not power down radio B. */ +	if (need_pwrdown_radioa) +		rtl92d_phy_powerdown_anotherphy(hw, false); +	else if (need_pwrdown_radiob) +		rtl92d_phy_powerdown_anotherphy(hw, true); +	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("<---\n")); +	return rtstatus; + +phy_rf_cfg_fail: +	return rtstatus; +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/rf.h b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h new file mode 100644 index 00000000000..74b9cfc39a8 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/rf.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92D_RF_H__ +#define __RTL92D_RF_H__ + +extern void rtl92d_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, +					    u8 bandwidth); +extern void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, +					      u8 *ppowerlevel); +extern void rtl92d_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, +					       u8 *ppowerlevel, u8 channel); +extern bool rtl92d_phy_rf6052_config(struct ieee80211_hw *hw); +extern bool rtl92d_phy_enable_anotherphy(struct ieee80211_hw *hw, bool bmac0); +extern void rtl92d_phy_powerdown_anotherphy(struct ieee80211_hw *hw, +					    bool bmac0); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c new file mode 100644 index 00000000000..08837744f6f --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c @@ -0,0 +1,423 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include <linux/vmalloc.h> + +#include "../wifi.h" +#include "../core.h" +#include "../pci.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "dm.h" +#include "hw.h" +#include "sw.h" +#include "trx.h" +#include "led.h" + +static void rtl92d_init_aspm_vars(struct ieee80211_hw *hw) +{ +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + +	/*close ASPM for AMD defaultly */ +	rtlpci->const_amdpci_aspm = 0; + +	/* +	 * ASPM PS mode. +	 * 0 - Disable ASPM, +	 * 1 - Enable ASPM without Clock Req, +	 * 2 - Enable ASPM with Clock Req, +	 * 3 - Alwyas Enable ASPM with Clock Req, +	 * 4 - Always Enable ASPM without Clock Req. +	 * set defult to RTL8192CE:3 RTL8192E:2 +	 * */ +	rtlpci->const_pci_aspm = 3; + +	/*Setting for PCI-E device */ +	rtlpci->const_devicepci_aspm_setting = 0x03; + +	/*Setting for PCI-E bridge */ +	rtlpci->const_hostpci_aspm_setting = 0x02; + +	/* +	 * In Hw/Sw Radio Off situation. +	 * 0 - Default, +	 * 1 - From ASPM setting without low Mac Pwr, +	 * 2 - From ASPM setting with low Mac Pwr, +	 * 3 - Bus D3 +	 * set default to RTL8192CE:0 RTL8192SE:2 +	 */ +	rtlpci->const_hwsw_rfoff_d3 = 0; + +	/* +	 * This setting works for those device with +	 * backdoor ASPM setting such as EPHY setting. +	 * 0 - Not support ASPM, +	 * 1 - Support ASPM, +	 * 2 - According to chipset. +	 */ +	rtlpci->const_support_pciaspm = 1; +} + +static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) +{ +	int err; +	u8 tid; +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	const struct firmware *firmware; +	static int header_print; + +	rtlpriv->dm.dm_initialgain_enable = true; +	rtlpriv->dm.dm_flag = 0; +	rtlpriv->dm.disable_framebursting = 0; +	rtlpriv->dm.thermalvalue = 0; +	rtlpriv->dm.useramask = 1; + +	/* dual mac */ +	if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) +		rtlpriv->phy.current_channel = 36; +	else +		rtlpriv->phy.current_channel = 1; + +	if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) { +		rtlpriv->rtlhal.disable_amsdu_8k = true; +		/* No long RX - reduce fragmentation */ +		rtlpci->rxbuffersize = 4096; +	} + +	rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13); + +	rtlpci->receive_config = ( +			RCR_APPFCS +			| RCR_AMF +			| RCR_ADF +			| RCR_APP_MIC +			| RCR_APP_ICV +			| RCR_AICV +			| RCR_ACRC32 +			| RCR_AB +			| RCR_AM +			| RCR_APM +			| RCR_APP_PHYST_RXFF +			| RCR_HTC_LOC_CTRL +	); + +	rtlpci->irq_mask[0] = (u32) ( +			IMR_ROK +			| IMR_VODOK +			| IMR_VIDOK +			| IMR_BEDOK +			| IMR_BKDOK +			| IMR_MGNTDOK +			| IMR_HIGHDOK +			| IMR_BDOK +			| IMR_RDU +			| IMR_RXFOVW +	); + +	rtlpci->irq_mask[1] = (u32) (IMR_CPWM | IMR_C2HCMD); + +	/* for LPS & IPS */ +	rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; +	rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; +	rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; +	rtlpriv->psc.reg_fwctrl_lps = 3; +	rtlpriv->psc.reg_max_lps_awakeintvl = 5; +	/* for ASPM, you can close aspm through +	 * set const_support_pciaspm = 0 */ +	rtl92d_init_aspm_vars(hw); + +	if (rtlpriv->psc.reg_fwctrl_lps == 1) +		rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; +	else if (rtlpriv->psc.reg_fwctrl_lps == 2) +		rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; +	else if (rtlpriv->psc.reg_fwctrl_lps == 3) +		rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + +	/* for firmware buf */ +	rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); +	if (!rtlpriv->rtlhal.pfirmware) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("Can't alloc buffer for fw.\n")); +		return 1; +	} + +	if (!header_print) { +		printk(KERN_INFO "rtl8192de: Driver for Realtek RTL8192DE" +		       " WLAN interface"); +		printk(KERN_INFO "rtl8192de: Loading firmware file %s\n", +		       rtlpriv->cfg->fw_name); +		header_print++; +	} +	/* request fw */ +	err = request_firmware(&firmware, rtlpriv->cfg->fw_name, +			       rtlpriv->io.dev); +	if (err) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("Failed to request firmware!\n")); +		return 1; +	} +	if (firmware->size > 0x8000) { +		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, +			 ("Firmware is too big!\n")); +		release_firmware(firmware); +		return 1; +	} +	memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); +	rtlpriv->rtlhal.fwsize = firmware->size; +	release_firmware(firmware); + +	/* for early mode */ +	rtlpriv->rtlhal.earlymode_enable = true; +	for (tid = 0; tid < 8; tid++) +		skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); +	return 0; +} + +static void rtl92d_deinit_sw_vars(struct ieee80211_hw *hw) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u8 tid; + +	if (rtlpriv->rtlhal.pfirmware) { +		vfree(rtlpriv->rtlhal.pfirmware); +		rtlpriv->rtlhal.pfirmware = NULL; +	} +	for (tid = 0; tid < 8; tid++) +		skb_queue_purge(&rtlpriv->mac80211.skb_waitq[tid]); +} + +static struct rtl_hal_ops rtl8192de_hal_ops = { +	.init_sw_vars = rtl92d_init_sw_vars, +	.deinit_sw_vars = rtl92d_deinit_sw_vars, +	.read_eeprom_info = rtl92de_read_eeprom_info, +	.interrupt_recognized = rtl92de_interrupt_recognized, +	.hw_init = rtl92de_hw_init, +	.hw_disable = rtl92de_card_disable, +	.hw_suspend = rtl92de_suspend, +	.hw_resume = rtl92de_resume, +	.enable_interrupt = rtl92de_enable_interrupt, +	.disable_interrupt = rtl92de_disable_interrupt, +	.set_network_type = rtl92de_set_network_type, +	.set_chk_bssid = rtl92de_set_check_bssid, +	.set_qos = rtl92de_set_qos, +	.set_bcn_reg = rtl92de_set_beacon_related_registers, +	.set_bcn_intv = rtl92de_set_beacon_interval, +	.update_interrupt_mask = rtl92de_update_interrupt_mask, +	.get_hw_reg = rtl92de_get_hw_reg, +	.set_hw_reg = rtl92de_set_hw_reg, +	.update_rate_tbl = rtl92de_update_hal_rate_tbl, +	.fill_tx_desc = rtl92de_tx_fill_desc, +	.fill_tx_cmddesc = rtl92de_tx_fill_cmddesc, +	.query_rx_desc = rtl92de_rx_query_desc, +	.set_channel_access = rtl92de_update_channel_access_setting, +	.radio_onoff_checking = rtl92de_gpio_radio_on_off_checking, +	.set_bw_mode = rtl92d_phy_set_bw_mode, +	.switch_channel = rtl92d_phy_sw_chnl, +	.dm_watchdog = rtl92d_dm_watchdog, +	.scan_operation_backup = rtl92d_phy_scan_operation_backup, +	.set_rf_power_state = rtl92d_phy_set_rf_power_state, +	.led_control = rtl92de_led_control, +	.set_desc = rtl92de_set_desc, +	.get_desc = rtl92de_get_desc, +	.tx_polling = rtl92de_tx_polling, +	.enable_hw_sec = rtl92de_enable_hw_security_config, +	.set_key = rtl92de_set_key, +	.init_sw_leds = rtl92de_init_sw_leds, +	.get_bbreg = rtl92d_phy_query_bb_reg, +	.set_bbreg = rtl92d_phy_set_bb_reg, +	.get_rfreg = rtl92d_phy_query_rf_reg, +	.set_rfreg = rtl92d_phy_set_rf_reg, +	.linked_set_reg = rtl92d_linked_set_reg, +}; + +static struct rtl_mod_params rtl92de_mod_params = { +	.sw_crypto = false, +	.inactiveps = true, +	.swctrl_lps = true, +	.fwctrl_lps = false, +}; + +static struct rtl_hal_cfg rtl92de_hal_cfg = { +	.bar_id = 2, +	.write_readback = true, +	.name = "rtl8192de", +	.fw_name = "rtlwifi/rtl8192defw.bin", +	.ops = &rtl8192de_hal_ops, +	.mod_params = &rtl92de_mod_params, + +	.maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, +	.maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, +	.maps[SYS_CLK] = REG_SYS_CLKR, +	.maps[MAC_RCR_AM] = RCR_AM, +	.maps[MAC_RCR_AB] = RCR_AB, +	.maps[MAC_RCR_ACRC32] = RCR_ACRC32, +	.maps[MAC_RCR_ACF] = RCR_ACF, +	.maps[MAC_RCR_AAP] = RCR_AAP, + +	.maps[EFUSE_TEST] = REG_EFUSE_TEST, +	.maps[EFUSE_CTRL] = REG_EFUSE_CTRL, +	.maps[EFUSE_CLK] = 0,	/* just for 92se */ +	.maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, +	.maps[EFUSE_PWC_EV12V] = PWC_EV12V, +	.maps[EFUSE_FEN_ELDR] = FEN_ELDR, +	.maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN, +	.maps[EFUSE_ANA8M] = 0,	/* just for 92se */ +	.maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE, +	.maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, +	.maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, + +	.maps[RWCAM] = REG_CAMCMD, +	.maps[WCAMI] = REG_CAMWRITE, +	.maps[RCAMO] = REG_CAMREAD, +	.maps[CAMDBG] = REG_CAMDBG, +	.maps[SECR] = REG_SECCFG, +	.maps[SEC_CAM_NONE] = CAM_NONE, +	.maps[SEC_CAM_WEP40] = CAM_WEP40, +	.maps[SEC_CAM_TKIP] = CAM_TKIP, +	.maps[SEC_CAM_AES] = CAM_AES, +	.maps[SEC_CAM_WEP104] = CAM_WEP104, + +	.maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, +	.maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, +	.maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, +	.maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, +	.maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, +	.maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, +	.maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, +	.maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, +	.maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, +	.maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, +	.maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, +	.maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, +	.maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, +	.maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, +	.maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, +	.maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, + +	.maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, +	.maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, +	.maps[RTL_IMR_BcnInt] = IMR_BcnInt, +	.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, +	.maps[RTL_IMR_RDU] = IMR_RDU, +	.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, +	.maps[RTL_IMR_BDOK] = IMR_BDOK, +	.maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, +	.maps[RTL_IMR_TBDER] = IMR_TBDER, +	.maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, +	.maps[RTL_IMR_TBDOK] = IMR_TBDOK, +	.maps[RTL_IMR_BKDOK] = IMR_BKDOK, +	.maps[RTL_IMR_BEDOK] = IMR_BEDOK, +	.maps[RTL_IMR_VIDOK] = IMR_VIDOK, +	.maps[RTL_IMR_VODOK] = IMR_VODOK, +	.maps[RTL_IMR_ROK] = IMR_ROK, +	.maps[RTL_IBSS_INT_MASKS] = (IMR_BcnInt | IMR_TBDOK | IMR_TBDER), + +	.maps[RTL_RC_CCK_RATE1M] = DESC92D_RATE1M, +	.maps[RTL_RC_CCK_RATE2M] = DESC92D_RATE2M, +	.maps[RTL_RC_CCK_RATE5_5M] = DESC92D_RATE5_5M, +	.maps[RTL_RC_CCK_RATE11M] = DESC92D_RATE11M, +	.maps[RTL_RC_OFDM_RATE6M] = DESC92D_RATE6M, +	.maps[RTL_RC_OFDM_RATE9M] = DESC92D_RATE9M, +	.maps[RTL_RC_OFDM_RATE12M] = DESC92D_RATE12M, +	.maps[RTL_RC_OFDM_RATE18M] = DESC92D_RATE18M, +	.maps[RTL_RC_OFDM_RATE24M] = DESC92D_RATE24M, +	.maps[RTL_RC_OFDM_RATE36M] = DESC92D_RATE36M, +	.maps[RTL_RC_OFDM_RATE48M] = DESC92D_RATE48M, +	.maps[RTL_RC_OFDM_RATE54M] = DESC92D_RATE54M, + +	.maps[RTL_RC_HT_RATEMCS7] = DESC92D_RATEMCS7, +	.maps[RTL_RC_HT_RATEMCS15] = DESC92D_RATEMCS15, +}; + +static struct pci_device_id rtl92de_pci_ids[] __devinitdata = { +	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8193, rtl92de_hal_cfg)}, +	{RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x002B, rtl92de_hal_cfg)}, +	{}, +}; + +MODULE_DEVICE_TABLE(pci, rtl92de_pci_ids); + +MODULE_AUTHOR("lizhaoming	<chaoming_li@realsil.com.cn>"); +MODULE_AUTHOR("Realtek WlanFAE	<wlanfae@realtek.com>"); +MODULE_AUTHOR("Larry Finger	<Larry.Finger@lwfinger.net>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Realtek 8192DE 802.11n Dual Mac PCI wireless"); +MODULE_FIRMWARE("rtlwifi/rtl8192defw.bin"); + +module_param_named(swenc, rtl92de_mod_params.sw_crypto, bool, 0444); +module_param_named(ips, rtl92de_mod_params.inactiveps, bool, 0444); +module_param_named(swlps, rtl92de_mod_params.swctrl_lps, bool, 0444); +module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444); +MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); +MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); +MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1" +		 " is open)\n"); + +static struct pci_driver rtl92de_driver = { +	.name = KBUILD_MODNAME, +	.id_table = rtl92de_pci_ids, +	.probe = rtl_pci_probe, +	.remove = rtl_pci_disconnect, + +#ifdef CONFIG_PM +	.suspend = rtl_pci_suspend, +	.resume = rtl_pci_resume, +#endif + +}; + +/* add global spin lock to solve the problem that + * Dul mac register operation on the same time */ +spinlock_t globalmutex_power; +spinlock_t globalmutex_for_fwdownload; +spinlock_t globalmutex_for_power_and_efuse; + +static int __init rtl92de_module_init(void) +{ +	int ret = 0; + +	spin_lock_init(&globalmutex_power); +	spin_lock_init(&globalmutex_for_fwdownload); +	spin_lock_init(&globalmutex_for_power_and_efuse); + +	ret = pci_register_driver(&rtl92de_driver); +	if (ret) +		RT_ASSERT(false, (": No device found\n")); +	return ret; +} + +static void __exit rtl92de_module_exit(void) +{ +	pci_unregister_driver(&rtl92de_driver); +} + +module_init(rtl92de_module_init); +module_exit(rtl92de_module_exit); diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.h b/drivers/net/wireless/rtlwifi/rtl8192de/sw.h new file mode 100644 index 00000000000..c95e47de134 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92DE_SW_H__ +#define __RTL92DE_SW_H__ + +extern spinlock_t globalmutex_power; +extern spinlock_t globalmutex_for_fwdownload; +extern spinlock_t globalmutex_for_power_and_efuse; + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.c b/drivers/net/wireless/rtlwifi/rtl8192de/table.c new file mode 100644 index 00000000000..bad7f9449ec --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/table.c @@ -0,0 +1,1690 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + * Created on  2010/12/23,  6:38 + *****************************************************************************/ + +#include <linux/types.h> + +#include "table.h" + +u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH] = { +	0x024, 0x0011800d, +	0x028, 0x00ffdb83, +	0x014, 0x088ba955, +	0x010, 0x49022b03, +	0x800, 0x80040002, +	0x804, 0x00000003, +	0x808, 0x0000fc00, +	0x80c, 0x0000000a, +	0x810, 0x80706388, +	0x814, 0x020c3d10, +	0x818, 0x02200385, +	0x81c, 0x00000000, +	0x820, 0x01000100, +	0x824, 0x00390004, +	0x828, 0x01000100, +	0x82c, 0x00390004, +	0x830, 0x27272727, +	0x834, 0x27272727, +	0x838, 0x27272727, +	0x83c, 0x27272727, +	0x840, 0x00010000, +	0x844, 0x00010000, +	0x848, 0x27272727, +	0x84c, 0x27272727, +	0x850, 0x00000000, +	0x854, 0x00000000, +	0x858, 0x569a569a, +	0x85c, 0x0c1b25a4, +	0x860, 0x66e60230, +	0x864, 0x061f0130, +	0x868, 0x27272727, +	0x86c, 0x272b2b2b, +	0x870, 0x07000700, +	0x874, 0x22188000, +	0x878, 0x08080808, +	0x87c, 0x00007ff8, +	0x880, 0xc0083070, +	0x884, 0x00000cd5, +	0x888, 0x00000000, +	0x88c, 0xcc0000c0, +	0x890, 0x00000800, +	0x894, 0xfffffffe, +	0x898, 0x40302010, +	0x89c, 0x00706050, +	0x900, 0x00000000, +	0x904, 0x00000023, +	0x908, 0x00000000, +	0x90c, 0x81121313, +	0xa00, 0x00d047c8, +	0xa04, 0x80ff000c, +	0xa08, 0x8c838300, +	0xa0c, 0x2e68120f, +	0xa10, 0x9500bb78, +	0xa14, 0x11144028, +	0xa18, 0x00881117, +	0xa1c, 0x89140f00, +	0xa20, 0x1a1b0000, +	0xa24, 0x090e1317, +	0xa28, 0x00000204, +	0xa2c, 0x00d30000, +	0xa70, 0x101fbf00, +	0xa74, 0x00000007, +	0xc00, 0x40071d40, +	0xc04, 0x03a05633, +	0xc08, 0x001000e4, +	0xc0c, 0x6c6c6c6c, +	0xc10, 0x08800000, +	0xc14, 0x40000100, +	0xc18, 0x08800000, +	0xc1c, 0x40000100, +	0xc20, 0x00000000, +	0xc24, 0x00000000, +	0xc28, 0x00000000, +	0xc2c, 0x00000000, +	0xc30, 0x69e9ac44, +	0xc34, 0x469652cf, +	0xc38, 0x49795994, +	0xc3c, 0x0a979718, +	0xc40, 0x1f7c403f, +	0xc44, 0x000100b7, +	0xc48, 0xec020107, +	0xc4c, 0x007f037f, +	0xc50, 0x69543420, +	0xc54, 0x43bc009e, +	0xc58, 0x69543420, +	0xc5c, 0x433c00a8, +	0xc60, 0x00000000, +	0xc64, 0x5116848b, +	0xc68, 0x47c00bff, +	0xc6c, 0x00000036, +	0xc70, 0x2c7f000d, +	0xc74, 0x058610db, +	0xc78, 0x0000001f, +	0xc7c, 0x40b95612, +	0xc80, 0x40000100, +	0xc84, 0x20f60000, +	0xc88, 0x40000100, +	0xc8c, 0x20e00000, +	0xc90, 0x00121820, +	0xc94, 0x00000007, +	0xc98, 0x00121820, +	0xc9c, 0x00007f7f, +	0xca0, 0x00000000, +	0xca4, 0x00000080, +	0xca8, 0x00000000, +	0xcac, 0x00000000, +	0xcb0, 0x00000000, +	0xcb4, 0x00000000, +	0xcb8, 0x00000000, +	0xcbc, 0x28000000, +	0xcc0, 0x00000000, +	0xcc4, 0x00000000, +	0xcc8, 0x00000000, +	0xccc, 0x00000000, +	0xcd0, 0x00000000, +	0xcd4, 0x00000000, +	0xcd8, 0x64b11e20, +	0xcdc, 0xe8767533, +	0xce0, 0x00222222, +	0xce4, 0x00000000, +	0xce8, 0x37644302, +	0xcec, 0x2f97d40c, +	0xd00, 0x00080740, +	0xd04, 0x00020403, +	0xd08, 0x0000907f, +	0xd0c, 0x20010201, +	0xd10, 0xa0633333, +	0xd14, 0x3333bc43, +	0xd18, 0x7a8f5b6b, +	0xd2c, 0xcc979975, +	0xd30, 0x00000000, +	0xd34, 0x80608404, +	0xd38, 0x00000000, +	0xd3c, 0x00027293, +	0xd40, 0x00000000, +	0xd44, 0x00000000, +	0xd48, 0x00000000, +	0xd4c, 0x00000000, +	0xd50, 0x6437140a, +	0xd54, 0x00000000, +	0xd58, 0x00000000, +	0xd5c, 0x30032064, +	0xd60, 0x4653de68, +	0xd64, 0x04518a3c, +	0xd68, 0x00002101, +	0xd6c, 0x2a201c16, +	0xd70, 0x1812362e, +	0xd74, 0x322c2220, +	0xd78, 0x000e3c24, +	0xe00, 0x2a2a2a2a, +	0xe04, 0x2a2a2a2a, +	0xe08, 0x03902a2a, +	0xe10, 0x2a2a2a2a, +	0xe14, 0x2a2a2a2a, +	0xe18, 0x2a2a2a2a, +	0xe1c, 0x2a2a2a2a, +	0xe28, 0x00000000, +	0xe30, 0x1000dc1f, +	0xe34, 0x10008c1f, +	0xe38, 0x02140102, +	0xe3c, 0x681604c2, +	0xe40, 0x01007c00, +	0xe44, 0x01004800, +	0xe48, 0xfb000000, +	0xe4c, 0x000028d1, +	0xe50, 0x1000dc1f, +	0xe54, 0x10008c1f, +	0xe58, 0x02140102, +	0xe5c, 0x28160d05, +	0xe60, 0x00000010, +	0xe68, 0x001b25a4, +	0xe6c, 0x63db25a4, +	0xe70, 0x63db25a4, +	0xe74, 0x0c126da4, +	0xe78, 0x0c126da4, +	0xe7c, 0x0c126da4, +	0xe80, 0x0c126da4, +	0xe84, 0x63db25a4, +	0xe88, 0x0c126da4, +	0xe8c, 0x63db25a4, +	0xed0, 0x63db25a4, +	0xed4, 0x63db25a4, +	0xed8, 0x63db25a4, +	0xedc, 0x001b25a4, +	0xee0, 0x001b25a4, +	0xeec, 0x6fdb25a4, +	0xf14, 0x00000003, +	0xf1c, 0x00000064, +	0xf4c, 0x00000004, +	0xf00, 0x00000300, +}; + +u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH] = { +	0xe00, 0xffffffff, 0x07090c0c, +	0xe04, 0xffffffff, 0x01020405, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x0b0c0c0e, +	0xe14, 0xffffffff, 0x01030506, +	0xe18, 0xffffffff, 0x0b0c0d0e, +	0xe1c, 0xffffffff, 0x01030509, +	0x830, 0xffffffff, 0x07090c0c, +	0x834, 0xffffffff, 0x01020405, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x0b0c0c0e, +	0x848, 0xffffffff, 0x01030506, +	0x84c, 0xffffffff, 0x0b0c0d0e, +	0x868, 0xffffffff, 0x01030509, +	0xe00, 0xffffffff, 0x00000000, +	0xe04, 0xffffffff, 0x00000000, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x00000000, +	0xe14, 0xffffffff, 0x00000000, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x00000000, +	0x834, 0xffffffff, 0x00000000, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x00000000, +	0x848, 0xffffffff, 0x00000000, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x04040404, +	0xe04, 0xffffffff, 0x00020204, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x06060606, +	0xe14, 0xffffffff, 0x00020406, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x04040404, +	0x834, 0xffffffff, 0x00020204, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x06060606, +	0x848, 0xffffffff, 0x00020406, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x00000000, +	0xe04, 0xffffffff, 0x00000000, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x00000000, +	0xe14, 0xffffffff, 0x00000000, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x00000000, +	0x834, 0xffffffff, 0x00000000, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x00000000, +	0x848, 0xffffffff, 0x00000000, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x00000000, +	0xe04, 0xffffffff, 0x00000000, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x00000000, +	0xe14, 0xffffffff, 0x00000000, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x00000000, +	0x834, 0xffffffff, 0x00000000, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x00000000, +	0x848, 0xffffffff, 0x00000000, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x04040404, +	0xe04, 0xffffffff, 0x00020204, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x00000000, +	0xe14, 0xffffffff, 0x00000000, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x04040404, +	0x834, 0xffffffff, 0x00020204, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x00000000, +	0x848, 0xffffffff, 0x00000000, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x00000000, +	0xe04, 0xffffffff, 0x00000000, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x00000000, +	0xe14, 0xffffffff, 0x00000000, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x00000000, +	0x834, 0xffffffff, 0x00000000, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x00000000, +	0x848, 0xffffffff, 0x00000000, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x04040404, +	0xe04, 0xffffffff, 0x00020204, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x08080808, +	0xe14, 0xffffffff, 0x00040408, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x04040404, +	0x834, 0xffffffff, 0x00020204, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x08080808, +	0x848, 0xffffffff, 0x00040408, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x04040404, +	0xe04, 0xffffffff, 0x00020204, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x08080808, +	0xe14, 0xffffffff, 0x00040408, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x04040404, +	0x834, 0xffffffff, 0x00020204, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x08080808, +	0x848, 0xffffffff, 0x00040408, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x04040404, +	0xe04, 0xffffffff, 0x00020204, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x08080808, +	0xe14, 0xffffffff, 0x00040408, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x04040404, +	0x834, 0xffffffff, 0x00020204, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x08080808, +	0x848, 0xffffffff, 0x00040408, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x04040404, +	0xe04, 0xffffffff, 0x00020204, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x08080808, +	0xe14, 0xffffffff, 0x00040408, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x04040404, +	0x834, 0xffffffff, 0x00020204, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x08080808, +	0x848, 0xffffffff, 0x00040408, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x04040404, +	0xe04, 0xffffffff, 0x00020204, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x08080808, +	0xe14, 0xffffffff, 0x00040408, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x04040404, +	0x834, 0xffffffff, 0x00020204, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x08080808, +	0x848, 0xffffffff, 0x00040408, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +	0xe00, 0xffffffff, 0x04040404, +	0xe04, 0xffffffff, 0x00020204, +	0xe08, 0x0000ff00, 0x00000000, +	0x86c, 0xffffff00, 0x00000000, +	0xe10, 0xffffffff, 0x08080808, +	0xe14, 0xffffffff, 0x00040408, +	0xe18, 0xffffffff, 0x00000000, +	0xe1c, 0xffffffff, 0x00000000, +	0x830, 0xffffffff, 0x04040404, +	0x834, 0xffffffff, 0x00020204, +	0x838, 0xffffff00, 0x00000000, +	0x86c, 0x000000ff, 0x00000000, +	0x83c, 0xffffffff, 0x08080808, +	0x848, 0xffffffff, 0x00040408, +	0x84c, 0xffffffff, 0x00000000, +	0x868, 0xffffffff, 0x00000000, +}; + +u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH] = { +	0x000, 0x00030000, +	0x001, 0x00030000, +	0x002, 0x00000000, +	0x003, 0x00018c63, +	0x004, 0x00018c63, +	0x008, 0x00084000, +	0x00b, 0x0001c000, +	0x00e, 0x00018c67, +	0x00f, 0x00000851, +	0x014, 0x00021440, +	0x018, 0x00017524, +	0x019, 0x00000000, +	0x01d, 0x000a1290, +	0x023, 0x00001558, +	0x01a, 0x00030a99, +	0x01b, 0x00040b00, +	0x01c, 0x000fc339, +	0x03a, 0x000a57eb, +	0x03b, 0x00020000, +	0x03c, 0x000ff454, +	0x020, 0x0000aa52, +	0x021, 0x00054000, +	0x040, 0x0000aa52, +	0x041, 0x00014000, +	0x025, 0x000803be, +	0x026, 0x000fc638, +	0x027, 0x00077c18, +	0x028, 0x000de471, +	0x029, 0x000d7110, +	0x02a, 0x0008cb04, +	0x02b, 0x0004128b, +	0x02c, 0x00001840, +	0x043, 0x0002444f, +	0x044, 0x0001adb0, +	0x045, 0x00056467, +	0x046, 0x0008992c, +	0x047, 0x0000452c, +	0x048, 0x000f9c43, +	0x049, 0x00002e0c, +	0x04a, 0x000546eb, +	0x04b, 0x0008966c, +	0x04c, 0x0000dde9, +	0x018, 0x00007401, +	0x000, 0x00070000, +	0x012, 0x000dc000, +	0x012, 0x00090000, +	0x012, 0x00051000, +	0x012, 0x00012000, +	0x013, 0x000287b7, +	0x013, 0x000247ab, +	0x013, 0x0002079f, +	0x013, 0x0001c793, +	0x013, 0x0001839b, +	0x013, 0x00014392, +	0x013, 0x0001019a, +	0x013, 0x0000c191, +	0x013, 0x00008194, +	0x013, 0x000040a0, +	0x013, 0x00000018, +	0x015, 0x0000f424, +	0x015, 0x0004f424, +	0x015, 0x0008f424, +	0x016, 0x000e1330, +	0x016, 0x000a1330, +	0x016, 0x00061330, +	0x016, 0x00021330, +	0x018, 0x00017524, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bc, +	0x013, 0x000247b0, +	0x013, 0x000203b4, +	0x013, 0x0001c3a8, +	0x013, 0x000181b4, +	0x013, 0x000141a8, +	0x013, 0x000100b0, +	0x013, 0x0000c0a4, +	0x013, 0x0000b02c, +	0x013, 0x00004020, +	0x013, 0x00000014, +	0x015, 0x0000f4c3, +	0x015, 0x0004f4c3, +	0x015, 0x0008f4c3, +	0x016, 0x000e085f, +	0x016, 0x000a085f, +	0x016, 0x0006085f, +	0x016, 0x0002085f, +	0x018, 0x00037524, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bc, +	0x013, 0x000247b0, +	0x013, 0x000203b4, +	0x013, 0x0001c3a8, +	0x013, 0x000181b4, +	0x013, 0x000141a8, +	0x013, 0x000100b0, +	0x013, 0x0000c0a4, +	0x013, 0x0000b02c, +	0x013, 0x00004020, +	0x013, 0x00000014, +	0x015, 0x0000f4c3, +	0x015, 0x0004f4c3, +	0x015, 0x0008f4c3, +	0x016, 0x000e085f, +	0x016, 0x000a085f, +	0x016, 0x0006085f, +	0x016, 0x0002085f, +	0x018, 0x00057568, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bc, +	0x013, 0x000247b0, +	0x013, 0x000203b4, +	0x013, 0x0001c3a8, +	0x013, 0x000181b4, +	0x013, 0x000141a8, +	0x013, 0x000100b0, +	0x013, 0x0000c0a4, +	0x013, 0x0000b02c, +	0x013, 0x00004020, +	0x013, 0x00000014, +	0x015, 0x0000f4c3, +	0x015, 0x0004f4c3, +	0x015, 0x0008f4c3, +	0x016, 0x000e085f, +	0x016, 0x000a085f, +	0x016, 0x0006085f, +	0x016, 0x0002085f, +	0x030, 0x0004470f, +	0x031, 0x00044ff0, +	0x032, 0x00000070, +	0x033, 0x000dd480, +	0x034, 0x000ffac0, +	0x035, 0x000b80c0, +	0x036, 0x00077000, +	0x037, 0x00064ff2, +	0x038, 0x000e7661, +	0x039, 0x00000e90, +	0x000, 0x00030000, +	0x018, 0x0000f401, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x01e, 0x00088009, +	0x01f, 0x00080003, +	0x0fe, 0x00000000, +	0x01e, 0x00088001, +	0x01f, 0x00080000, +	0x0fe, 0x00000000, +	0x018, 0x00097524, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x02b, 0x00041289, +	0x0fe, 0x00000000, +	0x02d, 0x0006aaaa, +	0x02e, 0x000b4d01, +	0x02d, 0x00080000, +	0x02e, 0x00004d02, +	0x02d, 0x00095555, +	0x02e, 0x00054d03, +	0x02d, 0x000aaaaa, +	0x02e, 0x000b4d04, +	0x02d, 0x000c0000, +	0x02e, 0x00004d05, +	0x02d, 0x000d5555, +	0x02e, 0x00054d06, +	0x02d, 0x000eaaaa, +	0x02e, 0x000b4d07, +	0x02d, 0x00000000, +	0x02e, 0x00005108, +	0x02d, 0x00015555, +	0x02e, 0x00055109, +	0x02d, 0x0002aaaa, +	0x02e, 0x000b510a, +	0x02d, 0x00040000, +	0x02e, 0x0000510b, +	0x02d, 0x00055555, +	0x02e, 0x0005510c, +}; + +u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH] = { +	0x000, 0x00030000, +	0x001, 0x00030000, +	0x002, 0x00000000, +	0x003, 0x00018c63, +	0x004, 0x00018c63, +	0x008, 0x00084000, +	0x00b, 0x0001c000, +	0x00e, 0x00018c67, +	0x00f, 0x00000851, +	0x014, 0x00021440, +	0x018, 0x00007401, +	0x019, 0x00000060, +	0x01d, 0x000a1290, +	0x023, 0x00001558, +	0x01a, 0x00030a99, +	0x01b, 0x00040b00, +	0x01c, 0x000fc339, +	0x03a, 0x000a57eb, +	0x03b, 0x00020000, +	0x03c, 0x000ff454, +	0x020, 0x0000aa52, +	0x021, 0x00054000, +	0x040, 0x0000aa52, +	0x041, 0x00014000, +	0x025, 0x000803be, +	0x026, 0x000fc638, +	0x027, 0x00077c18, +	0x028, 0x000d1c31, +	0x029, 0x000d7110, +	0x02a, 0x000aeb04, +	0x02b, 0x0004128b, +	0x02c, 0x00001840, +	0x043, 0x0002444f, +	0x044, 0x0001adb0, +	0x045, 0x00056467, +	0x046, 0x0008992c, +	0x047, 0x0000452c, +	0x048, 0x000f9c43, +	0x049, 0x00002e0c, +	0x04a, 0x000546eb, +	0x04b, 0x0008966c, +	0x04c, 0x0000dde9, +	0x018, 0x00007401, +	0x000, 0x00070000, +	0x012, 0x000dc000, +	0x012, 0x00090000, +	0x012, 0x00051000, +	0x012, 0x00012000, +	0x013, 0x000287b7, +	0x013, 0x000247ab, +	0x013, 0x0002079f, +	0x013, 0x0001c793, +	0x013, 0x0001839b, +	0x013, 0x00014392, +	0x013, 0x0001019a, +	0x013, 0x0000c191, +	0x013, 0x00008194, +	0x013, 0x000040a0, +	0x013, 0x00000018, +	0x015, 0x0000f424, +	0x015, 0x0004f424, +	0x015, 0x0008f424, +	0x016, 0x000e1330, +	0x016, 0x000a1330, +	0x016, 0x00061330, +	0x016, 0x00021330, +	0x018, 0x00017524, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bc, +	0x013, 0x000247b0, +	0x013, 0x000203b4, +	0x013, 0x0001c3a8, +	0x013, 0x000181b4, +	0x013, 0x000141a8, +	0x013, 0x000100b0, +	0x013, 0x0000c0a4, +	0x013, 0x0000b02c, +	0x013, 0x00004020, +	0x013, 0x00000014, +	0x015, 0x0000f4c3, +	0x015, 0x0004f4c3, +	0x015, 0x0008f4c3, +	0x016, 0x000e085f, +	0x016, 0x000a085f, +	0x016, 0x0006085f, +	0x016, 0x0002085f, +	0x018, 0x00037524, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bc, +	0x013, 0x000247b0, +	0x013, 0x000203b4, +	0x013, 0x0001c3a8, +	0x013, 0x000181b4, +	0x013, 0x000141a8, +	0x013, 0x000100b0, +	0x013, 0x0000c0a4, +	0x013, 0x0000b02c, +	0x013, 0x00004020, +	0x013, 0x00000014, +	0x015, 0x0000f4c3, +	0x015, 0x0004f4c3, +	0x015, 0x0008f4c3, +	0x016, 0x000e085f, +	0x016, 0x000a085f, +	0x016, 0x0006085f, +	0x016, 0x0002085f, +	0x018, 0x00057524, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bc, +	0x013, 0x000247b0, +	0x013, 0x000203b4, +	0x013, 0x0001c3a8, +	0x013, 0x000181b4, +	0x013, 0x000141a8, +	0x013, 0x000100b0, +	0x013, 0x0000c0a4, +	0x013, 0x0000b02c, +	0x013, 0x00004020, +	0x013, 0x00000014, +	0x015, 0x0000f4c3, +	0x015, 0x0004f4c3, +	0x015, 0x0008f4c3, +	0x016, 0x000e085f, +	0x016, 0x000a085f, +	0x016, 0x0006085f, +	0x016, 0x0002085f, +	0x030, 0x0004470f, +	0x031, 0x00044ff0, +	0x032, 0x00000070, +	0x033, 0x000dd480, +	0x034, 0x000ffac0, +	0x035, 0x000b80c0, +	0x036, 0x00077000, +	0x037, 0x00064ff2, +	0x038, 0x000e7661, +	0x039, 0x00000e90, +	0x000, 0x00030000, +	0x018, 0x0000f401, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x01e, 0x00088009, +	0x01f, 0x00080003, +	0x0fe, 0x00000000, +	0x01e, 0x00088001, +	0x01f, 0x00080000, +	0x0fe, 0x00000000, +	0x018, 0x00087401, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x02b, 0x00041289, +	0x0fe, 0x00000000, +	0x02d, 0x00066666, +	0x02e, 0x00064001, +	0x02d, 0x00091111, +	0x02e, 0x00014002, +	0x02d, 0x000bbbbb, +	0x02e, 0x000b4003, +	0x02d, 0x000e6666, +	0x02e, 0x00064004, +	0x02d, 0x00088888, +	0x02e, 0x00084005, +	0x02d, 0x0009dddd, +	0x02e, 0x000d4006, +	0x02d, 0x000b3333, +	0x02e, 0x00034007, +	0x02d, 0x00048888, +	0x02e, 0x00084408, +	0x02d, 0x000bbbbb, +	0x02e, 0x000b4409, +	0x02d, 0x000e6666, +	0x02e, 0x0006440a, +	0x02d, 0x00011111, +	0x02e, 0x0001480b, +	0x02d, 0x0003bbbb, +	0x02e, 0x000b480c, +	0x02d, 0x00066666, +	0x02e, 0x0006480d, +	0x02d, 0x000ccccc, +	0x02e, 0x000c480e, +}; + +u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH] = { +	0x000, 0x00030000, +	0x001, 0x00030000, +	0x002, 0x00000000, +	0x003, 0x00018c63, +	0x004, 0x00018c63, +	0x008, 0x00084000, +	0x00b, 0x0001c000, +	0x00e, 0x00018c67, +	0x00f, 0x00000851, +	0x014, 0x00021440, +	0x018, 0x00017524, +	0x019, 0x00000000, +	0x01d, 0x000a1290, +	0x023, 0x00001558, +	0x01a, 0x00030a99, +	0x01b, 0x00040b00, +	0x01c, 0x000fc339, +	0x03a, 0x000a57eb, +	0x03b, 0x00020000, +	0x03c, 0x000ff454, +	0x020, 0x0000aa52, +	0x021, 0x00054000, +	0x040, 0x0000aa52, +	0x041, 0x00014000, +	0x025, 0x000803be, +	0x026, 0x000fc638, +	0x027, 0x00077c18, +	0x028, 0x000de471, +	0x029, 0x000d7110, +	0x02a, 0x0008eb04, +	0x02b, 0x0004128b, +	0x02c, 0x00001840, +	0x043, 0x0002444f, +	0x044, 0x0001adb0, +	0x045, 0x00056467, +	0x046, 0x0008992c, +	0x047, 0x0000452c, +	0x048, 0x000c0443, +	0x049, 0x00000730, +	0x04a, 0x00050f0f, +	0x04b, 0x000896ee, +	0x04c, 0x0000ddee, +	0x018, 0x00007401, +	0x000, 0x00070000, +	0x012, 0x000dc000, +	0x012, 0x00090000, +	0x012, 0x00051000, +	0x012, 0x00012000, +	0x013, 0x000287b7, +	0x013, 0x000247ab, +	0x013, 0x0002079f, +	0x013, 0x0001c793, +	0x013, 0x0001839b, +	0x013, 0x00014392, +	0x013, 0x0001019a, +	0x013, 0x0000c191, +	0x013, 0x00008194, +	0x013, 0x000040a0, +	0x013, 0x00000018, +	0x015, 0x0000f424, +	0x015, 0x0004f424, +	0x015, 0x0008f424, +	0x016, 0x000e1330, +	0x016, 0x000a1330, +	0x016, 0x00061330, +	0x016, 0x00021330, +	0x018, 0x00017524, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bf, +	0x013, 0x000247b3, +	0x013, 0x000207a7, +	0x013, 0x0001c79b, +	0x013, 0x0001839f, +	0x013, 0x00014393, +	0x013, 0x00010399, +	0x013, 0x0000c38d, +	0x013, 0x00008199, +	0x013, 0x0000418d, +	0x013, 0x00000099, +	0x015, 0x0000f495, +	0x015, 0x0004f495, +	0x015, 0x0008f495, +	0x016, 0x000e1874, +	0x016, 0x000a1874, +	0x016, 0x00061874, +	0x016, 0x00021874, +	0x018, 0x00037564, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bf, +	0x013, 0x000247b3, +	0x013, 0x000207a7, +	0x013, 0x0001c79b, +	0x013, 0x0001839f, +	0x013, 0x00014393, +	0x013, 0x00010399, +	0x013, 0x0000c38d, +	0x013, 0x00008199, +	0x013, 0x0000418d, +	0x013, 0x00000099, +	0x015, 0x0000f495, +	0x015, 0x0004f495, +	0x015, 0x0008f495, +	0x016, 0x000e1874, +	0x016, 0x000a1874, +	0x016, 0x00061874, +	0x016, 0x00021874, +	0x018, 0x00057595, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bf, +	0x013, 0x000247b3, +	0x013, 0x000207a7, +	0x013, 0x0001c79b, +	0x013, 0x0001839f, +	0x013, 0x00014393, +	0x013, 0x00010399, +	0x013, 0x0000c38d, +	0x013, 0x00008199, +	0x013, 0x0000418d, +	0x013, 0x00000099, +	0x015, 0x0000f495, +	0x015, 0x0004f495, +	0x015, 0x0008f495, +	0x016, 0x000e1874, +	0x016, 0x000a1874, +	0x016, 0x00061874, +	0x016, 0x00021874, +	0x030, 0x0004470f, +	0x031, 0x00044ff0, +	0x032, 0x00000070, +	0x033, 0x000dd480, +	0x034, 0x000ffac0, +	0x035, 0x000b80c0, +	0x036, 0x00077000, +	0x037, 0x00064ff2, +	0x038, 0x000e7661, +	0x039, 0x00000e90, +	0x000, 0x00030000, +	0x018, 0x0000f401, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x01e, 0x00088009, +	0x01f, 0x00080003, +	0x0fe, 0x00000000, +	0x01e, 0x00088001, +	0x01f, 0x00080000, +	0x0fe, 0x00000000, +	0x018, 0x00097524, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x02b, 0x00041289, +	0x0fe, 0x00000000, +	0x02d, 0x0006aaaa, +	0x02e, 0x000b4d01, +	0x02d, 0x00080000, +	0x02e, 0x00004d02, +	0x02d, 0x00095555, +	0x02e, 0x00054d03, +	0x02d, 0x000aaaaa, +	0x02e, 0x000b4d04, +	0x02d, 0x000c0000, +	0x02e, 0x00004d05, +	0x02d, 0x000d5555, +	0x02e, 0x00054d06, +	0x02d, 0x000eaaaa, +	0x02e, 0x000b4d07, +	0x02d, 0x00000000, +	0x02e, 0x00005108, +	0x02d, 0x00015555, +	0x02e, 0x00055109, +	0x02d, 0x0002aaaa, +	0x02e, 0x000b510a, +	0x02d, 0x00040000, +	0x02e, 0x0000510b, +	0x02d, 0x00055555, +	0x02e, 0x0005510c, +}; + +u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH] = { +	0x000, 0x00030000, +	0x001, 0x00030000, +	0x002, 0x00000000, +	0x003, 0x00018c63, +	0x004, 0x00018c63, +	0x008, 0x00084000, +	0x00b, 0x0001c000, +	0x00e, 0x00018c67, +	0x00f, 0x00000851, +	0x014, 0x00021440, +	0x018, 0x00007401, +	0x019, 0x00000060, +	0x01d, 0x000a1290, +	0x023, 0x00001558, +	0x01a, 0x00030a99, +	0x01b, 0x00040b00, +	0x01c, 0x000fc339, +	0x03a, 0x000a57eb, +	0x03b, 0x00020000, +	0x03c, 0x000ff454, +	0x020, 0x0000aa52, +	0x021, 0x00054000, +	0x040, 0x0000aa52, +	0x041, 0x00014000, +	0x025, 0x000803be, +	0x026, 0x000fc638, +	0x027, 0x00077c18, +	0x028, 0x000d1c31, +	0x029, 0x000d7110, +	0x02a, 0x000aeb04, +	0x02b, 0x0004128b, +	0x02c, 0x00001840, +	0x043, 0x0002444f, +	0x044, 0x0001adb0, +	0x045, 0x00056467, +	0x046, 0x0008992c, +	0x047, 0x0000452c, +	0x048, 0x000c0443, +	0x049, 0x00000730, +	0x04a, 0x00050f0f, +	0x04b, 0x000896ee, +	0x04c, 0x0000ddee, +	0x018, 0x00007401, +	0x000, 0x00070000, +	0x012, 0x000dc000, +	0x012, 0x00090000, +	0x012, 0x00051000, +	0x012, 0x00012000, +	0x013, 0x000287b7, +	0x013, 0x000247ab, +	0x013, 0x0002079f, +	0x013, 0x0001c793, +	0x013, 0x0001839b, +	0x013, 0x00014392, +	0x013, 0x0001019a, +	0x013, 0x0000c191, +	0x013, 0x00008194, +	0x013, 0x000040a0, +	0x013, 0x00000018, +	0x015, 0x0000f424, +	0x015, 0x0004f424, +	0x015, 0x0008f424, +	0x016, 0x000e1330, +	0x016, 0x000a1330, +	0x016, 0x00061330, +	0x016, 0x00021330, +	0x018, 0x00017524, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bf, +	0x013, 0x000247b3, +	0x013, 0x000207a7, +	0x013, 0x0001c79b, +	0x013, 0x0001839f, +	0x013, 0x00014393, +	0x013, 0x00010399, +	0x013, 0x0000c38d, +	0x013, 0x00008199, +	0x013, 0x0000418d, +	0x013, 0x00000099, +	0x015, 0x0000f495, +	0x015, 0x0004f495, +	0x015, 0x0008f495, +	0x016, 0x000e1874, +	0x016, 0x000a1874, +	0x016, 0x00061874, +	0x016, 0x00021874, +	0x018, 0x00037564, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bf, +	0x013, 0x000247b3, +	0x013, 0x000207a7, +	0x013, 0x0001c79b, +	0x013, 0x0001839f, +	0x013, 0x00014393, +	0x013, 0x00010399, +	0x013, 0x0000c38d, +	0x013, 0x00008199, +	0x013, 0x0000418d, +	0x013, 0x00000099, +	0x015, 0x0000f495, +	0x015, 0x0004f495, +	0x015, 0x0008f495, +	0x016, 0x000e1874, +	0x016, 0x000a1874, +	0x016, 0x00061874, +	0x016, 0x00021874, +	0x018, 0x00057595, +	0x000, 0x00070000, +	0x012, 0x000cf000, +	0x012, 0x000bc000, +	0x012, 0x00078000, +	0x012, 0x00000000, +	0x013, 0x000287bf, +	0x013, 0x000247b3, +	0x013, 0x000207a7, +	0x013, 0x0001c79b, +	0x013, 0x0001839f, +	0x013, 0x00014393, +	0x013, 0x00010399, +	0x013, 0x0000c38d, +	0x013, 0x00008199, +	0x013, 0x0000418d, +	0x013, 0x00000099, +	0x015, 0x0000f495, +	0x015, 0x0004f495, +	0x015, 0x0008f495, +	0x016, 0x000e1874, +	0x016, 0x000a1874, +	0x016, 0x00061874, +	0x016, 0x00021874, +	0x030, 0x0004470f, +	0x031, 0x00044ff0, +	0x032, 0x00000070, +	0x033, 0x000dd480, +	0x034, 0x000ffac0, +	0x035, 0x000b80c0, +	0x036, 0x00077000, +	0x037, 0x00064ff2, +	0x038, 0x000e7661, +	0x039, 0x00000e90, +	0x000, 0x00030000, +	0x018, 0x0000f401, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x01e, 0x00088009, +	0x01f, 0x00080003, +	0x0fe, 0x00000000, +	0x01e, 0x00088001, +	0x01f, 0x00080000, +	0x0fe, 0x00000000, +	0x018, 0x00087401, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x0fe, 0x00000000, +	0x02b, 0x00041289, +	0x0fe, 0x00000000, +	0x02d, 0x00066666, +	0x02e, 0x00064001, +	0x02d, 0x00091111, +	0x02e, 0x00014002, +	0x02d, 0x000bbbbb, +	0x02e, 0x000b4003, +	0x02d, 0x000e6666, +	0x02e, 0x00064004, +	0x02d, 0x00088888, +	0x02e, 0x00084005, +	0x02d, 0x0009dddd, +	0x02e, 0x000d4006, +	0x02d, 0x000b3333, +	0x02e, 0x00034007, +	0x02d, 0x00048888, +	0x02e, 0x00084408, +	0x02d, 0x000bbbbb, +	0x02e, 0x000b4409, +	0x02d, 0x000e6666, +	0x02e, 0x0006440a, +	0x02d, 0x00011111, +	0x02e, 0x0001480b, +	0x02d, 0x0003bbbb, +	0x02e, 0x000b480c, +	0x02d, 0x00066666, +	0x02e, 0x0006480d, +	0x02d, 0x000ccccc, +	0x02e, 0x000c480e, +}; + +u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH] = { +	0x420, 0x00000080, +	0x423, 0x00000000, +	0x430, 0x00000000, +	0x431, 0x00000000, +	0x432, 0x00000000, +	0x433, 0x00000001, +	0x434, 0x00000004, +	0x435, 0x00000005, +	0x436, 0x00000006, +	0x437, 0x00000007, +	0x438, 0x00000000, +	0x439, 0x00000000, +	0x43a, 0x00000000, +	0x43b, 0x00000001, +	0x43c, 0x00000004, +	0x43d, 0x00000005, +	0x43e, 0x00000006, +	0x43f, 0x00000007, +	0x440, 0x00000050, +	0x441, 0x00000001, +	0x442, 0x00000000, +	0x444, 0x00000015, +	0x445, 0x000000f0, +	0x446, 0x0000000f, +	0x447, 0x00000000, +	0x462, 0x00000008, +	0x463, 0x00000003, +	0x4c8, 0x000000ff, +	0x4c9, 0x00000008, +	0x4cc, 0x000000ff, +	0x4cd, 0x000000ff, +	0x4ce, 0x00000001, +	0x500, 0x00000026, +	0x501, 0x000000a2, +	0x502, 0x0000002f, +	0x503, 0x00000000, +	0x504, 0x00000028, +	0x505, 0x000000a3, +	0x506, 0x0000005e, +	0x507, 0x00000000, +	0x508, 0x0000002b, +	0x509, 0x000000a4, +	0x50a, 0x0000005e, +	0x50b, 0x00000000, +	0x50c, 0x0000004f, +	0x50d, 0x000000a4, +	0x50e, 0x00000000, +	0x50f, 0x00000000, +	0x512, 0x0000001c, +	0x514, 0x0000000a, +	0x515, 0x00000010, +	0x516, 0x0000000a, +	0x517, 0x00000010, +	0x51a, 0x00000016, +	0x524, 0x0000000f, +	0x525, 0x0000004f, +	0x546, 0x00000040, +	0x547, 0x00000000, +	0x550, 0x00000010, +	0x551, 0x00000010, +	0x559, 0x00000002, +	0x55a, 0x00000002, +	0x55d, 0x000000ff, +	0x605, 0x00000030, +	0x608, 0x0000000e, +	0x609, 0x0000002a, +	0x652, 0x00000020, +	0x63c, 0x0000000a, +	0x63d, 0x0000000a, +	0x63e, 0x0000000e, +	0x63f, 0x0000000e, +	0x66e, 0x00000005, +	0x700, 0x00000021, +	0x701, 0x00000043, +	0x702, 0x00000065, +	0x703, 0x00000087, +	0x708, 0x00000021, +	0x709, 0x00000043, +	0x70a, 0x00000065, +	0x70b, 0x00000087, +}; + +u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH] = { +	0xc78, 0x7b000001, +	0xc78, 0x7b010001, +	0xc78, 0x7b020001, +	0xc78, 0x7b030001, +	0xc78, 0x7b040001, +	0xc78, 0x7b050001, +	0xc78, 0x7b060001, +	0xc78, 0x7a070001, +	0xc78, 0x79080001, +	0xc78, 0x78090001, +	0xc78, 0x770a0001, +	0xc78, 0x760b0001, +	0xc78, 0x750c0001, +	0xc78, 0x740d0001, +	0xc78, 0x730e0001, +	0xc78, 0x720f0001, +	0xc78, 0x71100001, +	0xc78, 0x70110001, +	0xc78, 0x6f120001, +	0xc78, 0x6e130001, +	0xc78, 0x6d140001, +	0xc78, 0x6c150001, +	0xc78, 0x6b160001, +	0xc78, 0x6a170001, +	0xc78, 0x69180001, +	0xc78, 0x68190001, +	0xc78, 0x671a0001, +	0xc78, 0x661b0001, +	0xc78, 0x651c0001, +	0xc78, 0x641d0001, +	0xc78, 0x631e0001, +	0xc78, 0x621f0001, +	0xc78, 0x61200001, +	0xc78, 0x60210001, +	0xc78, 0x49220001, +	0xc78, 0x48230001, +	0xc78, 0x47240001, +	0xc78, 0x46250001, +	0xc78, 0x45260001, +	0xc78, 0x44270001, +	0xc78, 0x43280001, +	0xc78, 0x42290001, +	0xc78, 0x412a0001, +	0xc78, 0x402b0001, +	0xc78, 0x262c0001, +	0xc78, 0x252d0001, +	0xc78, 0x242e0001, +	0xc78, 0x232f0001, +	0xc78, 0x22300001, +	0xc78, 0x21310001, +	0xc78, 0x20320001, +	0xc78, 0x06330001, +	0xc78, 0x05340001, +	0xc78, 0x04350001, +	0xc78, 0x03360001, +	0xc78, 0x02370001, +	0xc78, 0x01380001, +	0xc78, 0x00390001, +	0xc78, 0x003a0001, +	0xc78, 0x003b0001, +	0xc78, 0x003c0001, +	0xc78, 0x003d0001, +	0xc78, 0x003e0001, +	0xc78, 0x003f0001, +	0xc78, 0x7b400001, +	0xc78, 0x7b410001, +	0xc78, 0x7a420001, +	0xc78, 0x79430001, +	0xc78, 0x78440001, +	0xc78, 0x77450001, +	0xc78, 0x76460001, +	0xc78, 0x75470001, +	0xc78, 0x74480001, +	0xc78, 0x73490001, +	0xc78, 0x724a0001, +	0xc78, 0x714b0001, +	0xc78, 0x704c0001, +	0xc78, 0x6f4d0001, +	0xc78, 0x6e4e0001, +	0xc78, 0x6d4f0001, +	0xc78, 0x6c500001, +	0xc78, 0x6b510001, +	0xc78, 0x6a520001, +	0xc78, 0x69530001, +	0xc78, 0x68540001, +	0xc78, 0x67550001, +	0xc78, 0x66560001, +	0xc78, 0x65570001, +	0xc78, 0x64580001, +	0xc78, 0x63590001, +	0xc78, 0x625a0001, +	0xc78, 0x615b0001, +	0xc78, 0x605c0001, +	0xc78, 0x485d0001, +	0xc78, 0x475e0001, +	0xc78, 0x465f0001, +	0xc78, 0x45600001, +	0xc78, 0x44610001, +	0xc78, 0x43620001, +	0xc78, 0x42630001, +	0xc78, 0x41640001, +	0xc78, 0x40650001, +	0xc78, 0x27660001, +	0xc78, 0x26670001, +	0xc78, 0x25680001, +	0xc78, 0x24690001, +	0xc78, 0x236a0001, +	0xc78, 0x226b0001, +	0xc78, 0x216c0001, +	0xc78, 0x206d0001, +	0xc78, 0x206e0001, +	0xc78, 0x206f0001, +	0xc78, 0x20700001, +	0xc78, 0x20710001, +	0xc78, 0x20720001, +	0xc78, 0x20730001, +	0xc78, 0x20740001, +	0xc78, 0x20750001, +	0xc78, 0x20760001, +	0xc78, 0x20770001, +	0xc78, 0x20780001, +	0xc78, 0x20790001, +	0xc78, 0x207a0001, +	0xc78, 0x207b0001, +	0xc78, 0x207c0001, +	0xc78, 0x207d0001, +	0xc78, 0x207e0001, +	0xc78, 0x207f0001, +	0xc78, 0x38000002, +	0xc78, 0x38010002, +	0xc78, 0x38020002, +	0xc78, 0x38030002, +	0xc78, 0x38040002, +	0xc78, 0x38050002, +	0xc78, 0x38060002, +	0xc78, 0x38070002, +	0xc78, 0x38080002, +	0xc78, 0x3c090002, +	0xc78, 0x3e0a0002, +	0xc78, 0x400b0002, +	0xc78, 0x440c0002, +	0xc78, 0x480d0002, +	0xc78, 0x4c0e0002, +	0xc78, 0x500f0002, +	0xc78, 0x52100002, +	0xc78, 0x56110002, +	0xc78, 0x5a120002, +	0xc78, 0x5e130002, +	0xc78, 0x60140002, +	0xc78, 0x60150002, +	0xc78, 0x60160002, +	0xc78, 0x62170002, +	0xc78, 0x62180002, +	0xc78, 0x62190002, +	0xc78, 0x621a0002, +	0xc78, 0x621b0002, +	0xc78, 0x621c0002, +	0xc78, 0x621d0002, +	0xc78, 0x621e0002, +	0xc78, 0x621f0002, +	0xc78, 0x32000044, +	0xc78, 0x32010044, +	0xc78, 0x32020044, +	0xc78, 0x32030044, +	0xc78, 0x32040044, +	0xc78, 0x32050044, +	0xc78, 0x32060044, +	0xc78, 0x32070044, +	0xc78, 0x32080044, +	0xc78, 0x34090044, +	0xc78, 0x350a0044, +	0xc78, 0x360b0044, +	0xc78, 0x370c0044, +	0xc78, 0x380d0044, +	0xc78, 0x390e0044, +	0xc78, 0x3a0f0044, +	0xc78, 0x3e100044, +	0xc78, 0x42110044, +	0xc78, 0x44120044, +	0xc78, 0x46130044, +	0xc78, 0x4a140044, +	0xc78, 0x4e150044, +	0xc78, 0x50160044, +	0xc78, 0x55170044, +	0xc78, 0x5a180044, +	0xc78, 0x5e190044, +	0xc78, 0x641a0044, +	0xc78, 0x6e1b0044, +	0xc78, 0x6e1c0044, +	0xc78, 0x6e1d0044, +	0xc78, 0x6e1e0044, +	0xc78, 0x6e1f0044, +	0xc78, 0x6e1f0000, +}; + +u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH] = { +	0xc78, 0x7b000001, +	0xc78, 0x7b010001, +	0xc78, 0x7a020001, +	0xc78, 0x79030001, +	0xc78, 0x78040001, +	0xc78, 0x77050001, +	0xc78, 0x76060001, +	0xc78, 0x75070001, +	0xc78, 0x74080001, +	0xc78, 0x73090001, +	0xc78, 0x720a0001, +	0xc78, 0x710b0001, +	0xc78, 0x700c0001, +	0xc78, 0x6f0d0001, +	0xc78, 0x6e0e0001, +	0xc78, 0x6d0f0001, +	0xc78, 0x6c100001, +	0xc78, 0x6b110001, +	0xc78, 0x6a120001, +	0xc78, 0x69130001, +	0xc78, 0x68140001, +	0xc78, 0x67150001, +	0xc78, 0x66160001, +	0xc78, 0x65170001, +	0xc78, 0x64180001, +	0xc78, 0x63190001, +	0xc78, 0x621a0001, +	0xc78, 0x611b0001, +	0xc78, 0x601c0001, +	0xc78, 0x481d0001, +	0xc78, 0x471e0001, +	0xc78, 0x461f0001, +	0xc78, 0x45200001, +	0xc78, 0x44210001, +	0xc78, 0x43220001, +	0xc78, 0x42230001, +	0xc78, 0x41240001, +	0xc78, 0x40250001, +	0xc78, 0x27260001, +	0xc78, 0x26270001, +	0xc78, 0x25280001, +	0xc78, 0x24290001, +	0xc78, 0x232a0001, +	0xc78, 0x222b0001, +	0xc78, 0x212c0001, +	0xc78, 0x202d0001, +	0xc78, 0x202e0001, +	0xc78, 0x202f0001, +	0xc78, 0x20300001, +	0xc78, 0x20310001, +	0xc78, 0x20320001, +	0xc78, 0x20330001, +	0xc78, 0x20340001, +	0xc78, 0x20350001, +	0xc78, 0x20360001, +	0xc78, 0x20370001, +	0xc78, 0x20380001, +	0xc78, 0x20390001, +	0xc78, 0x203a0001, +	0xc78, 0x203b0001, +	0xc78, 0x203c0001, +	0xc78, 0x203d0001, +	0xc78, 0x203e0001, +	0xc78, 0x203f0001, +	0xc78, 0x32000044, +	0xc78, 0x32010044, +	0xc78, 0x32020044, +	0xc78, 0x32030044, +	0xc78, 0x32040044, +	0xc78, 0x32050044, +	0xc78, 0x32060044, +	0xc78, 0x32070044, +	0xc78, 0x32080044, +	0xc78, 0x34090044, +	0xc78, 0x350a0044, +	0xc78, 0x360b0044, +	0xc78, 0x370c0044, +	0xc78, 0x380d0044, +	0xc78, 0x390e0044, +	0xc78, 0x3a0f0044, +	0xc78, 0x3e100044, +	0xc78, 0x42110044, +	0xc78, 0x44120044, +	0xc78, 0x46130044, +	0xc78, 0x4a140044, +	0xc78, 0x4e150044, +	0xc78, 0x50160044, +	0xc78, 0x55170044, +	0xc78, 0x5a180044, +	0xc78, 0x5e190044, +	0xc78, 0x641a0044, +	0xc78, 0x6e1b0044, +	0xc78, 0x6e1c0044, +	0xc78, 0x6e1d0044, +	0xc78, 0x6e1e0044, +	0xc78, 0x6e1f0044, +	0xc78, 0x6e1f0000, +}; + +u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH] = { +	0xc78, 0x7b000001, +	0xc78, 0x7b010001, +	0xc78, 0x7b020001, +	0xc78, 0x7b030001, +	0xc78, 0x7b040001, +	0xc78, 0x7b050001, +	0xc78, 0x7b060001, +	0xc78, 0x7a070001, +	0xc78, 0x79080001, +	0xc78, 0x78090001, +	0xc78, 0x770a0001, +	0xc78, 0x760b0001, +	0xc78, 0x750c0001, +	0xc78, 0x740d0001, +	0xc78, 0x730e0001, +	0xc78, 0x720f0001, +	0xc78, 0x71100001, +	0xc78, 0x70110001, +	0xc78, 0x6f120001, +	0xc78, 0x6e130001, +	0xc78, 0x6d140001, +	0xc78, 0x6c150001, +	0xc78, 0x6b160001, +	0xc78, 0x6a170001, +	0xc78, 0x69180001, +	0xc78, 0x68190001, +	0xc78, 0x671a0001, +	0xc78, 0x661b0001, +	0xc78, 0x651c0001, +	0xc78, 0x641d0001, +	0xc78, 0x631e0001, +	0xc78, 0x621f0001, +	0xc78, 0x61200001, +	0xc78, 0x60210001, +	0xc78, 0x49220001, +	0xc78, 0x48230001, +	0xc78, 0x47240001, +	0xc78, 0x46250001, +	0xc78, 0x45260001, +	0xc78, 0x44270001, +	0xc78, 0x43280001, +	0xc78, 0x42290001, +	0xc78, 0x412a0001, +	0xc78, 0x402b0001, +	0xc78, 0x262c0001, +	0xc78, 0x252d0001, +	0xc78, 0x242e0001, +	0xc78, 0x232f0001, +	0xc78, 0x22300001, +	0xc78, 0x21310001, +	0xc78, 0x20320001, +	0xc78, 0x06330001, +	0xc78, 0x05340001, +	0xc78, 0x04350001, +	0xc78, 0x03360001, +	0xc78, 0x02370001, +	0xc78, 0x01380001, +	0xc78, 0x00390001, +	0xc78, 0x003a0001, +	0xc78, 0x003b0001, +	0xc78, 0x003c0001, +	0xc78, 0x003d0001, +	0xc78, 0x003e0001, +	0xc78, 0x003f0001, +	0xc78, 0x38000002, +	0xc78, 0x38010002, +	0xc78, 0x38020002, +	0xc78, 0x38030002, +	0xc78, 0x38040002, +	0xc78, 0x38050002, +	0xc78, 0x38060002, +	0xc78, 0x38070002, +	0xc78, 0x38080002, +	0xc78, 0x3c090002, +	0xc78, 0x3e0a0002, +	0xc78, 0x400b0002, +	0xc78, 0x440c0002, +	0xc78, 0x480d0002, +	0xc78, 0x4c0e0002, +	0xc78, 0x500f0002, +	0xc78, 0x52100002, +	0xc78, 0x56110002, +	0xc78, 0x5a120002, +	0xc78, 0x5e130002, +	0xc78, 0x60140002, +	0xc78, 0x60150002, +	0xc78, 0x60160002, +	0xc78, 0x62170002, +	0xc78, 0x62180002, +	0xc78, 0x62190002, +	0xc78, 0x621a0002, +	0xc78, 0x621b0002, +	0xc78, 0x621c0002, +	0xc78, 0x621d0002, +	0xc78, 0x621e0002, +	0xc78, 0x621f0002, +	0xc78, 0x6e1f0000, +}; diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/table.h b/drivers/net/wireless/rtlwifi/rtl8192de/table.h new file mode 100644 index 00000000000..93f30ca62d8 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/table.h @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + * Created on  2010/ 5/18,  1:41 + *****************************************************************************/ + +#ifndef __RTL92DE_TABLE__H_ +#define __RTL92DE_TABLE__H_ + +/*Created on  2011/ 1/14,  1:35*/ + +#define PHY_REG_2T_ARRAYLENGTH 380 +extern u32 rtl8192de_phy_reg_2tarray[PHY_REG_2T_ARRAYLENGTH]; +#define PHY_REG_ARRAY_PG_LENGTH 624 +extern u32 rtl8192de_phy_reg_array_pg[PHY_REG_ARRAY_PG_LENGTH]; +#define RADIOA_2T_ARRAYLENGTH 378 +extern u32 rtl8192de_radioa_2tarray[RADIOA_2T_ARRAYLENGTH]; +#define RADIOB_2T_ARRAYLENGTH 384 +extern u32 rtl8192de_radiob_2tarray[RADIOB_2T_ARRAYLENGTH]; +#define RADIOA_2T_INT_PA_ARRAYLENGTH 378 +extern u32 rtl8192de_radioa_2t_int_paarray[RADIOA_2T_INT_PA_ARRAYLENGTH]; +#define RADIOB_2T_INT_PA_ARRAYLENGTH 384 +extern u32 rtl8192de_radiob_2t_int_paarray[RADIOB_2T_INT_PA_ARRAYLENGTH]; +#define MAC_2T_ARRAYLENGTH 160 +extern u32 rtl8192de_mac_2tarray[MAC_2T_ARRAYLENGTH]; +#define AGCTAB_ARRAYLENGTH 386 +extern u32 rtl8192de_agctab_array[AGCTAB_ARRAYLENGTH]; +#define AGCTAB_5G_ARRAYLENGTH 194 +extern u32 rtl8192de_agctab_5garray[AGCTAB_5G_ARRAYLENGTH]; +#define AGCTAB_2G_ARRAYLENGTH 194 +extern u32 rtl8192de_agctab_2garray[AGCTAB_2G_ARRAYLENGTH]; + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c new file mode 100644 index 00000000000..dc86fcb0b3a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c @@ -0,0 +1,959 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#include "../wifi.h" +#include "../pci.h" +#include "../base.h" +#include "reg.h" +#include "def.h" +#include "phy.h" +#include "trx.h" +#include "led.h" + +static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue) +{ +	__le16 fc = rtl_get_fc(skb); + +	if (unlikely(ieee80211_is_beacon(fc))) +		return QSLT_BEACON; +	if (ieee80211_is_mgmt(fc)) +		return QSLT_MGNT; + +	return skb->priority; +} + +static int _rtl92de_rate_mapping(bool isht, u8 desc_rate) +{ +	int rate_idx; + +	if (false == isht) { +		switch (desc_rate) { +		case DESC92D_RATE1M: +			rate_idx = 0; +			break; +		case DESC92D_RATE2M: +			rate_idx = 1; +			break; +		case DESC92D_RATE5_5M: +			rate_idx = 2; +			break; +		case DESC92D_RATE11M: +			rate_idx = 3; +			break; +		case DESC92D_RATE6M: +			rate_idx = 4; +			break; +		case DESC92D_RATE9M: +			rate_idx = 5; +			break; +		case DESC92D_RATE12M: +			rate_idx = 6; +			break; +		case DESC92D_RATE18M: +			rate_idx = 7; +			break; +		case DESC92D_RATE24M: +			rate_idx = 8; +			break; +		case DESC92D_RATE36M: +			rate_idx = 9; +			break; +		case DESC92D_RATE48M: +			rate_idx = 10; +			break; +		case DESC92D_RATE54M: +			rate_idx = 11; +			break; +		default: +			rate_idx = 0; +			break; +		} +		return rate_idx; +	} else { +		switch (desc_rate) { +		case DESC92D_RATE1M: +			rate_idx = 0; +			break; +		case DESC92D_RATE2M: +			rate_idx = 1; +			break; +		case DESC92D_RATE5_5M: +			rate_idx = 2; +			break; +		case DESC92D_RATE11M: +			rate_idx = 3; +			break; +		case DESC92D_RATE6M: +			rate_idx = 4; +			break; +		case DESC92D_RATE9M: +			rate_idx = 5; +			break; +		case DESC92D_RATE12M: +			rate_idx = 6; +			break; +		case DESC92D_RATE18M: +			rate_idx = 7; +			break; +		case DESC92D_RATE24M: +			rate_idx = 8; +			break; +		case DESC92D_RATE36M: +			rate_idx = 9; +			break; +		case DESC92D_RATE48M: +			rate_idx = 10; +			break; +		case DESC92D_RATE54M: +			rate_idx = 11; +			break; +		default: +			rate_idx = 11; +			break; +		} +		return rate_idx; +	} +} + +static u8 _rtl92d_query_rxpwrpercentage(char antpower) +{ +	if ((antpower <= -100) || (antpower >= 20)) +		return 0; +	else if (antpower >= 0) +		return 100; +	else +		return 100 + antpower; +} + +static u8 _rtl92d_evm_db_to_percentage(char value) +{ +	char ret_val = value; + +	if (ret_val >= 0) +		ret_val = 0; +	if (ret_val <= -33) +		ret_val = -33; +	ret_val = 0 - ret_val; +	ret_val *= 3; +	if (ret_val == 99) +		ret_val = 100; +	return ret_val; +} + +static long _rtl92de_translate_todbm(struct ieee80211_hw *hw, +				     u8 signal_strength_index) +{ +	long signal_power; + +	signal_power = (long)((signal_strength_index + 1) >> 1); +	signal_power -= 95; +	return signal_power; +} + +static long _rtl92de_signal_scale_mapping(struct ieee80211_hw *hw, long currsig) +{ +	long retsig; + +	if (currsig >= 61 && currsig <= 100) +		retsig = 90 + ((currsig - 60) / 4); +	else if (currsig >= 41 && currsig <= 60) +		retsig = 78 + ((currsig - 40) / 2); +	else if (currsig >= 31 && currsig <= 40) +		retsig = 66 + (currsig - 30); +	else if (currsig >= 21 && currsig <= 30) +		retsig = 54 + (currsig - 20); +	else if (currsig >= 5 && currsig <= 20) +		retsig = 42 + (((currsig - 5) * 2) / 3); +	else if (currsig == 4) +		retsig = 36; +	else if (currsig == 3) +		retsig = 27; +	else if (currsig == 2) +		retsig = 18; +	else if (currsig == 1) +		retsig = 9; +	else +		retsig = currsig; +	return retsig; +} + +static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw, +				       struct rtl_stats *pstats, +				       struct rx_desc_92d *pdesc, +				       struct rx_fwinfo_92d *p_drvinfo, +				       bool packet_match_bssid, +				       bool packet_toself, +				       bool packet_beacon) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); +	struct phy_sts_cck_8192d *cck_buf; +	s8 rx_pwr_all, rx_pwr[4]; +	u8 rf_rx_num = 0, evm, pwdb_all; +	u8 i, max_spatial_stream; +	u32 rssi, total_rssi = 0; +	bool is_cck_rate; + +	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); +	pstats->packet_matchbssid = packet_match_bssid; +	pstats->packet_toself = packet_toself; +	pstats->packet_beacon = packet_beacon; +	pstats->is_cck = is_cck_rate; +	pstats->rx_mimo_signalquality[0] = -1; +	pstats->rx_mimo_signalquality[1] = -1; + +	if (is_cck_rate) { +		u8 report, cck_highpwr; +		cck_buf = (struct phy_sts_cck_8192d *)p_drvinfo; +		if (ppsc->rfpwr_state == ERFON) +			cck_highpwr = (u8) rtl_get_bbreg(hw, +						 RFPGA0_XA_HSSIPARAMETER2, +						 BIT(9)); +		else +			cck_highpwr = false; +		if (!cck_highpwr) { +			u8 cck_agc_rpt = cck_buf->cck_agc_rpt; +			report = cck_buf->cck_agc_rpt & 0xc0; +			report = report >> 6; +			switch (report) { +			case 0x3: +				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e); +				break; +			case 0x2: +				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e); +				break; +			case 0x1: +				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e); +				break; +			case 0x0: +				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e); +				break; +			} +		} else { +			u8 cck_agc_rpt = cck_buf->cck_agc_rpt; +			report = p_drvinfo->cfosho[0] & 0x60; +			report = report >> 5; +			switch (report) { +			case 0x3: +				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1); +				break; +			case 0x2: +				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1); +				break; +			case 0x1: +				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1); +				break; +			case 0x0: +				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1); +				break; +			} +		} +		pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all); +		/* CCK gain is smaller than OFDM/MCS gain,  */ +		/* so we add gain diff by experiences, the val is 6 */ +		pwdb_all += 6; +		if (pwdb_all > 100) +			pwdb_all = 100; +		/* modify the offset to make the same gain index with OFDM. */ +		if (pwdb_all > 34 && pwdb_all <= 42) +			pwdb_all -= 2; +		else if (pwdb_all > 26 && pwdb_all <= 34) +			pwdb_all -= 6; +		else if (pwdb_all > 14 && pwdb_all <= 26) +			pwdb_all -= 8; +		else if (pwdb_all > 4 && pwdb_all <= 14) +			pwdb_all -= 4; +		pstats->rx_pwdb_all = pwdb_all; +		pstats->recvsignalpower = rx_pwr_all; +		if (packet_match_bssid) { +			u8 sq; +			if (pstats->rx_pwdb_all > 40) { +				sq = 100; +			} else { +				sq = cck_buf->sq_rpt; +				if (sq > 64) +					sq = 0; +				else if (sq < 20) +					sq = 100; +				else +					sq = ((64 - sq) * 100) / 44; +			} +			pstats->signalquality = sq; +			pstats->rx_mimo_signalquality[0] = sq; +			pstats->rx_mimo_signalquality[1] = -1; +		} +	} else { +		rtlpriv->dm.rfpath_rxenable[0] = true; +		rtlpriv->dm.rfpath_rxenable[1] = true; +		for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) { +			if (rtlpriv->dm.rfpath_rxenable[i]) +				rf_rx_num++; +			rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) +				    - 110; +			rssi = _rtl92d_query_rxpwrpercentage(rx_pwr[i]); +			total_rssi += rssi; +			rtlpriv->stats.rx_snr_db[i] = +					 (long)(p_drvinfo->rxsnr[i] / 2); +			if (packet_match_bssid) +				pstats->rx_mimo_signalstrength[i] = (u8) rssi; +		} +		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 106; +		pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all); +		pstats->rx_pwdb_all = pwdb_all; +		pstats->rxpower = rx_pwr_all; +		pstats->recvsignalpower = rx_pwr_all; +		if (pdesc->rxht && pdesc->rxmcs >= DESC92D_RATEMCS8 && +		    pdesc->rxmcs <= DESC92D_RATEMCS15) +			max_spatial_stream = 2; +		else +			max_spatial_stream = 1; +		for (i = 0; i < max_spatial_stream; i++) { +			evm = _rtl92d_evm_db_to_percentage(p_drvinfo->rxevm[i]); +			if (packet_match_bssid) { +				if (i == 0) +					pstats->signalquality = +						 (u8)(evm & 0xff); +				pstats->rx_mimo_signalquality[i] = +						 (u8)(evm & 0xff); +			} +		} +	} +	if (is_cck_rate) +		pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw, +				pwdb_all)); +	else if (rf_rx_num != 0) +		pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw, +				total_rssi /= rf_rx_num)); +} + +static void rtl92d_loop_over_paths(struct ieee80211_hw *hw, +				   struct rtl_stats *pstats) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_phy *rtlphy = &(rtlpriv->phy); +	u8 rfpath; + +	for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; +	     rfpath++) { +		if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { +			rtlpriv->stats.rx_rssi_percentage[rfpath] = +			    pstats->rx_mimo_signalstrength[rfpath]; + +		} +		if (pstats->rx_mimo_signalstrength[rfpath] > +		    rtlpriv->stats.rx_rssi_percentage[rfpath]) { +			rtlpriv->stats.rx_rssi_percentage[rfpath] = +			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] * +			      (RX_SMOOTH_FACTOR - 1)) + +			     (pstats->rx_mimo_signalstrength[rfpath])) / +			    (RX_SMOOTH_FACTOR); +			rtlpriv->stats.rx_rssi_percentage[rfpath] = +			    rtlpriv->stats.rx_rssi_percentage[rfpath] + 1; +		} else { +			rtlpriv->stats.rx_rssi_percentage[rfpath] = +			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] * +			      (RX_SMOOTH_FACTOR - 1)) + +			     (pstats->rx_mimo_signalstrength[rfpath])) / +			    (RX_SMOOTH_FACTOR); +		} +	} +} + +static void _rtl92de_process_ui_rssi(struct ieee80211_hw *hw, +				     struct rtl_stats *pstats) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 last_rssi, tmpval; + +	if (pstats->packet_toself || pstats->packet_beacon) { +		rtlpriv->stats.rssi_calculate_cnt++; +		if (rtlpriv->stats.ui_rssi.total_num++ >= +		    PHY_RSSI_SLID_WIN_MAX) { +			rtlpriv->stats.ui_rssi.total_num = +						 PHY_RSSI_SLID_WIN_MAX; +			last_rssi = rtlpriv->stats.ui_rssi.elements[ +				rtlpriv->stats.ui_rssi.index]; +			rtlpriv->stats.ui_rssi.total_val -= last_rssi; +		} +		rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; +		rtlpriv->stats.ui_rssi.elements +			[rtlpriv->stats.ui_rssi.index++] = +			pstats->signalstrength; +		if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) +			rtlpriv->stats.ui_rssi.index = 0; +		tmpval = rtlpriv->stats.ui_rssi.total_val / +			rtlpriv->stats.ui_rssi.total_num; +		rtlpriv->stats.signal_strength = _rtl92de_translate_todbm(hw, +			(u8) tmpval); +		pstats->rssi = rtlpriv->stats.signal_strength; +	} +	if (!pstats->is_cck && pstats->packet_toself) +		rtl92d_loop_over_paths(hw, pstats); +} + +static void _rtl92de_update_rxsignalstatistics(struct ieee80211_hw *hw, +					       struct rtl_stats *pstats) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	int weighting = 0; + +	if (rtlpriv->stats.recv_signal_power == 0) +		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; +	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) +		weighting = 5; +	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) +		weighting = (-5); +	rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * +		5 + pstats->recvsignalpower + weighting) / 6; +} + +static void _rtl92de_process_pwdb(struct ieee80211_hw *hw, +				  struct rtl_stats *pstats) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	long undecorated_smoothed_pwdb; + +	if (mac->opmode == NL80211_IFTYPE_ADHOC	|| +		mac->opmode == NL80211_IFTYPE_AP) +		return; +	else +		undecorated_smoothed_pwdb = +		    rtlpriv->dm.undecorated_smoothed_pwdb; + +	if (pstats->packet_toself || pstats->packet_beacon) { +		if (undecorated_smoothed_pwdb < 0) +			undecorated_smoothed_pwdb = pstats->rx_pwdb_all; +		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) { +			undecorated_smoothed_pwdb = +			      (((undecorated_smoothed_pwdb) * +			      (RX_SMOOTH_FACTOR - 1)) + +			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); +			undecorated_smoothed_pwdb = +			      undecorated_smoothed_pwdb + 1; +		} else { +			undecorated_smoothed_pwdb = +			      (((undecorated_smoothed_pwdb) * +			      (RX_SMOOTH_FACTOR - 1)) + +			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); +		} +		rtlpriv->dm.undecorated_smoothed_pwdb = +				 undecorated_smoothed_pwdb; +		_rtl92de_update_rxsignalstatistics(hw, pstats); +	} +} + +static void rtl92d_loop_over_streams(struct ieee80211_hw *hw, +				     struct rtl_stats *pstats) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	int stream; + +	for (stream = 0; stream < 2; stream++) { +		if (pstats->rx_mimo_signalquality[stream] != -1) { +			if (rtlpriv->stats.rx_evm_percentage[stream] == 0) { +				rtlpriv->stats.rx_evm_percentage[stream] = +				    pstats->rx_mimo_signalquality[stream]; +			} +			rtlpriv->stats.rx_evm_percentage[stream] = +			    ((rtlpriv->stats.rx_evm_percentage[stream] +			      * (RX_SMOOTH_FACTOR - 1)) + +			     (pstats->rx_mimo_signalquality[stream] * 1)) / +			    (RX_SMOOTH_FACTOR); +		} +	} +} + +static void _rtl92de_process_ui_link_quality(struct ieee80211_hw *hw, +					     struct rtl_stats *pstats) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	u32 last_evm, tmpval; + +	if (pstats->signalquality == 0) +		return; +	if (pstats->packet_toself || pstats->packet_beacon) { +		if (rtlpriv->stats.ui_link_quality.total_num++ >= +		    PHY_LINKQUALITY_SLID_WIN_MAX) { +			rtlpriv->stats.ui_link_quality.total_num = +			    PHY_LINKQUALITY_SLID_WIN_MAX; +			last_evm = rtlpriv->stats.ui_link_quality.elements[ +				rtlpriv->stats.ui_link_quality.index]; +			rtlpriv->stats.ui_link_quality.total_val -= last_evm; +		} +		rtlpriv->stats.ui_link_quality.total_val += +						 pstats->signalquality; +		rtlpriv->stats.ui_link_quality.elements[ +			rtlpriv->stats.ui_link_quality.index++] = +						 pstats->signalquality; +		if (rtlpriv->stats.ui_link_quality.index >= +		    PHY_LINKQUALITY_SLID_WIN_MAX) +			rtlpriv->stats.ui_link_quality.index = 0; +		tmpval = rtlpriv->stats.ui_link_quality.total_val / +		    rtlpriv->stats.ui_link_quality.total_num; +		rtlpriv->stats.signal_quality = tmpval; +		rtlpriv->stats.last_sigstrength_inpercent = tmpval; +		rtl92d_loop_over_streams(hw, pstats); +	} +} + +static void _rtl92de_process_phyinfo(struct ieee80211_hw *hw, +				     u8 *buffer, +				     struct rtl_stats *pcurrent_stats) +{ + +	if (!pcurrent_stats->packet_matchbssid && +	    !pcurrent_stats->packet_beacon) +		return; + +	_rtl92de_process_ui_rssi(hw, pcurrent_stats); +	_rtl92de_process_pwdb(hw, pcurrent_stats); +	_rtl92de_process_ui_link_quality(hw, pcurrent_stats); +} + +static void _rtl92de_translate_rx_signal_stuff(struct ieee80211_hw *hw, +					       struct sk_buff *skb, +					       struct rtl_stats *pstats, +					       struct rx_desc_92d *pdesc, +					       struct rx_fwinfo_92d *p_drvinfo) +{ +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); +	struct ieee80211_hdr *hdr; +	u8 *tmp_buf; +	u8 *praddr; +	u16 type, cfc; +	__le16 fc; +	bool packet_matchbssid, packet_toself, packet_beacon; + +	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; +	hdr = (struct ieee80211_hdr *)tmp_buf; +	fc = hdr->frame_control; +	cfc = le16_to_cpu(fc); +	type = WLAN_FC_GET_TYPE(fc); +	praddr = hdr->addr1; +	packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && +	     (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ? +		  hdr->addr1 : (cfc & IEEE80211_FCTL_FROMDS) ? +		  hdr->addr2 : hdr->addr3)) && (!pstats->hwerror) && +		  (!pstats->crc) && (!pstats->icv)); +	packet_toself = packet_matchbssid && +			(!compare_ether_addr(praddr, rtlefuse->dev_addr)); +	if (ieee80211_is_beacon(fc)) +		packet_beacon = true; +	_rtl92de_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, +				   packet_matchbssid, packet_toself, +				   packet_beacon); +	_rtl92de_process_phyinfo(hw, tmp_buf, pstats); +} + +bool rtl92de_rx_query_desc(struct ieee80211_hw *hw,	struct rtl_stats *stats, +		struct ieee80211_rx_status *rx_status, +		u8 *p_desc, struct sk_buff *skb) +{ +	struct rx_fwinfo_92d *p_drvinfo; +	struct rx_desc_92d *pdesc = (struct rx_desc_92d *)p_desc; +	u32 phystatus = GET_RX_DESC_PHYST(pdesc); + +	stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); +	stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) * +				 RX_DRV_INFO_SIZE_UNIT; +	stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03); +	stats->icv = (u16) GET_RX_DESC_ICV(pdesc); +	stats->crc = (u16) GET_RX_DESC_CRC32(pdesc); +	stats->hwerror = (stats->crc | stats->icv); +	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc); +	stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc); +	stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc); +	stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1); +	stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1) +					 && (GET_RX_DESC_FAGGR(pdesc) == 1)); +	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc); +	stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc); +	rx_status->freq = hw->conf.channel->center_freq; +	rx_status->band = hw->conf.channel->band; +	if (GET_RX_DESC_CRC32(pdesc)) +		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; +	if (!GET_RX_DESC_SWDEC(pdesc)) +		rx_status->flag |= RX_FLAG_DECRYPTED; +	if (GET_RX_DESC_BW(pdesc)) +		rx_status->flag |= RX_FLAG_40MHZ; +	if (GET_RX_DESC_RXHT(pdesc)) +		rx_status->flag |= RX_FLAG_HT; +	rx_status->flag |= RX_FLAG_MACTIME_MPDU; +	if (stats->decrypted) +		rx_status->flag |= RX_FLAG_DECRYPTED; +	rx_status->rate_idx = _rtl92de_rate_mapping((bool) +						    GET_RX_DESC_RXHT(pdesc), +						    (u8) +						    GET_RX_DESC_RXMCS(pdesc)); +	rx_status->mactime = GET_RX_DESC_TSFL(pdesc); +	if (phystatus) { +		p_drvinfo = (struct rx_fwinfo_92d *)(skb->data + +						     stats->rx_bufshift); +		_rtl92de_translate_rx_signal_stuff(hw, +						   skb, stats, pdesc, +						   p_drvinfo); +	} +	/*rx_status->qual = stats->signal; */ +	rx_status->signal = stats->rssi + 10; +	/*rx_status->noise = -stats->noise; */ +	return true; +} + +static void _rtl92de_insert_emcontent(struct rtl_tcb_desc *ptcb_desc, +				      u8 *virtualaddress) +{ +	memset(virtualaddress, 0, 8); + +	SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num); +	SET_EARLYMODE_LEN0(virtualaddress, ptcb_desc->empkt_len[0]); +	SET_EARLYMODE_LEN1(virtualaddress, ptcb_desc->empkt_len[1]); +	SET_EARLYMODE_LEN2_1(virtualaddress, ptcb_desc->empkt_len[2] & 0xF); +	SET_EARLYMODE_LEN2_2(virtualaddress, ptcb_desc->empkt_len[2] >> 4); +	SET_EARLYMODE_LEN3(virtualaddress, ptcb_desc->empkt_len[3]); +	SET_EARLYMODE_LEN4(virtualaddress, ptcb_desc->empkt_len[4]); +} + +void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, +			  struct ieee80211_hdr *hdr, u8 *pdesc_tx, +			  struct ieee80211_tx_info *info, struct sk_buff *skb, +			  u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct rtl_hal *rtlhal = rtl_hal(rtlpriv); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); +	struct ieee80211_sta *sta = info->control.sta; +	u8 *pdesc = (u8 *) pdesc_tx; +	u16 seq_number; +	__le16 fc = hdr->frame_control; +	unsigned int buf_len = 0; +	unsigned int skb_len = skb->len; +	u8 fw_qsel = _rtl92de_map_hwqueue_to_fwqueue(skb, hw_queue); +	bool firstseg = ((hdr->seq_ctrl & +			cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0); +	bool lastseg = ((hdr->frame_control & +			cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0); +	dma_addr_t mapping; +	u8 bw_40 = 0; + +	if (mac->opmode == NL80211_IFTYPE_STATION) { +		bw_40 = mac->bw_40; +	} else if (mac->opmode == NL80211_IFTYPE_AP || +		mac->opmode == NL80211_IFTYPE_ADHOC) { +		if (sta) +			bw_40 = sta->ht_cap.cap & +				IEEE80211_HT_CAP_SUP_WIDTH_20_40; +	} +	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; +	rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); +	/* reserve 8 byte for AMPDU early mode */ +	if (rtlhal->earlymode_enable) { +		skb_push(skb, EM_HDR_LEN); +		memset(skb->data, 0, EM_HDR_LEN); +	} +	buf_len = skb->len; +	mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, +				 PCI_DMA_TODEVICE); +	CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d)); +	if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { +		firstseg = true; +		lastseg = true; +	} +	if (firstseg) { +		if (rtlhal->earlymode_enable) { +			SET_TX_DESC_PKT_OFFSET(pdesc, 1); +			SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN + +					   EM_HDR_LEN); +			if (ptcb_desc->empkt_num) { +				RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD, +					 ("Insert 8 byte.pTcb->EMPktNum:%d\n", +					  ptcb_desc->empkt_num)); +				_rtl92de_insert_emcontent(ptcb_desc, +							  (u8 *)(skb->data)); +			} +		} else { +			SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); +		} +		/* 5G have no CCK rate */ +		if (rtlhal->current_bandtype == BAND_ON_5G) +			if (ptcb_desc->hw_rate < DESC92D_RATE6M) +				ptcb_desc->hw_rate = DESC92D_RATE6M; +		SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); +		if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) +			SET_TX_DESC_DATA_SHORTGI(pdesc, 1); + +		if (rtlhal->macphymode == DUALMAC_DUALPHY && +			ptcb_desc->hw_rate == DESC92D_RATEMCS7) +			SET_TX_DESC_DATA_SHORTGI(pdesc, 1); + +		if (info->flags & IEEE80211_TX_CTL_AMPDU) { +			SET_TX_DESC_AGG_ENABLE(pdesc, 1); +			SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14); +		} +		SET_TX_DESC_SEQ(pdesc, seq_number); +		SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && +				       !ptcb_desc->cts_enable) ? 1 : 0)); +		SET_TX_DESC_HW_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable +					  || ptcb_desc->cts_enable) ? 1 : 0)); +		SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0)); +		SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); +		/* 5G have no CCK rate */ +		if (rtlhal->current_bandtype == BAND_ON_5G) +			if (ptcb_desc->rts_rate < DESC92D_RATE6M) +				ptcb_desc->rts_rate = DESC92D_RATE6M; +		SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); +		SET_TX_DESC_RTS_BW(pdesc, 0); +		SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc); +		SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= +			DESC92D_RATE54M) ? +			(ptcb_desc->rts_use_shortpreamble ? 1 : 0) : +			(ptcb_desc->rts_use_shortgi ? 1 : 0))); +		if (bw_40) { +			if (ptcb_desc->packet_bw) { +				SET_TX_DESC_DATA_BW(pdesc, 1); +				SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3); +			} else { +				SET_TX_DESC_DATA_BW(pdesc, 0); +				SET_TX_DESC_TX_SUB_CARRIER(pdesc, +							mac->cur_40_prime_sc); +			} +		} else { +			SET_TX_DESC_DATA_BW(pdesc, 0); +			SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); +		} +		SET_TX_DESC_LINIP(pdesc, 0); +		SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len); +		if (sta) { +			u8 ampdu_density = sta->ht_cap.ampdu_density; +			SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density); +		} +		if (info->control.hw_key) { +			struct ieee80211_key_conf *keyconf; + +			keyconf = info->control.hw_key; +			switch (keyconf->cipher) { +			case WLAN_CIPHER_SUITE_WEP40: +			case WLAN_CIPHER_SUITE_WEP104: +			case WLAN_CIPHER_SUITE_TKIP: +				SET_TX_DESC_SEC_TYPE(pdesc, 0x1); +				break; +			case WLAN_CIPHER_SUITE_CCMP: +				SET_TX_DESC_SEC_TYPE(pdesc, 0x3); +				break; +			default: +				SET_TX_DESC_SEC_TYPE(pdesc, 0x0); +				break; + +			} +		} +		SET_TX_DESC_PKT_ID(pdesc, 0); +		SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); +		SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); +		SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF); +		SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ? +				       1 : 0); +		SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0); + +		/* Set TxRate and RTSRate in TxDesc  */ +		/* This prevent Tx initial rate of new-coming packets */ +		/* from being overwritten by retried  packet rate.*/ +		if (!ptcb_desc->use_driver_rate) { +			SET_TX_DESC_RTS_RATE(pdesc, 0x08); +			/* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */ +		} +		if (ieee80211_is_data_qos(fc)) { +			if (mac->rdg_en) { +				RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, +					("Enable RDG function.\n")); +				SET_TX_DESC_RDG_ENABLE(pdesc, 1); +				SET_TX_DESC_HTC(pdesc, 1); +			} +		} +	} + +	SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); +	SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); +	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len); +	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); +	if (rtlpriv->dm.useramask) { +		SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index); +		SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); +	} else { +		SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index); +		SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index); +	} +	if (ieee80211_is_data_qos(fc)) +		SET_TX_DESC_QOS(pdesc, 1); + +	if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) { +		SET_TX_DESC_HWSEQ_EN(pdesc, 1); +		SET_TX_DESC_PKT_ID(pdesc, 8); +	} +	SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1)); +	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n")); +} + +void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, +			     u8 *pdesc, bool firstseg, +			     bool lastseg, struct sk_buff *skb) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); +	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); +	struct rtl_hal *rtlhal = rtl_hal(rtlpriv); +	u8 fw_queue = QSLT_BEACON; +	dma_addr_t mapping = pci_map_single(rtlpci->pdev, +		    skb->data, skb->len, PCI_DMA_TODEVICE); +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); +	__le16 fc = hdr->frame_control; + +	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); +	if (firstseg) +		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); +	/* 5G have no CCK rate +	 * Caution: The macros below are multi-line expansions. +	 * The braces are needed no matter what checkpatch says +	 */ +	if (rtlhal->current_bandtype == BAND_ON_5G) { +		SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE6M); +	} else { +		SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE1M); +	} +	SET_TX_DESC_SEQ(pdesc, 0); +	SET_TX_DESC_LINIP(pdesc, 0); +	SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); +	SET_TX_DESC_FIRST_SEG(pdesc, 1); +	SET_TX_DESC_LAST_SEG(pdesc, 1); +	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len)); +	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping); +	SET_TX_DESC_RATE_ID(pdesc, 7); +	SET_TX_DESC_MACID(pdesc, 0); +	SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len)); +	SET_TX_DESC_FIRST_SEG(pdesc, 1); +	SET_TX_DESC_LAST_SEG(pdesc, 1); +	SET_TX_DESC_OFFSET(pdesc, 0x20); +	SET_TX_DESC_USE_RATE(pdesc, 1); + +	if (!ieee80211_is_data_qos(fc) && ppsc->fwctrl_lps) { +		SET_TX_DESC_HWSEQ_EN(pdesc, 1); +		SET_TX_DESC_PKT_ID(pdesc, 8); +	} + +	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, +		      "H2C Tx Cmd Content\n", pdesc, TX_DESC_SIZE); +	wmb(); +	SET_TX_DESC_OWN(pdesc, 1); +} + +void rtl92de_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val) +{ +	if (istx) { +		switch (desc_name) { +		case HW_DESC_OWN: +			wmb(); +			SET_TX_DESC_OWN(pdesc, 1); +			break; +		case HW_DESC_TX_NEXTDESC_ADDR: +			SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); +			break; +		default: +			RT_ASSERT(false, ("ERR txdesc :%d" +					  " not process\n", desc_name)); +			break; +		} +	} else { +		switch (desc_name) { +		case HW_DESC_RXOWN: +			wmb(); +			SET_RX_DESC_OWN(pdesc, 1); +			break; +		case HW_DESC_RXBUFF_ADDR: +			SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val); +			break; +		case HW_DESC_RXPKT_LEN: +			SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val); +			break; +		case HW_DESC_RXERO: +			SET_RX_DESC_EOR(pdesc, 1); +			break; +		default: +			RT_ASSERT(false, ("ERR rxdesc :%d " +					  "not process\n", desc_name)); +			break; +		} +	} +} + +u32 rtl92de_get_desc(u8 *p_desc, bool istx, u8 desc_name) +{ +	u32 ret = 0; + +	if (istx) { +		switch (desc_name) { +		case HW_DESC_OWN: +			ret = GET_TX_DESC_OWN(p_desc); +			break; +		case HW_DESC_TXBUFF_ADDR: +			ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc); +			break; +		default: +			RT_ASSERT(false, ("ERR txdesc :%d " +					  "not process\n", desc_name)); +			break; +		} +	} else { +		struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; +		switch (desc_name) { +		case HW_DESC_OWN: +			ret = GET_RX_DESC_OWN(pdesc); +			break; +		case HW_DESC_RXPKT_LEN: +			ret = GET_RX_DESC_PKT_LEN(pdesc); +			break; +		default: +			RT_ASSERT(false, ("ERR rxdesc :%d " +					  "not process\n", desc_name)); +			break; +		} +	} +	return ret; +} + +void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) +{ +	struct rtl_priv *rtlpriv = rtl_priv(hw); +	if (hw_queue == BEACON_QUEUE) +		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4)); +	else +		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, +			       BIT(0) << (hw_queue)); +} diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h new file mode 100644 index 00000000000..992d6766e66 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h @@ -0,0 +1,756 @@ +/****************************************************************************** + * + * Copyright(c) 2009-2010  Realtek Corporation. + * + * 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. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +#ifndef __RTL92DE_TRX_H__ +#define __RTL92DE_TRX_H__ + +#define TX_DESC_SIZE				64 +#define TX_DESC_AGGR_SUBFRAME_SIZE		32 + +#define RX_DESC_SIZE				32 +#define RX_DRV_INFO_SIZE_UNIT			8 + +#define	TX_DESC_NEXT_DESC_OFFSET		40 +#define USB_HWDESC_HEADER_LEN			32 +#define CRCLENGTH				4 + +/* Define a macro that takes a le32 word, converts it to host ordering, + * right shifts by a specified count, creates a mask of the specified + * bit count, and extracts that number of bits. + */ + +#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask)		\ +	((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) &	\ +	BIT_LEN_MASK_32(__mask)) + +/* Define a macro that clears a bit field in an le32 word and + * sets the specified value into that bit field. The resulting + * value remains in le32 ordering; however, it is properly converted + * to host ordering for the clear and set operations before conversion + * back to le32. + */ + +#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val)	\ +	(*(__le32 *)(__pdesc) =					\ +	(cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) &	\ +	(~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) |		\ +	(((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift))))); + +/* macros to read/write various fields in RX or TX descriptors */ + +#define SET_TX_DESC_PKT_SIZE(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) +#define SET_TX_DESC_OFFSET(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) +#define SET_TX_DESC_BMC(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val) +#define SET_TX_DESC_HTC(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val) +#define SET_TX_DESC_LAST_SEG(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) +#define SET_TX_DESC_FIRST_SEG(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) +#define SET_TX_DESC_LINIP(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) +#define SET_TX_DESC_NO_ACM(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) +#define SET_TX_DESC_GF(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) +#define SET_TX_DESC_OWN(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + +#define GET_TX_DESC_PKT_SIZE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 0, 16) +#define GET_TX_DESC_OFFSET(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 16, 8) +#define GET_TX_DESC_BMC(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 24, 1) +#define GET_TX_DESC_HTC(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 25, 1) +#define GET_TX_DESC_LAST_SEG(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 26, 1) +#define GET_TX_DESC_FIRST_SEG(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 27, 1) +#define GET_TX_DESC_LINIP(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 28, 1) +#define GET_TX_DESC_NO_ACM(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 29, 1) +#define GET_TX_DESC_GF(__pdesc)				\ +	SHIFT_AND_MASK_LE(__pdesc, 30, 1) +#define GET_TX_DESC_OWN(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 31, 1) + +#define SET_TX_DESC_MACID(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val) +#define SET_TX_DESC_AGG_ENABLE(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val) +#define SET_TX_DESC_BK(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val) +#define SET_TX_DESC_RDG_ENABLE(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val) +#define SET_TX_DESC_QUEUE_SEL(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val) +#define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val) +#define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val) +#define SET_TX_DESC_PIFS(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val) +#define SET_TX_DESC_RATE_ID(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val) +#define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val) +#define SET_TX_DESC_EN_DESC_ID(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val) +#define SET_TX_DESC_SEC_TYPE(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val) +#define SET_TX_DESC_PKT_OFFSET(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+4, 26, 8, __val) + +#define GET_TX_DESC_MACID(__pdesc)					\ +	SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) +#define GET_TX_DESC_AGG_ENABLE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 5, 1) +#define GET_TX_DESC_AGG_BREAK(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 6, 1) +#define GET_TX_DESC_RDG_ENABLE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 7, 1) +#define GET_TX_DESC_QUEUE_SEL(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 8, 5) +#define GET_TX_DESC_RDG_NAV_EXT(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+4, 13, 1) +#define GET_TX_DESC_LSIG_TXOP_EN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) +#define GET_TX_DESC_PIFS(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) +#define GET_TX_DESC_RATE_ID(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) +#define GET_TX_DESC_NAV_USE_HDR(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+4, 20, 1) +#define GET_TX_DESC_EN_DESC_ID(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 21, 1) +#define GET_TX_DESC_SEC_TYPE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 22, 2) +#define GET_TX_DESC_PKT_OFFSET(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 24, 8) + +#define SET_TX_DESC_RTS_RC(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val) +#define SET_TX_DESC_DATA_RC(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val) +#define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val) +#define SET_TX_DESC_MORE_FRAG(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val) +#define SET_TX_DESC_RAW(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val) +#define SET_TX_DESC_CCX(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val) +#define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val) +#define SET_TX_DESC_ANTSEL_A(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val) +#define SET_TX_DESC_ANTSEL_B(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val) +#define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val) +#define SET_TX_DESC_TX_ANTL(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val) +#define SET_TX_DESC_TX_ANT_HT(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val) + +#define GET_TX_DESC_RTS_RC(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 0, 6) +#define GET_TX_DESC_DATA_RC(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 6, 6) +#define GET_TX_DESC_BAR_RTY_TH(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 14, 2) +#define GET_TX_DESC_MORE_FRAG(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 17, 1) +#define GET_TX_DESC_RAW(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 18, 1) +#define GET_TX_DESC_CCX(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 19, 1) +#define GET_TX_DESC_AMPDU_DENSITY(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+8, 20, 3) +#define GET_TX_DESC_ANTSEL_A(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 24, 1) +#define GET_TX_DESC_ANTSEL_B(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 25, 1) +#define GET_TX_DESC_TX_ANT_CCK(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 26, 2) +#define GET_TX_DESC_TX_ANTL(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 28, 2) +#define GET_TX_DESC_TX_ANT_HT(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 30, 2) + +#define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val) +#define SET_TX_DESC_TAIL_PAGE(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val) +#define SET_TX_DESC_SEQ(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val) +#define SET_TX_DESC_PKT_ID(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val) + +#define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+12, 0, 8) +#define GET_TX_DESC_TAIL_PAGE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+12, 8, 8) +#define GET_TX_DESC_SEQ(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+12, 16, 12) +#define GET_TX_DESC_PKT_ID(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+12, 28, 4) + +#define SET_TX_DESC_RTS_RATE(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val) +#define SET_TX_DESC_AP_DCFE(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val) +#define SET_TX_DESC_QOS(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val) +#define SET_TX_DESC_HWSEQ_EN(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val) +#define SET_TX_DESC_USE_RATE(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val) +#define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val) +#define SET_TX_DESC_DISABLE_FB(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val) +#define SET_TX_DESC_CTS2SELF(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val) +#define SET_TX_DESC_RTS_ENABLE(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val) +#define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val) +#define SET_TX_DESC_PORT_ID(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val) +#define SET_TX_DESC_WAIT_DCTS(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val) +#define SET_TX_DESC_CTS2AP_EN(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val) +#define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val) +#define SET_TX_DESC_TX_STBC(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val) +#define SET_TX_DESC_DATA_SHORT(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val) +#define SET_TX_DESC_DATA_BW(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val) +#define SET_TX_DESC_RTS_SHORT(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val) +#define SET_TX_DESC_RTS_BW(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val) +#define SET_TX_DESC_RTS_SC(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val) +#define SET_TX_DESC_RTS_STBC(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val) + +#define GET_TX_DESC_RTS_RATE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 0, 5) +#define GET_TX_DESC_AP_DCFE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 5, 1) +#define GET_TX_DESC_QOS(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 6, 1) +#define GET_TX_DESC_HWSEQ_EN(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 7, 1) +#define GET_TX_DESC_USE_RATE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 8, 1) +#define GET_TX_DESC_DISABLE_RTS_FB(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+16, 9, 1) +#define GET_TX_DESC_DISABLE_FB(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 10, 1) +#define GET_TX_DESC_CTS2SELF(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 11, 1) +#define GET_TX_DESC_RTS_ENABLE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 12, 1) +#define GET_TX_DESC_HW_RTS_ENABLE(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+16, 13, 1) +#define GET_TX_DESC_PORT_ID(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 14, 1) +#define GET_TX_DESC_WAIT_DCTS(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 18, 1) +#define GET_TX_DESC_CTS2AP_EN(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 19, 1) +#define GET_TX_DESC_TX_SUB_CARRIER(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+16, 20, 2) +#define GET_TX_DESC_TX_STBC(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 22, 2) +#define GET_TX_DESC_DATA_SHORT(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 24, 1) +#define GET_TX_DESC_DATA_BW(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 25, 1) +#define GET_TX_DESC_RTS_SHORT(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 26, 1) +#define GET_TX_DESC_RTS_BW(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 27, 1) +#define GET_TX_DESC_RTS_SC(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 28, 2) +#define GET_TX_DESC_RTS_STBC(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 30, 2) + +#define SET_TX_DESC_TX_RATE(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val) +#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val) +#define SET_TX_DESC_CCX_TAG(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val) +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val) +#define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val) + +#define GET_TX_DESC_TX_RATE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+20, 0, 6) +#define GET_TX_DESC_DATA_SHORTGI(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+20, 6, 1) +#define GET_TX_DESC_CCX_TAG(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+20, 7, 1) +#define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+20, 8, 5) +#define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+20, 13, 4) +#define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+20, 17, 1) +#define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+20, 18, 6) +#define GET_TX_DESC_USB_TXAGG_NUM(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+20, 24, 8) + +#define SET_TX_DESC_TXAGC_A(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val) +#define SET_TX_DESC_TXAGC_B(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val) +#define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val) +#define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val) +#define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val) +#define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val) +#define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+24, 24, 4, __val) +#define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val) + +#define GET_TX_DESC_TXAGC_A(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+24, 0, 5) +#define GET_TX_DESC_TXAGC_B(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+24, 5, 5) +#define GET_TX_DESC_USE_MAX_LEN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+24, 10, 1) +#define GET_TX_DESC_MAX_AGG_NUM(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+24, 11, 5) +#define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+24, 16, 4) +#define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+24, 20, 4) +#define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+24, 24, 4) +#define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+24, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val) +#define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val) +#define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val) +#define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val) +#define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val) + +#define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+28, 0, 16) +#define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+28, 16, 4) +#define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+28, 20, 4) +#define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+28, 24, 4) +#define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+28, 28, 4) + +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val) +#define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \ +	SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val) + +#define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+32, 0, 32) +#define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc)	\ +	SHIFT_AND_MASK_LE(__pdesc+36, 0, 32) + +#define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val)	\ +	SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val) +#define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \ +	SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val) + +#define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+40, 0, 32) +#define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc)	\ +	SHIFT_AND_MASK_LE(__pdesc+44, 0, 32) + +#define GET_RX_DESC_PKT_LEN(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 0, 14) +#define GET_RX_DESC_CRC32(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 14, 1) +#define GET_RX_DESC_ICV(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 15, 1) +#define GET_RX_DESC_DRV_INFO_SIZE(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc, 16, 4) +#define GET_RX_DESC_SECURITY(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 20, 3) +#define GET_RX_DESC_QOS(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 23, 1) +#define GET_RX_DESC_SHIFT(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 24, 2) +#define GET_RX_DESC_PHYST(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 26, 1) +#define GET_RX_DESC_SWDEC(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 27, 1) +#define GET_RX_DESC_LS(__pdesc)				\ +	SHIFT_AND_MASK_LE(__pdesc, 28, 1) +#define GET_RX_DESC_FS(__pdesc)				\ +	SHIFT_AND_MASK_LE(__pdesc, 29, 1) +#define GET_RX_DESC_EOR(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 30, 1) +#define GET_RX_DESC_OWN(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc, 31, 1) + +#define SET_RX_DESC_PKT_LEN(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) +#define SET_RX_DESC_EOR(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) +#define SET_RX_DESC_OWN(__pdesc, __val)			\ +	SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) + +#define GET_RX_DESC_MACID(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 0, 5) +#define GET_RX_DESC_TID(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 5, 4) +#define GET_RX_DESC_HWRSVD(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 9, 5) +#define GET_RX_DESC_PAGGR(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 14, 1) +#define GET_RX_DESC_FAGGR(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 15, 1) +#define GET_RX_DESC_A1_FIT(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 16, 4) +#define GET_RX_DESC_A2_FIT(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 20, 4) +#define GET_RX_DESC_PAM(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 24, 1) +#define GET_RX_DESC_PWR(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 25, 1) +#define GET_RX_DESC_MD(__pdesc)				\ +	SHIFT_AND_MASK_LE(__pdesc+4, 26, 1) +#define GET_RX_DESC_MF(__pdesc)				\ +	SHIFT_AND_MASK_LE(__pdesc+4, 27, 1) +#define GET_RX_DESC_TYPE(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+4, 28, 2) +#define GET_RX_DESC_MC(__pdesc)				\ +	SHIFT_AND_MASK_LE(__pdesc+4, 30, 1) +#define GET_RX_DESC_BC(__pdesc)				\ +	SHIFT_AND_MASK_LE(__pdesc+4, 31, 1) +#define GET_RX_DESC_SEQ(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 0, 12) +#define GET_RX_DESC_FRAG(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 12, 4) +#define GET_RX_DESC_NEXT_PKT_LEN(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+8, 16, 14) +#define GET_RX_DESC_NEXT_IND(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 30, 1) +#define GET_RX_DESC_RSVD(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+8, 31, 1) + +#define GET_RX_DESC_RXMCS(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+12, 0, 6) +#define GET_RX_DESC_RXHT(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+12, 6, 1) +#define GET_RX_DESC_SPLCP(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+12, 8, 1) +#define GET_RX_DESC_BW(__pdesc)				\ +	SHIFT_AND_MASK_LE(__pdesc+12, 9, 1) +#define GET_RX_DESC_HTC(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+12, 10, 1) +#define GET_RX_DESC_HWPC_ERR(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+12, 14, 1) +#define GET_RX_DESC_HWPC_IND(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+12, 15, 1) +#define GET_RX_DESC_IV0(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+12, 16, 16) + +#define GET_RX_DESC_IV1(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+16, 0, 32) +#define GET_RX_DESC_TSFL(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+20, 0, 32) + +#define GET_RX_DESC_BUFF_ADDR(__pdesc)			\ +	SHIFT_AND_MASK_LE(__pdesc+24, 0, 32) +#define GET_RX_DESC_BUFF_ADDR64(__pdesc)		\ +	SHIFT_AND_MASK_LE(__pdesc+28, 0, 32) + +#define SET_RX_DESC_BUFF_ADDR(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val) +#define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val)		\ +	SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val) + +#define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size)	\ +do {							\ +	if (_size > TX_DESC_NEXT_DESC_OFFSET)		\ +		memset((void *)__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET);	\ +	else						\ +		memset((void *)__pdesc, 0, _size);	\ +} while (0); + +#define RX_HAL_IS_CCK_RATE(_pdesc)\ +	(_pdesc->rxmcs == DESC92D_RATE1M ||		\ +	 _pdesc->rxmcs == DESC92D_RATE2M ||		\ +	 _pdesc->rxmcs == DESC92D_RATE5_5M ||		\ +	 _pdesc->rxmcs == DESC92D_RATE11M) + +/* For 92D early mode */ +#define SET_EARLYMODE_PKTNUM(__paddr, __value)		\ +	SET_BITS_OFFSET_LE(__paddr, 0, 3, __value) +#define SET_EARLYMODE_LEN0(__paddr, __value)		\ +	SET_BITS_OFFSET_LE(__paddr, 4, 12, __value) +#define SET_EARLYMODE_LEN1(__paddr, __value)		\ +	SET_BITS_OFFSET_LE(__paddr, 16, 12, __value) +#define SET_EARLYMODE_LEN2_1(__paddr, __value)		\ +	SET_BITS_OFFSET_LE(__paddr, 28, 4, __value) +#define SET_EARLYMODE_LEN2_2(__paddr, __value)		\ +	SET_BITS_OFFSET_LE(__paddr+4, 0, 8, __value) +#define SET_EARLYMODE_LEN3(__paddr, __value)		\ +	SET_BITS_OFFSET_LE(__paddr+4, 8, 12, __value) +#define SET_EARLYMODE_LEN4(__paddr, __value)		\ +	SET_BITS_OFFSET_LE(__paddr+4, 20, 12, __value) + +struct rx_fwinfo_92d { +	u8 gain_trsw[4]; +	u8 pwdb_all; +	u8 cfosho[4]; +	u8 cfotail[4]; +	char rxevm[2]; +	char rxsnr[4]; +	u8 pdsnr[2]; +	u8 csi_current[2]; +	u8 csi_target[2]; +	u8 sigevm; +	u8 max_ex_pwr; +	u8 ex_intf_flag:1; +	u8 sgi_en:1; +	u8 rxsc:2; +	u8 reserve:4; +} __packed; + +struct tx_desc_92d { +	u32 pktsize:16; +	u32 offset:8; +	u32 bmc:1; +	u32 htc:1; +	u32 lastseg:1; +	u32 firstseg:1; +	u32 linip:1; +	u32 noacm:1; +	u32 gf:1; +	u32 own:1; + +	u32 macid:5; +	u32 agg_en:1; +	u32 bk:1; +	u32 rdg_en:1; +	u32 queuesel:5; +	u32 rd_nav_ext:1; +	u32 lsig_txop_en:1; +	u32 pifs:1; +	u32 rateid:4; +	u32 nav_usehdr:1; +	u32 en_descid:1; +	u32 sectype:2; +	u32 pktoffset:8; + +	u32 rts_rc:6; +	u32 data_rc:6; +	u32 rsvd0:2; +	u32 bar_retryht:2; +	u32 rsvd1:1; +	u32 morefrag:1; +	u32 raw:1; +	u32 ccx:1; +	u32 ampdudensity:3; +	u32 rsvd2:1; +	u32 ant_sela:1; +	u32 ant_selb:1; +	u32 txant_cck:2; +	u32 txant_l:2; +	u32 txant_ht:2; + +	u32 nextheadpage:8; +	u32 tailpage:8; +	u32 seq:12; +	u32 pktid:4; + +	u32 rtsrate:5; +	u32 apdcfe:1; +	u32 qos:1; +	u32 hwseq_enable:1; +	u32 userrate:1; +	u32 dis_rtsfb:1; +	u32 dis_datafb:1; +	u32 cts2self:1; +	u32 rts_en:1; +	u32 hwrts_en:1; +	u32 portid:1; +	u32 rsvd3:3; +	u32 waitdcts:1; +	u32 cts2ap_en:1; +	u32 txsc:2; +	u32 stbc:2; +	u32 txshort:1; +	u32 txbw:1; +	u32 rtsshort:1; +	u32 rtsbw:1; +	u32 rtssc:2; +	u32 rtsstbc:2; + +	u32 txrate:6; +	u32 shortgi:1; +	u32 ccxt:1; +	u32 txrate_fb_lmt:5; +	u32 rtsrate_fb_lmt:4; +	u32 retrylmt_en:1; +	u32 txretrylmt:6; +	u32 usb_txaggnum:8; + +	u32 txagca:5; +	u32 txagcb:5; +	u32 usemaxlen:1; +	u32 maxaggnum:5; +	u32 mcsg1maxlen:4; +	u32 mcsg2maxlen:4; +	u32 mcsg3maxlen:4; +	u32 mcs7sgimaxlen:4; + +	u32 txbuffersize:16; +	u32 mcsg4maxlen:4; +	u32 mcsg5maxlen:4; +	u32 mcsg6maxlen:4; +	u32 mcsg15sgimaxlen:4; + +	u32 txbuffaddr; +	u32 txbufferaddr64; +	u32 nextdescaddress; +	u32 nextdescaddress64; + +	u32 reserve_pass_pcie_mm_limit[4]; +} __packed; + +struct rx_desc_92d { +	u32 length:14; +	u32 crc32:1; +	u32 icverror:1; +	u32 drv_infosize:4; +	u32 security:3; +	u32 qos:1; +	u32 shift:2; +	u32 phystatus:1; +	u32 swdec:1; +	u32 lastseg:1; +	u32 firstseg:1; +	u32 eor:1; +	u32 own:1; + +	u32 macid:5; +	u32 tid:4; +	u32 hwrsvd:5; +	u32 paggr:1; +	u32 faggr:1; +	u32 a1_fit:4; +	u32 a2_fit:4; +	u32 pam:1; +	u32 pwr:1; +	u32 moredata:1; +	u32 morefrag:1; +	u32 type:2; +	u32 mc:1; +	u32 bc:1; + +	u32 seq:12; +	u32 frag:4; +	u32 nextpktlen:14; +	u32 nextind:1; +	u32 rsvd:1; + +	u32 rxmcs:6; +	u32 rxht:1; +	u32 amsdu:1; +	u32 splcp:1; +	u32 bandwidth:1; +	u32 htc:1; +	u32 tcpchk_rpt:1; +	u32 ipcchk_rpt:1; +	u32 tcpchk_valid:1; +	u32 hwpcerr:1; +	u32 hwpcind:1; +	u32 iv0:16; + +	u32 iv1; + +	u32 tsfl; + +	u32 bufferaddress; +	u32 bufferaddress64; + +} __packed; + +void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, +			  struct ieee80211_hdr *hdr, +			  u8 *pdesc, struct ieee80211_tx_info *info, +			  struct sk_buff *skb, u8 hw_queue, +			  struct rtl_tcb_desc *ptcb_desc); +bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, +			   struct rtl_stats *stats, +			   struct ieee80211_rx_status *rx_status, +			   u8 *pdesc, struct sk_buff *skb); +void rtl92de_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); +u32 rtl92de_get_desc(u8 *pdesc, bool istx, u8 desc_name); +void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); +void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, +			     bool b_firstseg, bool b_lastseg, +			     struct sk_buff *skb); + +#endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c index da86db86fa4..4203a8531ca 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c @@ -222,7 +222,6 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)  	u32 low_rssi_thresh = 0;  	u32 middle_rssi_thresh = 0;  	u32 high_rssi_thresh = 0; -	u8 rssi_level;  	struct ieee80211_sta *sta = NULL;  	if (is_hal_stop(rtlhal)) @@ -272,18 +271,14 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)  		if (rtlpriv->dm.undecorated_smoothed_pwdb >  		    (long)high_rssi_thresh) {  			ra->ratr_state = DM_RATR_STA_HIGH; -			rssi_level = 1;  		} else if (rtlpriv->dm.undecorated_smoothed_pwdb >  			   (long)middle_rssi_thresh) {  			ra->ratr_state = DM_RATR_STA_LOW; -			rssi_level = 3;  		} else if (rtlpriv->dm.undecorated_smoothed_pwdb >  			   (long)low_rssi_thresh) {  			ra->ratr_state = DM_RATR_STA_LOW; -			rssi_level = 5;  		} else {  			ra->ratr_state = DM_RATR_STA_ULTRALOW; -			rssi_level = 6;  		}  		if (ra->pre_ratr_state != ra->ratr_state) { @@ -457,7 +452,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)  			if (rtlpriv->psc.rfpwr_state != ERFON)  				return; -			if (digtable.backoff_enable_flag == true) +			if (digtable.backoff_enable_flag)  				rtl92s_backoff_enable_flag(hw);  			else  				digtable.backoff_val = DM_DIG_BACKOFF; diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c index 3b5af0113d7..6f91a148c22 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c @@ -358,7 +358,6 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)  	struct fw_priv *pfw_priv = NULL;  	u8 *puc_mappedfile = NULL;  	u32 ul_filelength = 0; -	u32 file_length = 0;  	u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE;  	u8 fwstatus = FW_STATUS_INIT;  	bool rtstatus = true; @@ -370,7 +369,6 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)  	firmware->fwstatus = FW_STATUS_INIT;  	puc_mappedfile = firmware->sz_fw_tmpbuffer; -	file_length = firmware->sz_fw_tmpbufferlen;  	/* 1. Retrieve FW header. */  	firmware->pfwheader = (struct fw_hdr *) puc_mappedfile; diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index 2e9005d0454..b1d0213dc60 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c @@ -516,7 +516,7 @@ static u8 _rtl92se_rf_onoff_detect(struct ieee80211_hw *hw)  	mdelay(10);  	/* check GPIO3 */ -	u1tmp = rtl_read_byte(rtlpriv, GPIO_IN); +	u1tmp = rtl_read_byte(rtlpriv, GPIO_IN_SE);  	retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF;  	return retval; @@ -884,12 +884,10 @@ static void _rtl92se_hw_configure(struct ieee80211_hw *hw)  	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));  	u8 reg_bw_opmode = 0; -	u32 reg_ratr = 0, reg_rrsr = 0; +	u32 reg_rrsr = 0;  	u8 regtmp = 0;  	reg_bw_opmode = BW_OPMODE_20MHZ; -	reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | -				RATE_ALL_OFDM_2SS;  	reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG;  	regtmp = rtl_read_byte(rtlpriv, INIRTSMCS_SEL); @@ -996,7 +994,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)  		rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT;  		rtlpriv->psc.rfpwr_state = ERFON; -		rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason, true); +		/* FIXME: check spinlocks if this block is uncommented */ +		rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason);  	} else {  		/* gpio radio on/off is out of adapter start */  		if (rtlpriv->psc.hwradiooff == false) { @@ -1107,7 +1106,7 @@ void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)  	if (rtlpriv->psc.rfpwr_state != ERFON)  		return; -	if (check_bssid == true) { +	if (check_bssid) {  		reg_rcr |= (RCR_CBSSID);  		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr));  	} else if (check_bssid == false) { @@ -1122,14 +1121,12 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,  {  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	u8 bt_msr = rtl_read_byte(rtlpriv, MSR); -	enum led_ctl_mode ledaction = LED_CTL_NO_LINK;  	u32 temp;  	bt_msr &= ~MSR_LINK_MASK;  	switch (type) {  	case NL80211_IFTYPE_UNSPECIFIED:  		bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT); -		ledaction = LED_CTL_LINK;  		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,  			 ("Set Network type to NO LINK!\n"));  		break; @@ -1140,7 +1137,6 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw,  		break;  	case NL80211_IFTYPE_STATION:  		bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT); -		ledaction = LED_CTL_LINK;  		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,  			 ("Set Network type to STA!\n"));  		break; @@ -1218,8 +1214,6 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw)  	rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]);  	/* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */  	rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F); - -	rtlpci->irq_enabled = true;  }  void rtl92se_disable_interrupt(struct ieee80211_hw *hw) @@ -1230,7 +1224,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw)  	rtl_write_dword(rtlpriv, INTA_MASK, 0);  	rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); -	rtlpci->irq_enabled = false; +	synchronize_irq(rtlpci->pdev->irq);  } @@ -1655,7 +1649,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)  		rtlefuse->autoload_failflag = false;  	} -	if (rtlefuse->autoload_failflag == true) +	if (rtlefuse->autoload_failflag)  		return;  	_rtl8192se_get_IC_Inferiority(hw); @@ -2271,7 +2265,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));  	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); -	enum rf_pwrstate rfpwr_toset, cur_rfstate; +	enum rf_pwrstate rfpwr_toset /*, cur_rfstate */;  	unsigned long flag = 0;  	bool actuallyset = false;  	bool turnonbypowerdomain = false; @@ -2292,7 +2286,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)  		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);  	} -	cur_rfstate = ppsc->rfpwr_state; +	/* cur_rfstate = ppsc->rfpwr_state;*/  	/* because after _rtl92s_phy_set_rfhalt, all power  	 * closed, so we must open some power for GPIO check, @@ -2305,7 +2299,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)  	rfpwr_toset = _rtl92se_rf_onoff_detect(hw); -	if ((ppsc->hwradiooff == true) && (rfpwr_toset == ERFON)) { +	if ((ppsc->hwradiooff) && (rfpwr_toset == ERFON)) {  		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,  			 ("RFKILL-HW Radio ON, RF ON\n")); diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/rtlwifi/rtl8192se/led.c index 6d4f6661668..e3fe7c90ebf 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/led.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.c @@ -90,7 +90,7 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)  		break;  	case LED_PIN_LED0:  		ledcfg &= 0xf0; -		if (pcipriv->ledctl.led_opendrain == true) +		if (pcipriv->ledctl.led_opendrain)  			rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1)));  		else  			rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index 63b45e60a95..81a5aa4370c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c @@ -180,19 +180,18 @@ u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,  {  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	u32 original_value, readback_value, bitshift; -	unsigned long flags;  	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "  		 "bitmask(%#x)\n", regaddr, rfpath, bitmask)); -	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); +	spin_lock(&rtlpriv->locks.rf_lock);  	original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr);  	bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);  	readback_value = (original_value & bitmask) >> bitshift; -	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); +	spin_unlock(&rtlpriv->locks.rf_lock);  	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), "  		 "bitmask(%#x), original_value(%#x)\n", regaddr, rfpath, @@ -207,7 +206,6 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	struct rtl_phy *rtlphy = &(rtlpriv->phy);  	u32 original_value, bitshift; -	unsigned long flags;  	if (!((rtlphy->rf_pathmap >> rfpath) & 0x1))  		return; @@ -215,7 +213,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,  	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"  		 " data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath)); -	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); +	spin_lock(&rtlpriv->locks.rf_lock);  	if (bitmask != RFREG_OFFSET_MASK) {  		original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, @@ -226,7 +224,7 @@ void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,  	_rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data); -	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); +	spin_unlock(&rtlpriv->locks.rf_lock);  	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x), "  		 "data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath)); @@ -263,7 +261,6 @@ void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw,  	struct rtl_phy *rtlphy = &(rtlpriv->phy);  	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));  	u8 reg_bw_opmode; -	u8 reg_prsr_rsc;  	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("Switch to %s bandwidth\n",  		  rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? @@ -277,7 +274,8 @@ void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw,  	rtlphy->set_bwmode_inprogress = true;  	reg_bw_opmode = rtl_read_byte(rtlpriv, BW_OPMODE); -	reg_prsr_rsc = rtl_read_byte(rtlpriv, RRSR + 2); +	/* dummy read */ +	rtl_read_byte(rtlpriv, RRSR + 2);  	switch (rtlphy->current_chan_bw) {  	case HT_CHANNEL_WIDTH_20: @@ -546,8 +544,6 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,  	if (rfpwr_state == ppsc->rfpwr_state)  		return false; -	ppsc->set_rfpowerstate_inprogress = true; -  	switch (rfpwr_state) {  	case ERFON:{  			if ((ppsc->rfpwr_state == ERFOFF) && @@ -659,8 +655,6 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw,  	if (bresult)  		ppsc->rfpwr_state = rfpwr_state; -	ppsc->set_rfpowerstate_inprogress = false; -  	return bresult;  } @@ -1422,7 +1416,7 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw)  		break;  	case FW_CMD_HIGH_PWR_ENABLE:  		if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || -			(rtlpriv->dm.dynamic_txpower_enable == true)) +			rtlpriv->dm.dynamic_txpower_enable)  			break;  		/* CCA threshold */ @@ -1614,7 +1608,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)  				fw_cmdmap &= ~FW_DIG_ENABLE_CTL;  			if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || -			    (rtlpriv->dm.dynamic_txpower_enable == true)) +			    rtlpriv->dm.dynamic_txpower_enable)  				fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL;  			if ((digtable.dig_ext_port_stage == diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h index 0116eaddbfa..ea32ef2d409 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h @@ -248,12 +248,8 @@  #define	PSTIME					0x02E0  #define	TIMER0					0x02E4  #define	TIMER1					0x02E8 -#define	GPIO_CTRL				0x02EC -#define	GPIO_IN					0x02EC -#define	GPIO_OUT				0x02ED +#define	GPIO_IN_SE				0x02EC  #define	GPIO_IO_SEL				0x02EE -#define	GPIO_MOD				0x02EF -#define	GPIO_INTCTRL				0x02F0  #define	MAC_PINMUX_CFG				0x02F1  #define	LEDCFG					0x02F2  #define	PHY_REG					0x02F3 diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c index 1d3a4833039..c6e3a4ca42f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c @@ -410,7 +410,7 @@ void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel)  	      (rtlefuse->eeprom_regulatory != 0)))  		dont_inc_cck_or_turboscanoff = true; -	if (mac->act_scanning == true) { +	if (mac->act_scanning) {  		txagc = 0x3f;  		if (dont_inc_cck_or_turboscanoff)  			txagc = pwrlevel; diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 5cf442373d4..cffe30851f7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -581,7 +581,6 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,  	struct ieee80211_hdr *hdr;  	u8 *tmp_buf;  	u8 *praddr; -	u8 *psaddr;  	__le16 fc;  	u16 type, cfc;  	bool packet_matchbssid, packet_toself, packet_beacon; @@ -593,7 +592,6 @@ static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,  	cfc = le16_to_cpu(fc);  	type = WLAN_FC_GET_TYPE(fc);  	praddr = hdr->addr1; -	psaddr = hdr->addr2;  	packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&  	     (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ? @@ -663,7 +661,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,  	rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc); -	if (phystatus == true) { +	if (phystatus) {  		p_drvinfo = (struct rx_fwinfo *)(skb->data +  						 stats->rx_bufshift);  		_rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc, @@ -875,6 +873,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,  		SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));  		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); +		wmb();  		SET_TX_DESC_OWN(pdesc, 1);  	} else { /* H2C Command Desc format (Host TXCMD) */  		/* 92SE must set as 1 for firmware download HW DMA error */ @@ -893,6 +892,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,  		SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));  		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); +		wmb();  		SET_TX_DESC_OWN(pdesc, 1);  	} @@ -900,9 +900,10 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,  void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)  { -	if (istx == true) { +	if (istx) {  		switch (desc_name) {  		case HW_DESC_OWN: +			wmb();  			SET_TX_DESC_OWN(pdesc, 1);  			break;  		case HW_DESC_TX_NEXTDESC_ADDR: @@ -916,6 +917,7 @@ void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)  	} else {  		switch (desc_name) {  		case HW_DESC_RXOWN: +			wmb();  			SET_RX_STATUS_DESC_OWN(pdesc, 1);  			break;  		case HW_DESC_RXBUFF_ADDR: @@ -939,7 +941,7 @@ u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name)  {  	u32 ret = 0; -	if (istx == true) { +	if (istx) {  		switch (desc_name) {  		case HW_DESC_OWN:  			ret = GET_TX_DESC_OWN(desc); diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 693395ee98f..d3c3ffd3898 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -32,7 +32,6 @@  #include <linux/sched.h>  #include <linux/firmware.h> -#include <linux/version.h>  #include <linux/etherdevice.h>  #include <linux/vmalloc.h>  #include <linux/usb.h> @@ -303,9 +302,6 @@ enum hw_variables {  	HW_VAR_DATA_FILTER,  }; -#define HWSET_MAX_SIZE				128 -#define EFUSE_MAX_SECTION			16 -  enum _RT_MEDIA_STATUS {  	RT_MEDIA_DISCONNECT = 0,  	RT_MEDIA_CONNECT = 1 @@ -938,7 +934,7 @@ struct rtl_mac {  	int n_channels;  	int n_bitrates; -	bool offchan_deley; +	bool offchan_delay;  	/*filters */  	u32 rx_conf; @@ -1188,7 +1184,6 @@ struct rtl_efuse {  struct rtl_ps_ctl {  	bool pwrdomain_protect; -	bool set_rfpowerstate_inprogress;  	bool in_powersavemode;  	bool rfchange_inprogress;  	bool swrf_processing; @@ -1536,6 +1531,7 @@ struct rtl_works {  	/* For SW LPS */  	struct delayed_work ps_work;  	struct delayed_work ps_rfon_wq; +	struct tasklet_struct ips_leave_tasklet;  };  struct rtl_debug { @@ -1983,7 +1979,7 @@ static inline u16 rtl_get_tid(struct sk_buff *skb)  static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw,  					    struct ieee80211_vif *vif, -					    u8 *bssid) +					    const u8 *bssid)  {  	return ieee80211_find_sta(vif, bssid);  } diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c index f51a0241a44..f78694295c3 100644 --- a/drivers/net/wireless/wl1251/sdio.c +++ b/drivers/net/wireless/wl1251/sdio.c @@ -19,6 +19,7 @@   * Copyright (C) 2008 Google Inc   * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com)   */ +#include <linux/interrupt.h>  #include <linux/module.h>  #include <linux/mod_devicetable.h>  #include <linux/mmc/sdio_func.h> diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c index af6448c4d3e..eaa5f955620 100644 --- a/drivers/net/wireless/wl1251/spi.c +++ b/drivers/net/wireless/wl1251/spi.c @@ -19,6 +19,7 @@   *   */ +#include <linux/interrupt.h>  #include <linux/irq.h>  #include <linux/module.h>  #include <linux/slab.h> diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 35ce7b0f4a6..07bcb1548d8 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -11,7 +11,6 @@ config WL12XX  	depends on WL12XX_MENU && GENERIC_HARDIRQS  	depends on INET  	select FW_LOADER -	select CRC7  	---help---  	  This module adds support for wireless adapters based on TI wl1271 and  	  TI wl1273 chipsets. This module does *not* include support for wl1251. @@ -33,6 +32,7 @@ config WL12XX_HT  config WL12XX_SPI  	tristate "TI wl12xx SPI support"  	depends on WL12XX && SPI_MASTER +	select CRC7  	---help---  	  This module adds support for the SPI interface of adapters using  	  TI wl12xx chipsets.  Select this if your platform is using diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index c6ee530e5bf..7e33f1f4f3d 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c @@ -25,7 +25,6 @@  #include <linux/module.h>  #include <linux/platform_device.h> -#include <linux/crc7.h>  #include <linux/spi/spi.h>  #include <linux/slab.h> @@ -91,7 +90,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)  	struct acx_current_tx_power *acx;  	int ret; -	wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr"); +	wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr %d", power);  	if (power < 0 || power > 25)  		return -EINVAL; @@ -1068,6 +1067,7 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)  	mem_conf->tx_free_req = mem->min_req_tx_blocks;  	mem_conf->rx_free_req = mem->min_req_rx_blocks;  	mem_conf->tx_min = mem->tx_min; +	mem_conf->fwlog_blocks = wl->conf.fwlog.mem_blocks;  	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,  				   sizeof(*mem_conf)); @@ -1577,22 +1577,69 @@ out:  	return ret;  } -int wl1271_acx_max_tx_retry(struct wl1271 *wl) +int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)  { -	struct wl1271_acx_max_tx_retry *acx = NULL; +	struct wl1271_acx_ps_rx_streaming *rx_streaming; +	u32 conf_queues, enable_queues; +	int i, ret = 0; + +	wl1271_debug(DEBUG_ACX, "acx ps rx streaming"); + +	rx_streaming = kzalloc(sizeof(*rx_streaming), GFP_KERNEL); +	if (!rx_streaming) { +		ret = -ENOMEM; +		goto out; +	} + +	conf_queues = wl->conf.rx_streaming.queues; +	if (enable) +		enable_queues = conf_queues; +	else +		enable_queues = 0; + +	for (i = 0; i < 8; i++) { +		/* +		 * Skip non-changed queues, to avoid redundant acxs. +		 * this check assumes conf.rx_streaming.queues can't +		 * be changed while rx_streaming is enabled. +		 */ +		if (!(conf_queues & BIT(i))) +			continue; + +		rx_streaming->tid = i; +		rx_streaming->enable = enable_queues & BIT(i); +		rx_streaming->period = wl->conf.rx_streaming.interval; +		rx_streaming->timeout = wl->conf.rx_streaming.interval; + +		ret = wl1271_cmd_configure(wl, ACX_PS_RX_STREAMING, +					   rx_streaming, +					   sizeof(*rx_streaming)); +		if (ret < 0) { +			wl1271_warning("acx ps rx streaming failed: %d", ret); +			goto out; +		} +	} +out: +	kfree(rx_streaming); +	return ret; +} + +int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) +{ +	struct wl1271_acx_ap_max_tx_retry *acx = NULL;  	int ret; -	wl1271_debug(DEBUG_ACX, "acx max tx retry"); +	wl1271_debug(DEBUG_ACX, "acx ap max tx retry");  	acx = kzalloc(sizeof(*acx), GFP_KERNEL);  	if (!acx)  		return -ENOMEM; -	acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries); +	acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries);  	ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));  	if (ret < 0) { -		wl1271_warning("acx max tx retry failed: %d", ret); +		wl1271_warning("acx ap max tx retry failed: %d", ret);  		goto out;  	} diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 9a895e3cc61..d2eb86eccc0 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h @@ -828,6 +828,8 @@ struct wl1271_acx_sta_config_memory {  	u8 tx_free_req;  	u8 rx_free_req;  	u8 tx_min; +	u8 fwlog_blocks; +	u8 padding[3];  } __packed;  struct wl1271_acx_mem_map { @@ -1153,7 +1155,20 @@ struct wl1271_acx_fw_tsf_information {  	u8 padding[3];  } __packed; -struct wl1271_acx_max_tx_retry { +struct wl1271_acx_ps_rx_streaming { +	struct acx_header header; + +	u8 tid; +	u8 enable; + +	/* interval between triggers (10-100 msec) */ +	u8 period; + +	/* timeout before first trigger (0-200 msec) */ +	u8 timeout; +} __packed; + +struct wl1271_acx_ap_max_tx_retry {  	struct acx_header header;  	/* @@ -1384,7 +1399,8 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl,  int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,  				       bool enable);  int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); -int wl1271_acx_max_tx_retry(struct wl1271 *wl); +int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); +int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);  int wl1271_acx_config_ps(struct wl1271 *wl);  int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);  int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable); diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index b07f8b7e5f1..5ebc64d8940 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -102,6 +102,33 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)  	wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);  } +static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl) +{ +	unsigned int quirks = 0; +	unsigned int *fw_ver = wl->chip.fw_ver; + +	/* Only for wl127x */ +	if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) && +	    /* Check STA version */ +	    (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && +	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) || +	     /* Check AP version */ +	     ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) && +	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN)))) +		quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS; + +	/* Only new station firmwares support routing fw logs to the host */ +	if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && +	    (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN)) +		quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED; + +	/* This feature is not yet supported for AP mode */ +	if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) +		quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED; + +	return quirks; +} +  static void wl1271_parse_fw_ver(struct wl1271 *wl)  {  	int ret; @@ -116,6 +143,9 @@ static void wl1271_parse_fw_ver(struct wl1271 *wl)  		memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));  		return;  	} + +	/* Check if any quirks are needed with older fw versions */ +	wl->quirks |= wl12xx_get_fw_ver_quirks(wl);  }  static void wl1271_boot_fw_version(struct wl1271 *wl) @@ -483,9 +513,12 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)  		PERIODIC_SCAN_COMPLETE_EVENT_ID;  	if (wl->bss_type == BSS_TYPE_AP_BSS) -		wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; +		wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | +				  INACTIVE_STA_EVENT_ID | +				  MAX_TX_RETRY_EVENT_ID;  	else -		wl->event_mask |= DUMMY_PACKET_EVENT_ID; +		wl->event_mask |= DUMMY_PACKET_EVENT_ID | +			BA_SESSION_RX_CONSTRAINT_EVENT_ID;  	ret = wl1271_event_unmask(wl);  	if (ret < 0) { @@ -748,6 +781,9 @@ int wl1271_load_firmware(struct wl1271 *wl)  		clk |= (wl->ref_clock << 1) << 4;  	} +	if (wl->quirks & WL12XX_QUIRK_LPD_MODE) +		clk |= SCRATCH_ENABLE_LPD; +  	wl1271_write32(wl, DRPW_SCRATCH_START, clk);  	wl1271_set_partition(wl, &part_table[PART_WORK]); diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 42935ac7266..97dd237a958 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -23,7 +23,6 @@  #include <linux/module.h>  #include <linux/platform_device.h> -#include <linux/crc7.h>  #include <linux/spi/spi.h>  #include <linux/etherdevice.h>  #include <linux/ieee80211.h> @@ -106,7 +105,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,  fail:  	WARN_ON(1); -	ieee80211_queue_work(wl->hw, &wl->recovery_work); +	wl12xx_queue_recovery_work(wl);  	return ret;  } @@ -135,6 +134,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)  	/* Override the REF CLK from the NVS with the one from platform data */  	gen_parms->general_params.ref_clock = wl->ref_clock; +	/* LPD mode enable (bits 6-7) in WL1271 AP mode only */ +	if (wl->quirks & WL12XX_QUIRK_LPD_MODE) +		gen_parms->general_params.general_settings |= +			GENERAL_SETTINGS_DRPW_LPD; +  	ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);  	if (ret < 0) {  		wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); @@ -352,7 +356,7 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)  	ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);  	if (ret != 0) { -		ieee80211_queue_work(wl->hw, &wl->recovery_work); +		wl12xx_queue_recovery_work(wl);  		return ret;  	} @@ -396,10 +400,6 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)  	join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; -	/* reset TX security counters */ -	wl->tx_security_last_seq = 0; -	wl->tx_security_seq = 0; -  	wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",  		join->basic_rate_set, join->supported_rate_set); @@ -1080,7 +1080,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl)  	memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); -	cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC); +	cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);  	cmd->bss_index = WL1271_AP_BSS_INDEX;  	cmd->global_hlid = WL1271_AP_GLOBAL_HLID;  	cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; @@ -1167,14 +1167,7 @@ int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)  	cmd->bss_index = WL1271_AP_BSS_INDEX;  	cmd->aid = sta->aid;  	cmd->hlid = hlid; - -	/* -	 * FIXME: Does STA support QOS? We need to propagate this info from -	 * hostapd. Currently not that important since this is only used for -	 * sending the correct flavor of null-data packet in response to a -	 * trigger. -	 */ -	cmd->wmm = 0; +	cmd->wmm = sta->wme ? 1 : 0;  	cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,  						sta->supp_rates[wl->band])); @@ -1230,3 +1223,87 @@ out_free:  out:  	return ret;  } + +int wl12xx_cmd_config_fwlog(struct wl1271 *wl) +{ +	struct wl12xx_cmd_config_fwlog *cmd; +	int ret = 0; + +	wl1271_debug(DEBUG_CMD, "cmd config firmware logger"); + +	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); +	if (!cmd) { +		ret = -ENOMEM; +		goto out; +	} + +	cmd->logger_mode = wl->conf.fwlog.mode; +	cmd->log_severity = wl->conf.fwlog.severity; +	cmd->timestamp = wl->conf.fwlog.timestamp; +	cmd->output = wl->conf.fwlog.output; +	cmd->threshold = wl->conf.fwlog.threshold; + +	ret = wl1271_cmd_send(wl, CMD_CONFIG_FWLOGGER, cmd, sizeof(*cmd), 0); +	if (ret < 0) { +		wl1271_error("failed to send config firmware logger command"); +		goto out_free; +	} + +out_free: +	kfree(cmd); + +out: +	return ret; +} + +int wl12xx_cmd_start_fwlog(struct wl1271 *wl) +{ +	struct wl12xx_cmd_start_fwlog *cmd; +	int ret = 0; + +	wl1271_debug(DEBUG_CMD, "cmd start firmware logger"); + +	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); +	if (!cmd) { +		ret = -ENOMEM; +		goto out; +	} + +	ret = wl1271_cmd_send(wl, CMD_START_FWLOGGER, cmd, sizeof(*cmd), 0); +	if (ret < 0) { +		wl1271_error("failed to send start firmware logger command"); +		goto out_free; +	} + +out_free: +	kfree(cmd); + +out: +	return ret; +} + +int wl12xx_cmd_stop_fwlog(struct wl1271 *wl) +{ +	struct wl12xx_cmd_stop_fwlog *cmd; +	int ret = 0; + +	wl1271_debug(DEBUG_CMD, "cmd stop firmware logger"); + +	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); +	if (!cmd) { +		ret = -ENOMEM; +		goto out; +	} + +	ret = wl1271_cmd_send(wl, CMD_STOP_FWLOGGER, cmd, sizeof(*cmd), 0); +	if (ret < 0) { +		wl1271_error("failed to send stop firmware logger command"); +		goto out_free; +	} + +out_free: +	kfree(cmd); + +out: +	return ret; +} diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h index 5cac95d9480..1f7037292c1 100644 --- a/drivers/net/wireless/wl12xx/cmd.h +++ b/drivers/net/wireless/wl12xx/cmd.h @@ -70,6 +70,9 @@ int wl1271_cmd_start_bss(struct wl1271 *wl);  int wl1271_cmd_stop_bss(struct wl1271 *wl);  int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);  int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid); +int wl12xx_cmd_config_fwlog(struct wl1271 *wl); +int wl12xx_cmd_start_fwlog(struct wl1271 *wl); +int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);  enum wl1271_commands {  	CMD_INTERROGATE     = 1,    /*use this to read information elements*/ @@ -107,6 +110,9 @@ enum wl1271_commands {  	CMD_START_PERIODIC_SCAN      = 50,  	CMD_STOP_PERIODIC_SCAN       = 51,  	CMD_SET_STA_STATE            = 52, +	CMD_CONFIG_FWLOGGER          = 53, +	CMD_START_FWLOGGER           = 54, +	CMD_STOP_FWLOGGER            = 55,  	/* AP mode commands */  	CMD_BSS_START                = 60, @@ -575,4 +581,60 @@ struct wl1271_cmd_remove_sta {  	u8 padding1;  } __packed; +/* + * Continuous mode - packets are transferred to the host periodically + * via the data path. + * On demand - Log messages are stored in a cyclic buffer in the + * firmware, and only transferred to the host when explicitly requested + */ +enum wl12xx_fwlogger_log_mode { +	WL12XX_FWLOG_CONTINUOUS, +	WL12XX_FWLOG_ON_DEMAND +}; + +/* Include/exclude timestamps from the log messages */ +enum wl12xx_fwlogger_timestamp { +	WL12XX_FWLOG_TIMESTAMP_DISABLED, +	WL12XX_FWLOG_TIMESTAMP_ENABLED +}; + +/* + * Logs can be routed to the debug pinouts (where available), to the host bus + * (SDIO/SPI), or dropped + */ +enum wl12xx_fwlogger_output { +	WL12XX_FWLOG_OUTPUT_NONE, +	WL12XX_FWLOG_OUTPUT_DBG_PINS, +	WL12XX_FWLOG_OUTPUT_HOST, +}; + +struct wl12xx_cmd_config_fwlog { +	struct wl1271_cmd_header header; + +	/* See enum wl12xx_fwlogger_log_mode */ +	u8 logger_mode; + +	/* Minimum log level threshold */ +	u8 log_severity; + +	/* Include/exclude timestamps from the log messages */ +	u8 timestamp; + +	/* See enum wl1271_fwlogger_output */ +	u8 output; + +	/* Regulates the frequency of log messages */ +	u8 threshold; + +	u8 padding[3]; +} __packed; + +struct wl12xx_cmd_start_fwlog { +	struct wl1271_cmd_header header; +} __packed; + +struct wl12xx_cmd_stop_fwlog { +	struct wl1271_cmd_header header; +} __packed; +  #endif /* __WL1271_CMD_H__ */ diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index c83fefb6662..6080e01d92c 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h @@ -713,8 +713,16 @@ struct conf_tx_settings {  	/*  	 * AP-mode - allow this number of TX retries to a station before an  	 * event is triggered from FW. +	 * In AP-mode the hlids of unreachable stations are given in the +	 * "sta_tx_retry_exceeded" member in the event mailbox.  	 */ -	u16 ap_max_tx_retries; +	u8 max_tx_retries; + +	/* +	 * AP-mode - after this number of seconds a connected station is +	 * considered inactive. +	 */ +	u16 ap_aging_period;  	/*  	 * Configuration for TID parameters. @@ -1248,6 +1256,59 @@ struct conf_fm_coex {  	u8 swallow_clk_diff;  }; +struct conf_rx_streaming_settings { +	/* +	 * RX Streaming duration (in msec) from last tx/rx +	 * +	 * Range: u32 +	 */ +	u32 duration; + +	/* +	 * Bitmap of tids to be polled during RX streaming. +	 * (Note: it doesn't look like it really matters) +	 * +	 * Range: 0x1-0xff +	 */ +	u8 queues; + +	/* +	 * RX Streaming interval. +	 * (Note:this value is also used as the rx streaming timeout) +	 * Range: 0 (disabled), 10 - 100 +	 */ +	u8 interval; + +	/* +	 * enable rx streaming also when there is no coex activity +	 */ +	u8 always; +}; + +struct conf_fwlog { +	/* Continuous or on-demand */ +	u8 mode; + +	/* +	 * Number of memory blocks dedicated for the FW logger +	 * +	 * Range: 1-3, or 0 to disable the FW logger +	 */ +	u8 mem_blocks; + +	/* Minimum log level threshold */ +	u8 severity; + +	/* Include/exclude timestamps from the log messages */ +	u8 timestamp; + +	/* See enum wl1271_fwlogger_output */ +	u8 output; + +	/* Regulates the frequency of log messages */ +	u8 threshold; +}; +  struct conf_drv_settings {  	struct conf_sg_settings sg;  	struct conf_rx_settings rx; @@ -1263,6 +1324,8 @@ struct conf_drv_settings {  	struct conf_memory_settings mem_wl127x;  	struct conf_memory_settings mem_wl128x;  	struct conf_fm_coex fm_coex; +	struct conf_rx_streaming_settings rx_streaming; +	struct conf_fwlog fwlog;  	u8 hci_io_ds;  }; diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index f1f8df9b6cd..37934b5601c 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c @@ -30,6 +30,7 @@  #include "acx.h"  #include "ps.h"  #include "io.h" +#include "tx.h"  /* ms */  #define WL1271_DEBUGFS_STATS_LIFETIME 1000 @@ -71,6 +72,14 @@ static const struct file_operations name## _ops = {			\  	if (!entry || IS_ERR(entry))					\  		goto err;						\ +#define DEBUGFS_ADD_PREFIX(prefix, name, parent)			\ +	do {								\ +		entry = debugfs_create_file(#name, 0400, parent,	\ +				    wl, &prefix## _## name## _ops);	\ +		if (!entry || IS_ERR(entry))				\ +			goto err;					\ +	} while (0); +  #define DEBUGFS_FWSTATS_FILE(sub, name, fmt)				\  static ssize_t sub## _ ##name## _read(struct file *file,		\  				      char __user *userbuf,		\ @@ -225,7 +234,7 @@ static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,  	char buf[20];  	int res; -	queue_len = wl->tx_queue_count; +	queue_len = wl1271_tx_total_queue_count(wl);  	res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);  	return simple_read_from_buffer(userbuf, count, ppos, buf, res); @@ -298,7 +307,7 @@ static ssize_t start_recovery_write(struct file *file,  	struct wl1271 *wl = file->private_data;  	mutex_lock(&wl->mutex); -	ieee80211_queue_work(wl->hw, &wl->recovery_work); +	wl12xx_queue_recovery_work(wl);  	mutex_unlock(&wl->mutex);  	return count; @@ -330,10 +339,16 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,  #define DRIVER_STATE_PRINT_HEX(x)  DRIVER_STATE_PRINT(x, "0x%x")  	DRIVER_STATE_PRINT_INT(tx_blocks_available); -	DRIVER_STATE_PRINT_INT(tx_allocated_blocks); +	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[0]); +	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[1]); +	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[2]); +	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[3]);  	DRIVER_STATE_PRINT_INT(tx_frames_cnt);  	DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); -	DRIVER_STATE_PRINT_INT(tx_queue_count); +	DRIVER_STATE_PRINT_INT(tx_queue_count[0]); +	DRIVER_STATE_PRINT_INT(tx_queue_count[1]); +	DRIVER_STATE_PRINT_INT(tx_queue_count[2]); +	DRIVER_STATE_PRINT_INT(tx_queue_count[3]);  	DRIVER_STATE_PRINT_INT(tx_packets_count);  	DRIVER_STATE_PRINT_INT(tx_results_count);  	DRIVER_STATE_PRINT_LHEX(flags); @@ -341,7 +356,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,  	DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]);  	DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]);  	DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); -	DRIVER_STATE_PRINT_INT(tx_security_last_seq); +	DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb);  	DRIVER_STATE_PRINT_INT(rx_counter);  	DRIVER_STATE_PRINT_INT(session_counter);  	DRIVER_STATE_PRINT_INT(state); @@ -527,11 +542,129 @@ static const struct file_operations beacon_interval_ops = {  	.llseek = default_llseek,  }; +static ssize_t rx_streaming_interval_write(struct file *file, +			   const char __user *user_buf, +			   size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; +	char buf[10]; +	size_t len; +	unsigned long value; +	int ret; + +	len = min(count, sizeof(buf) - 1); +	if (copy_from_user(buf, user_buf, len)) +		return -EFAULT; +	buf[len] = '\0'; + +	ret = kstrtoul(buf, 0, &value); +	if (ret < 0) { +		wl1271_warning("illegal value in rx_streaming_interval!"); +		return -EINVAL; +	} + +	/* valid values: 0, 10-100 */ +	if (value && (value < 10 || value > 100)) { +		wl1271_warning("value is not in range!"); +		return -ERANGE; +	} + +	mutex_lock(&wl->mutex); + +	wl->conf.rx_streaming.interval = value; + +	ret = wl1271_ps_elp_wakeup(wl); +	if (ret < 0) +		goto out; + +	wl1271_recalc_rx_streaming(wl); + +	wl1271_ps_elp_sleep(wl); +out: +	mutex_unlock(&wl->mutex); +	return count; +} + +static ssize_t rx_streaming_interval_read(struct file *file, +			    char __user *userbuf, +			    size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; +	return wl1271_format_buffer(userbuf, count, ppos, +				    "%d\n", wl->conf.rx_streaming.interval); +} + +static const struct file_operations rx_streaming_interval_ops = { +	.read = rx_streaming_interval_read, +	.write = rx_streaming_interval_write, +	.open = wl1271_open_file_generic, +	.llseek = default_llseek, +}; + +static ssize_t rx_streaming_always_write(struct file *file, +			   const char __user *user_buf, +			   size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; +	char buf[10]; +	size_t len; +	unsigned long value; +	int ret; + +	len = min(count, sizeof(buf) - 1); +	if (copy_from_user(buf, user_buf, len)) +		return -EFAULT; +	buf[len] = '\0'; + +	ret = kstrtoul(buf, 0, &value); +	if (ret < 0) { +		wl1271_warning("illegal value in rx_streaming_write!"); +		return -EINVAL; +	} + +	/* valid values: 0, 10-100 */ +	if (!(value == 0 || value == 1)) { +		wl1271_warning("value is not in valid!"); +		return -EINVAL; +	} + +	mutex_lock(&wl->mutex); + +	wl->conf.rx_streaming.always = value; + +	ret = wl1271_ps_elp_wakeup(wl); +	if (ret < 0) +		goto out; + +	wl1271_recalc_rx_streaming(wl); + +	wl1271_ps_elp_sleep(wl); +out: +	mutex_unlock(&wl->mutex); +	return count; +} + +static ssize_t rx_streaming_always_read(struct file *file, +			    char __user *userbuf, +			    size_t count, loff_t *ppos) +{ +	struct wl1271 *wl = file->private_data; +	return wl1271_format_buffer(userbuf, count, ppos, +				    "%d\n", wl->conf.rx_streaming.always); +} + +static const struct file_operations rx_streaming_always_ops = { +	.read = rx_streaming_always_read, +	.write = rx_streaming_always_write, +	.open = wl1271_open_file_generic, +	.llseek = default_llseek, +}; +  static int wl1271_debugfs_add_files(struct wl1271 *wl,  				     struct dentry *rootdir)  {  	int ret = 0; -	struct dentry *entry, *stats; +	struct dentry *entry, *stats, *streaming;  	stats = debugfs_create_dir("fw-statistics", rootdir);  	if (!stats || IS_ERR(stats)) { @@ -640,6 +773,14 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,  	DEBUGFS_ADD(dtim_interval, rootdir);  	DEBUGFS_ADD(beacon_interval, rootdir); +	streaming = debugfs_create_dir("rx_streaming", rootdir); +	if (!streaming || IS_ERR(streaming)) +		goto err; + +	DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); +	DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); + +  	return 0;  err: diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index c3c554cd658..304aaa2ee01 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c @@ -133,10 +133,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl,  		if (ret < 0)  			break; -		/* enable beacon early termination */ -		ret = wl1271_acx_bet_enable(wl, true); -		if (ret < 0) -			break; +		/* +		 * BET has only a minor effect in 5GHz and masks +		 * channel switch IEs, so we only enable BET on 2.4GHz +		*/ +		if (wl->band == IEEE80211_BAND_2GHZ) +			/* enable beacon early termination */ +			ret = wl1271_acx_bet_enable(wl, true);  		if (wl->ps_compl) {  			complete(wl->ps_compl); @@ -168,6 +171,36 @@ static void wl1271_event_rssi_trigger(struct wl1271 *wl,  	wl->last_rssi_event = event;  } +static void wl1271_stop_ba_event(struct wl1271 *wl, u8 ba_allowed) +{ +	/* Convert the value to bool */ +	wl->ba_allowed = !!ba_allowed; + +	/* +	 * Return in case: +	 * there are not BA open or the event indication is to allowed BA +	 */ +	if ((!wl->ba_rx_bitmap) || (wl->ba_allowed)) +		return; + +	ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, wl->bssid); +} + +static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, +					       u8 enable) +{ +	if (enable) { +		/* disable dynamic PS when requested by the firmware */ +		ieee80211_disable_dyn_ps(wl->vif); +		set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); +	} else { +		ieee80211_enable_dyn_ps(wl->vif); +		clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); +		wl1271_recalc_rx_streaming(wl); +	} + +} +  static void wl1271_event_mbox_dump(struct event_mailbox *mbox)  {  	wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); @@ -181,6 +214,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)  	u32 vector;  	bool beacon_loss = false;  	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); +	bool disconnect_sta = false; +	unsigned long sta_bitmap = 0;  	wl1271_event_mbox_dump(mbox); @@ -211,14 +246,10 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)  		}  	} -	/* disable dynamic PS when requested by the firmware */  	if (vector & SOFT_GEMINI_SENSE_EVENT_ID && -	    wl->bss_type == BSS_TYPE_STA_BSS) { -		if (mbox->soft_gemini_sense_info) -			ieee80211_disable_dyn_ps(wl->vif); -		else -			ieee80211_enable_dyn_ps(wl->vif); -	} +	    wl->bss_type == BSS_TYPE_STA_BSS) +		wl12xx_event_soft_gemini_sense(wl, +					       mbox->soft_gemini_sense_info);  	/*  	 * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon @@ -252,12 +283,60 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)  			wl1271_event_rssi_trigger(wl, mbox);  	} +	if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) { +		wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " +			     "ba_allowed = 0x%x", mbox->ba_allowed); + +		if (wl->vif) +			wl1271_stop_ba_event(wl, mbox->ba_allowed); +	} +  	if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {  		wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");  		if (wl->vif)  			wl1271_tx_dummy_packet(wl);  	} +	/* +	 * "TX retries exceeded" has a different meaning according to mode. +	 * In AP mode the offending station is disconnected. +	 */ +	if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) { +		wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); +		sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); +		disconnect_sta = true; +	} + +	if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { +		wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); +		sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); +		disconnect_sta = true; +	} + +	if (is_ap && disconnect_sta) { +		u32 num_packets = wl->conf.tx.max_tx_retries; +		struct ieee80211_sta *sta; +		const u8 *addr; +		int h; + +		for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); +		     h < AP_MAX_LINKS; +		     h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { +			if (!wl1271_is_active_sta(wl, h)) +				continue; + +			addr = wl->links[h].addr; + +			rcu_read_lock(); +			sta = ieee80211_find_sta(wl->vif, addr); +			if (sta) { +				wl1271_debug(DEBUG_EVENT, "remove sta %d", h); +				ieee80211_report_low_ack(sta, num_packets); +			} +			rcu_read_unlock(); +		} +	} +  	if (wl->vif && beacon_loss)  		ieee80211_connection_loss(wl->vif); diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index b6cf06e565a..e524ad6fe4e 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h @@ -58,20 +58,23 @@ enum {  	CHANNEL_SWITCH_COMPLETE_EVENT_ID	 = BIT(17),  	BSS_LOSE_EVENT_ID			 = BIT(18),  	REGAINED_BSS_EVENT_ID			 = BIT(19), -	ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID	 = BIT(20), +	MAX_TX_RETRY_EVENT_ID			 = BIT(20),  	/* STA: dummy paket for dynamic mem blocks */  	DUMMY_PACKET_EVENT_ID                    = BIT(21),  	/* AP: STA remove complete */  	STA_REMOVE_COMPLETE_EVENT_ID             = BIT(21),  	SOFT_GEMINI_SENSE_EVENT_ID		 = BIT(22), +	/* STA: SG prediction */  	SOFT_GEMINI_PREDICTION_EVENT_ID		 = BIT(23), +	/* AP: Inactive STA */ +	INACTIVE_STA_EVENT_ID			 = BIT(23),  	SOFT_GEMINI_AVALANCHE_EVENT_ID		 = BIT(24),  	PLT_RX_CALIBRATION_COMPLETE_EVENT_ID	 = BIT(25),  	DBG_EVENT_ID				 = BIT(26),  	HEALTH_CHECK_REPLY_EVENT_ID		 = BIT(27),  	PERIODIC_SCAN_COMPLETE_EVENT_ID		 = BIT(28),  	PERIODIC_SCAN_REPORT_EVENT_ID		 = BIT(29), -	BA_SESSION_TEAR_DOWN_EVENT_ID		 = BIT(30), +	BA_SESSION_RX_CONSTRAINT_EVENT_ID	 = BIT(30),  	EVENT_MBOX_ALL_EVENT_ID			 = 0x7fffffff,  }; @@ -119,10 +122,27 @@ struct event_mailbox {  	/* AP FW only */  	u8 hlid_removed; + +	/* a bitmap of hlids for stations that have been inactive too long */  	__le16 sta_aging_status; + +	/* a bitmap of hlids for stations which didn't respond to TX */  	__le16 sta_tx_retry_exceeded; -	u8 reserved_5[24]; +	/* +	 * Bitmap, Each bit set represents the Role ID for which this constraint +	 * is set. Range: 0 - FF, FF means ANY role +	 */ +	u8 ba_role_id; +	/* +	 * Bitmap, Each bit set represents the Link ID for which this constraint +	 * is set. Not applicable if ba_role_id is set to ANY role (FF). +	 * Range: 0 - FFFF, FFFF means ANY link in that role +	 */ +	u8 ba_link_id; +	u8 ba_allowed; + +	u8 reserved_5[21];  } __packed;  int wl1271_event_unmask(struct wl1271 *wl); @@ -130,4 +150,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl);  int wl1271_event_handle(struct wl1271 *wl, u8 mbox);  void wl1271_pspoll_work(struct work_struct *work); +/* Functions from main.c */ +bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid); +  #endif diff --git a/drivers/net/wireless/wl12xx/ini.h b/drivers/net/wireless/wl12xx/ini.h index 1420c842b8f..4cf9ecc5621 100644 --- a/drivers/net/wireless/wl12xx/ini.h +++ b/drivers/net/wireless/wl12xx/ini.h @@ -24,6 +24,9 @@  #ifndef __INI_H__  #define __INI_H__ +#define GENERAL_SETTINGS_DRPW_LPD 0xc0 +#define SCRATCH_ENABLE_LPD        BIT(25) +  #define WL1271_INI_MAX_SMART_REFLEX_PARAM 16  struct wl1271_ini_general_params { diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index a8f4f156c05..c3e9a2e4410 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c @@ -321,6 +321,20 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)  	return 0;  } +static int wl12xx_init_fwlog(struct wl1271 *wl) +{ +	int ret; + +	if (wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED) +		return 0; + +	ret = wl12xx_cmd_config_fwlog(wl); +	if (ret < 0) +		return ret; + +	return 0; +} +  static int wl1271_sta_hw_init(struct wl1271 *wl)  {  	int ret; @@ -382,6 +396,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)  	if (ret < 0)  		return ret; +	/* Configure the FW logger */ +	ret = wl12xx_init_fwlog(wl); +	if (ret < 0) +		return ret; +  	return 0;  } @@ -428,7 +447,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)  	if (ret < 0)  		return ret; -	ret = wl1271_acx_max_tx_retry(wl); +	ret = wl1271_acx_ap_max_tx_retry(wl);  	if (ret < 0)  		return ret; @@ -436,6 +455,11 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)  	if (ret < 0)  		return ret; +	/* initialize Tx power */ +	ret = wl1271_acx_tx_power(wl, wl->power_level); +	if (ret < 0) +		return ret; +  	return 0;  } @@ -541,6 +565,7 @@ static int wl1271_set_ba_policies(struct wl1271 *wl)  	/* Reset the BA RX indicators */  	wl->ba_rx_bitmap = 0; +	wl->ba_allowed = true;  	/* validate that FW support BA */  	wl1271_check_ba_support(wl); diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c index da5c1ad942a..c2da66f4504 100644 --- a/drivers/net/wireless/wl12xx/io.c +++ b/drivers/net/wireless/wl12xx/io.c @@ -23,7 +23,6 @@  #include <linux/module.h>  #include <linux/platform_device.h> -#include <linux/crc7.h>  #include <linux/spi/spi.h>  #include "wl12xx.h" @@ -128,12 +127,14 @@ EXPORT_SYMBOL_GPL(wl1271_set_partition);  void wl1271_io_reset(struct wl1271 *wl)  { -	wl->if_ops->reset(wl); +	if (wl->if_ops->reset) +		wl->if_ops->reset(wl);  }  void wl1271_io_init(struct wl1271 *wl)  { -	wl->if_ops->init(wl); +	if (wl->if_ops->init) +		wl->if_ops->init(wl);  }  void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h index beed621a8ae..a2fe4f506ad 100644 --- a/drivers/net/wireless/wl12xx/io.h +++ b/drivers/net/wireless/wl12xx/io.h @@ -25,6 +25,7 @@  #ifndef __IO_H__  #define __IO_H__ +#include <linux/irqreturn.h>  #include "reg.h"  #define HW_ACCESS_MEMORY_MAX_RANGE	0x1FFC0 @@ -128,6 +129,20 @@ static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf,  	wl1271_raw_write(wl, physical, buf, len, fixed);  } +static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, +				      void *buf, size_t len, bool fixed) +{ +	int physical; +	int addr; + +	/* Addresses are stored internally as addresses to 32 bytes blocks */ +	addr = hwaddr << 5; + +	physical = wl1271_translate_addr(wl, addr); + +	wl1271_raw_read(wl, physical, buf, len, fixed); +} +  static inline u32 wl1271_read32(struct wl1271 *wl, int addr)  {  	return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr)); diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index e6497dc669d..e58c22d21e3 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c @@ -31,6 +31,7 @@  #include <linux/platform_device.h>  #include <linux/slab.h>  #include <linux/wl12xx.h> +#include <linux/sched.h>  #include "wl12xx.h"  #include "wl12xx_80211.h" @@ -209,7 +210,8 @@ static struct conf_drv_settings default_conf = {  				.tx_op_limit = 1504,  			},  		}, -		.ap_max_tx_retries = 100, +		.max_tx_retries = 100, +		.ap_aging_period = 300,  		.tid_conf_count = 4,  		.tid_conf = {  			[CONF_TX_AC_BE] = { @@ -362,9 +364,25 @@ static struct conf_drv_settings default_conf = {  		.fm_disturbed_band_margin     = 0xff,       /* default */  		.swallow_clk_diff             = 0xff,       /* default */  	}, +	.rx_streaming = { +		.duration                      = 150, +		.queues                        = 0x1, +		.interval                      = 20, +		.always                        = 0, +	}, +	.fwlog = { +		.mode                         = WL12XX_FWLOG_ON_DEMAND, +		.mem_blocks                   = 2, +		.severity                     = 0, +		.timestamp                    = WL12XX_FWLOG_TIMESTAMP_DISABLED, +		.output                       = WL12XX_FWLOG_OUTPUT_HOST, +		.threshold                    = 0, +	},  	.hci_io_ds = HCI_IO_DS_6MA,  }; +static char *fwlog_param; +  static void __wl1271_op_remove_interface(struct wl1271 *wl,  					 bool reset_tx_queues);  static void wl1271_free_ap_keys(struct wl1271 *wl); @@ -388,6 +406,22 @@ static struct platform_device wl1271_device = {  static DEFINE_MUTEX(wl_list_mutex);  static LIST_HEAD(wl_list); +static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) +{ +	int ret; +	if (operstate != IF_OPER_UP) +		return 0; + +	if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) +		return 0; + +	ret = wl1271_cmd_set_sta_state(wl); +	if (ret < 0) +		return ret; + +	wl1271_info("Association completed."); +	return 0; +}  static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,  			     void *arg)  { @@ -437,11 +471,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,  	if (ret < 0)  		goto out; -	if ((dev->operstate == IF_OPER_UP) && -	    !test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) { -		wl1271_cmd_set_sta_state(wl); -		wl1271_info("Association completed."); -	} +	wl1271_check_operstate(wl, dev->operstate);  	wl1271_ps_elp_sleep(wl); @@ -473,6 +503,117 @@ static int wl1271_reg_notify(struct wiphy *wiphy,  	return 0;  } +static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable) +{ +	int ret = 0; + +	/* we should hold wl->mutex */ +	ret = wl1271_acx_ps_rx_streaming(wl, enable); +	if (ret < 0) +		goto out; + +	if (enable) +		set_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags); +	else +		clear_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags); +out: +	return ret; +} + +/* + * this function is being called when the rx_streaming interval + * has beed changed or rx_streaming should be disabled + */ +int wl1271_recalc_rx_streaming(struct wl1271 *wl) +{ +	int ret = 0; +	int period = wl->conf.rx_streaming.interval; + +	/* don't reconfigure if rx_streaming is disabled */ +	if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) +		goto out; + +	/* reconfigure/disable according to new streaming_period */ +	if (period && +	    test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) && +	    (wl->conf.rx_streaming.always || +	     test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) +		ret = wl1271_set_rx_streaming(wl, true); +	else { +		ret = wl1271_set_rx_streaming(wl, false); +		/* don't cancel_work_sync since we might deadlock */ +		del_timer_sync(&wl->rx_streaming_timer); +	} +out: +	return ret; +} + +static void wl1271_rx_streaming_enable_work(struct work_struct *work) +{ +	int ret; +	struct wl1271 *wl = +		container_of(work, struct wl1271, rx_streaming_enable_work); + +	mutex_lock(&wl->mutex); + +	if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) || +	    !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || +	    (!wl->conf.rx_streaming.always && +	     !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) +		goto out; + +	if (!wl->conf.rx_streaming.interval) +		goto out; + +	ret = wl1271_ps_elp_wakeup(wl); +	if (ret < 0) +		goto out; + +	ret = wl1271_set_rx_streaming(wl, true); +	if (ret < 0) +		goto out_sleep; + +	/* stop it after some time of inactivity */ +	mod_timer(&wl->rx_streaming_timer, +		  jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration)); + +out_sleep: +	wl1271_ps_elp_sleep(wl); +out: +	mutex_unlock(&wl->mutex); +} + +static void wl1271_rx_streaming_disable_work(struct work_struct *work) +{ +	int ret; +	struct wl1271 *wl = +		container_of(work, struct wl1271, rx_streaming_disable_work); + +	mutex_lock(&wl->mutex); + +	if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) +		goto out; + +	ret = wl1271_ps_elp_wakeup(wl); +	if (ret < 0) +		goto out; + +	ret = wl1271_set_rx_streaming(wl, false); +	if (ret) +		goto out_sleep; + +out_sleep: +	wl1271_ps_elp_sleep(wl); +out: +	mutex_unlock(&wl->mutex); +} + +static void wl1271_rx_streaming_timer(unsigned long data) +{ +	struct wl1271 *wl = (struct wl1271 *)data; +	ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work); +} +  static void wl1271_conf_init(struct wl1271 *wl)  { @@ -488,8 +629,24 @@ static void wl1271_conf_init(struct wl1271 *wl)  	/* apply driver default configuration */  	memcpy(&wl->conf, &default_conf, sizeof(default_conf)); -} +	/* Adjust settings according to optional module parameters */ +	if (fwlog_param) { +		if (!strcmp(fwlog_param, "continuous")) { +			wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS; +		} else if (!strcmp(fwlog_param, "ondemand")) { +			wl->conf.fwlog.mode = WL12XX_FWLOG_ON_DEMAND; +		} else if (!strcmp(fwlog_param, "dbgpins")) { +			wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS; +			wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_DBG_PINS; +		} else if (!strcmp(fwlog_param, "disable")) { +			wl->conf.fwlog.mem_blocks = 0; +			wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_NONE; +		} else { +			wl1271_error("Unknown fwlog parameter %s", fwlog_param); +		} +	} +}  static int wl1271_plt_init(struct wl1271 *wl)  { @@ -667,13 +824,24 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl,  	}  } +static u32 wl1271_tx_allocated_blocks(struct wl1271 *wl) +{ +	int i; +	u32 total_alloc_blocks = 0; + +	for (i = 0; i < NUM_TX_QUEUES; i++) +		total_alloc_blocks += wl->tx_allocated_blocks[i]; + +	return total_alloc_blocks; +} +  static void wl1271_fw_status(struct wl1271 *wl,  			     struct wl1271_fw_full_status *full_status)  {  	struct wl1271_fw_common_status *status = &full_status->common;  	struct timespec ts;  	u32 old_tx_blk_count = wl->tx_blocks_available; -	u32 freed_blocks = 0; +	u32 freed_blocks = 0, ac_freed_blocks;  	int i;  	if (wl->bss_type == BSS_TYPE_AP_BSS) { @@ -693,21 +861,23 @@ static void wl1271_fw_status(struct wl1271 *wl,  	/* update number of available TX blocks */  	for (i = 0; i < NUM_TX_QUEUES; i++) { -		freed_blocks += le32_to_cpu(status->tx_released_blks[i]) - -				wl->tx_blocks_freed[i]; +		ac_freed_blocks = le32_to_cpu(status->tx_released_blks[i]) - +				  wl->tx_blocks_freed[i]; +		freed_blocks += ac_freed_blocks; + +		wl->tx_allocated_blocks[i] -= ac_freed_blocks;  		wl->tx_blocks_freed[i] =  			le32_to_cpu(status->tx_released_blks[i]);  	} -	wl->tx_allocated_blocks -= freed_blocks; -  	if (wl->bss_type == BSS_TYPE_AP_BSS) {  		/* Update num of allocated TX blocks per link and ps status */  		wl1271_irq_update_links_status(wl, &full_status->ap);  		wl->tx_blocks_available += freed_blocks;  	} else { -		int avail = full_status->sta.tx_total - wl->tx_allocated_blocks; +		int avail = full_status->sta.tx_total - +			    wl1271_tx_allocated_blocks(wl);  		/*  		 * The FW might change the total number of TX memblocks before @@ -741,7 +911,7 @@ static void wl1271_flush_deferred_work(struct wl1271 *wl)  	/* Return sent skbs to the network stack */  	while ((skb = skb_dequeue(&wl->deferred_tx_queue))) -		ieee80211_tx_status(wl->hw, skb); +		ieee80211_tx_status_ni(wl->hw, skb);  }  static void wl1271_netstack_work(struct work_struct *work) @@ -808,7 +978,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)  		if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {  			wl1271_error("watchdog interrupt received! "  				     "starting recovery."); -			ieee80211_queue_work(wl->hw, &wl->recovery_work); +			wl12xx_queue_recovery_work(wl);  			/* restarting the chip. ignore any other interrupt. */  			goto out; @@ -822,7 +992,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)  			/* Check if any tx blocks were freed */  			spin_lock_irqsave(&wl->wl_lock, flags);  			if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && -			    wl->tx_queue_count) { +			    wl1271_tx_total_queue_count(wl) > 0) {  				spin_unlock_irqrestore(&wl->wl_lock, flags);  				/*  				 * In order to avoid starvation of the TX path, @@ -870,7 +1040,7 @@ out:  	/* In case TX was not handled here, queue TX work */  	clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags);  	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) && -	    wl->tx_queue_count) +	    wl1271_tx_total_queue_count(wl) > 0)  		ieee80211_queue_work(wl->hw, &wl->tx_work);  	spin_unlock_irqrestore(&wl->wl_lock, flags); @@ -970,6 +1140,89 @@ out:  	return ret;  } +void wl12xx_queue_recovery_work(struct wl1271 *wl) +{ +	if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) +		ieee80211_queue_work(wl->hw, &wl->recovery_work); +} + +size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) +{ +	size_t len = 0; + +	/* The FW log is a length-value list, find where the log end */ +	while (len < maxlen) { +		if (memblock[len] == 0) +			break; +		if (len + memblock[len] + 1 > maxlen) +			break; +		len += memblock[len] + 1; +	} + +	/* Make sure we have enough room */ +	len = min(len, (size_t)(PAGE_SIZE - wl->fwlog_size)); + +	/* Fill the FW log file, consumed by the sysfs fwlog entry */ +	memcpy(wl->fwlog + wl->fwlog_size, memblock, len); +	wl->fwlog_size += len; + +	return len; +} + +static void wl12xx_read_fwlog_panic(struct wl1271 *wl) +{ +	u32 addr; +	u32 first_addr; +	u8 *block; + +	if ((wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED) || +	    (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) || +	    (wl->conf.fwlog.mem_blocks == 0)) +		return; + +	wl1271_info("Reading FW panic log"); + +	block = kmalloc(WL12XX_HW_BLOCK_SIZE, GFP_KERNEL); +	if (!block) +		return; + +	/* +	 * Make sure the chip is awake and the logger isn't active. +	 * This might fail if the firmware hanged. +	 */ +	if (!wl1271_ps_elp_wakeup(wl)) +		wl12xx_cmd_stop_fwlog(wl); + +	/* Read the first memory block address */ +	wl1271_fw_status(wl, wl->fw_status); +	first_addr = __le32_to_cpu(wl->fw_status->sta.log_start_addr); +	if (!first_addr) +		goto out; + +	/* Traverse the memory blocks linked list */ +	addr = first_addr; +	do { +		memset(block, 0, WL12XX_HW_BLOCK_SIZE); +		wl1271_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE, +				   false); + +		/* +		 * Memory blocks are linked to one another. The first 4 bytes +		 * of each memory block hold the hardware address of the next +		 * one. The last memory block points to the first one. +		 */ +		addr = __le32_to_cpup((__le32 *)block); +		if (!wl12xx_copy_fwlog(wl, block + sizeof(addr), +				       WL12XX_HW_BLOCK_SIZE - sizeof(addr))) +			break; +	} while (addr && (addr != first_addr)); + +	wake_up_interruptible(&wl->fwlog_waitq); + +out: +	kfree(block); +} +  static void wl1271_recovery_work(struct work_struct *work)  {  	struct wl1271 *wl = @@ -980,9 +1233,23 @@ static void wl1271_recovery_work(struct work_struct *work)  	if (wl->state != WL1271_STATE_ON)  		goto out; +	/* Avoid a recursive recovery */ +	set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); + +	wl12xx_read_fwlog_panic(wl); +  	wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",  		    wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); +	/* +	 * Advance security sequence number to overcome potential progress +	 * in the firmware during recovery. This doens't hurt if the network is +	 * not encrypted. +	 */ +	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || +	    test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) +		wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; +  	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))  		ieee80211_connection_loss(wl->vif); @@ -996,6 +1263,9 @@ static void wl1271_recovery_work(struct work_struct *work)  	/* reboot the chipset */  	__wl1271_op_remove_interface(wl, false); + +	clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); +  	ieee80211_restart_hw(wl->hw);  	/* @@ -1074,9 +1344,13 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)  		wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",  			     wl->chip.id); -		/* end-of-transaction flag should be set in wl127x AP mode */ +		/* +		 * 'end-of-transaction flag' and 'LPD mode flag' +		 * should be set in wl127x AP mode only +		 */  		if (wl->bss_type == BSS_TYPE_AP_BSS) -			wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; +			wl->quirks |= (WL12XX_QUIRK_END_OF_TRANSACTION | +				       WL12XX_QUIRK_LPD_MODE);  		ret = wl1271_setup(wl);  		if (ret < 0) @@ -1089,6 +1363,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)  		ret = wl1271_setup(wl);  		if (ret < 0)  			goto out; +  		if (wl1271_set_block_size(wl))  			wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT;  		break; @@ -1117,24 +1392,6 @@ out:  	return ret;  } -static unsigned int wl1271_get_fw_ver_quirks(struct wl1271 *wl) -{ -	unsigned int quirks = 0; -	unsigned int *fw_ver = wl->chip.fw_ver; - -	/* Only for wl127x */ -	if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) && -	    /* Check STA version */ -	    (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) && -	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) || -	     /* Check AP version */ -	     ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) && -	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN)))) -		quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS; - -	return quirks; -} -  int wl1271_plt_start(struct wl1271 *wl)  {  	int retries = WL1271_BOOT_RETRIES; @@ -1171,8 +1428,6 @@ int wl1271_plt_start(struct wl1271 *wl)  		wl1271_notice("firmware booted in PLT mode (%s)",  			      wl->chip.fw_ver_str); -		/* Check if any quirks are needed with older fw versions */ -		wl->quirks |= wl1271_get_fw_ver_quirks(wl);  		goto out;  irq_disable: @@ -1242,26 +1497,27 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  {  	struct wl1271 *wl = hw->priv;  	unsigned long flags; -	int q; +	int q, mapping;  	u8 hlid = 0; -	q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); +	mapping = skb_get_queue_mapping(skb); +	q = wl1271_tx_get_queue(mapping);  	if (wl->bss_type == BSS_TYPE_AP_BSS)  		hlid = wl1271_tx_get_hlid(skb);  	spin_lock_irqsave(&wl->wl_lock, flags); -	wl->tx_queue_count++; +	wl->tx_queue_count[q]++;  	/*  	 * The workqueue is slow to process the tx_queue and we need stop  	 * the queue here, otherwise the queue will get too long.  	 */ -	if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) { -		wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); -		ieee80211_stop_queues(wl->hw); -		set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); +	if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) { +		wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q); +		ieee80211_stop_queue(wl->hw, mapping); +		set_bit(q, &wl->stopped_queues_map);  	}  	/* queue the packet */ @@ -1287,10 +1543,11 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  int wl1271_tx_dummy_packet(struct wl1271 *wl)  {  	unsigned long flags; +	int q = wl1271_tx_get_queue(skb_get_queue_mapping(wl->dummy_packet));  	spin_lock_irqsave(&wl->wl_lock, flags);  	set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); -	wl->tx_queue_count++; +	wl->tx_queue_count[q]++;  	spin_unlock_irqrestore(&wl->wl_lock, flags);  	/* The FW is low on RX memory blocks, so send the dummy packet asap */ @@ -1352,15 +1609,15 @@ static struct notifier_block wl1271_dev_notifier = {  };  #ifdef CONFIG_PM -static int wl1271_configure_suspend(struct wl1271 *wl) +static int wl1271_configure_suspend_sta(struct wl1271 *wl)  { -	int ret; - -	if (wl->bss_type != BSS_TYPE_STA_BSS) -		return 0; +	int ret = 0;  	mutex_lock(&wl->mutex); +	if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) +		goto out_unlock; +  	ret = wl1271_ps_elp_wakeup(wl);  	if (ret < 0)  		goto out_unlock; @@ -1403,11 +1660,44 @@ out:  } +static int wl1271_configure_suspend_ap(struct wl1271 *wl) +{ +	int ret = 0; + +	mutex_lock(&wl->mutex); + +	if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) +		goto out_unlock; + +	ret = wl1271_ps_elp_wakeup(wl); +	if (ret < 0) +		goto out_unlock; + +	ret = wl1271_acx_set_ap_beacon_filter(wl, true); + +	wl1271_ps_elp_sleep(wl); +out_unlock: +	mutex_unlock(&wl->mutex); +	return ret; + +} + +static int wl1271_configure_suspend(struct wl1271 *wl) +{ +	if (wl->bss_type == BSS_TYPE_STA_BSS) +		return wl1271_configure_suspend_sta(wl); +	if (wl->bss_type == BSS_TYPE_AP_BSS) +		return wl1271_configure_suspend_ap(wl); +	return 0; +} +  static void wl1271_configure_resume(struct wl1271 *wl)  {  	int ret; +	bool is_sta = wl->bss_type == BSS_TYPE_STA_BSS; +	bool is_ap = wl->bss_type == BSS_TYPE_AP_BSS; -	if (wl->bss_type != BSS_TYPE_STA_BSS) +	if (!is_sta && !is_ap)  		return;  	mutex_lock(&wl->mutex); @@ -1415,10 +1705,14 @@ static void wl1271_configure_resume(struct wl1271 *wl)  	if (ret < 0)  		goto out; -	/* exit psm if it wasn't configured */ -	if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) -		wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, -				   wl->basic_rate, true); +	if (is_sta) { +		/* exit psm if it wasn't configured */ +		if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) +			wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, +					   wl->basic_rate, true); +	} else if (is_ap) { +		wl1271_acx_set_ap_beacon_filter(wl, false); +	}  	wl1271_ps_elp_sleep(wl);  out: @@ -1429,69 +1723,68 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,  			    struct cfg80211_wowlan *wow)  {  	struct wl1271 *wl = hw->priv; +	int ret; +  	wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); -	wl->wow_enabled = !!wow; -	if (wl->wow_enabled) { -		int ret; -		ret = wl1271_configure_suspend(wl); -		if (ret < 0) { -			wl1271_warning("couldn't prepare device to suspend"); -			return ret; -		} -		/* flush any remaining work */ -		wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); -		flush_delayed_work(&wl->scan_complete_work); +	WARN_ON(!wow || !wow->any); -		/* -		 * disable and re-enable interrupts in order to flush -		 * the threaded_irq -		 */ -		wl1271_disable_interrupts(wl); +	wl->wow_enabled = true; +	ret = wl1271_configure_suspend(wl); +	if (ret < 0) { +		wl1271_warning("couldn't prepare device to suspend"); +		return ret; +	} +	/* flush any remaining work */ +	wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); -		/* -		 * set suspended flag to avoid triggering a new threaded_irq -		 * work. no need for spinlock as interrupts are disabled. -		 */ -		set_bit(WL1271_FLAG_SUSPENDED, &wl->flags); +	/* +	 * disable and re-enable interrupts in order to flush +	 * the threaded_irq +	 */ +	wl1271_disable_interrupts(wl); + +	/* +	 * set suspended flag to avoid triggering a new threaded_irq +	 * work. no need for spinlock as interrupts are disabled. +	 */ +	set_bit(WL1271_FLAG_SUSPENDED, &wl->flags); + +	wl1271_enable_interrupts(wl); +	flush_work(&wl->tx_work); +	flush_delayed_work(&wl->pspoll_work); +	flush_delayed_work(&wl->elp_work); -		wl1271_enable_interrupts(wl); -		flush_work(&wl->tx_work); -		flush_delayed_work(&wl->pspoll_work); -		flush_delayed_work(&wl->elp_work); -	}  	return 0;  }  static int wl1271_op_resume(struct ieee80211_hw *hw)  {  	struct wl1271 *wl = hw->priv; +	unsigned long flags; +	bool run_irq_work = false; +  	wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",  		     wl->wow_enabled); +	WARN_ON(!wl->wow_enabled);  	/*  	 * re-enable irq_work enqueuing, and call irq_work directly if  	 * there is a pending work.  	 */ -	if (wl->wow_enabled) { -		struct wl1271 *wl = hw->priv; -		unsigned long flags; -		bool run_irq_work = false; - -		spin_lock_irqsave(&wl->wl_lock, flags); -		clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags); -		if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags)) -			run_irq_work = true; -		spin_unlock_irqrestore(&wl->wl_lock, flags); - -		if (run_irq_work) { -			wl1271_debug(DEBUG_MAC80211, -				     "run postponed irq_work directly"); -			wl1271_irq(0, wl); -			wl1271_enable_interrupts(wl); -		} +	spin_lock_irqsave(&wl->wl_lock, flags); +	clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags); +	if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags)) +		run_irq_work = true; +	spin_unlock_irqrestore(&wl->wl_lock, flags); -		wl1271_configure_resume(wl); +	if (run_irq_work) { +		wl1271_debug(DEBUG_MAC80211, +			     "run postponed irq_work directly"); +		wl1271_irq(0, wl); +		wl1271_enable_interrupts(wl);  	} +	wl1271_configure_resume(wl); +	wl->wow_enabled = false;  	return 0;  } @@ -1629,9 +1922,6 @@ power_off:  	strncpy(wiphy->fw_version, wl->chip.fw_ver_str,  		sizeof(wiphy->fw_version)); -	/* Check if any quirks are needed with older fw versions */ -	wl->quirks |= wl1271_get_fw_ver_quirks(wl); -  	/*  	 * Now we know if 11a is supported (info from the NVS), so disable  	 * 11a channels if not supported @@ -1694,6 +1984,9 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,  	cancel_delayed_work_sync(&wl->scan_complete_work);  	cancel_work_sync(&wl->netstack_work);  	cancel_work_sync(&wl->tx_work); +	del_timer_sync(&wl->rx_streaming_timer); +	cancel_work_sync(&wl->rx_streaming_enable_work); +	cancel_work_sync(&wl->rx_streaming_disable_work);  	cancel_delayed_work_sync(&wl->pspoll_work);  	cancel_delayed_work_sync(&wl->elp_work); @@ -1714,11 +2007,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,  	wl->psm_entry_retry = 0;  	wl->power_level = WL1271_DEFAULT_POWER_LEVEL;  	wl->tx_blocks_available = 0; -	wl->tx_allocated_blocks = 0;  	wl->tx_results_count = 0;  	wl->tx_packets_count = 0; -	wl->tx_security_last_seq = 0; -	wl->tx_security_seq = 0;  	wl->time_offset = 0;  	wl->session_counter = 0;  	wl->rate_set = CONF_TX_RATE_MASK_BASIC; @@ -1737,8 +2027,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,  	 */  	wl->flags = 0; -	for (i = 0; i < NUM_TX_QUEUES; i++) +	for (i = 0; i < NUM_TX_QUEUES; i++) {  		wl->tx_blocks_freed[i] = 0; +		wl->tx_allocated_blocks[i] = 0; +	}  	wl1271_debugfs_reset(wl); @@ -1891,6 +2183,10 @@ static int wl1271_unjoin(struct wl1271 *wl)  	clear_bit(WL1271_FLAG_JOINED, &wl->flags);  	memset(wl->bssid, 0, ETH_ALEN); +	/* reset TX security counters on a clean disconnect */ +	wl->tx_security_last_seq_lsb = 0; +	wl->tx_security_seq = 0; +  	/* stop filtering packets based on bssid */  	wl1271_configure_filters(wl, FIF_OTHER_BSS); @@ -1983,6 +2279,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)  			wl->channel = channel;  		} +		if ((changed & IEEE80211_CONF_CHANGE_POWER)) +			wl->power_level = conf->power_level; +  		goto out;  	} @@ -2490,6 +2789,44 @@ out:  	return ret;  } +static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, +				     struct ieee80211_vif *vif) +{ +	struct wl1271 *wl = hw->priv; +	int ret; + +	wl1271_debug(DEBUG_MAC80211, "mac80211 cancel hw scan"); + +	mutex_lock(&wl->mutex); + +	if (wl->state == WL1271_STATE_OFF) +		goto out; + +	if (wl->scan.state == WL1271_SCAN_STATE_IDLE) +		goto out; + +	ret = wl1271_ps_elp_wakeup(wl); +	if (ret < 0) +		goto out; + +	if (wl->scan.state != WL1271_SCAN_STATE_DONE) { +		ret = wl1271_scan_stop(wl); +		if (ret < 0) +			goto out_sleep; +	} +	wl->scan.state = WL1271_SCAN_STATE_IDLE; +	memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); +	wl->scan.req = NULL; +	ieee80211_scan_completed(wl->hw, true); + +out_sleep: +	wl1271_ps_elp_sleep(wl); +out: +	mutex_unlock(&wl->mutex); + +	cancel_delayed_work_sync(&wl->scan_complete_work); +} +  static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw,  				      struct ieee80211_vif *vif,  				      struct cfg80211_sched_scan_request *req, @@ -2780,24 +3117,6 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,  		}  	} -	if (changed & BSS_CHANGED_IBSS) { -		wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d", -			     bss_conf->ibss_joined); - -		if (bss_conf->ibss_joined) { -			u32 rates = bss_conf->basic_rates; -			wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, -									 rates); -			wl->basic_rate = wl1271_tx_min_rate_get(wl); - -			/* by default, use 11b rates */ -			wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; -			ret = wl1271_acx_sta_rate_policies(wl); -			if (ret < 0) -				goto out; -		} -	} -  	ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);  	if (ret < 0)  		goto out; @@ -3023,6 +3342,24 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,  		}  	} +	if (changed & BSS_CHANGED_IBSS) { +		wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d", +			     bss_conf->ibss_joined); + +		if (bss_conf->ibss_joined) { +			u32 rates = bss_conf->basic_rates; +			wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, +									 rates); +			wl->basic_rate = wl1271_tx_min_rate_get(wl); + +			/* by default, use 11b rates */ +			wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; +			ret = wl1271_acx_sta_rate_policies(wl); +			if (ret < 0) +				goto out; +		} +	} +  	ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);  	if (ret < 0)  		goto out; @@ -3061,6 +3398,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,  			wl1271_warning("cmd join failed %d", ret);  			goto out;  		} +		wl1271_check_operstate(wl, ieee80211_get_operstate(vif));  	}  out: @@ -3251,6 +3589,12 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)  	__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);  } +bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) +{ +	int id = hlid - WL1271_AP_STA_HLID_START; +	return test_bit(id, wl->ap_hlid_map); +} +  static int wl1271_op_sta_add(struct ieee80211_hw *hw,  			     struct ieee80211_vif *vif,  			     struct ieee80211_sta *sta) @@ -3354,9 +3698,12 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,  	if (ret < 0)  		goto out; +	wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu: Rx tid %d action %d", +		     tid, action); +  	switch (action) {  	case IEEE80211_AMPDU_RX_START: -		if (wl->ba_support) { +		if ((wl->ba_support) && (wl->ba_allowed)) {  			ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,  								 true);  			if (!ret) @@ -3406,7 +3753,7 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)  		goto out;  	/* packets are considered pending if in the TX queue or the FW */ -	ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0); +	ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0);  	/* the above is appropriate for STA mode for PS purposes */  	WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); @@ -3569,40 +3916,40 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = {  /* 5 GHz band channels for WL1273 */  static struct ieee80211_channel wl1271_channels_5ghz[] = { -	{ .hw_value = 7, .center_freq = 5035}, -	{ .hw_value = 8, .center_freq = 5040}, -	{ .hw_value = 9, .center_freq = 5045}, -	{ .hw_value = 11, .center_freq = 5055}, -	{ .hw_value = 12, .center_freq = 5060}, -	{ .hw_value = 16, .center_freq = 5080}, -	{ .hw_value = 34, .center_freq = 5170}, -	{ .hw_value = 36, .center_freq = 5180}, -	{ .hw_value = 38, .center_freq = 5190}, -	{ .hw_value = 40, .center_freq = 5200}, -	{ .hw_value = 42, .center_freq = 5210}, -	{ .hw_value = 44, .center_freq = 5220}, -	{ .hw_value = 46, .center_freq = 5230}, -	{ .hw_value = 48, .center_freq = 5240}, -	{ .hw_value = 52, .center_freq = 5260}, -	{ .hw_value = 56, .center_freq = 5280}, -	{ .hw_value = 60, .center_freq = 5300}, -	{ .hw_value = 64, .center_freq = 5320}, -	{ .hw_value = 100, .center_freq = 5500}, -	{ .hw_value = 104, .center_freq = 5520}, -	{ .hw_value = 108, .center_freq = 5540}, -	{ .hw_value = 112, .center_freq = 5560}, -	{ .hw_value = 116, .center_freq = 5580}, -	{ .hw_value = 120, .center_freq = 5600}, -	{ .hw_value = 124, .center_freq = 5620}, -	{ .hw_value = 128, .center_freq = 5640}, -	{ .hw_value = 132, .center_freq = 5660}, -	{ .hw_value = 136, .center_freq = 5680}, -	{ .hw_value = 140, .center_freq = 5700}, -	{ .hw_value = 149, .center_freq = 5745}, -	{ .hw_value = 153, .center_freq = 5765}, -	{ .hw_value = 157, .center_freq = 5785}, -	{ .hw_value = 161, .center_freq = 5805}, -	{ .hw_value = 165, .center_freq = 5825}, +	{ .hw_value = 7, .center_freq = 5035, .max_power = 25 }, +	{ .hw_value = 8, .center_freq = 5040, .max_power = 25 }, +	{ .hw_value = 9, .center_freq = 5045, .max_power = 25 }, +	{ .hw_value = 11, .center_freq = 5055, .max_power = 25 }, +	{ .hw_value = 12, .center_freq = 5060, .max_power = 25 }, +	{ .hw_value = 16, .center_freq = 5080, .max_power = 25 }, +	{ .hw_value = 34, .center_freq = 5170, .max_power = 25 }, +	{ .hw_value = 36, .center_freq = 5180, .max_power = 25 }, +	{ .hw_value = 38, .center_freq = 5190, .max_power = 25 }, +	{ .hw_value = 40, .center_freq = 5200, .max_power = 25 }, +	{ .hw_value = 42, .center_freq = 5210, .max_power = 25 }, +	{ .hw_value = 44, .center_freq = 5220, .max_power = 25 }, +	{ .hw_value = 46, .center_freq = 5230, .max_power = 25 }, +	{ .hw_value = 48, .center_freq = 5240, .max_power = 25 }, +	{ .hw_value = 52, .center_freq = 5260, .max_power = 25 }, +	{ .hw_value = 56, .center_freq = 5280, .max_power = 25 }, +	{ .hw_value = 60, .center_freq = 5300, .max_power = 25 }, +	{ .hw_value = 64, .center_freq = 5320, .max_power = 25 }, +	{ .hw_value = 100, .center_freq = 5500, .max_power = 25 }, +	{ .hw_value = 104, .center_freq = 5520, .max_power = 25 }, +	{ .hw_value = 108, .center_freq = 5540, .max_power = 25 }, +	{ .hw_value = 112, .center_freq = 5560, .max_power = 25 }, +	{ .hw_value = 116, .center_freq = 5580, .max_power = 25 }, +	{ .hw_value = 120, .center_freq = 5600, .max_power = 25 }, +	{ .hw_value = 124, .center_freq = 5620, .max_power = 25 }, +	{ .hw_value = 128, .center_freq = 5640, .max_power = 25 }, +	{ .hw_value = 132, .center_freq = 5660, .max_power = 25 }, +	{ .hw_value = 136, .center_freq = 5680, .max_power = 25 }, +	{ .hw_value = 140, .center_freq = 5700, .max_power = 25 }, +	{ .hw_value = 149, .center_freq = 5745, .max_power = 25 }, +	{ .hw_value = 153, .center_freq = 5765, .max_power = 25 }, +	{ .hw_value = 157, .center_freq = 5785, .max_power = 25 }, +	{ .hw_value = 161, .center_freq = 5805, .max_power = 25 }, +	{ .hw_value = 165, .center_freq = 5825, .max_power = 25 },  };  /* mapping to indexes for wl1271_rates_5ghz */ @@ -3663,6 +4010,7 @@ static const struct ieee80211_ops wl1271_ops = {  	.tx = wl1271_op_tx,  	.set_key = wl1271_op_set_key,  	.hw_scan = wl1271_op_hw_scan, +	.cancel_hw_scan = wl1271_op_cancel_hw_scan,  	.sched_scan_start = wl1271_op_sched_scan_start,  	.sched_scan_stop = wl1271_op_sched_scan_stop,  	.bss_info_changed = wl1271_op_bss_info_changed, @@ -3781,6 +4129,69 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev,  static DEVICE_ATTR(hw_pg_ver, S_IRUGO | S_IWUSR,  		   wl1271_sysfs_show_hw_pg_ver, NULL); +static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj, +				       struct bin_attribute *bin_attr, +				       char *buffer, loff_t pos, size_t count) +{ +	struct device *dev = container_of(kobj, struct device, kobj); +	struct wl1271 *wl = dev_get_drvdata(dev); +	ssize_t len; +	int ret; + +	ret = mutex_lock_interruptible(&wl->mutex); +	if (ret < 0) +		return -ERESTARTSYS; + +	/* Let only one thread read the log at a time, blocking others */ +	while (wl->fwlog_size == 0) { +		DEFINE_WAIT(wait); + +		prepare_to_wait_exclusive(&wl->fwlog_waitq, +					  &wait, +					  TASK_INTERRUPTIBLE); + +		if (wl->fwlog_size != 0) { +			finish_wait(&wl->fwlog_waitq, &wait); +			break; +		} + +		mutex_unlock(&wl->mutex); + +		schedule(); +		finish_wait(&wl->fwlog_waitq, &wait); + +		if (signal_pending(current)) +			return -ERESTARTSYS; + +		ret = mutex_lock_interruptible(&wl->mutex); +		if (ret < 0) +			return -ERESTARTSYS; +	} + +	/* Check if the fwlog is still valid */ +	if (wl->fwlog_size < 0) { +		mutex_unlock(&wl->mutex); +		return 0; +	} + +	/* Seeking is not supported - old logs are not kept. Disregard pos. */ +	len = min(count, (size_t)wl->fwlog_size); +	wl->fwlog_size -= len; +	memcpy(buffer, wl->fwlog, len); + +	/* Make room for new messages */ +	memmove(wl->fwlog, wl->fwlog + len, wl->fwlog_size); + +	mutex_unlock(&wl->mutex); + +	return len; +} + +static struct bin_attribute fwlog_attr = { +	.attr = {.name = "fwlog", .mode = S_IRUSR}, +	.read = wl1271_sysfs_read_fwlog, +}; +  int wl1271_register_hw(struct wl1271 *wl)  {  	int ret; @@ -3961,6 +4372,17 @@ struct ieee80211_hw *wl1271_alloc_hw(void)  	INIT_WORK(&wl->tx_work, wl1271_tx_work);  	INIT_WORK(&wl->recovery_work, wl1271_recovery_work);  	INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); +	INIT_WORK(&wl->rx_streaming_enable_work, +		  wl1271_rx_streaming_enable_work); +	INIT_WORK(&wl->rx_streaming_disable_work, +		  wl1271_rx_streaming_disable_work); + +	wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); +	if (!wl->freezable_wq) { +		ret = -ENOMEM; +		goto err_hw; +	} +  	wl->channel = WL1271_DEFAULT_CHANNEL;  	wl->beacon_int = WL1271_DEFAULT_BEACON_INT;  	wl->default_key = 0; @@ -3986,6 +4408,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void)  	wl->quirks = 0;  	wl->platform_quirks = 0;  	wl->sched_scanning = false; +	wl->tx_security_seq = 0; +	wl->tx_security_last_seq_lsb = 0; + +	setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, +		    (unsigned long) wl); +	wl->fwlog_size = 0; +	init_waitqueue_head(&wl->fwlog_waitq);  	memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));  	for (i = 0; i < ACX_TX_DESCRIPTORS; i++) @@ -4003,7 +4432,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)  	wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);  	if (!wl->aggr_buf) {  		ret = -ENOMEM; -		goto err_hw; +		goto err_wq;  	}  	wl->dummy_packet = wl12xx_alloc_dummy_packet(wl); @@ -4012,11 +4441,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void)  		goto err_aggr;  	} +	/* Allocate one page for the FW log */ +	wl->fwlog = (u8 *)get_zeroed_page(GFP_KERNEL); +	if (!wl->fwlog) { +		ret = -ENOMEM; +		goto err_dummy_packet; +	} +  	/* Register platform device */  	ret = platform_device_register(wl->plat_dev);  	if (ret) {  		wl1271_error("couldn't register platform device"); -		goto err_dummy_packet; +		goto err_fwlog;  	}  	dev_set_drvdata(&wl->plat_dev->dev, wl); @@ -4034,20 +4470,36 @@ struct ieee80211_hw *wl1271_alloc_hw(void)  		goto err_bt_coex_state;  	} +	/* Create sysfs file for the FW log */ +	ret = device_create_bin_file(&wl->plat_dev->dev, &fwlog_attr); +	if (ret < 0) { +		wl1271_error("failed to create sysfs file fwlog"); +		goto err_hw_pg_ver; +	} +  	return hw; +err_hw_pg_ver: +	device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); +  err_bt_coex_state:  	device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state);  err_platform:  	platform_device_unregister(wl->plat_dev); +err_fwlog: +	free_page((unsigned long)wl->fwlog); +  err_dummy_packet:  	dev_kfree_skb(wl->dummy_packet);  err_aggr:  	free_pages((unsigned long)wl->aggr_buf, order); +err_wq: +	destroy_workqueue(wl->freezable_wq); +  err_hw:  	wl1271_debugfs_exit(wl);  	kfree(plat_dev); @@ -4063,7 +4515,15 @@ EXPORT_SYMBOL_GPL(wl1271_alloc_hw);  int wl1271_free_hw(struct wl1271 *wl)  { +	/* Unblock any fwlog readers */ +	mutex_lock(&wl->mutex); +	wl->fwlog_size = -1; +	wake_up_interruptible_all(&wl->fwlog_waitq); +	mutex_unlock(&wl->mutex); + +	device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr);  	platform_device_unregister(wl->plat_dev); +	free_page((unsigned long)wl->fwlog);  	dev_kfree_skb(wl->dummy_packet);  	free_pages((unsigned long)wl->aggr_buf,  			get_order(WL1271_AGGR_BUFFER_SIZE)); @@ -4078,6 +4538,7 @@ int wl1271_free_hw(struct wl1271 *wl)  	kfree(wl->fw_status);  	kfree(wl->tx_res_if); +	destroy_workqueue(wl->freezable_wq);  	ieee80211_free_hw(wl->hw); @@ -4090,6 +4551,10 @@ EXPORT_SYMBOL_GPL(wl12xx_debug_level);  module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);  MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); +module_param_named(fwlog, fwlog_param, charp, 0); +MODULE_PARM_DESC(keymap, +		 "FW logger options: continuous, ondemand, dbgpins or disable"); +  MODULE_LICENSE("GPL");  MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");  MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index b59b67711a1..3548377ab9c 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c @@ -118,7 +118,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)  			&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));  		if (ret == 0) {  			wl1271_error("ELP wakeup timeout!"); -			ieee80211_queue_work(wl->hw, &wl->recovery_work); +			wl12xx_queue_recovery_work(wl);  			ret = -ETIMEDOUT;  			goto err;  		} else if (ret < 0) { @@ -169,9 +169,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,  		wl1271_debug(DEBUG_PSM, "leaving psm");  		/* disable beacon early termination */ -		ret = wl1271_acx_bet_enable(wl, false); -		if (ret < 0) -			return ret; +		if (wl->band == IEEE80211_BAND_2GHZ) { +			ret = wl1271_acx_bet_enable(wl, false); +			if (ret < 0) +				return ret; +		}  		/* disable beacon filtering */  		ret = wl1271_acx_beacon_filter_opt(wl, false); @@ -191,24 +193,27 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,  static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)  { -	int i, filtered = 0; +	int i;  	struct sk_buff *skb;  	struct ieee80211_tx_info *info;  	unsigned long flags; +	int filtered[NUM_TX_QUEUES];  	/* filter all frames currently the low level queus for this hlid */  	for (i = 0; i < NUM_TX_QUEUES; i++) { +		filtered[i] = 0;  		while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {  			info = IEEE80211_SKB_CB(skb);  			info->flags |= IEEE80211_TX_STAT_TX_FILTERED;  			info->status.rates[0].idx = -1; -			ieee80211_tx_status(wl->hw, skb); -			filtered++; +			ieee80211_tx_status_ni(wl->hw, skb); +			filtered[i]++;  		}  	}  	spin_lock_irqsave(&wl->wl_lock, flags); -	wl->tx_queue_count -= filtered; +	for (i = 0; i < NUM_TX_QUEUES; i++) +		wl->tx_queue_count[i] -= filtered[i];  	spin_unlock_irqrestore(&wl->wl_lock, flags);  	wl1271_handle_tx_low_watermark(wl); diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 70091035e01..0450fb49dbb 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c @@ -22,6 +22,7 @@   */  #include <linux/gfp.h> +#include <linux/sched.h>  #include "wl12xx.h"  #include "acx.h" @@ -95,6 +96,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)  	struct ieee80211_hdr *hdr;  	u8 *buf;  	u8 beacon = 0; +	u8 is_data = 0;  	/*  	 * In PLT mode we seem to get frames and mac80211 warns about them, @@ -106,6 +108,13 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)  	/* the data read starts with the descriptor */  	desc = (struct wl1271_rx_descriptor *) data; +	if (desc->packet_class == WL12XX_RX_CLASS_LOGGER) { +		size_t len = length - sizeof(*desc); +		wl12xx_copy_fwlog(wl, data + sizeof(*desc), len); +		wake_up_interruptible(&wl->fwlog_waitq); +		return 0; +	} +  	switch (desc->status & WL1271_RX_DESC_STATUS_MASK) {  	/* discard corrupted packets */  	case WL1271_RX_DESC_DRIVER_RX_Q_FAIL: @@ -137,6 +146,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)  	hdr = (struct ieee80211_hdr *)skb->data;  	if (ieee80211_is_beacon(hdr->frame_control))  		beacon = 1; +	if (ieee80211_is_data_present(hdr->frame_control)) +		is_data = 1;  	wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); @@ -147,9 +158,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)  	skb_trim(skb, skb->len - desc->pad_len);  	skb_queue_tail(&wl->deferred_rx_queue, skb); -	ieee80211_queue_work(wl->hw, &wl->netstack_work); +	queue_work(wl->freezable_wq, &wl->netstack_work); -	return 0; +	return is_data;  }  void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status) @@ -162,6 +173,8 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)  	u32 mem_block;  	u32 pkt_length;  	u32 pkt_offset; +	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); +	bool had_data = false;  	while (drv_rx_counter != fw_rx_counter) {  		buf_size = 0; @@ -214,9 +227,11 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)  			 * conditions, in that case the received frame will just  			 * be dropped.  			 */ -			wl1271_rx_handle_data(wl, -					      wl->aggr_buf + pkt_offset, -					      pkt_length); +			if (wl1271_rx_handle_data(wl, +						  wl->aggr_buf + pkt_offset, +						  pkt_length) == 1) +				had_data = true; +  			wl->rx_counter++;  			drv_rx_counter++;  			drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK; @@ -230,6 +245,20 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)  	 */  	if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)  		wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); + +	if (!is_ap && wl->conf.rx_streaming.interval && had_data && +	    (wl->conf.rx_streaming.always || +	     test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { +		u32 timeout = wl->conf.rx_streaming.duration; + +		/* restart rx streaming */ +		if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) +			ieee80211_queue_work(wl->hw, +					     &wl->rx_streaming_enable_work); + +		mod_timer(&wl->rx_streaming_timer, +			  jiffies + msecs_to_jiffies(timeout)); +	}  }  void wl1271_set_default_filters(struct wl1271 *wl) diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h index 75fabf83649..c88e3fa1d60 100644 --- a/drivers/net/wireless/wl12xx/rx.h +++ b/drivers/net/wireless/wl12xx/rx.h @@ -97,6 +97,18 @@  #define RX_BUF_SIZE_MASK      0xFFF00  #define RX_BUF_SIZE_SHIFT_DIV 6 +enum { +	WL12XX_RX_CLASS_UNKNOWN, +	WL12XX_RX_CLASS_MANAGEMENT, +	WL12XX_RX_CLASS_DATA, +	WL12XX_RX_CLASS_QOS_DATA, +	WL12XX_RX_CLASS_BCN_PRBRSP, +	WL12XX_RX_CLASS_EAPOL, +	WL12XX_RX_CLASS_BA_EVENT, +	WL12XX_RX_CLASS_AMSDU, +	WL12XX_RX_CLASS_LOGGER, +}; +  struct wl1271_rx_descriptor {  	__le16 length;  	u8  status; diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 56f76abc754..edfe01c321c 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c @@ -62,7 +62,7 @@ void wl1271_scan_complete_work(struct work_struct *work)  	if (wl->scan.failed) {  		wl1271_info("Scan completed due to error."); -		ieee80211_queue_work(wl->hw, &wl->recovery_work); +		wl12xx_queue_recovery_work(wl);  	}  out: @@ -321,12 +321,39 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,  	return 0;  } +int wl1271_scan_stop(struct wl1271 *wl) +{ +	struct wl1271_cmd_header *cmd = NULL; +	int ret = 0; + +	if (WARN_ON(wl->scan.state == WL1271_SCAN_STATE_IDLE)) +		return -EINVAL; + +	wl1271_debug(DEBUG_CMD, "cmd scan stop"); + +	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); +	if (!cmd) { +		ret = -ENOMEM; +		goto out; +	} + +	ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, cmd, +			      sizeof(*cmd), 0); +	if (ret < 0) { +		wl1271_error("cmd stop_scan failed"); +		goto out; +	} +out: +	kfree(cmd); +	return ret; +} +  static int  wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,  				    struct cfg80211_sched_scan_request *req,  				    struct conn_scan_ch_params *channels,  				    u32 band, bool radar, bool passive, -				    int start) +				    int start, int max_channels)  {  	struct conf_sched_scan_settings *c = &wl->conf.sched_scan;  	int i, j; @@ -334,7 +361,7 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,  	bool force_passive = !req->n_ssids;  	for (i = 0, j = start; -	     i < req->n_channels && j < MAX_CHANNELS_ALL_BANDS; +	     i < req->n_channels && j < max_channels;  	     i++) {  		flags = req->channels[i]->flags; @@ -380,46 +407,42 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,  	return j - start;  } -static int +static bool  wl1271_scan_sched_scan_channels(struct wl1271 *wl,  				struct cfg80211_sched_scan_request *req,  				struct wl1271_cmd_sched_scan_config *cfg)  { -	int idx = 0; -  	cfg->passive[0] = -		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, +		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2,  						    IEEE80211_BAND_2GHZ, -						    false, true, idx); -	idx += cfg->passive[0]; - +						    false, true, 0, +						    MAX_CHANNELS_2GHZ);  	cfg->active[0] = -		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, +		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_2,  						    IEEE80211_BAND_2GHZ, -						    false, false, idx); -	/* -	 * 5GHz channels always start at position 14, not immediately -	 * after the last 2.4GHz channel -	 */ -	idx = 14; - +						    false, false, +						    cfg->passive[0], +						    MAX_CHANNELS_2GHZ);  	cfg->passive[1] = -		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, +		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,  						    IEEE80211_BAND_5GHZ, -						    false, true, idx); -	idx += cfg->passive[1]; - +						    false, true, 0, +						    MAX_CHANNELS_5GHZ);  	cfg->dfs = -		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, +		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,  						    IEEE80211_BAND_5GHZ, -						    true, true, idx); -	idx += cfg->dfs; - +						    true, true, +						    cfg->passive[1], +						    MAX_CHANNELS_5GHZ);  	cfg->active[1] = -		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, +		wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels_5,  						    IEEE80211_BAND_5GHZ, -						    false, false, idx); -	idx += cfg->active[1]; +						    false, false, +						    cfg->passive[1] + cfg->dfs, +						    MAX_CHANNELS_5GHZ); +	/* 802.11j channels are not supported yet */ +	cfg->passive[2] = 0; +	cfg->active[2] = 0;  	wl1271_debug(DEBUG_SCAN, "    2.4GHz: active %d passive %d",  		     cfg->active[0], cfg->passive[0]); @@ -427,7 +450,9 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,  		     cfg->active[1], cfg->passive[1]);  	wl1271_debug(DEBUG_SCAN, "    DFS: %d", cfg->dfs); -	return idx; +	return  cfg->passive[0] || cfg->active[0] || +		cfg->passive[1] || cfg->active[1] || cfg->dfs || +		cfg->passive[2] || cfg->active[2];  }  int wl1271_scan_sched_scan_config(struct wl1271 *wl, @@ -436,7 +461,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,  {  	struct wl1271_cmd_sched_scan_config *cfg = NULL;  	struct conf_sched_scan_settings *c = &wl->conf.sched_scan; -	int i, total_channels, ret; +	int i, ret;  	bool force_passive = !req->n_ssids;  	wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config"); @@ -471,8 +496,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,  		cfg->ssid_len = 0;  	} -	total_channels = wl1271_scan_sched_scan_channels(wl, req, cfg); -	if (total_channels == 0) { +	if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {  		wl1271_error("scan channel list is empty");  		ret = -EINVAL;  		goto out; diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h index a0b6c5d67b0..d882e4da71b 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/wl12xx/scan.h @@ -28,6 +28,7 @@  int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,  		struct cfg80211_scan_request *req); +int wl1271_scan_stop(struct wl1271 *wl);  int wl1271_scan_build_probe_req(struct wl1271 *wl,  				const u8 *ssid, size_t ssid_len,  				const u8 *ie, size_t ie_len, u8 band); @@ -112,19 +113,14 @@ struct wl1271_cmd_trigger_scan_to {  	__le32 timeout;  } __packed; -#define MAX_CHANNELS_ALL_BANDS 41 +#define MAX_CHANNELS_2GHZ	14 +#define MAX_CHANNELS_5GHZ	23 +#define MAX_CHANNELS_4GHZ	4 +  #define SCAN_MAX_CYCLE_INTERVALS 16  #define SCAN_MAX_BANDS 3  enum { -	SCAN_CHANNEL_TYPE_2GHZ_PASSIVE, -	SCAN_CHANNEL_TYPE_2GHZ_ACTIVE, -	SCAN_CHANNEL_TYPE_5GHZ_PASSIVE, -	SCAN_CHANNEL_TYPE_5GHZ_ACTIVE, -	SCAN_CHANNEL_TYPE_5GHZ_DFS, -}; - -enum {  	SCAN_SSID_FILTER_ANY      = 0,  	SCAN_SSID_FILTER_SPECIFIC = 1,  	SCAN_SSID_FILTER_LIST     = 2, @@ -182,7 +178,9 @@ struct wl1271_cmd_sched_scan_config {  	u8 padding[3]; -	struct conn_scan_ch_params channels[MAX_CHANNELS_ALL_BANDS]; +	struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ]; +	struct conn_scan_ch_params channels_5[MAX_CHANNELS_5GHZ]; +	struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ];  } __packed; diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index 536e5065454..5cf18c2c23f 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c @@ -23,7 +23,6 @@  #include <linux/irq.h>  #include <linux/module.h> -#include <linux/crc7.h>  #include <linux/vmalloc.h>  #include <linux/mmc/sdio_func.h>  #include <linux/mmc/sdio_ids.h> @@ -45,7 +44,7 @@  #define SDIO_DEVICE_ID_TI_WL1271	0x4076  #endif -static const struct sdio_device_id wl1271_devices[] = { +static const struct sdio_device_id wl1271_devices[] __devinitconst = {  	{ SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) },  	{}  }; @@ -107,14 +106,6 @@ static void wl1271_sdio_enable_interrupts(struct wl1271 *wl)  	enable_irq(wl->irq);  } -static void wl1271_sdio_reset(struct wl1271 *wl) -{ -} - -static void wl1271_sdio_init(struct wl1271 *wl) -{ -} -  static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,  				 size_t len, bool fixed)  { @@ -170,15 +161,17 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)  	struct sdio_func *func = wl_to_func(wl);  	int ret; -	/* Make sure the card will not be powered off by runtime PM */ -	ret = pm_runtime_get_sync(&func->dev); -	if (ret < 0) -		goto out; - -	/* Runtime PM might be disabled, so power up the card manually */ -	ret = mmc_power_restore_host(func->card->host); -	if (ret < 0) -		goto out; +	/* If enabled, tell runtime PM not to power off the card */ +	if (pm_runtime_enabled(&func->dev)) { +		ret = pm_runtime_get_sync(&func->dev); +		if (ret) +			goto out; +	} else { +		/* Runtime PM is disabled: power up the card manually */ +		ret = mmc_power_restore_host(func->card->host); +		if (ret < 0) +			goto out; +	}  	sdio_claim_host(func);  	sdio_enable_func(func); @@ -195,13 +188,16 @@ static int wl1271_sdio_power_off(struct wl1271 *wl)  	sdio_disable_func(func);  	sdio_release_host(func); -	/* Runtime PM might be disabled, so power off the card manually */ +	/* Power off the card manually, even if runtime PM is enabled. */  	ret = mmc_power_save_host(func->card->host);  	if (ret < 0)  		return ret; -	/* Let runtime PM know the card is powered off */ -	return pm_runtime_put_sync(&func->dev); +	/* If enabled, let runtime PM know the card is powered off */ +	if (pm_runtime_enabled(&func->dev)) +		ret = pm_runtime_put_sync(&func->dev); + +	return ret;  }  static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) @@ -215,8 +211,6 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)  static struct wl1271_if_operations sdio_ops = {  	.read		= wl1271_sdio_raw_read,  	.write		= wl1271_sdio_raw_write, -	.reset		= wl1271_sdio_reset, -	.init		= wl1271_sdio_init,  	.power		= wl1271_sdio_set_power,  	.dev		= wl1271_sdio_wl_to_dev,  	.enable_irq	= wl1271_sdio_enable_interrupts, @@ -278,17 +272,19 @@ static int __devinit wl1271_probe(struct sdio_func *func,  		goto out_free;  	} -	enable_irq_wake(wl->irq); -	device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1); +	ret = enable_irq_wake(wl->irq); +	if (!ret) { +		wl->irq_wake_enabled = true; +		device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1); -	disable_irq(wl->irq); - -	/* if sdio can keep power while host is suspended, enable wow */ -	mmcflags = sdio_get_host_pm_caps(func); -	wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags); +		/* if sdio can keep power while host is suspended, enable wow */ +		mmcflags = sdio_get_host_pm_caps(func); +		wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags); -	if (mmcflags & MMC_PM_KEEP_POWER) -		hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; +		if (mmcflags & MMC_PM_KEEP_POWER) +			hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; +	} +	disable_irq(wl->irq);  	ret = wl1271_init_ieee80211(wl);  	if (ret) @@ -303,8 +299,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,  	/* Tell PM core that we don't need the card to be powered now */  	pm_runtime_put_noidle(&func->dev); -	wl1271_notice("initialized"); -  	return 0;   out_irq: @@ -324,8 +318,10 @@ static void __devexit wl1271_remove(struct sdio_func *func)  	pm_runtime_get_noresume(&func->dev);  	wl1271_unregister_hw(wl); -	device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0); -	disable_irq_wake(wl->irq); +	if (wl->irq_wake_enabled) { +		device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0); +		disable_irq_wake(wl->irq); +	}  	free_irq(wl->irq, wl);  	wl1271_free_hw(wl);  } @@ -402,23 +398,12 @@ static struct sdio_driver wl1271_sdio_driver = {  static int __init wl1271_init(void)  { -	int ret; - -	ret = sdio_register_driver(&wl1271_sdio_driver); -	if (ret < 0) { -		wl1271_error("failed to register sdio driver: %d", ret); -		goto out; -	} - -out: -	return ret; +	return sdio_register_driver(&wl1271_sdio_driver);  }  static void __exit wl1271_exit(void)  {  	sdio_unregister_driver(&wl1271_sdio_driver); - -	wl1271_notice("unloaded");  }  module_init(wl1271_init); diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c index 51662bb6801..e0b3736d7e1 100644 --- a/drivers/net/wireless/wl12xx/spi.c +++ b/drivers/net/wireless/wl12xx/spi.c @@ -21,6 +21,7 @@   *   */ +#include <linux/interrupt.h>  #include <linux/irq.h>  #include <linux/module.h>  #include <linux/crc7.h> @@ -435,8 +436,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)  	if (ret)  		goto out_irq; -	wl1271_notice("initialized"); -  	return 0;   out_irq: @@ -473,23 +472,12 @@ static struct spi_driver wl1271_spi_driver = {  static int __init wl1271_init(void)  { -	int ret; - -	ret = spi_register_driver(&wl1271_spi_driver); -	if (ret < 0) { -		wl1271_error("failed to register spi driver: %d", ret); -		goto out; -	} - -out: -	return ret; +	return spi_register_driver(&wl1271_spi_driver);  }  static void __exit wl1271_exit(void)  {  	spi_unregister_driver(&wl1271_spi_driver); - -	wl1271_notice("unloaded");  }  module_init(wl1271_init); diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index da351d7cd1f..5d5e1ef8720 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -260,7 +260,7 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])  {  	wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover"); -	ieee80211_queue_work(wl->hw, &wl->recovery_work); +	wl12xx_queue_recovery_work(wl);  	return 0;  } diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index ca3ab1c1ace..48fde96ce0d 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c @@ -168,7 +168,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,  	u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;  	u32 len;  	u32 total_blocks; -	int id, ret = -EBUSY; +	int id, ret = -EBUSY, ac;  	u32 spare_blocks;  	if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS)) @@ -206,7 +206,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,  		desc->id = id;  		wl->tx_blocks_available -= total_blocks; -		wl->tx_allocated_blocks += total_blocks; + +		ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); +		wl->tx_allocated_blocks[ac] += total_blocks;  		if (wl->bss_type == BSS_TYPE_AP_BSS)  			wl->links[hlid].allocated_blks += total_blocks; @@ -383,6 +385,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,  	if (ret < 0)  		return ret; +	wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); +  	if (wl->bss_type == BSS_TYPE_AP_BSS) {  		wl1271_tx_ap_update_inconnection_sta(wl, skb);  		wl1271_tx_regulate_link(wl, hlid); @@ -390,8 +394,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,  		wl1271_tx_update_filters(wl, skb);  	} -	wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); -  	/*  	 * The length of each packet is stored in terms of  	 * words. Thus, we must pad the skb data to make sure its @@ -442,37 +444,62 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)  void wl1271_handle_tx_low_watermark(struct wl1271 *wl)  {  	unsigned long flags; +	int i; -	if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && -	    wl->tx_queue_count <= WL1271_TX_QUEUE_LOW_WATERMARK) { -		/* firmware buffer has space, restart queues */ -		spin_lock_irqsave(&wl->wl_lock, flags); -		ieee80211_wake_queues(wl->hw); -		clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); -		spin_unlock_irqrestore(&wl->wl_lock, flags); +	for (i = 0; i < NUM_TX_QUEUES; i++) { +		if (test_bit(i, &wl->stopped_queues_map) && +		    wl->tx_queue_count[i] <= WL1271_TX_QUEUE_LOW_WATERMARK) { +			/* firmware buffer has space, restart queues */ +			spin_lock_irqsave(&wl->wl_lock, flags); +			ieee80211_wake_queue(wl->hw, +					     wl1271_tx_get_mac80211_queue(i)); +			clear_bit(i, &wl->stopped_queues_map); +			spin_unlock_irqrestore(&wl->wl_lock, flags); +		}  	}  } +static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, +						struct sk_buff_head *queues) +{ +	int i, q = -1; +	u32 min_blks = 0xffffffff; + +	/* +	 * Find a non-empty ac where: +	 * 1. There are packets to transmit +	 * 2. The FW has the least allocated blocks +	 */ +	for (i = 0; i < NUM_TX_QUEUES; i++) +		if (!skb_queue_empty(&queues[i]) && +		    (wl->tx_allocated_blocks[i] < min_blks)) { +			q = i; +			min_blks = wl->tx_allocated_blocks[q]; +		} + +	if (q == -1) +		return NULL; + +	return &queues[q]; +} +  static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)  {  	struct sk_buff *skb = NULL;  	unsigned long flags; +	struct sk_buff_head *queue; -	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]); -	if (skb) +	queue = wl1271_select_queue(wl, wl->tx_queue); +	if (!queue)  		goto out; -	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]); -	if (skb) -		goto out; -	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]); -	if (skb) -		goto out; -	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]); + +	skb = skb_dequeue(queue);  out:  	if (skb) { +		int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));  		spin_lock_irqsave(&wl->wl_lock, flags); -		wl->tx_queue_count--; +		wl->tx_queue_count[q]--;  		spin_unlock_irqrestore(&wl->wl_lock, flags);  	} @@ -484,6 +511,7 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)  	struct sk_buff *skb = NULL;  	unsigned long flags;  	int i, h, start_hlid; +	struct sk_buff_head *queue;  	/* start from the link after the last one */  	start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS; @@ -492,25 +520,25 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)  	for (i = 0; i < AP_MAX_LINKS; i++) {  		h = (start_hlid + i) % AP_MAX_LINKS; -		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]); -		if (skb) -			goto out; -		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]); -		if (skb) -			goto out; -		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]); -		if (skb) -			goto out; -		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]); +		/* only consider connected stations */ +		if (h >= WL1271_AP_STA_HLID_START && +		    !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map)) +			continue; + +		queue = wl1271_select_queue(wl, wl->links[h].tx_queue); +		if (!queue) +			continue; + +		skb = skb_dequeue(queue);  		if (skb) -			goto out; +			break;  	} -out:  	if (skb) { +		int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));  		wl->last_tx_hlid = h;  		spin_lock_irqsave(&wl->wl_lock, flags); -		wl->tx_queue_count--; +		wl->tx_queue_count[q]--;  		spin_unlock_irqrestore(&wl->wl_lock, flags);  	} else {  		wl->last_tx_hlid = 0; @@ -531,9 +559,12 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)  	if (!skb &&  	    test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { +		int q; +  		skb = wl->dummy_packet; +		q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));  		spin_lock_irqsave(&wl->wl_lock, flags); -		wl->tx_queue_count--; +		wl->tx_queue_count[q]--;  		spin_unlock_irqrestore(&wl->wl_lock, flags);  	} @@ -558,21 +589,33 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)  	}  	spin_lock_irqsave(&wl->wl_lock, flags); -	wl->tx_queue_count++; +	wl->tx_queue_count[q]++;  	spin_unlock_irqrestore(&wl->wl_lock, flags);  } +static bool wl1271_tx_is_data_present(struct sk_buff *skb) +{ +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + +	return ieee80211_is_data_present(hdr->frame_control); +} +  void wl1271_tx_work_locked(struct wl1271 *wl)  {  	struct sk_buff *skb;  	u32 buf_offset = 0;  	bool sent_packets = false; +	bool had_data = false; +	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);  	int ret;  	if (unlikely(wl->state == WL1271_STATE_OFF))  		return;  	while ((skb = wl1271_skb_dequeue(wl))) { +		if (wl1271_tx_is_data_present(skb)) +			had_data = true; +  		ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);  		if (ret == -EAGAIN) {  			/* @@ -619,6 +662,19 @@ out_ack:  		wl1271_handle_tx_low_watermark(wl);  	} +	if (!is_ap && wl->conf.rx_streaming.interval && had_data && +	    (wl->conf.rx_streaming.always || +	     test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { +		u32 timeout = wl->conf.rx_streaming.duration; + +		/* enable rx streaming */ +		if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) +			ieee80211_queue_work(wl->hw, +					     &wl->rx_streaming_enable_work); + +		mod_timer(&wl->rx_streaming_timer, +			  jiffies + msecs_to_jiffies(timeout)); +	}  }  void wl1271_tx_work(struct work_struct *work) @@ -679,10 +735,24 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,  	wl->stats.retry_count += result->ack_failures; -	/* update security sequence number */ -	wl->tx_security_seq += (result->lsb_security_sequence_number - -				wl->tx_security_last_seq); -	wl->tx_security_last_seq = result->lsb_security_sequence_number; +	/* +	 * update sequence number only when relevant, i.e. only in +	 * sessions of TKIP, AES and GEM (not in open or WEP sessions) +	 */ +	if (info->control.hw_key && +	    (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP || +	     info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP || +	     info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) { +		u8 fw_lsb = result->tx_security_sequence_number_lsb; +		u8 cur_lsb = wl->tx_security_last_seq_lsb; + +		/* +		 * update security sequence number, taking care of potential +		 * wrap-around +		 */ +		wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256; +		wl->tx_security_last_seq_lsb = fw_lsb; +	}  	/* remove private header from packet */  	skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); @@ -702,7 +772,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,  	/* return the packet to the stack */  	skb_queue_tail(&wl->deferred_tx_queue, skb); -	ieee80211_queue_work(wl->hw, &wl->netstack_work); +	queue_work(wl->freezable_wq, &wl->netstack_work);  	wl1271_free_tx_id(wl, result->id);  } @@ -747,23 +817,26 @@ void wl1271_tx_complete(struct wl1271 *wl)  void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)  {  	struct sk_buff *skb; -	int i, total = 0; +	int i;  	unsigned long flags;  	struct ieee80211_tx_info *info; +	int total[NUM_TX_QUEUES];  	for (i = 0; i < NUM_TX_QUEUES; i++) { +		total[i] = 0;  		while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {  			wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb);  			info = IEEE80211_SKB_CB(skb);  			info->status.rates[0].idx = -1;  			info->status.rates[0].count = 0; -			ieee80211_tx_status(wl->hw, skb); -			total++; +			ieee80211_tx_status_ni(wl->hw, skb); +			total[i]++;  		}  	}  	spin_lock_irqsave(&wl->wl_lock, flags); -	wl->tx_queue_count -= total; +	for (i = 0; i < NUM_TX_QUEUES; i++) +		wl->tx_queue_count[i] -= total[i];  	spin_unlock_irqrestore(&wl->wl_lock, flags);  	wl1271_handle_tx_low_watermark(wl); @@ -795,13 +868,14 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)  					info = IEEE80211_SKB_CB(skb);  					info->status.rates[0].idx = -1;  					info->status.rates[0].count = 0; -					ieee80211_tx_status(wl->hw, skb); +					ieee80211_tx_status_ni(wl->hw, skb);  				}  			} +			wl->tx_queue_count[i] = 0;  		}  	} -	wl->tx_queue_count = 0; +	wl->stopped_queues_map = 0;  	/*  	 * Make sure the driver is at a consistent state, in case this @@ -838,7 +912,7 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)  			info->status.rates[0].idx = -1;  			info->status.rates[0].count = 0; -			ieee80211_tx_status(wl->hw, skb); +			ieee80211_tx_status_ni(wl->hw, skb);  		}  	}  } @@ -854,8 +928,10 @@ void wl1271_tx_flush(struct wl1271 *wl)  	while (!time_after(jiffies, timeout)) {  		mutex_lock(&wl->mutex);  		wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d", -			     wl->tx_frames_cnt, wl->tx_queue_count); -		if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) { +			     wl->tx_frames_cnt, +			     wl1271_tx_total_queue_count(wl)); +		if ((wl->tx_frames_cnt == 0) && +		    (wl1271_tx_total_queue_count(wl) == 0)) {  			mutex_unlock(&wl->mutex);  			return;  		} diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index 832f9258d67..5d719b5a3d1 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h @@ -150,7 +150,7 @@ struct wl1271_tx_hw_res_descr {  	   (from 1st EDCA AIFS counter until TX Complete). */  	__le32 medium_delay;  	/* LS-byte of last TKIP seq-num (saved per AC for recovery). */ -	u8 lsb_security_sequence_number; +	u8 tx_security_sequence_number_lsb;  	/* Retry count - number of transmissions without successful ACK.*/  	u8 ack_failures;  	/* The rate that succeeded getting ACK @@ -182,6 +182,32 @@ static inline int wl1271_tx_get_queue(int queue)  	}  } +static inline int wl1271_tx_get_mac80211_queue(int queue) +{ +	switch (queue) { +	case CONF_TX_AC_VO: +		return 0; +	case CONF_TX_AC_VI: +		return 1; +	case CONF_TX_AC_BE: +		return 2; +	case CONF_TX_AC_BK: +		return 3; +	default: +		return 2; +	} +} + +static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) +{ +	int i, count = 0; + +	for (i = 0; i < NUM_TX_QUEUES; i++) +		count += wl->tx_queue_count[i]; + +	return count; +} +  void wl1271_tx_work(struct work_struct *work);  void wl1271_tx_work_locked(struct wl1271 *wl);  void wl1271_tx_complete(struct wl1271 *wl); diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index fbe8f46d123..1a8751eb814 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h @@ -144,6 +144,7 @@ extern u32 wl12xx_debug_level;  #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))  #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff)) +#define WL1271_TX_SQN_POST_RECOVERY_PADDING 0xff  #define WL1271_CIPHER_SUITE_GEM 0x00147201 @@ -172,7 +173,6 @@ extern u32 wl12xx_debug_level;  #define WL1271_PS_STA_MAX_BLOCKS  (2 * 9)  #define WL1271_AP_BSS_INDEX        0 -#define WL1271_AP_DEF_INACTIV_SEC  300  #define WL1271_AP_DEF_BEACON_EXP   20  #define ACX_TX_DESCRIPTORS         32 @@ -226,6 +226,8 @@ enum {  #define FW_VER_MINOR_1_SPARE_STA_MIN 58  #define FW_VER_MINOR_1_SPARE_AP_MIN  47 +#define FW_VER_MINOR_FWLOG_STA_MIN 70 +  struct wl1271_chip {  	u32 id;  	char fw_ver_str[ETHTOOL_BUSINFO_LEN]; @@ -284,8 +286,7 @@ struct wl1271_fw_sta_status {  	u8  tx_total;  	u8  reserved1;  	__le16 reserved2; -	/* Total structure size is 68 bytes */ -	u32 padding; +	__le32 log_start_addr;  } __packed;  struct wl1271_fw_full_status { @@ -359,6 +360,9 @@ enum wl12xx_flags {  	WL1271_FLAG_DUMMY_PACKET_PENDING,  	WL1271_FLAG_SUSPENDED,  	WL1271_FLAG_PENDING_WORK, +	WL1271_FLAG_SOFT_GEMINI, +	WL1271_FLAG_RX_STREAMING_STARTED, +	WL1271_FLAG_RECOVERY_IN_PROGRESS,  };  struct wl1271_link { @@ -420,7 +424,7 @@ struct wl1271 {  	/* Accounting for allocated / available TX blocks on HW */  	u32 tx_blocks_freed[NUM_TX_QUEUES];  	u32 tx_blocks_available; -	u32 tx_allocated_blocks; +	u32 tx_allocated_blocks[NUM_TX_QUEUES];  	u32 tx_results_count;  	/* Transmitted TX packets counter for chipset interface */ @@ -434,7 +438,8 @@ struct wl1271 {  	/* Frames scheduled for transmission, not handled yet */  	struct sk_buff_head tx_queue[NUM_TX_QUEUES]; -	int tx_queue_count; +	int tx_queue_count[NUM_TX_QUEUES]; +	long stopped_queues_map;  	/* Frames received, not handled yet by mac80211 */  	struct sk_buff_head deferred_rx_queue; @@ -443,15 +448,23 @@ struct wl1271 {  	struct sk_buff_head deferred_tx_queue;  	struct work_struct tx_work; +	struct workqueue_struct *freezable_wq;  	/* Pending TX frames */  	unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)];  	struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];  	int tx_frames_cnt; -	/* Security sequence number counters */ -	u8 tx_security_last_seq; -	s64 tx_security_seq; +	/* +	 * Security sequence number +	 *     bits 0-15: lower 16 bits part of sequence number +	 *     bits 16-47: higher 32 bits part of sequence number +	 *     bits 48-63: not in use +	 */ +	u64 tx_security_seq; + +	/* 8 bits of the last sequence number in use */ +	u8 tx_security_last_seq_lsb;  	/* FW Rx counter */  	u32 rx_counter; @@ -468,6 +481,15 @@ struct wl1271 {  	/* Network stack work  */  	struct work_struct netstack_work; +	/* FW log buffer */ +	u8 *fwlog; + +	/* Number of valid bytes in the FW log buffer */ +	ssize_t fwlog_size; + +	/* Sysfs FW log entry readers wait queue */ +	wait_queue_head_t fwlog_waitq; +  	/* Hardware recovery work */  	struct work_struct recovery_work; @@ -508,6 +530,11 @@ struct wl1271 {  	/* Default key (for WEP) */  	u32 default_key; +	/* Rx Streaming */ +	struct work_struct rx_streaming_enable_work; +	struct work_struct rx_streaming_disable_work; +	struct timer_list rx_streaming_timer; +  	unsigned int filters;  	unsigned int rx_config;  	unsigned int rx_filter; @@ -564,6 +591,7 @@ struct wl1271 {  	/* RX BA constraint value */  	bool ba_support;  	u8 ba_rx_bitmap; +	bool ba_allowed;  	int tcxo_clock; @@ -572,6 +600,7 @@ struct wl1271 {  	 * (currently, only "ANY" trigger is supported)  	 */  	bool wow_enabled; +	bool irq_wake_enabled;  	/*  	 * AP-mode - links indexed by HLID. The global and broadcast links @@ -601,6 +630,9 @@ struct wl1271_station {  int wl1271_plt_start(struct wl1271 *wl);  int wl1271_plt_stop(struct wl1271 *wl); +int wl1271_recalc_rx_streaming(struct wl1271 *wl); +void wl12xx_queue_recovery_work(struct wl1271 *wl); +size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);  #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ @@ -608,8 +640,8 @@ int wl1271_plt_stop(struct wl1271 *wl);  #define WL1271_DEFAULT_POWER_LEVEL 0 -#define WL1271_TX_QUEUE_LOW_WATERMARK  10 -#define WL1271_TX_QUEUE_HIGH_WATERMARK 25 +#define WL1271_TX_QUEUE_LOW_WATERMARK  32 +#define WL1271_TX_QUEUE_HIGH_WATERMARK 256  #define WL1271_DEFERRED_QUEUE_LIMIT    64 @@ -636,4 +668,15 @@ int wl1271_plt_stop(struct wl1271 *wl);  /* WL128X requires aggregated packets to be aligned to the SDIO block size */  #define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT	BIT(2) +/* + * WL127X AP mode requires Low Power DRPw (LPD) enable to reduce power + * consumption + */ +#define WL12XX_QUIRK_LPD_MODE                   BIT(3) + +/* Older firmwares did not implement the FW logger over bus feature */ +#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED	BIT(4) + +#define WL12XX_HW_BLOCK_SIZE	256 +  #endif diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 4be7c3b5b26..117c4123943 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -21,6 +21,8 @@  #ifndef _ZD_CHIP_H  #define _ZD_CHIP_H +#include <net/mac80211.h> +  #include "zd_rf.h"  #include "zd_usb.h" diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h index 5463ca9ebc0..9a1b013f81b 100644 --- a/drivers/net/wireless/zd1211rw/zd_def.h +++ b/drivers/net/wireless/zd1211rw/zd_def.h @@ -37,9 +37,15 @@ typedef u16 __nocast zd_addr_t;  	if (net_ratelimit()) \  		dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \  } while (0) +#  define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \ +	bool __cond = !!(cond); \ +	if (unlikely(__cond)) \ +		dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \ +})  #else  #  define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)  #  define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0) +#  define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0)  #endif /* DEBUG */  #ifdef DEBUG diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 5037c8b2b41..cabfae1e70b 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -143,7 +143,7 @@ static void beacon_enable(struct zd_mac *mac);  static void beacon_disable(struct zd_mac *mac);  static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);  static int zd_mac_config_beacon(struct ieee80211_hw *hw, -				struct sk_buff *beacon); +				struct sk_buff *beacon, bool in_intr);  static int zd_reg2alpha2(u8 regdomain, char *alpha2)  { @@ -160,6 +160,22 @@ static int zd_reg2alpha2(u8 regdomain, char *alpha2)  	return 1;  } +static int zd_check_signal(struct ieee80211_hw *hw, int signal) +{ +	struct zd_mac *mac = zd_hw_mac(hw); + +	dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100, +			"%s: signal value from device not in range 0..100, " +			"but %d.\n", __func__, signal); + +	if (signal < 0) +		signal = 0; +	else if (signal > 100) +		signal = 100; + +	return signal; +} +  int zd_mac_preinit_hw(struct ieee80211_hw *hw)  {  	int r; @@ -387,10 +403,8 @@ int zd_restore_settings(struct zd_mac *mac)  	    mac->type == NL80211_IFTYPE_AP) {  		if (mac->vif != NULL) {  			beacon = ieee80211_beacon_get(mac->hw, mac->vif); -			if (beacon) { -				zd_mac_config_beacon(mac->hw, beacon); -				kfree_skb(beacon); -			} +			if (beacon) +				zd_mac_config_beacon(mac->hw, beacon, false);  		}  		zd_set_beacon_interval(&mac->chip, beacon_interval, @@ -461,7 +475,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,  	if (i<IEEE80211_TX_MAX_RATES)  		info->status.rates[i].idx = -1; /* terminate */ -	info->status.ack_signal = ackssi; +	info->status.ack_signal = zd_check_signal(hw, ackssi);  	ieee80211_tx_status_irqsafe(hw, skb);  } @@ -664,7 +678,34 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,  	/* FIXME: Management frame? */  } -static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) +static bool zd_mac_match_cur_beacon(struct zd_mac *mac, struct sk_buff *beacon) +{ +	if (!mac->beacon.cur_beacon) +		return false; + +	if (mac->beacon.cur_beacon->len != beacon->len) +		return false; + +	return !memcmp(beacon->data, mac->beacon.cur_beacon->data, beacon->len); +} + +static void zd_mac_free_cur_beacon_locked(struct zd_mac *mac) +{ +	ZD_ASSERT(mutex_is_locked(&mac->chip.mutex)); + +	kfree_skb(mac->beacon.cur_beacon); +	mac->beacon.cur_beacon = NULL; +} + +static void zd_mac_free_cur_beacon(struct zd_mac *mac) +{ +	mutex_lock(&mac->chip.mutex); +	zd_mac_free_cur_beacon_locked(mac); +	mutex_unlock(&mac->chip.mutex); +} + +static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon, +				bool in_intr)  {  	struct zd_mac *mac = zd_hw_mac(hw);  	int r, ret, num_cmds, req_pos = 0; @@ -674,13 +715,21 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)  	unsigned long end_jiffies, message_jiffies;  	struct zd_ioreq32 *ioreqs; +	mutex_lock(&mac->chip.mutex); + +	/* Check if hw already has this beacon. */ +	if (zd_mac_match_cur_beacon(mac, beacon)) { +		r = 0; +		goto out_nofree; +	} +  	/* Alloc memory for full beacon write at once. */  	num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;  	ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL); -	if (!ioreqs) -		return -ENOMEM; - -	mutex_lock(&mac->chip.mutex); +	if (!ioreqs) { +		r = -ENOMEM; +		goto out_nofree; +	}  	r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);  	if (r < 0) @@ -688,6 +737,10 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)  	r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);  	if (r < 0)  		goto release_sema; +	if (in_intr && tmp & 0x2) { +		r = -EBUSY; +		goto release_sema; +	}  	end_jiffies = jiffies + HZ / 2; /*~500ms*/  	message_jiffies = jiffies + HZ / 10; /*~100ms*/ @@ -742,7 +795,7 @@ release_sema:  	end_jiffies = jiffies + HZ / 2; /*~500ms*/  	ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);  	while (ret < 0) { -		if (time_is_before_eq_jiffies(end_jiffies)) { +		if (in_intr || time_is_before_eq_jiffies(end_jiffies)) {  			ret = -ETIMEDOUT;  			break;  		} @@ -757,9 +810,19 @@ release_sema:  	if (r < 0 || ret < 0) {  		if (r >= 0)  			r = ret; + +		/* We don't know if beacon was written successfully or not, +		 * so clear current. */ +		zd_mac_free_cur_beacon_locked(mac); +  		goto out;  	} +	/* Beacon has now been written successfully, update current. */ +	zd_mac_free_cur_beacon_locked(mac); +	mac->beacon.cur_beacon = beacon; +	beacon = NULL; +  	/* 802.11b/g 2.4G CCK 1Mb  	 * 802.11a, not yet implemented, uses different values (see GPL vendor  	 * driver) @@ -767,11 +830,17 @@ release_sema:  	r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),  				CR_BCN_PLCP_CFG);  out: -	mutex_unlock(&mac->chip.mutex);  	kfree(ioreqs); +out_nofree: +	kfree_skb(beacon); +	mutex_unlock(&mac->chip.mutex); +  	return r;  reset_device: +	zd_mac_free_cur_beacon_locked(mac); +	kfree_skb(beacon); +  	mutex_unlock(&mac->chip.mutex);  	kfree(ioreqs); @@ -982,7 +1051,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)  	stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;  	stats.band = IEEE80211_BAND_2GHZ; -	stats.signal = status->signal_strength; +	stats.signal = zd_check_signal(hw, status->signal_strength);  	rate = zd_rx_rate(buffer, status); @@ -1057,6 +1126,8 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,  	mac->vif = NULL;  	zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);  	zd_write_mac_addr(&mac->chip, NULL); + +	zd_mac_free_cur_beacon(mac);  }  static int zd_op_config(struct ieee80211_hw *hw, u32 changed) @@ -1094,10 +1165,8 @@ static void zd_beacon_done(struct zd_mac *mac)  	 * Fetch next beacon so that tim_count is updated.  	 */  	beacon = ieee80211_beacon_get(mac->hw, mac->vif); -	if (beacon) { -		zd_mac_config_beacon(mac->hw, beacon); -		kfree_skb(beacon); -	} +	if (beacon) +		zd_mac_config_beacon(mac->hw, beacon, true);  	spin_lock_irq(&mac->lock);  	mac->beacon.last_update = jiffies; @@ -1222,9 +1291,8 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,  			if (beacon) {  				zd_chip_disable_hwint(&mac->chip); -				zd_mac_config_beacon(hw, beacon); +				zd_mac_config_beacon(hw, beacon, false);  				zd_chip_enable_hwint(&mac->chip); -				kfree_skb(beacon);  			}  		} @@ -1361,7 +1429,8 @@ static void beacon_watchdog_handler(struct work_struct *work)  	spin_lock_irq(&mac->lock);  	interval = mac->beacon.interval;  	period = mac->beacon.period; -	timeout = mac->beacon.last_update + msecs_to_jiffies(interval) + HZ; +	timeout = mac->beacon.last_update + +			msecs_to_jiffies(interval * 1024 / 1000) * 3;  	spin_unlock_irq(&mac->lock);  	if (interval > 0 && time_is_before_jiffies(timeout)) { @@ -1374,8 +1443,9 @@ static void beacon_watchdog_handler(struct work_struct *work)  		beacon = ieee80211_beacon_get(mac->hw, mac->vif);  		if (beacon) { -			zd_mac_config_beacon(mac->hw, beacon); -			kfree_skb(beacon); +			zd_mac_free_cur_beacon(mac); + +			zd_mac_config_beacon(mac->hw, beacon, false);  		}  		zd_set_beacon_interval(&mac->chip, interval, period, mac->type); @@ -1410,6 +1480,8 @@ static void beacon_disable(struct zd_mac *mac)  {  	dev_dbg_f(zd_mac_dev(mac), "\n");  	cancel_delayed_work_sync(&mac->beacon.watchdog_work); + +	zd_mac_free_cur_beacon(mac);  }  #define LINK_LED_WORK_DELAY HZ diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index f8c93c3fe75..c01eca859f9 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -165,6 +165,7 @@ struct housekeeping {  struct beacon {  	struct delayed_work watchdog_work; +	struct sk_buff *cur_beacon;  	unsigned long last_update;  	u16 interval;  	u8 period; diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 631194d4982..cf0d69dd7be 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -111,6 +111,9 @@ MODULE_DEVICE_TABLE(usb, usb_ids);  #define FW_ZD1211_PREFIX	"zd1211/zd1211_"  #define FW_ZD1211B_PREFIX	"zd1211/zd1211b_" +static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req, +			    unsigned int count); +  /* USB device initialization */  static void int_urb_complete(struct urb *urb); @@ -365,6 +368,20 @@ exit:  #define urb_dev(urb) (&(urb)->dev->dev) +static inline void handle_regs_int_override(struct urb *urb) +{ +	struct zd_usb *usb = urb->context; +	struct zd_usb_interrupt *intr = &usb->intr; + +	spin_lock(&intr->lock); +	if (atomic_read(&intr->read_regs_enabled)) { +		atomic_set(&intr->read_regs_enabled, 0); +		intr->read_regs_int_overridden = 1; +		complete(&intr->read_regs.completion); +	} +	spin_unlock(&intr->lock); +} +  static inline void handle_regs_int(struct urb *urb)  {  	struct zd_usb *usb = urb->context; @@ -383,25 +400,45 @@ static inline void handle_regs_int(struct urb *urb)  				USB_MAX_EP_INT_BUFFER);  		spin_unlock(&mac->lock);  		schedule_work(&mac->process_intr); -	} else if (intr->read_regs_enabled) { -		intr->read_regs.length = len = urb->actual_length; - +	} else if (atomic_read(&intr->read_regs_enabled)) { +		len = urb->actual_length; +		intr->read_regs.length = urb->actual_length;  		if (len > sizeof(intr->read_regs.buffer))  			len = sizeof(intr->read_regs.buffer); +  		memcpy(intr->read_regs.buffer, urb->transfer_buffer, len); -		intr->read_regs_enabled = 0; + +		/* Sometimes USB_INT_ID_REGS is not overridden, but comes after +		 * USB_INT_ID_RETRY_FAILED. Read-reg retry then gets this +		 * delayed USB_INT_ID_REGS, but leaves USB_INT_ID_REGS of +		 * retry unhandled. Next read-reg command then might catch +		 * this wrong USB_INT_ID_REGS. Fix by ignoring wrong reads. +		 */ +		if (!check_read_regs(usb, intr->read_regs.req, +						intr->read_regs.req_count)) +			goto out; + +		atomic_set(&intr->read_regs_enabled, 0); +		intr->read_regs_int_overridden = 0;  		complete(&intr->read_regs.completion); +  		goto out;  	}  out:  	spin_unlock(&intr->lock); + +	/* CR_INTERRUPT might override read_reg too. */ +	if (int_num == CR_INTERRUPT && atomic_read(&intr->read_regs_enabled)) +		handle_regs_int_override(urb);  }  static void int_urb_complete(struct urb *urb)  {  	int r;  	struct usb_int_header *hdr; +	struct zd_usb *usb; +	struct zd_usb_interrupt *intr;  	switch (urb->status) {  	case 0: @@ -430,6 +467,14 @@ static void int_urb_complete(struct urb *urb)  		goto resubmit;  	} +	/* USB_INT_ID_RETRY_FAILED triggered by tx-urb submit can override +	 * pending USB_INT_ID_REGS causing read command timeout. +	 */ +	usb = urb->context; +	intr = &usb->intr; +	if (hdr->id != USB_INT_ID_REGS && atomic_read(&intr->read_regs_enabled)) +		handle_regs_int_override(urb); +  	switch (hdr->id) {  	case USB_INT_ID_REGS:  		handle_regs_int(urb); @@ -579,8 +624,8 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,  	if (length < sizeof(struct rx_length_info)) {  		/* It's not a complete packet anyhow. */ -		printk("%s: invalid, small RX packet : %d\n", -		       __func__, length); +		dev_dbg_f(zd_usb_dev(usb), "invalid, small RX packet : %d\n", +					   length);  		return;  	}  	length_info = (struct rx_length_info *) @@ -1129,6 +1174,7 @@ static inline void init_usb_interrupt(struct zd_usb *usb)  	spin_lock_init(&intr->lock);  	intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));  	init_completion(&intr->read_regs.completion); +	atomic_set(&intr->read_regs_enabled, 0);  	intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);  } @@ -1563,12 +1609,16 @@ static int usb_int_regs_length(unsigned int count)  	return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);  } -static void prepare_read_regs_int(struct zd_usb *usb) +static void prepare_read_regs_int(struct zd_usb *usb, +				  struct usb_req_read_regs *req, +				  unsigned int count)  {  	struct zd_usb_interrupt *intr = &usb->intr;  	spin_lock_irq(&intr->lock); -	intr->read_regs_enabled = 1; +	atomic_set(&intr->read_regs_enabled, 1); +	intr->read_regs.req = req; +	intr->read_regs.req_count = count;  	INIT_COMPLETION(intr->read_regs.completion);  	spin_unlock_irq(&intr->lock);  } @@ -1578,22 +1628,18 @@ static void disable_read_regs_int(struct zd_usb *usb)  	struct zd_usb_interrupt *intr = &usb->intr;  	spin_lock_irq(&intr->lock); -	intr->read_regs_enabled = 0; +	atomic_set(&intr->read_regs_enabled, 0);  	spin_unlock_irq(&intr->lock);  } -static int get_results(struct zd_usb *usb, u16 *values, -	               struct usb_req_read_regs *req, unsigned int count) +static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req, +			    unsigned int count)  { -	int r;  	int i;  	struct zd_usb_interrupt *intr = &usb->intr;  	struct read_regs_int *rr = &intr->read_regs;  	struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer; -	spin_lock_irq(&intr->lock); - -	r = -EIO;  	/* The created block size seems to be larger than expected.  	 * However results appear to be correct.  	 */ @@ -1601,13 +1647,14 @@ static int get_results(struct zd_usb *usb, u16 *values,  		dev_dbg_f(zd_usb_dev(usb),  			 "error: actual length %d less than expected %d\n",  			 rr->length, usb_int_regs_length(count)); -		goto error_unlock; +		return false;  	} +  	if (rr->length > sizeof(rr->buffer)) {  		dev_dbg_f(zd_usb_dev(usb),  			 "error: actual length %d exceeds buffer size %zu\n",  			 rr->length, sizeof(rr->buffer)); -		goto error_unlock; +		return false;  	}  	for (i = 0; i < count; i++) { @@ -1617,8 +1664,39 @@ static int get_results(struct zd_usb *usb, u16 *values,  				 "rd[%d] addr %#06hx expected %#06hx\n", i,  				 le16_to_cpu(rd->addr),  				 le16_to_cpu(req->addr[i])); -			goto error_unlock; +			return false;  		} +	} + +	return true; +} + +static int get_results(struct zd_usb *usb, u16 *values, +		       struct usb_req_read_regs *req, unsigned int count, +		       bool *retry) +{ +	int r; +	int i; +	struct zd_usb_interrupt *intr = &usb->intr; +	struct read_regs_int *rr = &intr->read_regs; +	struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer; + +	spin_lock_irq(&intr->lock); + +	r = -EIO; + +	/* Read failed because firmware bug? */ +	*retry = !!intr->read_regs_int_overridden; +	if (*retry) +		goto error_unlock; + +	if (!check_read_regs(usb, req, count)) { +		dev_dbg_f(zd_usb_dev(usb), "error: invalid read regs\n"); +		goto error_unlock; +	} + +	for (i = 0; i < count; i++) { +		struct reg_data *rd = ®s->regs[i];  		values[i] = le16_to_cpu(rd->value);  	} @@ -1631,11 +1709,11 @@ error_unlock:  int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,  	             const zd_addr_t *addresses, unsigned int count)  { -	int r; -	int i, req_len, actual_req_len; +	int r, i, req_len, actual_req_len, try_count = 0;  	struct usb_device *udev;  	struct usb_req_read_regs *req = NULL;  	unsigned long timeout; +	bool retry = false;  	if (count < 1) {  		dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n"); @@ -1671,8 +1749,10 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,  	for (i = 0; i < count; i++)  		req->addr[i] = cpu_to_le16((u16)addresses[i]); +retry_read: +	try_count++;  	udev = zd_usb_to_usbdev(usb); -	prepare_read_regs_int(usb); +	prepare_read_regs_int(usb, req, count);  	r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);  	if (r) {  		dev_dbg_f(zd_usb_dev(usb), @@ -1696,7 +1776,12 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,  		goto error;  	} -	r = get_results(usb, values, req, count); +	r = get_results(usb, values, req, count, &retry); +	if (retry && try_count < 20) { +		dev_dbg_f(zd_usb_dev(usb), "read retry, tries so far: %d\n", +				try_count); +		goto retry_read; +	}  error:  	return r;  } diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h index bf942843b73..99193b456a7 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/zd1211rw/zd_usb.h @@ -144,6 +144,8 @@ struct usb_int_retry_fail {  struct read_regs_int {  	struct completion completion; +	struct usb_req_read_regs *req; +	unsigned int req_count;  	/* Stores the USB int structure and contains the USB address of the  	 * first requested register before request.  	 */ @@ -169,7 +171,8 @@ struct zd_usb_interrupt {  	void *buffer;  	dma_addr_t buffer_dma;  	int interval; -	u8 read_regs_enabled:1; +	atomic_t read_regs_enabled; +	u8 read_regs_int_overridden:1;  };  static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)  |