Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next
Conflicts: drivers/net/wireless/iwlwifi/iwl-eeprom.c
This commit is contained in:
		
				commit
				
					
						b6038961df
					
				
			
		
					 53 changed files with 2330 additions and 2554 deletions
				
			
		|  | @ -1,31 +1,17 @@ | ||||||
| # DVM
 | obj-$(CONFIG_IWLDVM)	+= dvm/ | ||||||
| obj-$(CONFIG_IWLDVM)   += iwldvm.o |  | ||||||
| iwldvm-objs		:= iwl-agn.o iwl-agn-rs.o iwl-mac80211.o |  | ||||||
| iwldvm-objs		+= iwl-ucode.o iwl-agn-tx.o |  | ||||||
| iwldvm-objs		+= iwl-agn-lib.o iwl-agn-calib.o |  | ||||||
| iwldvm-objs		+= iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o |  | ||||||
| iwldvm-objs		+= iwl-eeprom.o iwl-power.o |  | ||||||
| iwldvm-objs		+= iwl-scan.o iwl-led.o |  | ||||||
| iwldvm-objs		+= iwl-agn-rxon.o iwl-agn-devices.o |  | ||||||
| 
 |  | ||||||
| iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |  | ||||||
| iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-testmode.o |  | ||||||
| 
 | 
 | ||||||
| CFLAGS_iwl-devtrace.o := -I$(src) | CFLAGS_iwl-devtrace.o := -I$(src) | ||||||
| 
 | 
 | ||||||
| # WIFI
 | # common
 | ||||||
| obj-$(CONFIG_IWLWIFI)	+= iwlwifi.o | obj-$(CONFIG_IWLWIFI)	+= iwlwifi.o | ||||||
| iwlwifi-objs		+= iwl-5000.o |  | ||||||
| iwlwifi-objs		+= iwl-6000.o |  | ||||||
| iwlwifi-objs		+= iwl-1000.o |  | ||||||
| iwlwifi-objs		+= iwl-2000.o |  | ||||||
| iwlwifi-objs		+= iwl-io.o | iwlwifi-objs		+= iwl-io.o | ||||||
| iwlwifi-objs		+= iwl-pci.o |  | ||||||
| iwlwifi-objs		+= iwl-drv.o | iwlwifi-objs		+= iwl-drv.o | ||||||
| iwlwifi-objs		+= iwl-debug.o | iwlwifi-objs		+= iwl-debug.o | ||||||
| iwlwifi-objs		+= iwl-notif-wait.o | iwlwifi-objs		+= iwl-notif-wait.o | ||||||
| iwlwifi-objs		+= iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o | iwlwifi-objs		+= iwl-eeprom-read.o iwl-eeprom-parse.o | ||||||
|  | iwlwifi-objs		+= pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o | ||||||
|  | iwlwifi-objs		+= pcie/1000.o pcie/2000.o pcie/5000.o pcie/6000.o | ||||||
| 
 | 
 | ||||||
| iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | ||||||
| 
 | 
 | ||||||
| ccflags-y += -D__CHECK_ENDIAN__ | ccflags-y += -D__CHECK_ENDIAN__ -I$(src) | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								drivers/net/wireless/iwlwifi/dvm/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								drivers/net/wireless/iwlwifi/dvm/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | # DVM
 | ||||||
|  | obj-$(CONFIG_IWLDVM)	+= iwldvm.o | ||||||
|  | iwldvm-objs		+= main.o rs.o mac80211.o ucode.o tx.o | ||||||
|  | iwldvm-objs		+= lib.o calib.o tt.o sta.o rx.o | ||||||
|  | 
 | ||||||
|  | iwldvm-objs		+= power.o | ||||||
|  | iwldvm-objs		+= scan.o led.o | ||||||
|  | iwldvm-objs		+= rxon.o devices.o | ||||||
|  | 
 | ||||||
|  | iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o | ||||||
|  | iwldvm-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += testmode.o | ||||||
|  | 
 | ||||||
|  | ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ | ||||||
|  | @ -63,9 +63,10 @@ | ||||||
| #ifndef __iwl_agn_h__ | #ifndef __iwl_agn_h__ | ||||||
| #define __iwl_agn_h__ | #define __iwl_agn_h__ | ||||||
| 
 | 
 | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-config.h" | #include "iwl-config.h" | ||||||
| 
 | 
 | ||||||
|  | #include "dev.h" | ||||||
|  | 
 | ||||||
| /* The first 11 queues (0-10) are used otherwise */ | /* The first 11 queues (0-10) are used otherwise */ | ||||||
| #define IWLAGN_FIRST_AMPDU_QUEUE	11 | #define IWLAGN_FIRST_AMPDU_QUEUE	11 | ||||||
| 
 | 
 | ||||||
|  | @ -91,7 +92,6 @@ extern struct iwl_lib_ops iwl6030_lib; | ||||||
| #define STATUS_CT_KILL		1 | #define STATUS_CT_KILL		1 | ||||||
| #define STATUS_ALIVE		2 | #define STATUS_ALIVE		2 | ||||||
| #define STATUS_READY		3 | #define STATUS_READY		3 | ||||||
| #define STATUS_GEO_CONFIGURED	4 |  | ||||||
| #define STATUS_EXIT_PENDING	5 | #define STATUS_EXIT_PENDING	5 | ||||||
| #define STATUS_STATISTICS	6 | #define STATUS_STATISTICS	6 | ||||||
| #define STATUS_SCANNING		7 | #define STATUS_SCANNING		7 | ||||||
|  | @ -101,6 +101,7 @@ extern struct iwl_lib_ops iwl6030_lib; | ||||||
| #define STATUS_CHANNEL_SWITCH_PENDING 11 | #define STATUS_CHANNEL_SWITCH_PENDING 11 | ||||||
| #define STATUS_SCAN_COMPLETE	12 | #define STATUS_SCAN_COMPLETE	12 | ||||||
| #define STATUS_POWER_PMI	13 | #define STATUS_POWER_PMI	13 | ||||||
|  | #define STATUS_SCAN_ROC_EXPIRED 14 | ||||||
| 
 | 
 | ||||||
| struct iwl_ucode_capabilities; | struct iwl_ucode_capabilities; | ||||||
| 
 | 
 | ||||||
|  | @ -255,6 +256,10 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv, | ||||||
| 				   enum iwl_scan_type scan_type, | 				   enum iwl_scan_type scan_type, | ||||||
| 				   enum ieee80211_band band); | 				   enum ieee80211_band band); | ||||||
| 
 | 
 | ||||||
|  | void iwl_scan_roc_expired(struct iwl_priv *priv); | ||||||
|  | void iwl_scan_offchannel_skb(struct iwl_priv *priv); | ||||||
|  | void iwl_scan_offchannel_skb_status(struct iwl_priv *priv); | ||||||
|  | 
 | ||||||
| /* For faster active scanning, scan will move to the next channel if fewer than
 | /* For faster active scanning, scan will move to the next channel if fewer than
 | ||||||
|  * PLCP_QUIET_THRESH packets are heard on this channel within |  * PLCP_QUIET_THRESH packets are heard on this channel within | ||||||
|  * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell |  * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell | ||||||
|  | @ -437,10 +442,8 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, | ||||||
| 
 | 
 | ||||||
| static inline int iwl_is_ready(struct iwl_priv *priv) | static inline int iwl_is_ready(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
 | 	/* The adapter is 'ready' if READY EXIT_PENDING is not set */ | ||||||
| 	 * set but EXIT_PENDING is not */ |  | ||||||
| 	return test_bit(STATUS_READY, &priv->status) && | 	return test_bit(STATUS_READY, &priv->status) && | ||||||
| 	       test_bit(STATUS_GEO_CONFIGURED, &priv->status) && |  | ||||||
| 	       !test_bit(STATUS_EXIT_PENDING, &priv->status); | 	       !test_bit(STATUS_EXIT_PENDING, &priv->status); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -518,85 +521,4 @@ static inline const char *iwl_dvm_get_cmd_string(u8 cmd) | ||||||
| 		return s; | 		return s; | ||||||
| 	return "UNKNOWN"; | 	return "UNKNOWN"; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| /* API method exported for mvm hybrid state */ |  | ||||||
| void iwl_setup_deferred_work(struct iwl_priv *priv); |  | ||||||
| int iwl_send_wimax_coex(struct iwl_priv *priv); |  | ||||||
| int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); |  | ||||||
| void iwl_option_config(struct iwl_priv *priv); |  | ||||||
| void iwl_set_hw_params(struct iwl_priv *priv); |  | ||||||
| void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags); |  | ||||||
| int iwl_init_drv(struct iwl_priv *priv); |  | ||||||
| void iwl_uninit_drv(struct iwl_priv *priv); |  | ||||||
| void iwl_send_bt_config(struct iwl_priv *priv); |  | ||||||
| void iwl_rf_kill_ct_config(struct iwl_priv *priv); |  | ||||||
| int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx); |  | ||||||
| void iwl_teardown_interface(struct iwl_priv *priv, |  | ||||||
| 			    struct ieee80211_vif *vif, |  | ||||||
| 			    bool mode_change); |  | ||||||
| int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx); |  | ||||||
| void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx); |  | ||||||
| void iwlagn_check_needed_chains(struct iwl_priv *priv, |  | ||||||
| 				struct iwl_rxon_context *ctx, |  | ||||||
| 				struct ieee80211_bss_conf *bss_conf); |  | ||||||
| void iwlagn_chain_noise_reset(struct iwl_priv *priv); |  | ||||||
| int iwlagn_update_beacon(struct iwl_priv *priv, |  | ||||||
| 			 struct ieee80211_vif *vif); |  | ||||||
| void iwl_tt_handler(struct iwl_priv *priv); |  | ||||||
| void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode); |  | ||||||
| void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue); |  | ||||||
| void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state); |  | ||||||
| void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb); |  | ||||||
| void iwl_nic_error(struct iwl_op_mode *op_mode); |  | ||||||
| void iwl_cmd_queue_full(struct iwl_op_mode *op_mode); |  | ||||||
| void iwl_nic_config(struct iwl_op_mode *op_mode); |  | ||||||
| int iwlagn_mac_set_tim(struct ieee80211_hw *hw, |  | ||||||
| 		       struct ieee80211_sta *sta, bool set); |  | ||||||
| void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, |  | ||||||
| 			      enum ieee80211_rssi_event rssi_event); |  | ||||||
| int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw); |  | ||||||
| int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw); |  | ||||||
| void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop); |  | ||||||
| void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue); |  | ||||||
| void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, |  | ||||||
| 			       struct ieee80211_channel_switch *ch_switch); |  | ||||||
| int iwlagn_mac_sta_state(struct ieee80211_hw *hw, |  | ||||||
| 			 struct ieee80211_vif *vif, |  | ||||||
| 			 struct ieee80211_sta *sta, |  | ||||||
| 			 enum ieee80211_sta_state old_state, |  | ||||||
| 			 enum ieee80211_sta_state new_state); |  | ||||||
| int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, |  | ||||||
| 			    struct ieee80211_vif *vif, |  | ||||||
| 			    enum ieee80211_ampdu_mlme_action action, |  | ||||||
| 			    struct ieee80211_sta *sta, u16 tid, u16 *ssn, |  | ||||||
| 			    u8 buf_size); |  | ||||||
| int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, |  | ||||||
| 		       struct ieee80211_vif *vif, |  | ||||||
| 		       struct cfg80211_scan_request *req); |  | ||||||
| void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, |  | ||||||
| 			   struct ieee80211_vif *vif, |  | ||||||
| 			   enum sta_notify_cmd cmd, |  | ||||||
| 			   struct ieee80211_sta *sta); |  | ||||||
| void iwlagn_configure_filter(struct ieee80211_hw *hw, |  | ||||||
| 			     unsigned int changed_flags, |  | ||||||
| 			     unsigned int *total_flags, |  | ||||||
| 			     u64 multicast); |  | ||||||
| int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, |  | ||||||
| 		       struct ieee80211_vif *vif, u16 queue, |  | ||||||
| 		       const struct ieee80211_tx_queue_params *params); |  | ||||||
| void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, |  | ||||||
| 			       struct ieee80211_vif *vif, |  | ||||||
| 			       struct cfg80211_gtk_rekey_data *data); |  | ||||||
| void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, |  | ||||||
| 				struct ieee80211_vif *vif, |  | ||||||
| 				struct ieee80211_key_conf *keyconf, |  | ||||||
| 				struct ieee80211_sta *sta, |  | ||||||
| 				u32 iv32, u16 *phase1key); |  | ||||||
| int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |  | ||||||
| 		       struct ieee80211_vif *vif, |  | ||||||
| 		       struct ieee80211_sta *sta, |  | ||||||
| 		       struct ieee80211_key_conf *key); |  | ||||||
| void iwlagn_mac_stop(struct ieee80211_hw *hw); |  | ||||||
| void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); |  | ||||||
| int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); |  | ||||||
| #endif /* __iwl_agn_h__ */ | #endif /* __iwl_agn_h__ */ | ||||||
|  | @ -63,10 +63,11 @@ | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| 
 | 
 | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-agn-calib.h" |  | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-agn.h" | 
 | ||||||
|  | #include "dev.h" | ||||||
|  | #include "calib.h" | ||||||
|  | #include "agn.h" | ||||||
| 
 | 
 | ||||||
| /*****************************************************************************
 | /*****************************************************************************
 | ||||||
|  * INIT calibrations framework |  * INIT calibrations framework | ||||||
|  | @ -832,14 +833,14 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | ||||||
| 	 * To be safe, simply mask out any chains that we know | 	 * To be safe, simply mask out any chains that we know | ||||||
| 	 * are not on the device. | 	 * are not on the device. | ||||||
| 	 */ | 	 */ | ||||||
| 	active_chains &= priv->hw_params.valid_rx_ant; | 	active_chains &= priv->eeprom_data->valid_rx_ant; | ||||||
| 
 | 
 | ||||||
| 	num_tx_chains = 0; | 	num_tx_chains = 0; | ||||||
| 	for (i = 0; i < NUM_RX_CHAINS; i++) { | 	for (i = 0; i < NUM_RX_CHAINS; i++) { | ||||||
| 		/* loops on all the bits of
 | 		/* loops on all the bits of
 | ||||||
| 		 * priv->hw_setting.valid_tx_ant */ | 		 * priv->hw_setting.valid_tx_ant */ | ||||||
| 		u8 ant_msk = (1 << i); | 		u8 ant_msk = (1 << i); | ||||||
| 		if (!(priv->hw_params.valid_tx_ant & ant_msk)) | 		if (!(priv->eeprom_data->valid_tx_ant & ant_msk)) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		num_tx_chains++; | 		num_tx_chains++; | ||||||
|  | @ -853,7 +854,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | ||||||
| 			 * connect the first valid tx chain | 			 * connect the first valid tx chain | ||||||
| 			 */ | 			 */ | ||||||
| 			first_chain = | 			first_chain = | ||||||
| 				find_first_chain(priv->hw_params.valid_tx_ant); | 				find_first_chain(priv->eeprom_data->valid_tx_ant); | ||||||
| 			data->disconn_array[first_chain] = 0; | 			data->disconn_array[first_chain] = 0; | ||||||
| 			active_chains |= BIT(first_chain); | 			active_chains |= BIT(first_chain); | ||||||
| 			IWL_DEBUG_CALIB(priv, | 			IWL_DEBUG_CALIB(priv, | ||||||
|  | @ -863,13 +864,13 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig, | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (active_chains != priv->hw_params.valid_rx_ant && | 	if (active_chains != priv->eeprom_data->valid_rx_ant && | ||||||
| 	    active_chains != priv->chain_noise_data.active_chains) | 	    active_chains != priv->chain_noise_data.active_chains) | ||||||
| 		IWL_DEBUG_CALIB(priv, | 		IWL_DEBUG_CALIB(priv, | ||||||
| 				"Detected that not all antennas are connected! " | 				"Detected that not all antennas are connected! " | ||||||
| 				"Connected: %#x, valid: %#x.\n", | 				"Connected: %#x, valid: %#x.\n", | ||||||
| 				active_chains, | 				active_chains, | ||||||
| 				priv->hw_params.valid_rx_ant); | 				priv->eeprom_data->valid_rx_ant); | ||||||
| 
 | 
 | ||||||
| 	/* Save for use within RXON, TX, SCAN commands, etc. */ | 	/* Save for use within RXON, TX, SCAN commands, etc. */ | ||||||
| 	data->active_chains = active_chains; | 	data->active_chains = active_chains; | ||||||
|  | @ -1054,7 +1055,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | ||||||
| 	    priv->cfg->bt_params->advanced_bt_coexist) { | 	    priv->cfg->bt_params->advanced_bt_coexist) { | ||||||
| 		/* Disable disconnected antenna algorithm for advanced
 | 		/* Disable disconnected antenna algorithm for advanced
 | ||||||
| 		   bt coex, assuming valid antennas are connected */ | 		   bt coex, assuming valid antennas are connected */ | ||||||
| 		data->active_chains = priv->hw_params.valid_rx_ant; | 		data->active_chains = priv->eeprom_data->valid_rx_ant; | ||||||
| 		for (i = 0; i < NUM_RX_CHAINS; i++) | 		for (i = 0; i < NUM_RX_CHAINS; i++) | ||||||
| 			if (!(data->active_chains & (1<<i))) | 			if (!(data->active_chains & (1<<i))) | ||||||
| 				data->disconn_array[i] = 1; | 				data->disconn_array[i] = 1; | ||||||
|  | @ -1083,8 +1084,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv) | ||||||
| 	IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", | 	IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", | ||||||
| 			min_average_noise, min_average_noise_antenna_i); | 			min_average_noise, min_average_noise_antenna_i); | ||||||
| 
 | 
 | ||||||
| 	iwlagn_gain_computation(priv, average_noise, | 	iwlagn_gain_computation( | ||||||
| 				find_first_chain(priv->hw_params.valid_rx_ant)); | 		priv, average_noise, | ||||||
|  | 		find_first_chain(priv->eeprom_data->valid_rx_ant)); | ||||||
| 
 | 
 | ||||||
| 	/* Some power changes may have been made during the calibration.
 | 	/* Some power changes may have been made during the calibration.
 | ||||||
| 	 * Update and commit the RXON | 	 * Update and commit the RXON | ||||||
|  | @ -62,8 +62,8 @@ | ||||||
| #ifndef __iwl_calib_h__ | #ifndef __iwl_calib_h__ | ||||||
| #define __iwl_calib_h__ | #define __iwl_calib_h__ | ||||||
| 
 | 
 | ||||||
| #include "iwl-dev.h" | #include "dev.h" | ||||||
| #include "iwl-commands.h" | #include "commands.h" | ||||||
| 
 | 
 | ||||||
| void iwl_chain_noise_calibration(struct iwl_priv *priv); | void iwl_chain_noise_calibration(struct iwl_priv *priv); | ||||||
| void iwl_sensitivity_calibration(struct iwl_priv *priv); | void iwl_sensitivity_calibration(struct iwl_priv *priv); | ||||||
|  | @ -61,9 +61,9 @@ | ||||||
|  * |  * | ||||||
|  *****************************************************************************/ |  *****************************************************************************/ | ||||||
| /*
 | /*
 | ||||||
|  * Please use this file (iwl-commands.h) only for uCode API definitions. |  * Please use this file (commands.h) only for uCode API definitions. | ||||||
|  * Please use iwl-xxxx-hw.h for hardware-related definitions. |  * Please use iwl-xxxx-hw.h for hardware-related definitions. | ||||||
|  * Please use iwl-dev.h for driver implementation definitions. |  * Please use dev.h for driver implementation definitions. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #ifndef __iwl_commands_h__ | #ifndef __iwl_commands_h__ | ||||||
|  | @ -30,16 +30,12 @@ | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/debugfs.h> | #include <linux/debugfs.h> | ||||||
| 
 |  | ||||||
| #include <linux/ieee80211.h> | #include <linux/ieee80211.h> | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-debug.h" | #include "iwl-debug.h" | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-agn.h" | #include "dev.h" | ||||||
| #include "iwl-modparams.h" | #include "agn.h" | ||||||
| 
 | 
 | ||||||
| /* create and remove of files */ | /* create and remove of files */ | ||||||
| #define DEBUGFS_ADD_FILE(name, parent, mode) do {			\ | #define DEBUGFS_ADD_FILE(name, parent, mode) do {			\ | ||||||
|  | @ -307,13 +303,13 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | ||||||
| 	const u8 *ptr; | 	const u8 *ptr; | ||||||
| 	char *buf; | 	char *buf; | ||||||
| 	u16 eeprom_ver; | 	u16 eeprom_ver; | ||||||
| 	size_t eeprom_len = priv->cfg->base_params->eeprom_size; | 	size_t eeprom_len = priv->eeprom_blob_size; | ||||||
| 	buf_size = 4 * eeprom_len + 256; | 	buf_size = 4 * eeprom_len + 256; | ||||||
| 
 | 
 | ||||||
| 	if (eeprom_len % 16) | 	if (eeprom_len % 16) | ||||||
| 		return -ENODATA; | 		return -ENODATA; | ||||||
| 
 | 
 | ||||||
| 	ptr = priv->eeprom; | 	ptr = priv->eeprom_blob; | ||||||
| 	if (!ptr) | 	if (!ptr) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
|  | @ -322,11 +318,9 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | ||||||
| 	if (!buf) | 	if (!buf) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
| 	eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | 	eeprom_ver = priv->eeprom_data->eeprom_version; | ||||||
| 	pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " | 	pos += scnprintf(buf + pos, buf_size - pos, | ||||||
| 			"version: 0x%x\n", | 			 "NVM version: 0x%x\n", eeprom_ver); | ||||||
| 			(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) |  | ||||||
| 			 ? "OTP" : "EEPROM", eeprom_ver); |  | ||||||
| 	for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 	for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | ||||||
| 		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | ||||||
| 		hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | 		hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | ||||||
|  | @ -351,9 +345,6 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | ||||||
| 	char *buf; | 	char *buf; | ||||||
| 	ssize_t ret; | 	ssize_t ret; | ||||||
| 
 | 
 | ||||||
| 	if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) |  | ||||||
| 		return -EAGAIN; |  | ||||||
| 
 |  | ||||||
| 	buf = kzalloc(bufsz, GFP_KERNEL); | 	buf = kzalloc(bufsz, GFP_KERNEL); | ||||||
| 	if (!buf) | 	if (!buf) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
|  | @ -426,8 +417,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | ||||||
| 		test_bit(STATUS_ALIVE, &priv->status)); | 		test_bit(STATUS_ALIVE, &priv->status)); | ||||||
| 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", | ||||||
| 		test_bit(STATUS_READY, &priv->status)); | 		test_bit(STATUS_READY, &priv->status)); | ||||||
| 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", |  | ||||||
| 		test_bit(STATUS_GEO_CONFIGURED, &priv->status)); |  | ||||||
| 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", | ||||||
| 		test_bit(STATUS_EXIT_PENDING, &priv->status)); | 		test_bit(STATUS_EXIT_PENDING, &priv->status)); | ||||||
| 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", | 	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", | ||||||
|  | @ -1341,17 +1330,17 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | ||||||
| 	if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { | 	if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) { | ||||||
| 		pos += scnprintf(buf + pos, bufsz - pos, | 		pos += scnprintf(buf + pos, bufsz - pos, | ||||||
| 			"tx power: (1/2 dB step)\n"); | 			"tx power: (1/2 dB step)\n"); | ||||||
| 		if ((priv->hw_params.valid_tx_ant & ANT_A) && | 		if ((priv->eeprom_data->valid_tx_ant & ANT_A) && | ||||||
| 		    tx->tx_power.ant_a) | 		    tx->tx_power.ant_a) | ||||||
| 			pos += scnprintf(buf + pos, bufsz - pos, | 			pos += scnprintf(buf + pos, bufsz - pos, | ||||||
| 					fmt_hex, "antenna A:", | 					fmt_hex, "antenna A:", | ||||||
| 					tx->tx_power.ant_a); | 					tx->tx_power.ant_a); | ||||||
| 		if ((priv->hw_params.valid_tx_ant & ANT_B) && | 		if ((priv->eeprom_data->valid_tx_ant & ANT_B) && | ||||||
| 		    tx->tx_power.ant_b) | 		    tx->tx_power.ant_b) | ||||||
| 			pos += scnprintf(buf + pos, bufsz - pos, | 			pos += scnprintf(buf + pos, bufsz - pos, | ||||||
| 					fmt_hex, "antenna B:", | 					fmt_hex, "antenna B:", | ||||||
| 					tx->tx_power.ant_b); | 					tx->tx_power.ant_b); | ||||||
| 		if ((priv->hw_params.valid_tx_ant & ANT_C) && | 		if ((priv->eeprom_data->valid_tx_ant & ANT_C) && | ||||||
| 		    tx->tx_power.ant_c) | 		    tx->tx_power.ant_c) | ||||||
| 			pos += scnprintf(buf + pos, bufsz - pos, | 			pos += scnprintf(buf + pos, bufsz - pos, | ||||||
| 					fmt_hex, "antenna C:", | 					fmt_hex, "antenna C:", | ||||||
|  | @ -24,8 +24,8 @@ | ||||||
|  * |  * | ||||||
|  *****************************************************************************/ |  *****************************************************************************/ | ||||||
| /*
 | /*
 | ||||||
|  * Please use this file (iwl-dev.h) for driver implementation definitions. |  * Please use this file (dev.h) for driver implementation definitions. | ||||||
|  * Please use iwl-commands.h for uCode API definitions. |  * Please use commands.h for uCode API definitions. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #ifndef __iwl_dev_h__ | #ifndef __iwl_dev_h__ | ||||||
|  | @ -39,17 +39,18 @@ | ||||||
| #include <linux/mutex.h> | #include <linux/mutex.h> | ||||||
| 
 | 
 | ||||||
| #include "iwl-fw.h" | #include "iwl-fw.h" | ||||||
| #include "iwl-eeprom.h" | #include "iwl-eeprom-parse.h" | ||||||
| #include "iwl-csr.h" | #include "iwl-csr.h" | ||||||
| #include "iwl-debug.h" | #include "iwl-debug.h" | ||||||
| #include "iwl-agn-hw.h" | #include "iwl-agn-hw.h" | ||||||
| #include "iwl-led.h" |  | ||||||
| #include "iwl-power.h" |  | ||||||
| #include "iwl-agn-rs.h" |  | ||||||
| #include "iwl-agn-tt.h" |  | ||||||
| #include "iwl-trans.h" |  | ||||||
| #include "iwl-op-mode.h" | #include "iwl-op-mode.h" | ||||||
| #include "iwl-notif-wait.h" | #include "iwl-notif-wait.h" | ||||||
|  | #include "iwl-trans.h" | ||||||
|  | 
 | ||||||
|  | #include "led.h" | ||||||
|  | #include "power.h" | ||||||
|  | #include "rs.h" | ||||||
|  | #include "tt.h" | ||||||
| 
 | 
 | ||||||
| /* CT-KILL constants */ | /* CT-KILL constants */ | ||||||
| #define CT_KILL_THRESHOLD_LEGACY   110 /* in Celsius */ | #define CT_KILL_THRESHOLD_LEGACY   110 /* in Celsius */ | ||||||
|  | @ -87,33 +88,6 @@ | ||||||
| 
 | 
 | ||||||
| #define IWL_NUM_SCAN_RATES         (2) | #define IWL_NUM_SCAN_RATES         (2) | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * One for each channel, holds all channel setup data |  | ||||||
|  * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant |  | ||||||
|  *     with one another! |  | ||||||
|  */ |  | ||||||
| struct iwl_channel_info { |  | ||||||
| 	struct iwl_eeprom_channel eeprom;	/* EEPROM regulatory limit */ |  | ||||||
| 	struct iwl_eeprom_channel ht40_eeprom;	/* EEPROM regulatory limit for
 |  | ||||||
| 						 * HT40 channel */ |  | ||||||
| 
 |  | ||||||
| 	u8 channel;	  /* channel number */ |  | ||||||
| 	u8 flags;	  /* flags copied from EEPROM */ |  | ||||||
| 	s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ |  | ||||||
| 	s8 curr_txpow;	  /* (dBm) regulatory/spectrum/user (not h/w) limit */ |  | ||||||
| 	s8 min_power;	  /* always 0 */ |  | ||||||
| 	s8 scan_power;	  /* (dBm) regul. eeprom, direct scans, any rate */ |  | ||||||
| 
 |  | ||||||
| 	u8 group_index;	  /* 0-4, maps channel to group1/2/3/4/5 */ |  | ||||||
| 	u8 band_index;	  /* 0-4, maps channel to band1/2/3/4/5 */ |  | ||||||
| 	enum ieee80211_band band; |  | ||||||
| 
 |  | ||||||
| 	/* HT40 channel info */ |  | ||||||
| 	s8 ht40_max_power_avg;	/* (dBm) regul. eeprom, normal Tx, any rate */ |  | ||||||
| 	u8 ht40_flags;		/* flags copied from EEPROM */ |  | ||||||
| 	u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * Minimum number of queues. MAX_NUM is defined in hw specific files. |  * Minimum number of queues. MAX_NUM is defined in hw specific files. | ||||||
|  * Set the minimum to accommodate |  * Set the minimum to accommodate | ||||||
|  | @ -153,29 +127,6 @@ union iwl_ht_rate_supp { | ||||||
| 	}; | 	}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define CFG_HT_RX_AMPDU_FACTOR_8K   (0x0) |  | ||||||
| #define CFG_HT_RX_AMPDU_FACTOR_16K  (0x1) |  | ||||||
| #define CFG_HT_RX_AMPDU_FACTOR_32K  (0x2) |  | ||||||
| #define CFG_HT_RX_AMPDU_FACTOR_64K  (0x3) |  | ||||||
| #define CFG_HT_RX_AMPDU_FACTOR_DEF  CFG_HT_RX_AMPDU_FACTOR_64K |  | ||||||
| #define CFG_HT_RX_AMPDU_FACTOR_MAX  CFG_HT_RX_AMPDU_FACTOR_64K |  | ||||||
| #define CFG_HT_RX_AMPDU_FACTOR_MIN  CFG_HT_RX_AMPDU_FACTOR_8K |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Maximal MPDU density for TX aggregation |  | ||||||
|  * 4 - 2us density |  | ||||||
|  * 5 - 4us density |  | ||||||
|  * 6 - 8us density |  | ||||||
|  * 7 - 16us density |  | ||||||
|  */ |  | ||||||
| #define CFG_HT_MPDU_DENSITY_2USEC   (0x4) |  | ||||||
| #define CFG_HT_MPDU_DENSITY_4USEC   (0x5) |  | ||||||
| #define CFG_HT_MPDU_DENSITY_8USEC   (0x6) |  | ||||||
| #define CFG_HT_MPDU_DENSITY_16USEC  (0x7) |  | ||||||
| #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC |  | ||||||
| #define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC |  | ||||||
| #define CFG_HT_MPDU_DENSITY_MIN     (0x1) |  | ||||||
| 
 |  | ||||||
| struct iwl_ht_config { | struct iwl_ht_config { | ||||||
| 	bool single_chain_sufficient; | 	bool single_chain_sufficient; | ||||||
| 	enum ieee80211_smps_mode smps; /* current smps mode */ | 	enum ieee80211_smps_mode smps; /* current smps mode */ | ||||||
|  | @ -445,23 +396,6 @@ enum { | ||||||
| 	MEASUREMENT_ACTIVE = (1 << 1), | 	MEASUREMENT_ACTIVE = (1 << 1), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| enum iwl_nvm_type { |  | ||||||
| 	NVM_DEVICE_TYPE_EEPROM = 0, |  | ||||||
| 	NVM_DEVICE_TYPE_OTP, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Two types of OTP memory access modes |  | ||||||
|  *   IWL_OTP_ACCESS_ABSOLUTE - absolute address mode, |  | ||||||
|  * 			        based on physical memory addressing |  | ||||||
|  *   IWL_OTP_ACCESS_RELATIVE - relative address mode, |  | ||||||
|  * 			       based on logical memory addressing |  | ||||||
|  */ |  | ||||||
| enum iwl_access_mode { |  | ||||||
| 	IWL_OTP_ACCESS_ABSOLUTE, |  | ||||||
| 	IWL_OTP_ACCESS_RELATIVE, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /* reply_tx_statistics (for _agn devices) */ | /* reply_tx_statistics (for _agn devices) */ | ||||||
| struct reply_tx_error_statistics { | struct reply_tx_error_statistics { | ||||||
| 	u32 pp_delay; | 	u32 pp_delay; | ||||||
|  | @ -632,9 +566,6 @@ enum iwl_scan_type { | ||||||
|  * |  * | ||||||
|  * @tx_chains_num: Number of TX chains |  * @tx_chains_num: Number of TX chains | ||||||
|  * @rx_chains_num: Number of RX chains |  * @rx_chains_num: Number of RX chains | ||||||
|  * @valid_tx_ant: usable antennas for TX |  | ||||||
|  * @valid_rx_ant: usable antennas for RX |  | ||||||
|  * @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX) |  | ||||||
|  * @sku: sku read from EEPROM |  * @sku: sku read from EEPROM | ||||||
|  * @ct_kill_threshold: temperature threshold - in hw dependent unit |  * @ct_kill_threshold: temperature threshold - in hw dependent unit | ||||||
|  * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit |  * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit | ||||||
|  | @ -645,9 +576,6 @@ enum iwl_scan_type { | ||||||
| struct iwl_hw_params { | struct iwl_hw_params { | ||||||
| 	u8  tx_chains_num; | 	u8  tx_chains_num; | ||||||
| 	u8  rx_chains_num; | 	u8  rx_chains_num; | ||||||
| 	u8  valid_tx_ant; |  | ||||||
| 	u8  valid_rx_ant; |  | ||||||
| 	u8  ht40_channel; |  | ||||||
| 	bool use_rts_for_aggregation; | 	bool use_rts_for_aggregation; | ||||||
| 	u16 sku; | 	u16 sku; | ||||||
| 	u32 ct_kill_threshold; | 	u32 ct_kill_threshold; | ||||||
|  | @ -664,9 +592,6 @@ struct iwl_lib_ops { | ||||||
| 	/* device specific configuration */ | 	/* device specific configuration */ | ||||||
| 	void (*nic_config)(struct iwl_priv *priv); | 	void (*nic_config)(struct iwl_priv *priv); | ||||||
| 
 | 
 | ||||||
| 	/* eeprom operations (as defined in iwl-eeprom.h) */ |  | ||||||
| 	struct iwl_eeprom_ops eeprom_ops; |  | ||||||
| 
 |  | ||||||
| 	/* temperature */ | 	/* temperature */ | ||||||
| 	void (*temperature)(struct iwl_priv *priv); | 	void (*temperature)(struct iwl_priv *priv); | ||||||
| }; | }; | ||||||
|  | @ -735,8 +660,6 @@ struct iwl_priv { | ||||||
| 
 | 
 | ||||||
| 	/* ieee device used by generic ieee processing code */ | 	/* ieee device used by generic ieee processing code */ | ||||||
| 	struct ieee80211_hw *hw; | 	struct ieee80211_hw *hw; | ||||||
| 	struct ieee80211_channel *ieee_channels; |  | ||||||
| 	struct ieee80211_rate *ieee_rates; |  | ||||||
| 
 | 
 | ||||||
| 	struct list_head calib_results; | 	struct list_head calib_results; | ||||||
| 
 | 
 | ||||||
|  | @ -755,8 +678,6 @@ struct iwl_priv { | ||||||
| 
 | 
 | ||||||
| 	struct iwl_notif_wait_data notif_wait; | 	struct iwl_notif_wait_data notif_wait; | ||||||
| 
 | 
 | ||||||
| 	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |  | ||||||
| 
 |  | ||||||
| 	/* spectrum measurement report caching */ | 	/* spectrum measurement report caching */ | ||||||
| 	struct iwl_spectrum_notification measure_report; | 	struct iwl_spectrum_notification measure_report; | ||||||
| 	u8 measurement_status; | 	u8 measurement_status; | ||||||
|  | @ -787,11 +708,6 @@ struct iwl_priv { | ||||||
| 	bool ucode_loaded; | 	bool ucode_loaded; | ||||||
| 	bool init_ucode_run;		/* Don't run init uCode again */ | 	bool init_ucode_run;		/* Don't run init uCode again */ | ||||||
| 
 | 
 | ||||||
| 	/* we allocate array of iwl_channel_info for NIC's valid channels.
 |  | ||||||
| 	 *    Access via channel # using indirect index array */ |  | ||||||
| 	struct iwl_channel_info *channel_info;	/* channel info array */ |  | ||||||
| 	u8 channel_count;	/* # of channels */ |  | ||||||
| 
 |  | ||||||
| 	u8 plcp_delta_threshold; | 	u8 plcp_delta_threshold; | ||||||
| 
 | 
 | ||||||
| 	/* thermal calibration */ | 	/* thermal calibration */ | ||||||
|  | @ -846,6 +762,7 @@ struct iwl_priv { | ||||||
| 	struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; | 	struct iwl_station_entry stations[IWLAGN_STATION_COUNT]; | ||||||
| 	unsigned long ucode_key_table; | 	unsigned long ucode_key_table; | ||||||
| 	struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; | 	struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; | ||||||
|  | 	atomic_t num_aux_in_flight; | ||||||
| 
 | 
 | ||||||
| 	u8 mac80211_registered; | 	u8 mac80211_registered; | ||||||
| 
 | 
 | ||||||
|  | @ -950,10 +867,8 @@ struct iwl_priv { | ||||||
| 
 | 
 | ||||||
| 	struct delayed_work scan_check; | 	struct delayed_work scan_check; | ||||||
| 
 | 
 | ||||||
| 	/* TX Power */ | 	/* TX Power settings */ | ||||||
| 	s8 tx_power_user_lmt; | 	s8 tx_power_user_lmt; | ||||||
| 	s8 tx_power_device_lmt; |  | ||||||
| 	s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ |  | ||||||
| 	s8 tx_power_next; | 	s8 tx_power_next; | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_IWLWIFI_DEBUGFS | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||||||
|  | @ -964,9 +879,10 @@ struct iwl_priv { | ||||||
| 	void *wowlan_sram; | 	void *wowlan_sram; | ||||||
| #endif /* CONFIG_IWLWIFI_DEBUGFS */ | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | ||||||
| 
 | 
 | ||||||
| 	/* eeprom -- this is in the card's little endian byte order */ | 	struct iwl_eeprom_data *eeprom_data; | ||||||
| 	u8 *eeprom; | 	/* eeprom blob for debugfs/testmode */ | ||||||
| 	enum iwl_nvm_type nvm_device_type; | 	u8 *eeprom_blob; | ||||||
|  | 	size_t eeprom_blob_size; | ||||||
| 
 | 
 | ||||||
| 	struct work_struct txpower_work; | 	struct work_struct txpower_work; | ||||||
| 	u32 calib_disabled; | 	u32 calib_disabled; | ||||||
|  | @ -1001,8 +917,6 @@ struct iwl_priv { | ||||||
| 	enum iwl_ucode_type cur_ucode; | 	enum iwl_ucode_type cur_ucode; | ||||||
| }; /*iwl_priv */ | }; /*iwl_priv */ | ||||||
| 
 | 
 | ||||||
| extern struct kmem_cache *iwl_tx_cmd_pool; |  | ||||||
| 
 |  | ||||||
| static inline struct iwl_rxon_context * | static inline struct iwl_rxon_context * | ||||||
| iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) | iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) | ||||||
| { | { | ||||||
|  | @ -1036,36 +950,4 @@ static inline int iwl_is_any_associated(struct iwl_priv *priv) | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline int is_channel_valid(const struct iwl_channel_info *ch_info) |  | ||||||
| { |  | ||||||
| 	if (ch_info == NULL) |  | ||||||
| 		return 0; |  | ||||||
| 	return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline int is_channel_radar(const struct iwl_channel_info *ch_info) |  | ||||||
| { |  | ||||||
| 	return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info) |  | ||||||
| { |  | ||||||
| 	return ch_info->band == IEEE80211_BAND_5GHZ; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info) |  | ||||||
| { |  | ||||||
| 	return ch_info->band == IEEE80211_BAND_2GHZ; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline int is_channel_passive(const struct iwl_channel_info *ch) |  | ||||||
| { |  | ||||||
| 	return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline int is_channel_ibss(const struct iwl_channel_info *ch) |  | ||||||
| { |  | ||||||
| 	return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif				/* __iwl_dev_h__ */ | #endif				/* __iwl_dev_h__ */ | ||||||
|  | @ -27,11 +27,14 @@ | ||||||
| /*
 | /*
 | ||||||
|  * DVM device-specific data & functions |  * DVM device-specific data & functions | ||||||
|  */ |  */ | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-commands.h" |  | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-prph.h" | #include "iwl-prph.h" | ||||||
|  | #include "iwl-eeprom-parse.h" | ||||||
|  | 
 | ||||||
|  | #include "agn.h" | ||||||
|  | #include "dev.h" | ||||||
|  | #include "commands.h" | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * 1000 series |  * 1000 series | ||||||
|  | @ -58,11 +61,6 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) | ||||||
| /* NIC configuration for 1000 series */ | /* NIC configuration for 1000 series */ | ||||||
| static void iwl1000_nic_config(struct iwl_priv *priv) | static void iwl1000_nic_config(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	/* set CSR_HW_CONFIG_REG for uCode use */ |  | ||||||
| 	iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG, |  | ||||||
| 		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | |  | ||||||
| 		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); |  | ||||||
| 
 |  | ||||||
| 	/* Setting digital SVR for 1000 card to 1.32V */ | 	/* Setting digital SVR for 1000 card to 1.32V */ | ||||||
| 	/* locking is acquired in iwl_set_bits_mask_prph() function */ | 	/* locking is acquired in iwl_set_bits_mask_prph() function */ | ||||||
| 	iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG, | 	iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG, | ||||||
|  | @ -170,16 +168,6 @@ static const struct iwl_sensitivity_ranges iwl1000_sensitivity = { | ||||||
| 
 | 
 | ||||||
| static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ); |  | ||||||
| 
 |  | ||||||
| 	priv->hw_params.tx_chains_num = |  | ||||||
| 		num_of_ant(priv->hw_params.valid_tx_ant); |  | ||||||
| 	if (priv->cfg->rx_with_siso_diversity) |  | ||||||
| 		priv->hw_params.rx_chains_num = 1; |  | ||||||
| 	else |  | ||||||
| 		priv->hw_params.rx_chains_num = |  | ||||||
| 			num_of_ant(priv->hw_params.valid_rx_ant); |  | ||||||
| 
 |  | ||||||
| 	iwl1000_set_ct_threshold(priv); | 	iwl1000_set_ct_threshold(priv); | ||||||
| 
 | 
 | ||||||
| 	/* Set initial sensitivity parameters */ | 	/* Set initial sensitivity parameters */ | ||||||
|  | @ -189,17 +177,6 @@ static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | ||||||
| struct iwl_lib_ops iwl1000_lib = { | struct iwl_lib_ops iwl1000_lib = { | ||||||
| 	.set_hw_params = iwl1000_hw_set_hw_params, | 	.set_hw_params = iwl1000_hw_set_hw_params, | ||||||
| 	.nic_config = iwl1000_nic_config, | 	.nic_config = iwl1000_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_REG_BAND_24_HT40_CHANNELS, |  | ||||||
| 			EEPROM_REGULATORY_BAND_NO_HT40, |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 	.temperature = iwlagn_temperature, | 	.temperature = iwlagn_temperature, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -219,8 +196,6 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv) | ||||||
| /* NIC configuration for 2000 series */ | /* NIC configuration for 2000 series */ | ||||||
| static void iwl2000_nic_config(struct iwl_priv *priv) | static void iwl2000_nic_config(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	iwl_rf_config(priv); |  | ||||||
| 
 |  | ||||||
| 	iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 	iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | ||||||
| 		    CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); | 		    CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); | ||||||
| } | } | ||||||
|  | @ -251,16 +226,6 @@ static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { | ||||||
| 
 | 
 | ||||||
| static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ); |  | ||||||
| 
 |  | ||||||
| 	priv->hw_params.tx_chains_num = |  | ||||||
| 		num_of_ant(priv->hw_params.valid_tx_ant); |  | ||||||
| 	if (priv->cfg->rx_with_siso_diversity) |  | ||||||
| 		priv->hw_params.rx_chains_num = 1; |  | ||||||
| 	else |  | ||||||
| 		priv->hw_params.rx_chains_num = |  | ||||||
| 			num_of_ant(priv->hw_params.valid_rx_ant); |  | ||||||
| 
 |  | ||||||
| 	iwl2000_set_ct_threshold(priv); | 	iwl2000_set_ct_threshold(priv); | ||||||
| 
 | 
 | ||||||
| 	/* Set initial sensitivity parameters */ | 	/* Set initial sensitivity parameters */ | ||||||
|  | @ -270,36 +235,12 @@ static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | ||||||
| struct iwl_lib_ops iwl2000_lib = { | struct iwl_lib_ops iwl2000_lib = { | ||||||
| 	.set_hw_params = iwl2000_hw_set_hw_params, | 	.set_hw_params = iwl2000_hw_set_hw_params, | ||||||
| 	.nic_config = iwl2000_nic_config, | 	.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, |  | ||||||
| 		}, |  | ||||||
| 		.enhanced_txpower = true, |  | ||||||
| 	}, |  | ||||||
| 	.temperature = iwlagn_temperature, | 	.temperature = iwlagn_temperature, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct iwl_lib_ops iwl2030_lib = { | struct iwl_lib_ops iwl2030_lib = { | ||||||
| 	.set_hw_params = iwl2000_hw_set_hw_params, | 	.set_hw_params = iwl2000_hw_set_hw_params, | ||||||
| 	.nic_config = iwl2000_nic_config, | 	.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, |  | ||||||
| 		}, |  | ||||||
| 		.enhanced_txpower = true, |  | ||||||
| 	}, |  | ||||||
| 	.temperature = iwlagn_temperature, | 	.temperature = iwlagn_temperature, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -311,8 +252,6 @@ struct iwl_lib_ops iwl2030_lib = { | ||||||
| /* NIC configuration for 5000 series */ | /* NIC configuration for 5000 series */ | ||||||
| static void iwl5000_nic_config(struct iwl_priv *priv) | static void iwl5000_nic_config(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	iwl_rf_config(priv); |  | ||||||
| 
 |  | ||||||
| 	/* W/A : NIC is stuck in a reset state after Early PCIe power off
 | 	/* W/A : NIC is stuck in a reset state after Early PCIe power off
 | ||||||
| 	 * (PCIe power is lost before PERST# is asserted), | 	 * (PCIe power is lost before PERST# is asserted), | ||||||
| 	 * causing ME FW to lose ownership and not being able to obtain it back. | 	 * causing ME FW to lose ownership and not being able to obtain it back. | ||||||
|  | @ -376,11 +315,9 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | ||||||
| static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	u16 temperature, voltage; | 	u16 temperature, voltage; | ||||||
| 	__le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv, |  | ||||||
| 				EEPROM_KELVIN_TEMPERATURE); |  | ||||||
| 
 | 
 | ||||||
| 	temperature = le16_to_cpu(temp_calib[0]); | 	temperature = le16_to_cpu(priv->eeprom_data->kelvin_temperature); | ||||||
| 	voltage = le16_to_cpu(temp_calib[1]); | 	voltage = le16_to_cpu(priv->eeprom_data->kelvin_voltage); | ||||||
| 
 | 
 | ||||||
| 	/* offset = temp - volt / coeff */ | 	/* offset = temp - volt / coeff */ | ||||||
| 	return (s32)(temperature - | 	return (s32)(temperature - | ||||||
|  | @ -404,14 +341,6 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) | ||||||
| 
 | 
 | ||||||
| static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) | static void 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.tx_chains_num = |  | ||||||
| 		num_of_ant(priv->hw_params.valid_tx_ant); |  | ||||||
| 	priv->hw_params.rx_chains_num = |  | ||||||
| 		num_of_ant(priv->hw_params.valid_rx_ant); |  | ||||||
| 
 |  | ||||||
| 	iwl5000_set_ct_threshold(priv); | 	iwl5000_set_ct_threshold(priv); | ||||||
| 
 | 
 | ||||||
| 	/* Set initial sensitivity parameters */ | 	/* Set initial sensitivity parameters */ | ||||||
|  | @ -420,14 +349,6 @@ static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) | ||||||
| 
 | 
 | ||||||
| static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) | static void 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.tx_chains_num = |  | ||||||
| 		num_of_ant(priv->hw_params.valid_tx_ant); |  | ||||||
| 	priv->hw_params.rx_chains_num = |  | ||||||
| 		num_of_ant(priv->hw_params.valid_rx_ant); |  | ||||||
| 
 |  | ||||||
| 	iwl5150_set_ct_threshold(priv); | 	iwl5150_set_ct_threshold(priv); | ||||||
| 
 | 
 | ||||||
| 	/* Set initial sensitivity parameters */ | 	/* Set initial sensitivity parameters */ | ||||||
|  | @ -455,7 +376,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | ||||||
| 	 */ | 	 */ | ||||||
| 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||||||
| 	struct iwl5000_channel_switch_cmd cmd; | 	struct iwl5000_channel_switch_cmd cmd; | ||||||
| 	const struct iwl_channel_info *ch_info; |  | ||||||
| 	u32 switch_time_in_usec, ucode_switch_time; | 	u32 switch_time_in_usec, ucode_switch_time; | ||||||
| 	u16 ch; | 	u16 ch; | ||||||
| 	u32 tsf_low; | 	u32 tsf_low; | ||||||
|  | @ -505,14 +425,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | ||||||
| 	} | 	} | ||||||
| 	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | 	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||||||
| 		      cmd.switch_time); | 		      cmd.switch_time); | ||||||
| 	ch_info = iwl_get_channel_info(priv, priv->band, ch); | 	cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; | ||||||
| 	if (ch_info) |  | ||||||
| 		cmd.expect_beacon = is_channel_radar(ch_info); |  | ||||||
| 	else { |  | ||||||
| 		IWL_ERR(priv, "invalid channel switch from %u to %u\n", |  | ||||||
| 			ctx->active.channel, ch); |  | ||||||
| 		return -EFAULT; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	return iwl_dvm_send_cmd(priv, &hcmd); | 	return iwl_dvm_send_cmd(priv, &hcmd); | ||||||
| } | } | ||||||
|  | @ -521,17 +434,6 @@ struct iwl_lib_ops iwl5000_lib = { | ||||||
| 	.set_hw_params = iwl5000_hw_set_hw_params, | 	.set_hw_params = iwl5000_hw_set_hw_params, | ||||||
| 	.set_channel_switch = iwl5000_hw_channel_switch, | 	.set_channel_switch = iwl5000_hw_channel_switch, | ||||||
| 	.nic_config = iwl5000_nic_config, | 	.nic_config = iwl5000_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_REG_BAND_24_HT40_CHANNELS, |  | ||||||
| 			EEPROM_REG_BAND_52_HT40_CHANNELS |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 	.temperature = iwlagn_temperature, | 	.temperature = iwlagn_temperature, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -539,17 +441,6 @@ struct iwl_lib_ops iwl5150_lib = { | ||||||
| 	.set_hw_params = iwl5150_hw_set_hw_params, | 	.set_hw_params = iwl5150_hw_set_hw_params, | ||||||
| 	.set_channel_switch = iwl5000_hw_channel_switch, | 	.set_channel_switch = iwl5000_hw_channel_switch, | ||||||
| 	.nic_config = iwl5000_nic_config, | 	.nic_config = iwl5000_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_REG_BAND_24_HT40_CHANNELS, |  | ||||||
| 			EEPROM_REG_BAND_52_HT40_CHANNELS |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
| 	.temperature = iwl5150_temperature, | 	.temperature = iwl5150_temperature, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -570,8 +461,6 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | ||||||
| /* NIC configuration for 6000 series */ | /* NIC configuration for 6000 series */ | ||||||
| static void iwl6000_nic_config(struct iwl_priv *priv) | static void iwl6000_nic_config(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	iwl_rf_config(priv); |  | ||||||
| 
 |  | ||||||
| 	switch (priv->cfg->device_family) { | 	switch (priv->cfg->device_family) { | ||||||
| 	case IWL_DEVICE_FAMILY_6005: | 	case IWL_DEVICE_FAMILY_6005: | ||||||
| 	case IWL_DEVICE_FAMILY_6030: | 	case IWL_DEVICE_FAMILY_6030: | ||||||
|  | @ -584,13 +473,13 @@ static void iwl6000_nic_config(struct iwl_priv *priv) | ||||||
| 		break; | 		break; | ||||||
| 	case IWL_DEVICE_FAMILY_6050: | 	case IWL_DEVICE_FAMILY_6050: | ||||||
| 		/* Indicate calibration version to uCode. */ | 		/* Indicate calibration version to uCode. */ | ||||||
| 		if (iwl_eeprom_calib_version(priv) >= 6) | 		if (priv->eeprom_data->calib_version >= 6) | ||||||
| 			iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 			iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | ||||||
| 					CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 					CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | ||||||
| 		break; | 		break; | ||||||
| 	case IWL_DEVICE_FAMILY_6150: | 	case IWL_DEVICE_FAMILY_6150: | ||||||
| 		/* Indicate calibration version to uCode. */ | 		/* Indicate calibration version to uCode. */ | ||||||
| 		if (iwl_eeprom_calib_version(priv) >= 6) | 		if (priv->eeprom_data->calib_version >= 6) | ||||||
| 			iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 			iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | ||||||
| 					CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 					CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | ||||||
| 		iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | 		iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, | ||||||
|  | @ -627,17 +516,6 @@ static const struct iwl_sensitivity_ranges iwl6000_sensitivity = { | ||||||
| 
 | 
 | ||||||
| static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) | static void 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.tx_chains_num = |  | ||||||
| 		num_of_ant(priv->hw_params.valid_tx_ant); |  | ||||||
| 	if (priv->cfg->rx_with_siso_diversity) |  | ||||||
| 		priv->hw_params.rx_chains_num = 1; |  | ||||||
| 	else |  | ||||||
| 		priv->hw_params.rx_chains_num = |  | ||||||
| 			num_of_ant(priv->hw_params.valid_rx_ant); |  | ||||||
| 
 |  | ||||||
| 	iwl6000_set_ct_threshold(priv); | 	iwl6000_set_ct_threshold(priv); | ||||||
| 
 | 
 | ||||||
| 	/* Set initial sensitivity parameters */ | 	/* Set initial sensitivity parameters */ | ||||||
|  | @ -654,7 +532,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | ||||||
| 	 */ | 	 */ | ||||||
| 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||||||
| 	struct iwl6000_channel_switch_cmd cmd; | 	struct iwl6000_channel_switch_cmd cmd; | ||||||
| 	const struct iwl_channel_info *ch_info; |  | ||||||
| 	u32 switch_time_in_usec, ucode_switch_time; | 	u32 switch_time_in_usec, ucode_switch_time; | ||||||
| 	u16 ch; | 	u16 ch; | ||||||
| 	u32 tsf_low; | 	u32 tsf_low; | ||||||
|  | @ -704,14 +581,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | ||||||
| 	} | 	} | ||||||
| 	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | 	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||||||
| 		      cmd.switch_time); | 		      cmd.switch_time); | ||||||
| 	ch_info = iwl_get_channel_info(priv, priv->band, ch); | 	cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; | ||||||
| 	if (ch_info) |  | ||||||
| 		cmd.expect_beacon = is_channel_radar(ch_info); |  | ||||||
| 	else { |  | ||||||
| 		IWL_ERR(priv, "invalid channel switch from %u to %u\n", |  | ||||||
| 			ctx->active.channel, ch); |  | ||||||
| 		return -EFAULT; |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	return iwl_dvm_send_cmd(priv, &hcmd); | 	return iwl_dvm_send_cmd(priv, &hcmd); | ||||||
| } | } | ||||||
|  | @ -720,18 +590,6 @@ struct iwl_lib_ops iwl6000_lib = { | ||||||
| 	.set_hw_params = iwl6000_hw_set_hw_params, | 	.set_hw_params = iwl6000_hw_set_hw_params, | ||||||
| 	.set_channel_switch = iwl6000_hw_channel_switch, | 	.set_channel_switch = iwl6000_hw_channel_switch, | ||||||
| 	.nic_config = iwl6000_nic_config, | 	.nic_config = iwl6000_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_REG_BAND_52_HT40_CHANNELS |  | ||||||
| 		}, |  | ||||||
| 		.enhanced_txpower = true, |  | ||||||
| 	}, |  | ||||||
| 	.temperature = iwlagn_temperature, | 	.temperature = iwlagn_temperature, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -739,17 +597,5 @@ struct iwl_lib_ops iwl6030_lib = { | ||||||
| 	.set_hw_params = iwl6000_hw_set_hw_params, | 	.set_hw_params = iwl6000_hw_set_hw_params, | ||||||
| 	.set_channel_switch = iwl6000_hw_channel_switch, | 	.set_channel_switch = iwl6000_hw_channel_switch, | ||||||
| 	.nic_config = iwl6000_nic_config, | 	.nic_config = iwl6000_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_REG_BAND_52_HT40_CHANNELS |  | ||||||
| 		}, |  | ||||||
| 		.enhanced_txpower = true, |  | ||||||
| 	}, |  | ||||||
| 	.temperature = iwlagn_temperature, | 	.temperature = iwlagn_temperature, | ||||||
| }; | }; | ||||||
|  | @ -34,12 +34,11 @@ | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| #include <linux/etherdevice.h> | #include <linux/etherdevice.h> | ||||||
| #include <asm/unaligned.h> | #include <asm/unaligned.h> | ||||||
| 
 |  | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-modparams.h" | #include "iwl-modparams.h" | ||||||
|  | #include "dev.h" | ||||||
|  | #include "agn.h" | ||||||
| 
 | 
 | ||||||
| /* Throughput		OFF time(ms)	ON time (ms)
 | /* Throughput		OFF time(ms)	ON time (ms)
 | ||||||
|  *	>300			25		25 |  *	>300			25		25 | ||||||
|  | @ -33,13 +33,14 @@ | ||||||
| #include <linux/sched.h> | #include <linux/sched.h> | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| 
 | 
 | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-agn-hw.h" | #include "iwl-agn-hw.h" | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-modparams.h" | #include "iwl-modparams.h" | ||||||
| 
 | 
 | ||||||
|  | #include "dev.h" | ||||||
|  | #include "agn.h" | ||||||
|  | 
 | ||||||
| int iwlagn_hw_valid_rtc_data_addr(u32 addr) | int iwlagn_hw_valid_rtc_data_addr(u32 addr) | ||||||
| { | { | ||||||
| 	return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && | 	return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && | ||||||
|  | @ -58,8 +59,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | ||||||
| 	/* half dBm need to multiply */ | 	/* half dBm need to multiply */ | ||||||
| 	tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | 	tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | ||||||
| 
 | 
 | ||||||
| 	if (priv->tx_power_lmt_in_half_dbm && | 	if (tx_power_cmd.global_lmt > priv->eeprom_data->max_tx_pwr_half_dbm) { | ||||||
| 	    priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { |  | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * For the newer devices which using enhanced/extend tx power | 		 * For the newer devices which using enhanced/extend tx power | ||||||
| 		 * table in EEPROM, the format is in half dBm. driver need to | 		 * table in EEPROM, the format is in half dBm. driver need to | ||||||
|  | @ -71,7 +71,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv) | ||||||
| 		 * "tx_power_user_lmt" is higher than EEPROM value (in | 		 * "tx_power_user_lmt" is higher than EEPROM value (in | ||||||
| 		 * half-dBm format), lower the tx power based on EEPROM | 		 * half-dBm format), lower the tx power based on EEPROM | ||||||
| 		 */ | 		 */ | ||||||
| 		tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | 		tx_power_cmd.global_lmt = | ||||||
|  | 			priv->eeprom_data->max_tx_pwr_half_dbm; | ||||||
| 	} | 	} | ||||||
| 	tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; | 	tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; | ||||||
| 	tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; | 	tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; | ||||||
|  | @ -617,6 +618,11 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv, | ||||||
| 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||||||
| 	int ave_rssi; | 	int ave_rssi; | ||||||
| 
 | 
 | ||||||
|  | 	if (!ctx->vif || (ctx->vif->type != NL80211_IFTYPE_STATION)) { | ||||||
|  | 		IWL_DEBUG_INFO(priv, "BSS ctx not active or not in sta mode\n"); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	ave_rssi = ieee80211_ave_rssi(ctx->vif); | 	ave_rssi = ieee80211_ave_rssi(ctx->vif); | ||||||
| 	if (!ave_rssi) { | 	if (!ave_rssi) { | ||||||
| 		/* no rssi data, no changes to reduce tx power */ | 		/* no rssi data, no changes to reduce tx power */ | ||||||
|  | @ -818,7 +824,7 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | ||||||
| 	if (priv->chain_noise_data.active_chains) | 	if (priv->chain_noise_data.active_chains) | ||||||
| 		active_chains = priv->chain_noise_data.active_chains; | 		active_chains = priv->chain_noise_data.active_chains; | ||||||
| 	else | 	else | ||||||
| 		active_chains = priv->hw_params.valid_rx_ant; | 		active_chains = priv->eeprom_data->valid_rx_ant; | ||||||
| 
 | 
 | ||||||
| 	if (priv->cfg->bt_params && | 	if (priv->cfg->bt_params && | ||||||
| 	    priv->cfg->bt_params->advanced_bt_coexist && | 	    priv->cfg->bt_params->advanced_bt_coexist && | ||||||
|  | @ -38,19 +38,20 @@ | ||||||
| #include <linux/etherdevice.h> | #include <linux/etherdevice.h> | ||||||
| #include <linux/if_arp.h> | #include <linux/if_arp.h> | ||||||
| 
 | 
 | ||||||
|  | #include <net/ieee80211_radiotap.h> | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| 
 | 
 | ||||||
| #include <asm/div64.h> | #include <asm/div64.h> | ||||||
| 
 | 
 | ||||||
| #include "iwl-eeprom.h" |  | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-agn-calib.h" |  | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-op-mode.h" | #include "iwl-op-mode.h" | ||||||
| #include "iwl-modparams.h" | #include "iwl-modparams.h" | ||||||
| 
 | 
 | ||||||
|  | #include "dev.h" | ||||||
|  | #include "calib.h" | ||||||
|  | #include "agn.h" | ||||||
|  | 
 | ||||||
| /*****************************************************************************
 | /*****************************************************************************
 | ||||||
|  * |  * | ||||||
|  * mac80211 entry point functions |  * mac80211 entry point functions | ||||||
|  | @ -154,6 +155,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | ||||||
| 		    IEEE80211_HW_SCAN_WHILE_IDLE; | 		    IEEE80211_HW_SCAN_WHILE_IDLE; | ||||||
| 
 | 
 | ||||||
| 	hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; | 	hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; | ||||||
|  | 	hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FMT; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Including the following line will crash some AP's.  This | 	 * Including the following line will crash some AP's.  This | ||||||
|  | @ -237,12 +239,12 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | ||||||
| 
 | 
 | ||||||
| 	hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | 	hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; | ||||||
| 
 | 
 | ||||||
| 	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) | 	if (priv->eeprom_data->bands[IEEE80211_BAND_2GHZ].n_channels) | ||||||
| 		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||||||
| 			&priv->bands[IEEE80211_BAND_2GHZ]; | 			&priv->eeprom_data->bands[IEEE80211_BAND_2GHZ]; | ||||||
| 	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) | 	if (priv->eeprom_data->bands[IEEE80211_BAND_5GHZ].n_channels) | ||||||
| 		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||||||
| 			&priv->bands[IEEE80211_BAND_5GHZ]; | 			&priv->eeprom_data->bands[IEEE80211_BAND_5GHZ]; | ||||||
| 
 | 
 | ||||||
| 	hw->wiphy->hw_version = priv->trans->hw_id; | 	hw->wiphy->hw_version = priv->trans->hw_id; | ||||||
| 
 | 
 | ||||||
|  | @ -341,7 +343,7 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_mac_stop(struct ieee80211_hw *hw) | static void iwlagn_mac_stop(struct ieee80211_hw *hw) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||||||
| 
 | 
 | ||||||
|  | @ -369,7 +371,7 @@ void iwlagn_mac_stop(struct ieee80211_hw *hw) | ||||||
| 	IWL_DEBUG_MAC80211(priv, "leave\n"); | 	IWL_DEBUG_MAC80211(priv, "leave\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | ||||||
| 				      struct ieee80211_vif *vif, | 				      struct ieee80211_vif *vif, | ||||||
| 				      struct cfg80211_gtk_rekey_data *data) | 				      struct cfg80211_gtk_rekey_data *data) | ||||||
| { | { | ||||||
|  | @ -397,7 +399,8 @@ void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw, | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_PM_SLEEP | #ifdef CONFIG_PM_SLEEP | ||||||
| 
 | 
 | ||||||
| int iwlagn_mac_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | static int iwlagn_mac_suspend(struct ieee80211_hw *hw, | ||||||
|  | 			      struct cfg80211_wowlan *wowlan) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||||||
| 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||||||
|  | @ -508,7 +511,7 @@ static void iwlagn_mac_set_wakeup(struct ieee80211_hw *hw, bool enabled) | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||||||
| 
 | 
 | ||||||
|  | @ -519,7 +522,7 @@ void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||||||
| 		dev_kfree_skb_any(skb); | 		dev_kfree_skb_any(skb); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | ||||||
| 				       struct ieee80211_vif *vif, | 				       struct ieee80211_vif *vif, | ||||||
| 				       struct ieee80211_key_conf *keyconf, | 				       struct ieee80211_key_conf *keyconf, | ||||||
| 				       struct ieee80211_sta *sta, | 				       struct ieee80211_sta *sta, | ||||||
|  | @ -530,7 +533,7 @@ void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | ||||||
| 	iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); | 	iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||||||
| 			      struct ieee80211_vif *vif, | 			      struct ieee80211_vif *vif, | ||||||
| 			      struct ieee80211_sta *sta, | 			      struct ieee80211_sta *sta, | ||||||
| 			      struct ieee80211_key_conf *key) | 			      struct ieee80211_key_conf *key) | ||||||
|  | @ -633,7 +636,7 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | ||||||
| 				   struct ieee80211_vif *vif, | 				   struct ieee80211_vif *vif, | ||||||
| 				   enum ieee80211_ampdu_mlme_action action, | 				   enum ieee80211_ampdu_mlme_action action, | ||||||
| 				   struct ieee80211_sta *sta, u16 tid, u16 *ssn, | 				   struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||||||
|  | @ -664,7 +667,7 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | ||||||
| 		ret = iwl_sta_rx_agg_stop(priv, sta, tid); | 		ret = iwl_sta_rx_agg_stop(priv, sta, tid); | ||||||
| 		break; | 		break; | ||||||
| 	case IEEE80211_AMPDU_TX_START: | 	case IEEE80211_AMPDU_TX_START: | ||||||
| 		if (!priv->trans->ops->tx_agg_setup) | 		if (!priv->trans->ops->txq_enable) | ||||||
| 			break; | 			break; | ||||||
| 		if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) | 		if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) | ||||||
| 			break; | 			break; | ||||||
|  | @ -759,7 +762,7 @@ static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw, | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | ||||||
| 				struct ieee80211_vif *vif, | 				struct ieee80211_vif *vif, | ||||||
| 				struct ieee80211_sta *sta, | 				struct ieee80211_sta *sta, | ||||||
| 				enum ieee80211_sta_state old_state, | 				enum ieee80211_sta_state old_state, | ||||||
|  | @ -842,11 +845,10 @@ int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | ||||||
| 				      struct ieee80211_channel_switch *ch_switch) | 				      struct ieee80211_channel_switch *ch_switch) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||||||
| 	const struct iwl_channel_info *ch_info; |  | ||||||
| 	struct ieee80211_conf *conf = &hw->conf; | 	struct ieee80211_conf *conf = &hw->conf; | ||||||
| 	struct ieee80211_channel *channel = ch_switch->channel; | 	struct ieee80211_channel *channel = ch_switch->channel; | ||||||
| 	struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 	struct iwl_ht_config *ht_conf = &priv->current_ht_config; | ||||||
|  | @ -883,12 +885,6 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | ||||||
| 	if (le16_to_cpu(ctx->active.channel) == ch) | 	if (le16_to_cpu(ctx->active.channel) == ch) | ||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	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; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	priv->current_ht_config.smps = conf->smps_mode; | 	priv->current_ht_config.smps = conf->smps_mode; | ||||||
| 
 | 
 | ||||||
| 	/* Configure HT40 channels */ | 	/* Configure HT40 channels */ | ||||||
|  | @ -937,7 +933,7 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) | ||||||
| 		ieee80211_chswitch_done(ctx->vif, is_success); | 		ieee80211_chswitch_done(ctx->vif, is_success); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_configure_filter(struct ieee80211_hw *hw, | static void iwlagn_configure_filter(struct ieee80211_hw *hw, | ||||||
| 				    unsigned int changed_flags, | 				    unsigned int changed_flags, | ||||||
| 				    unsigned int *total_flags, | 				    unsigned int *total_flags, | ||||||
| 				    u64 multicast) | 				    u64 multicast) | ||||||
|  | @ -987,7 +983,7 @@ void iwlagn_configure_filter(struct ieee80211_hw *hw, | ||||||
| 			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | 			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) | static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||||||
| 
 | 
 | ||||||
|  | @ -1114,7 +1110,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||||||
| 
 | 
 | ||||||
|  | @ -1131,7 +1127,7 @@ int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | ||||||
| 				     enum ieee80211_rssi_event rssi_event) | 				     enum ieee80211_rssi_event rssi_event) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||||||
|  | @ -1156,7 +1152,7 @@ void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw, | ||||||
| 	IWL_DEBUG_MAC80211(priv, "leave\n"); | 	IWL_DEBUG_MAC80211(priv, "leave\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | static int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | ||||||
| 			      struct ieee80211_sta *sta, bool set) | 			      struct ieee80211_sta *sta, bool set) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||||||
|  | @ -1166,7 +1162,7 @@ int iwlagn_mac_set_tim(struct ieee80211_hw *hw, | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | ||||||
| 			      struct ieee80211_vif *vif, u16 queue, | 			      struct ieee80211_vif *vif, u16 queue, | ||||||
| 			      const struct ieee80211_tx_queue_params *params) | 			      const struct ieee80211_tx_queue_params *params) | ||||||
| { | { | ||||||
|  | @ -1210,7 +1206,7 @@ int iwlagn_mac_conf_tx(struct ieee80211_hw *hw, | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw) | static int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 	struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | ||||||
| 
 | 
 | ||||||
|  | @ -1226,7 +1222,8 @@ static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | ||||||
| 	return iwlagn_commit_rxon(priv, ctx); | 	return iwlagn_commit_rxon(priv, ctx); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwl_setup_interface(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | static int iwl_setup_interface(struct iwl_priv *priv, | ||||||
|  | 			       struct iwl_rxon_context *ctx) | ||||||
| { | { | ||||||
| 	struct ieee80211_vif *vif = ctx->vif; | 	struct ieee80211_vif *vif = ctx->vif; | ||||||
| 	int err, ac; | 	int err, ac; | ||||||
|  | @ -1346,7 +1343,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_teardown_interface(struct iwl_priv *priv, | static void iwl_teardown_interface(struct iwl_priv *priv, | ||||||
| 				   struct ieee80211_vif *vif, | 				   struct ieee80211_vif *vif, | ||||||
| 				   bool mode_change) | 				   bool mode_change) | ||||||
| { | { | ||||||
|  | @ -1489,7 +1486,7 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw, | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, | static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw, | ||||||
| 			      struct ieee80211_vif *vif, | 			      struct ieee80211_vif *vif, | ||||||
| 			      struct cfg80211_scan_request *req) | 			      struct cfg80211_scan_request *req) | ||||||
| { | { | ||||||
|  | @ -1546,7 +1543,7 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | ||||||
| 	iwl_send_add_sta(priv, &cmd, CMD_ASYNC); | 	iwl_send_add_sta(priv, &cmd, CMD_ASYNC); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, | static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, | ||||||
| 				  struct ieee80211_vif *vif, | 				  struct ieee80211_vif *vif, | ||||||
| 				  enum sta_notify_cmd cmd, | 				  enum sta_notify_cmd cmd, | ||||||
| 				  struct ieee80211_sta *sta) | 				  struct ieee80211_sta *sta) | ||||||
|  | @ -44,16 +44,18 @@ | ||||||
| 
 | 
 | ||||||
| #include <asm/div64.h> | #include <asm/div64.h> | ||||||
| 
 | 
 | ||||||
| #include "iwl-eeprom.h" | #include "iwl-eeprom-read.h" | ||||||
| #include "iwl-dev.h" | #include "iwl-eeprom-parse.h" | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-agn-calib.h" |  | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-op-mode.h" | #include "iwl-op-mode.h" | ||||||
| #include "iwl-drv.h" | #include "iwl-drv.h" | ||||||
| #include "iwl-modparams.h" | #include "iwl-modparams.h" | ||||||
| 
 | 
 | ||||||
|  | #include "dev.h" | ||||||
|  | #include "calib.h" | ||||||
|  | #include "agn.h" | ||||||
|  | 
 | ||||||
| /******************************************************************************
 | /******************************************************************************
 | ||||||
|  * |  * | ||||||
|  * module boiler plate |  * module boiler plate | ||||||
|  | @ -79,6 +81,8 @@ MODULE_VERSION(DRV_VERSION); | ||||||
| MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | ||||||
| MODULE_LICENSE("GPL"); | MODULE_LICENSE("GPL"); | ||||||
| 
 | 
 | ||||||
|  | static const struct iwl_op_mode_ops iwl_dvm_ops; | ||||||
|  | 
 | ||||||
| void iwl_update_chain_flags(struct iwl_priv *priv) | void iwl_update_chain_flags(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	struct iwl_rxon_context *ctx; | 	struct iwl_rxon_context *ctx; | ||||||
|  | @ -179,7 +183,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | ||||||
| 		rate = info->control.rates[0].idx; | 		rate = info->control.rates[0].idx; | ||||||
| 
 | 
 | ||||||
| 	priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 	priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | ||||||
| 					      priv->hw_params.valid_tx_ant); | 					      priv->eeprom_data->valid_tx_ant); | ||||||
| 	rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 	rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||||||
| 
 | 
 | ||||||
| 	/* In mac80211, rates for 5 GHz start at 0 */ | 	/* In mac80211, rates for 5 GHz start at 0 */ | ||||||
|  | @ -577,7 +581,7 @@ static const u8 iwlagn_pan_ac_to_queue[] = { | ||||||
| 	7, 6, 5, 4, | 	7, 6, 5, 4, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
|  | @ -644,7 +648,7 @@ void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | ||||||
| 	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | 	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_rf_kill_ct_config(struct iwl_priv *priv) | static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	struct iwl_ct_kill_config cmd; | 	struct iwl_ct_kill_config cmd; | ||||||
| 	struct iwl_ct_kill_throttling_config adv_cmd; | 	struct iwl_ct_kill_throttling_config adv_cmd; | ||||||
|  | @ -725,7 +729,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_send_bt_config(struct iwl_priv *priv) | static void iwl_send_bt_config(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	struct iwl_bt_cmd bt_cmd = { | 	struct iwl_bt_cmd bt_cmd = { | ||||||
| 		.lead_time = BT_LEAD_TIME_DEF, | 		.lead_time = BT_LEAD_TIME_DEF, | ||||||
|  | @ -813,7 +817,7 @@ int iwl_alive_start(struct iwl_priv *priv) | ||||||
| 	ieee80211_wake_queues(priv->hw); | 	ieee80211_wake_queues(priv->hw); | ||||||
| 
 | 
 | ||||||
| 	/* Configure Tx antenna selection based on H/W config */ | 	/* Configure Tx antenna selection based on H/W config */ | ||||||
| 	iwlagn_send_tx_ant_config(priv, priv->hw_params.valid_tx_ant); | 	iwlagn_send_tx_ant_config(priv, priv->eeprom_data->valid_tx_ant); | ||||||
| 
 | 
 | ||||||
| 	if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { | 	if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { | ||||||
| 		struct iwl_rxon_cmd *active_rxon = | 		struct iwl_rxon_cmd *active_rxon = | ||||||
|  | @ -931,11 +935,12 @@ void iwl_down(struct iwl_priv *priv) | ||||||
| 	priv->ucode_loaded = false; | 	priv->ucode_loaded = false; | ||||||
| 	iwl_trans_stop_device(priv->trans); | 	iwl_trans_stop_device(priv->trans); | ||||||
| 
 | 
 | ||||||
|  | 	/* Set num_aux_in_flight must be done after the transport is stopped */ | ||||||
|  | 	atomic_set(&priv->num_aux_in_flight, 0); | ||||||
|  | 
 | ||||||
| 	/* Clear out all status bits but a few that are stable across reset */ | 	/* Clear out all status bits but a few that are stable across reset */ | ||||||
| 	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << | 	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << | ||||||
| 				STATUS_RF_KILL_HW | | 				STATUS_RF_KILL_HW | | ||||||
| 			test_bit(STATUS_GEO_CONFIGURED, &priv->status) << |  | ||||||
| 				STATUS_GEO_CONFIGURED | |  | ||||||
| 			test_bit(STATUS_FW_ERROR, &priv->status) << | 			test_bit(STATUS_FW_ERROR, &priv->status) << | ||||||
| 				STATUS_FW_ERROR | | 				STATUS_FW_ERROR | | ||||||
| 			test_bit(STATUS_EXIT_PENDING, &priv->status) << | 			test_bit(STATUS_EXIT_PENDING, &priv->status) << | ||||||
|  | @ -1077,7 +1082,7 @@ static void iwlagn_disable_roc_work(struct work_struct *work) | ||||||
|  * |  * | ||||||
|  *****************************************************************************/ |  *****************************************************************************/ | ||||||
| 
 | 
 | ||||||
| void iwl_setup_deferred_work(struct iwl_priv *priv) | static void iwl_setup_deferred_work(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	priv->workqueue = create_singlethread_workqueue(DRV_NAME); | 	priv->workqueue = create_singlethread_workqueue(DRV_NAME); | ||||||
| 
 | 
 | ||||||
|  | @ -1122,224 +1127,14 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv) | ||||||
| 	del_timer_sync(&priv->ucode_trace); | 	del_timer_sync(&priv->ucode_trace); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void iwl_init_hw_rates(struct ieee80211_rate *rates) | static int iwl_init_drv(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	int i; |  | ||||||
| 
 |  | ||||||
| 	for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { |  | ||||||
| 		rates[i].bitrate = iwl_rates[i].ieee * 5; |  | ||||||
| 		rates[i].hw_value = i; /* Rate scaling will work on indexes */ |  | ||||||
| 		rates[i].hw_value_short = i; |  | ||||||
| 		rates[i].flags = 0; |  | ||||||
| 		if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) { |  | ||||||
| 			/*
 |  | ||||||
| 			 * If CCK != 1M then set short preamble rate flag. |  | ||||||
| 			 */ |  | ||||||
| 			rates[i].flags |= |  | ||||||
| 				(iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ? |  | ||||||
| 					0 : IEEE80211_RATE_SHORT_PREAMBLE; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ |  | ||||||
| #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ |  | ||||||
| static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, |  | ||||||
| 			      struct ieee80211_sta_ht_cap *ht_info, |  | ||||||
| 			      enum ieee80211_band band) |  | ||||||
| { |  | ||||||
| 	u16 max_bit_rate = 0; |  | ||||||
| 	u8 rx_chains_num = priv->hw_params.rx_chains_num; |  | ||||||
| 	u8 tx_chains_num = priv->hw_params.tx_chains_num; |  | ||||||
| 
 |  | ||||||
| 	ht_info->cap = 0; |  | ||||||
| 	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); |  | ||||||
| 
 |  | ||||||
| 	ht_info->ht_supported = true; |  | ||||||
| 
 |  | ||||||
| 	if (priv->cfg->ht_params && |  | ||||||
| 	    priv->cfg->ht_params->ht_greenfield_support) |  | ||||||
| 		ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; |  | ||||||
| 	ht_info->cap |= IEEE80211_HT_CAP_SGI_20; |  | ||||||
| 	max_bit_rate = MAX_BIT_RATE_20_MHZ; |  | ||||||
| 	if (priv->hw_params.ht40_channel & BIT(band)) { |  | ||||||
| 		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |  | ||||||
| 		ht_info->cap |= IEEE80211_HT_CAP_SGI_40; |  | ||||||
| 		ht_info->mcs.rx_mask[4] = 0x01; |  | ||||||
| 		max_bit_rate = MAX_BIT_RATE_40_MHZ; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (iwlwifi_mod_params.amsdu_size_8K) |  | ||||||
| 		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; |  | ||||||
| 
 |  | ||||||
| 	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; |  | ||||||
| 	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; |  | ||||||
| 
 |  | ||||||
| 	ht_info->mcs.rx_mask[0] = 0xFF; |  | ||||||
| 	if (rx_chains_num >= 2) |  | ||||||
| 		ht_info->mcs.rx_mask[1] = 0xFF; |  | ||||||
| 	if (rx_chains_num >= 3) |  | ||||||
| 		ht_info->mcs.rx_mask[2] = 0xFF; |  | ||||||
| 
 |  | ||||||
| 	/* Highest supported Rx data rate */ |  | ||||||
| 	max_bit_rate *= rx_chains_num; |  | ||||||
| 	WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); |  | ||||||
| 	ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); |  | ||||||
| 
 |  | ||||||
| 	/* Tx MCS capabilities */ |  | ||||||
| 	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |  | ||||||
| 	if (tx_chains_num != rx_chains_num) { |  | ||||||
| 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; |  | ||||||
| 		ht_info->mcs.tx_params |= ((tx_chains_num - 1) << |  | ||||||
| 				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom |  | ||||||
|  */ |  | ||||||
| static int iwl_init_geos(struct iwl_priv *priv) |  | ||||||
| { |  | ||||||
| 	struct iwl_channel_info *ch; |  | ||||||
| 	struct ieee80211_supported_band *sband; |  | ||||||
| 	struct ieee80211_channel *channels; |  | ||||||
| 	struct ieee80211_channel *geo_ch; |  | ||||||
| 	struct ieee80211_rate *rates; |  | ||||||
| 	int i = 0; |  | ||||||
| 	s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN; |  | ||||||
| 
 |  | ||||||
| 	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || |  | ||||||
| 	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { |  | ||||||
| 		IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); |  | ||||||
| 		set_bit(STATUS_GEO_CONFIGURED, &priv->status); |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	channels = kcalloc(priv->channel_count, |  | ||||||
| 			   sizeof(struct ieee80211_channel), GFP_KERNEL); |  | ||||||
| 	if (!channels) |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 
 |  | ||||||
| 	rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate), |  | ||||||
| 			GFP_KERNEL); |  | ||||||
| 	if (!rates) { |  | ||||||
| 		kfree(channels); |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/* 5.2GHz channels start after the 2.4GHz channels */ |  | ||||||
| 	sband = &priv->bands[IEEE80211_BAND_5GHZ]; |  | ||||||
| 	sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; |  | ||||||
| 	/* just OFDM */ |  | ||||||
| 	sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; |  | ||||||
| 	sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; |  | ||||||
| 
 |  | ||||||
| 	if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) |  | ||||||
| 		iwl_init_ht_hw_capab(priv, &sband->ht_cap, |  | ||||||
| 					 IEEE80211_BAND_5GHZ); |  | ||||||
| 
 |  | ||||||
| 	sband = &priv->bands[IEEE80211_BAND_2GHZ]; |  | ||||||
| 	sband->channels = channels; |  | ||||||
| 	/* OFDM & CCK */ |  | ||||||
| 	sband->bitrates = rates; |  | ||||||
| 	sband->n_bitrates = IWL_RATE_COUNT_LEGACY; |  | ||||||
| 
 |  | ||||||
| 	if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE) |  | ||||||
| 		iwl_init_ht_hw_capab(priv, &sband->ht_cap, |  | ||||||
| 					 IEEE80211_BAND_2GHZ); |  | ||||||
| 
 |  | ||||||
| 	priv->ieee_channels = channels; |  | ||||||
| 	priv->ieee_rates = rates; |  | ||||||
| 
 |  | ||||||
| 	for (i = 0;  i < priv->channel_count; i++) { |  | ||||||
| 		ch = &priv->channel_info[i]; |  | ||||||
| 
 |  | ||||||
| 		/* FIXME: might be removed if scan is OK */ |  | ||||||
| 		if (!is_channel_valid(ch)) |  | ||||||
| 			continue; |  | ||||||
| 
 |  | ||||||
| 		sband =  &priv->bands[ch->band]; |  | ||||||
| 
 |  | ||||||
| 		geo_ch = &sband->channels[sband->n_channels++]; |  | ||||||
| 
 |  | ||||||
| 		geo_ch->center_freq = |  | ||||||
| 			ieee80211_channel_to_frequency(ch->channel, ch->band); |  | ||||||
| 		geo_ch->max_power = ch->max_power_avg; |  | ||||||
| 		geo_ch->max_antenna_gain = 0xff; |  | ||||||
| 		geo_ch->hw_value = ch->channel; |  | ||||||
| 
 |  | ||||||
| 		if (is_channel_valid(ch)) { |  | ||||||
| 			if (!(ch->flags & EEPROM_CHANNEL_IBSS)) |  | ||||||
| 				geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; |  | ||||||
| 
 |  | ||||||
| 			if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) |  | ||||||
| 				geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; |  | ||||||
| 
 |  | ||||||
| 			if (ch->flags & EEPROM_CHANNEL_RADAR) |  | ||||||
| 				geo_ch->flags |= IEEE80211_CHAN_RADAR; |  | ||||||
| 
 |  | ||||||
| 			geo_ch->flags |= ch->ht40_extension_channel; |  | ||||||
| 
 |  | ||||||
| 			if (ch->max_power_avg > max_tx_power) |  | ||||||
| 				max_tx_power = ch->max_power_avg; |  | ||||||
| 		} else { |  | ||||||
| 			geo_ch->flags |= IEEE80211_CHAN_DISABLED; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", |  | ||||||
| 				ch->channel, geo_ch->center_freq, |  | ||||||
| 				is_channel_a_band(ch) ?  "5.2" : "2.4", |  | ||||||
| 				geo_ch->flags & IEEE80211_CHAN_DISABLED ? |  | ||||||
| 				"restricted" : "valid", |  | ||||||
| 				 geo_ch->flags); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	priv->tx_power_device_lmt = max_tx_power; |  | ||||||
| 	priv->tx_power_user_lmt = max_tx_power; |  | ||||||
| 	priv->tx_power_next = max_tx_power; |  | ||||||
| 
 |  | ||||||
| 	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && |  | ||||||
| 	     priv->hw_params.sku & EEPROM_SKU_CAP_BAND_52GHZ) { |  | ||||||
| 		IWL_INFO(priv, "Incorrectly detected BG card as ABG. " |  | ||||||
| 			"Please send your %s to maintainer.\n", |  | ||||||
| 			priv->trans->hw_id_str); |  | ||||||
| 		priv->hw_params.sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (iwlwifi_mod_params.disable_5ghz) |  | ||||||
| 		priv->bands[IEEE80211_BAND_5GHZ].n_channels = 0; |  | ||||||
| 
 |  | ||||||
| 	IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", |  | ||||||
| 		   priv->bands[IEEE80211_BAND_2GHZ].n_channels, |  | ||||||
| 		   priv->bands[IEEE80211_BAND_5GHZ].n_channels); |  | ||||||
| 
 |  | ||||||
| 	set_bit(STATUS_GEO_CONFIGURED, &priv->status); |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * iwl_free_geos - undo allocations in iwl_init_geos |  | ||||||
|  */ |  | ||||||
| static void iwl_free_geos(struct iwl_priv *priv) |  | ||||||
| { |  | ||||||
| 	kfree(priv->ieee_channels); |  | ||||||
| 	kfree(priv->ieee_rates); |  | ||||||
| 	clear_bit(STATUS_GEO_CONFIGURED, &priv->status); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int iwl_init_drv(struct iwl_priv *priv) |  | ||||||
| { |  | ||||||
| 	int ret; |  | ||||||
| 
 |  | ||||||
| 	spin_lock_init(&priv->sta_lock); | 	spin_lock_init(&priv->sta_lock); | ||||||
| 
 | 
 | ||||||
| 	mutex_init(&priv->mutex); | 	mutex_init(&priv->mutex); | ||||||
| 
 | 
 | ||||||
| 	INIT_LIST_HEAD(&priv->calib_results); | 	INIT_LIST_HEAD(&priv->calib_results); | ||||||
| 
 | 
 | ||||||
| 	priv->ieee_channels = NULL; |  | ||||||
| 	priv->ieee_rates = NULL; |  | ||||||
| 	priv->band = IEEE80211_BAND_2GHZ; | 	priv->band = IEEE80211_BAND_2GHZ; | ||||||
| 
 | 
 | ||||||
| 	priv->plcp_delta_threshold = | 	priv->plcp_delta_threshold = | ||||||
|  | @ -1370,31 +1165,11 @@ int iwl_init_drv(struct iwl_priv *priv) | ||||||
| 		priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; | 		priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ret = iwl_init_channel_map(priv); |  | ||||||
| 	if (ret) { |  | ||||||
| 		IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); |  | ||||||
| 		goto err; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	ret = iwl_init_geos(priv); |  | ||||||
| 	if (ret) { |  | ||||||
| 		IWL_ERR(priv, "initializing geos failed: %d\n", ret); |  | ||||||
| 		goto err_free_channel_map; |  | ||||||
| 	} |  | ||||||
| 	iwl_init_hw_rates(priv->ieee_rates); |  | ||||||
| 
 |  | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 |  | ||||||
| err_free_channel_map: |  | ||||||
| 	iwl_free_channel_map(priv); |  | ||||||
| err: |  | ||||||
| 	return ret; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_uninit_drv(struct iwl_priv *priv) | static void iwl_uninit_drv(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	iwl_free_geos(priv); |  | ||||||
| 	iwl_free_channel_map(priv); |  | ||||||
| 	kfree(priv->scan_cmd); | 	kfree(priv->scan_cmd); | ||||||
| 	kfree(priv->beacon_cmd); | 	kfree(priv->beacon_cmd); | ||||||
| 	kfree(rcu_dereference_raw(priv->noa_data)); | 	kfree(rcu_dereference_raw(priv->noa_data)); | ||||||
|  | @ -1404,7 +1179,7 @@ void iwl_uninit_drv(struct iwl_priv *priv) | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_set_hw_params(struct iwl_priv *priv) | static void iwl_set_hw_params(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	if (priv->cfg->ht_params) | 	if (priv->cfg->ht_params) | ||||||
| 		priv->hw_params.use_rts_for_aggregation = | 		priv->hw_params.use_rts_for_aggregation = | ||||||
|  | @ -1420,7 +1195,7 @@ void iwl_set_hw_params(struct iwl_priv *priv) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* show what optional capabilities we have */ | /* show what optional capabilities we have */ | ||||||
| void iwl_option_config(struct iwl_priv *priv) | static void iwl_option_config(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| #ifdef CONFIG_IWLWIFI_DEBUG | #ifdef CONFIG_IWLWIFI_DEBUG | ||||||
| 	IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n"); | 	IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n"); | ||||||
|  | @ -1453,6 +1228,42 @@ void iwl_option_config(struct iwl_priv *priv) | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | ||||||
|  | { | ||||||
|  | 	u16 radio_cfg; | ||||||
|  | 
 | ||||||
|  | 	priv->hw_params.sku = priv->eeprom_data->sku; | ||||||
|  | 
 | ||||||
|  | 	if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE && | ||||||
|  | 	    !priv->cfg->ht_params) { | ||||||
|  | 		IWL_ERR(priv, "Invalid 11n configuration\n"); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!priv->hw_params.sku) { | ||||||
|  | 		IWL_ERR(priv, "Invalid device sku\n"); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	IWL_INFO(priv, "Device SKU: 0x%X\n", priv->hw_params.sku); | ||||||
|  | 
 | ||||||
|  | 	radio_cfg = priv->eeprom_data->radio_cfg; | ||||||
|  | 
 | ||||||
|  | 	priv->hw_params.tx_chains_num = | ||||||
|  | 		num_of_ant(priv->eeprom_data->valid_tx_ant); | ||||||
|  | 	if (priv->cfg->rx_with_siso_diversity) | ||||||
|  | 		priv->hw_params.rx_chains_num = 1; | ||||||
|  | 	else | ||||||
|  | 		priv->hw_params.rx_chains_num = | ||||||
|  | 			num_of_ant(priv->eeprom_data->valid_rx_ant); | ||||||
|  | 
 | ||||||
|  | 	IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", | ||||||
|  | 		 priv->eeprom_data->valid_tx_ant, | ||||||
|  | 		 priv->eeprom_data->valid_rx_ant); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | ||||||
| 						 const struct iwl_cfg *cfg, | 						 const struct iwl_cfg *cfg, | ||||||
| 						 const struct iwl_fw *fw) | 						 const struct iwl_fw *fw) | ||||||
|  | @ -1538,7 +1349,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | ||||||
| 		trans_cfg.queue_watchdog_timeout = | 		trans_cfg.queue_watchdog_timeout = | ||||||
| 			priv->cfg->base_params->wd_timeout; | 			priv->cfg->base_params->wd_timeout; | ||||||
| 	else | 	else | ||||||
| 		trans_cfg.queue_watchdog_timeout = IWL_WATCHHDOG_DISABLED; | 		trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED; | ||||||
| 	trans_cfg.command_names = iwl_dvm_cmd_strings; | 	trans_cfg.command_names = iwl_dvm_cmd_strings; | ||||||
| 
 | 
 | ||||||
| 	ucode_flags = fw->ucode_capa.flags; | 	ucode_flags = fw->ucode_capa.flags; | ||||||
|  | @ -1598,25 +1409,33 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | ||||||
| 		goto out_free_hw; | 		goto out_free_hw; | ||||||
| 
 | 
 | ||||||
| 	/* Read the EEPROM */ | 	/* Read the EEPROM */ | ||||||
| 	if (iwl_eeprom_init(priv, priv->trans->hw_rev)) { | 	if (iwl_read_eeprom(priv->trans, &priv->eeprom_blob, | ||||||
|  | 			    &priv->eeprom_blob_size)) { | ||||||
| 		IWL_ERR(priv, "Unable to init EEPROM\n"); | 		IWL_ERR(priv, "Unable to init EEPROM\n"); | ||||||
| 		goto out_free_hw; | 		goto out_free_hw; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	/* Reset chip to save power until we load uCode during "up". */ | 	/* Reset chip to save power until we load uCode during "up". */ | ||||||
| 	iwl_trans_stop_hw(priv->trans, false); | 	iwl_trans_stop_hw(priv->trans, false); | ||||||
| 
 | 
 | ||||||
| 	if (iwl_eeprom_check_version(priv)) | 	priv->eeprom_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg, | ||||||
|  | 						  priv->eeprom_blob, | ||||||
|  | 						  priv->eeprom_blob_size); | ||||||
|  | 	if (!priv->eeprom_data) | ||||||
|  | 		goto out_free_eeprom_blob; | ||||||
|  | 
 | ||||||
|  | 	if (iwl_eeprom_check_version(priv->eeprom_data, priv->trans)) | ||||||
| 		goto out_free_eeprom; | 		goto out_free_eeprom; | ||||||
| 
 | 
 | ||||||
| 	if (iwl_eeprom_init_hw_params(priv)) | 	if (iwl_eeprom_init_hw_params(priv)) | ||||||
| 		goto out_free_eeprom; | 		goto out_free_eeprom; | ||||||
| 
 | 
 | ||||||
| 	/* extract MAC Address */ | 	/* extract MAC Address */ | ||||||
| 	iwl_eeprom_get_mac(priv, priv->addresses[0].addr); | 	memcpy(priv->addresses[0].addr, priv->eeprom_data->hw_addr, ETH_ALEN); | ||||||
| 	IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); | 	IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); | ||||||
| 	priv->hw->wiphy->addresses = priv->addresses; | 	priv->hw->wiphy->addresses = priv->addresses; | ||||||
| 	priv->hw->wiphy->n_addresses = 1; | 	priv->hw->wiphy->n_addresses = 1; | ||||||
| 	num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS); | 	num_mac = priv->eeprom_data->n_hw_addrs; | ||||||
| 	if (num_mac > 1) { | 	if (num_mac > 1) { | ||||||
| 		memcpy(priv->addresses[1].addr, priv->addresses[0].addr, | 		memcpy(priv->addresses[1].addr, priv->addresses[0].addr, | ||||||
| 		       ETH_ALEN); | 		       ETH_ALEN); | ||||||
|  | @ -1710,8 +1529,10 @@ out_destroy_workqueue: | ||||||
| 	destroy_workqueue(priv->workqueue); | 	destroy_workqueue(priv->workqueue); | ||||||
| 	priv->workqueue = NULL; | 	priv->workqueue = NULL; | ||||||
| 	iwl_uninit_drv(priv); | 	iwl_uninit_drv(priv); | ||||||
|  | out_free_eeprom_blob: | ||||||
|  | 	kfree(priv->eeprom_blob); | ||||||
| out_free_eeprom: | out_free_eeprom: | ||||||
| 	iwl_eeprom_free(priv); | 	iwl_free_eeprom_data(priv->eeprom_data); | ||||||
| out_free_hw: | out_free_hw: | ||||||
| 	ieee80211_free_hw(priv->hw); | 	ieee80211_free_hw(priv->hw); | ||||||
| out: | out: | ||||||
|  | @ -1719,7 +1540,7 @@ out: | ||||||
| 	return op_mode; | 	return op_mode; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||||||
| 
 | 
 | ||||||
|  | @ -1736,7 +1557,8 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | ||||||
| 	priv->ucode_loaded = false; | 	priv->ucode_loaded = false; | ||||||
| 	iwl_trans_stop_device(priv->trans); | 	iwl_trans_stop_device(priv->trans); | ||||||
| 
 | 
 | ||||||
| 	iwl_eeprom_free(priv); | 	kfree(priv->eeprom_blob); | ||||||
|  | 	iwl_free_eeprom_data(priv->eeprom_data); | ||||||
| 
 | 
 | ||||||
| 	/*netif_stop_queue(dev); */ | 	/*netif_stop_queue(dev); */ | ||||||
| 	flush_workqueue(priv->workqueue); | 	flush_workqueue(priv->workqueue); | ||||||
|  | @ -2184,7 +2006,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_nic_error(struct iwl_op_mode *op_mode) | static void iwl_nic_error(struct iwl_op_mode *op_mode) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||||||
| 
 | 
 | ||||||
|  | @ -2197,7 +2019,7 @@ void iwl_nic_error(struct iwl_op_mode *op_mode) | ||||||
| 	iwlagn_fw_error(priv, false); | 	iwlagn_fw_error(priv, false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) | static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||||||
| 
 | 
 | ||||||
|  | @ -2207,9 +2029,49 @@ void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_nic_config(struct iwl_op_mode *op_mode) | #define EEPROM_RF_CONFIG_TYPE_MAX      0x3 | ||||||
|  | 
 | ||||||
|  | static void iwl_nic_config(struct iwl_op_mode *op_mode) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||||||
|  | 	u16 radio_cfg = priv->eeprom_data->radio_cfg; | ||||||
|  | 
 | ||||||
|  | 	/* SKU Control */ | ||||||
|  | 	iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, | ||||||
|  | 			  CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH | | ||||||
|  | 			  CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP, | ||||||
|  | 			  (CSR_HW_REV_STEP(priv->trans->hw_rev) << | ||||||
|  | 				CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) | | ||||||
|  | 			  (CSR_HW_REV_DASH(priv->trans->hw_rev) << | ||||||
|  | 				CSR_HW_IF_CONFIG_REG_POS_MAC_DASH)); | ||||||
|  | 
 | ||||||
|  | 	/* write radio config values to register */ | ||||||
|  | 	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) { | ||||||
|  | 		u32 reg_val = | ||||||
|  | 			EEPROM_RF_CFG_TYPE_MSK(radio_cfg) << | ||||||
|  | 				CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE | | ||||||
|  | 			EEPROM_RF_CFG_STEP_MSK(radio_cfg) << | ||||||
|  | 				CSR_HW_IF_CONFIG_REG_POS_PHY_STEP | | ||||||
|  | 			EEPROM_RF_CFG_DASH_MSK(radio_cfg) << | ||||||
|  | 				CSR_HW_IF_CONFIG_REG_POS_PHY_DASH; | ||||||
|  | 
 | ||||||
|  | 		iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, | ||||||
|  | 				  CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE | | ||||||
|  | 				  CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP | | ||||||
|  | 				  CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val); | ||||||
|  | 
 | ||||||
|  | 		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->trans, CSR_HW_IF_CONFIG_REG, | ||||||
|  | 		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||||||
|  | 		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||||||
| 
 | 
 | ||||||
| 	priv->lib->nic_config(priv); | 	priv->lib->nic_config(priv); | ||||||
| } | } | ||||||
|  | @ -2222,7 +2084,7 @@ static void iwl_wimax_active(struct iwl_op_mode *op_mode) | ||||||
| 	IWL_ERR(priv, "RF is used by WiMAX\n"); | 	IWL_ERR(priv, "RF is used by WiMAX\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||||||
| 	int mq = priv->queue_to_mac80211[queue]; | 	int mq = priv->queue_to_mac80211[queue]; | ||||||
|  | @ -2241,7 +2103,7 @@ void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | ||||||
| 	ieee80211_stop_queue(priv->hw, mq); | 	ieee80211_stop_queue(priv->hw, mq); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) | static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||||||
| 	int mq = priv->queue_to_mac80211[queue]; | 	int mq = priv->queue_to_mac80211[queue]; | ||||||
|  | @ -2281,16 +2143,17 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv) | ||||||
| 	priv->passive_no_rx = false; | 	priv->passive_no_rx = false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | ||||||
| { | { | ||||||
|  | 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||||||
| 	struct ieee80211_tx_info *info; | 	struct ieee80211_tx_info *info; | ||||||
| 
 | 
 | ||||||
| 	info = IEEE80211_SKB_CB(skb); | 	info = IEEE80211_SKB_CB(skb); | ||||||
| 	kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); | 	iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); | ||||||
| 	dev_kfree_skb_any(skb); | 	dev_kfree_skb_any(skb); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | ||||||
| { | { | ||||||
| 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 	struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||||||
| 
 | 
 | ||||||
|  | @ -2302,7 +2165,7 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | ||||||
| 	wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); | 	wiphy_rfkill_set_hw_state(priv->hw->wiphy, state); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const struct iwl_op_mode_ops iwl_dvm_ops = { | static const struct iwl_op_mode_ops iwl_dvm_ops = { | ||||||
| 	.start = iwl_op_mode_dvm_start, | 	.start = iwl_op_mode_dvm_start, | ||||||
| 	.stop = iwl_op_mode_dvm_stop, | 	.stop = iwl_op_mode_dvm_stop, | ||||||
| 	.rx = iwl_rx_dispatch, | 	.rx = iwl_rx_dispatch, | ||||||
|  | @ -2321,9 +2184,6 @@ const struct iwl_op_mode_ops iwl_dvm_ops = { | ||||||
|  * driver and module entry point |  * driver and module entry point | ||||||
|  * |  * | ||||||
|  *****************************************************************************/ |  *****************************************************************************/ | ||||||
| 
 |  | ||||||
| struct kmem_cache *iwl_tx_cmd_pool; |  | ||||||
| 
 |  | ||||||
| static int __init iwl_init(void) | static int __init iwl_init(void) | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | @ -2331,29 +2191,18 @@ static int __init iwl_init(void) | ||||||
| 	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); | 	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); | ||||||
| 	pr_info(DRV_COPYRIGHT "\n"); | 	pr_info(DRV_COPYRIGHT "\n"); | ||||||
| 
 | 
 | ||||||
| 	iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd", |  | ||||||
| 					    sizeof(struct iwl_device_cmd), |  | ||||||
| 					    sizeof(void *), 0, NULL); |  | ||||||
| 	if (!iwl_tx_cmd_pool) |  | ||||||
| 		return -ENOMEM; |  | ||||||
| 
 |  | ||||||
| 	ret = iwlagn_rate_control_register(); | 	ret = iwlagn_rate_control_register(); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		pr_err("Unable to register rate control algorithm: %d\n", ret); | 		pr_err("Unable to register rate control algorithm: %d\n", ret); | ||||||
| 		goto error_rc_register; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops); | 	ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		pr_err("Unable to register op_mode: %d\n", ret); | 		pr_err("Unable to register op_mode: %d\n", ret); | ||||||
| 		goto error_opmode_register; |  | ||||||
| 	} |  | ||||||
| 	return ret; |  | ||||||
| 
 |  | ||||||
| error_opmode_register: |  | ||||||
| 		iwlagn_rate_control_unregister(); | 		iwlagn_rate_control_unregister(); | ||||||
| error_rc_register: | 	} | ||||||
| 	kmem_cache_destroy(iwl_tx_cmd_pool); | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| module_init(iwl_init); | module_init(iwl_init); | ||||||
|  | @ -2362,6 +2211,5 @@ static void __exit iwl_exit(void) | ||||||
| { | { | ||||||
| 	iwl_opmode_deregister("iwldvm"); | 	iwl_opmode_deregister("iwldvm"); | ||||||
| 	iwlagn_rate_control_unregister(); | 	iwlagn_rate_control_unregister(); | ||||||
| 	kmem_cache_destroy(iwl_tx_cmd_pool); |  | ||||||
| } | } | ||||||
| module_exit(iwl_exit); | module_exit(iwl_exit); | ||||||
|  | @ -31,18 +31,15 @@ | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
| 
 |  | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| 
 |  | ||||||
| #include "iwl-eeprom.h" |  | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-commands.h" |  | ||||||
| #include "iwl-debug.h" | #include "iwl-debug.h" | ||||||
| #include "iwl-power.h" |  | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-modparams.h" | #include "iwl-modparams.h" | ||||||
|  | #include "dev.h" | ||||||
|  | #include "agn.h" | ||||||
|  | #include "commands.h" | ||||||
|  | #include "power.h" | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Setting power level allows the card to go to sleep when not busy. |  * Setting power level allows the card to go to sleep when not busy. | ||||||
|  | @ -28,7 +28,7 @@ | ||||||
| #ifndef __iwl_power_setting_h__ | #ifndef __iwl_power_setting_h__ | ||||||
| #define __iwl_power_setting_h__ | #define __iwl_power_setting_h__ | ||||||
| 
 | 
 | ||||||
| #include "iwl-commands.h" | #include "commands.h" | ||||||
| 
 | 
 | ||||||
| struct iwl_power_mgr { | struct iwl_power_mgr { | ||||||
| 	struct iwl_powertable_cmd sleep_cmd; | 	struct iwl_powertable_cmd sleep_cmd; | ||||||
|  | @ -35,10 +35,8 @@ | ||||||
| 
 | 
 | ||||||
| #include <linux/workqueue.h> | #include <linux/workqueue.h> | ||||||
| 
 | 
 | ||||||
| #include "iwl-dev.h" | #include "dev.h" | ||||||
| #include "iwl-agn.h" | #include "agn.h" | ||||||
| #include "iwl-op-mode.h" |  | ||||||
| #include "iwl-modparams.h" |  | ||||||
| 
 | 
 | ||||||
| #define RS_NAME "iwl-agn-rs" | #define RS_NAME "iwl-agn-rs" | ||||||
| 
 | 
 | ||||||
|  | @ -819,7 +817,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, | ||||||
| 
 | 
 | ||||||
| 		if (num_of_ant(tbl->ant_type) > 1) | 		if (num_of_ant(tbl->ant_type) > 1) | ||||||
| 			tbl->ant_type = | 			tbl->ant_type = | ||||||
| 			    first_antenna(priv->hw_params.valid_tx_ant); | 			    first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 
 | 
 | ||||||
| 		tbl->is_ht40 = 0; | 		tbl->is_ht40 = 0; | ||||||
| 		tbl->is_SGI = 0; | 		tbl->is_SGI = 0; | ||||||
|  | @ -1447,7 +1445,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | ||||||
| 	u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 	u32 sz = (sizeof(struct iwl_scale_tbl_info) - | ||||||
| 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | ||||||
| 	u8 start_action; | 	u8 start_action; | ||||||
| 	u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 	u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; | ||||||
| 	u8 tx_chains_num = priv->hw_params.tx_chains_num; | 	u8 tx_chains_num = priv->hw_params.tx_chains_num; | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
| 	u8 update_search_tbl_counter = 0; | 	u8 update_search_tbl_counter = 0; | ||||||
|  | @ -1465,7 +1463,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | ||||||
| 	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||||||
| 		/* avoid antenna B and MIMO */ | 		/* avoid antenna B and MIMO */ | ||||||
| 		valid_tx_ant = | 		valid_tx_ant = | ||||||
| 			first_antenna(priv->hw_params.valid_tx_ant); | 			first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 		if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && | 		if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2 && | ||||||
| 		    tbl->action != IWL_LEGACY_SWITCH_SISO) | 		    tbl->action != IWL_LEGACY_SWITCH_SISO) | ||||||
| 			tbl->action = IWL_LEGACY_SWITCH_SISO; | 			tbl->action = IWL_LEGACY_SWITCH_SISO; | ||||||
|  | @ -1489,7 +1487,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | ||||||
| 		else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | 		else if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | ||||||
| 			tbl->action = IWL_LEGACY_SWITCH_SISO; | 			tbl->action = IWL_LEGACY_SWITCH_SISO; | ||||||
| 		valid_tx_ant = | 		valid_tx_ant = | ||||||
| 			first_antenna(priv->hw_params.valid_tx_ant); | 			first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	start_action = tbl->action; | 	start_action = tbl->action; | ||||||
|  | @ -1623,7 +1621,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | ||||||
| 	u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 	u32 sz = (sizeof(struct iwl_scale_tbl_info) - | ||||||
| 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | ||||||
| 	u8 start_action; | 	u8 start_action; | ||||||
| 	u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 	u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; | ||||||
| 	u8 tx_chains_num = priv->hw_params.tx_chains_num; | 	u8 tx_chains_num = priv->hw_params.tx_chains_num; | ||||||
| 	u8 update_search_tbl_counter = 0; | 	u8 update_search_tbl_counter = 0; | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -1641,7 +1639,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | ||||||
| 	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | 	case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS: | ||||||
| 		/* avoid antenna B and MIMO */ | 		/* avoid antenna B and MIMO */ | ||||||
| 		valid_tx_ant = | 		valid_tx_ant = | ||||||
| 			first_antenna(priv->hw_params.valid_tx_ant); | 			first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 		if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) | 		if (tbl->action != IWL_SISO_SWITCH_ANTENNA1) | ||||||
| 			tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 			tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||||||
| 		break; | 		break; | ||||||
|  | @ -1659,7 +1657,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | ||||||
| 	/* configure as 1x1 if bt full concurrency */ | 	/* configure as 1x1 if bt full concurrency */ | ||||||
| 	if (priv->bt_full_concurrent) { | 	if (priv->bt_full_concurrent) { | ||||||
| 		valid_tx_ant = | 		valid_tx_ant = | ||||||
| 			first_antenna(priv->hw_params.valid_tx_ant); | 			first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 		if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | 		if (tbl->action >= IWL_LEGACY_SWITCH_ANTENNA2) | ||||||
| 			tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 			tbl->action = IWL_SISO_SWITCH_ANTENNA1; | ||||||
| 	} | 	} | ||||||
|  | @ -1795,7 +1793,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | ||||||
| 	u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 	u32 sz = (sizeof(struct iwl_scale_tbl_info) - | ||||||
| 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | ||||||
| 	u8 start_action; | 	u8 start_action; | ||||||
| 	u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 	u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; | ||||||
| 	u8 tx_chains_num = priv->hw_params.tx_chains_num; | 	u8 tx_chains_num = priv->hw_params.tx_chains_num; | ||||||
| 	u8 update_search_tbl_counter = 0; | 	u8 update_search_tbl_counter = 0; | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -1965,7 +1963,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | ||||||
| 	u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 	u32 sz = (sizeof(struct iwl_scale_tbl_info) - | ||||||
| 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | ||||||
| 	u8 start_action; | 	u8 start_action; | ||||||
| 	u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 	u8 valid_tx_ant = priv->eeprom_data->valid_tx_ant; | ||||||
| 	u8 tx_chains_num = priv->hw_params.tx_chains_num; | 	u8 tx_chains_num = priv->hw_params.tx_chains_num; | ||||||
| 	int ret; | 	int ret; | ||||||
| 	u8 update_search_tbl_counter = 0; | 	u8 update_search_tbl_counter = 0; | ||||||
|  | @ -2699,7 +2697,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, | ||||||
| 
 | 
 | ||||||
| 	i = lq_sta->last_txrate_idx; | 	i = lq_sta->last_txrate_idx; | ||||||
| 
 | 
 | ||||||
| 	valid_tx_ant = priv->hw_params.valid_tx_ant; | 	valid_tx_ant = priv->eeprom_data->valid_tx_ant; | ||||||
| 
 | 
 | ||||||
| 	if (!lq_sta->search_better_tbl) | 	if (!lq_sta->search_better_tbl) | ||||||
| 		active_tbl = lq_sta->active_tbl; | 		active_tbl = lq_sta->active_tbl; | ||||||
|  | @ -2893,15 +2891,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i | ||||||
| 
 | 
 | ||||||
| 	/* These values will be overridden later */ | 	/* These values will be overridden later */ | ||||||
| 	lq_sta->lq.general_params.single_stream_ant_msk = | 	lq_sta->lq.general_params.single_stream_ant_msk = | ||||||
| 		first_antenna(priv->hw_params.valid_tx_ant); | 		first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 	lq_sta->lq.general_params.dual_stream_ant_msk = | 	lq_sta->lq.general_params.dual_stream_ant_msk = | ||||||
| 		priv->hw_params.valid_tx_ant & | 		priv->eeprom_data->valid_tx_ant & | ||||||
| 		~first_antenna(priv->hw_params.valid_tx_ant); | 		~first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 	if (!lq_sta->lq.general_params.dual_stream_ant_msk) { | 	if (!lq_sta->lq.general_params.dual_stream_ant_msk) { | ||||||
| 		lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; | 		lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; | ||||||
| 	} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | 	} else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) { | ||||||
| 		lq_sta->lq.general_params.dual_stream_ant_msk = | 		lq_sta->lq.general_params.dual_stream_ant_msk = | ||||||
| 			priv->hw_params.valid_tx_ant; | 			priv->eeprom_data->valid_tx_ant; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* as default allow aggregation for all tids */ | 	/* as default allow aggregation for all tids */ | ||||||
|  | @ -2947,7 +2945,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | ||||||
| 	if (priv && priv->bt_full_concurrent) { | 	if (priv && priv->bt_full_concurrent) { | ||||||
| 		/* 1x1 only */ | 		/* 1x1 only */ | ||||||
| 		tbl_type.ant_type = | 		tbl_type.ant_type = | ||||||
| 			first_antenna(priv->hw_params.valid_tx_ant); | 			first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* How many times should we repeat the initial rate? */ | 	/* How many times should we repeat the initial rate? */ | ||||||
|  | @ -2979,7 +2977,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | ||||||
| 		if (priv->bt_full_concurrent) | 		if (priv->bt_full_concurrent) | ||||||
| 			valid_tx_ant = ANT_A; | 			valid_tx_ant = ANT_A; | ||||||
| 		else | 		else | ||||||
| 			valid_tx_ant = priv->hw_params.valid_tx_ant; | 			valid_tx_ant = priv->eeprom_data->valid_tx_ant; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Fill rest of rate table */ | 	/* Fill rest of rate table */ | ||||||
|  | @ -3013,7 +3011,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | ||||||
| 		if (priv && priv->bt_full_concurrent) { | 		if (priv && priv->bt_full_concurrent) { | ||||||
| 			/* 1x1 only */ | 			/* 1x1 only */ | ||||||
| 			tbl_type.ant_type = | 			tbl_type.ant_type = | ||||||
| 			    first_antenna(priv->hw_params.valid_tx_ant); | 			    first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		/* Indicate to uCode which entries might be MIMO.
 | 		/* Indicate to uCode which entries might be MIMO.
 | ||||||
|  | @ -3100,7 +3098,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | ||||||
| 	u8 ant_sel_tx; | 	u8 ant_sel_tx; | ||||||
| 
 | 
 | ||||||
| 	priv = lq_sta->drv; | 	priv = lq_sta->drv; | ||||||
| 	valid_tx_ant = priv->hw_params.valid_tx_ant; | 	valid_tx_ant = priv->eeprom_data->valid_tx_ant; | ||||||
| 	if (lq_sta->dbg_fixed_rate) { | 	if (lq_sta->dbg_fixed_rate) { | ||||||
| 		ant_sel_tx = | 		ant_sel_tx = | ||||||
| 		  ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) | 		  ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) | ||||||
|  | @ -3171,9 +3169,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | ||||||
| 	desc += sprintf(buff+desc, "fixed rate 0x%X\n", | 	desc += sprintf(buff+desc, "fixed rate 0x%X\n", | ||||||
| 			lq_sta->dbg_fixed_rate); | 			lq_sta->dbg_fixed_rate); | ||||||
| 	desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", | 	desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", | ||||||
| 	    (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", | 	    (priv->eeprom_data->valid_tx_ant & ANT_A) ? "ANT_A," : "", | ||||||
| 	    (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", | 	    (priv->eeprom_data->valid_tx_ant & ANT_B) ? "ANT_B," : "", | ||||||
| 	    (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); | 	    (priv->eeprom_data->valid_tx_ant & ANT_C) ? "ANT_C" : ""); | ||||||
| 	desc += sprintf(buff+desc, "lq type %s\n", | 	desc += sprintf(buff+desc, "lq type %s\n", | ||||||
| 	   (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | 	   (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); | ||||||
| 	if (is_Ht(tbl->lq_type)) { | 	if (is_Ht(tbl->lq_type)) { | ||||||
|  | @ -29,9 +29,10 @@ | ||||||
| 
 | 
 | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| 
 | 
 | ||||||
| #include "iwl-commands.h" |  | ||||||
| #include "iwl-config.h" | #include "iwl-config.h" | ||||||
| 
 | 
 | ||||||
|  | #include "commands.h" | ||||||
|  | 
 | ||||||
| struct iwl_rate_info { | struct iwl_rate_info { | ||||||
| 	u8 plcp;	/* uCode API:  IWL_RATE_6M_PLCP, etc. */ | 	u8 plcp;	/* uCode API:  IWL_RATE_6M_PLCP, etc. */ | ||||||
| 	u8 plcp_siso;	/* uCode API:  IWL_RATE_SISO_6M_PLCP, etc. */ | 	u8 plcp_siso;	/* uCode API:  IWL_RATE_SISO_6M_PLCP, etc. */ | ||||||
|  | @ -32,12 +32,10 @@ | ||||||
| #include <linux/sched.h> | #include <linux/sched.h> | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| #include <asm/unaligned.h> | #include <asm/unaligned.h> | ||||||
| #include "iwl-eeprom.h" |  | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-agn-calib.h" | #include "dev.h" | ||||||
| #include "iwl-agn.h" | #include "calib.h" | ||||||
| #include "iwl-modparams.h" | #include "agn.h" | ||||||
| 
 | 
 | ||||||
| #define IWL_CMD_ENTRY(x) [x] = #x | #define IWL_CMD_ENTRY(x) [x] = #x | ||||||
| 
 | 
 | ||||||
|  | @ -1012,6 +1010,8 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, | ||||||
| 		rx_status.flag |= RX_FLAG_40MHZ; | 		rx_status.flag |= RX_FLAG_40MHZ; | ||||||
| 	if (rate_n_flags & RATE_MCS_SGI_MSK) | 	if (rate_n_flags & RATE_MCS_SGI_MSK) | ||||||
| 		rx_status.flag |= RX_FLAG_SHORT_GI; | 		rx_status.flag |= RX_FLAG_SHORT_GI; | ||||||
|  | 	if (rate_n_flags & RATE_MCS_GF_MSK) | ||||||
|  | 		rx_status.flag |= RX_FLAG_HT_GF; | ||||||
| 
 | 
 | ||||||
| 	iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, | 	iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||||||
| 				    rxb, &rx_status); | 				    rxb, &rx_status); | ||||||
|  | @ -25,11 +25,11 @@ | ||||||
|  *****************************************************************************/ |  *****************************************************************************/ | ||||||
| 
 | 
 | ||||||
| #include <linux/etherdevice.h> | #include <linux/etherdevice.h> | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-agn-calib.h" |  | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-modparams.h" | #include "iwl-modparams.h" | ||||||
|  | #include "dev.h" | ||||||
|  | #include "agn.h" | ||||||
|  | #include "calib.h" | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * initialize rxon structure with default values from eeprom |  * initialize rxon structure with default values from eeprom | ||||||
|  | @ -37,8 +37,6 @@ | ||||||
| void iwl_connection_init_rx_config(struct iwl_priv *priv, | void iwl_connection_init_rx_config(struct iwl_priv *priv, | ||||||
| 				   struct iwl_rxon_context *ctx) | 				   struct iwl_rxon_context *ctx) | ||||||
| { | { | ||||||
| 	const struct iwl_channel_info *ch_info; |  | ||||||
| 
 |  | ||||||
| 	memset(&ctx->staging, 0, sizeof(ctx->staging)); | 	memset(&ctx->staging, 0, sizeof(ctx->staging)); | ||||||
| 
 | 
 | ||||||
| 	if (!ctx->vif) { | 	if (!ctx->vif) { | ||||||
|  | @ -80,14 +78,8 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | ||||||
| 		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | 		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	ch_info = iwl_get_channel_info(priv, priv->band, | 	ctx->staging.channel = cpu_to_le16(priv->hw->conf.channel->hw_value); | ||||||
| 				       le16_to_cpu(ctx->active.channel)); | 	priv->band = priv->hw->conf.channel->band; | ||||||
| 
 |  | ||||||
| 	if (!ch_info) |  | ||||||
| 		ch_info = &priv->channel_info[0]; |  | ||||||
| 
 |  | ||||||
| 	ctx->staging.channel = cpu_to_le16(ch_info->channel); |  | ||||||
| 	priv->band = ch_info->band; |  | ||||||
| 
 | 
 | ||||||
| 	iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); | 	iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); | ||||||
| 
 | 
 | ||||||
|  | @ -175,7 +167,8 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv, | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | static void iwlagn_update_qos(struct iwl_priv *priv, | ||||||
|  | 			      struct iwl_rxon_context *ctx) | ||||||
| { | { | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -202,7 +195,7 @@ void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | ||||||
| 		IWL_DEBUG_QUIET_RFKILL(priv, "Failed to update QoS\n"); | 		IWL_DEBUG_QUIET_RFKILL(priv, "Failed to update QoS\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwlagn_update_beacon(struct iwl_priv *priv, | static int iwlagn_update_beacon(struct iwl_priv *priv, | ||||||
| 				struct ieee80211_vif *vif) | 				struct ieee80211_vif *vif) | ||||||
| { | { | ||||||
| 	lockdep_assert_held(&priv->mutex); | 	lockdep_assert_held(&priv->mutex); | ||||||
|  | @ -427,10 +420,10 @@ static int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (tx_power > priv->tx_power_device_lmt) { | 	if (tx_power > DIV_ROUND_UP(priv->eeprom_data->max_tx_pwr_half_dbm, 2)) { | ||||||
| 		IWL_WARN(priv, | 		IWL_WARN(priv, | ||||||
| 			"Requested user TXPOWER %d above upper limit %d.\n", | 			"Requested user TXPOWER %d above upper limit %d.\n", | ||||||
| 			 tx_power, priv->tx_power_device_lmt); | 			 tx_power, priv->eeprom_data->max_tx_pwr_half_dbm); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -863,7 +856,7 @@ static int iwl_check_rxon_cmd(struct iwl_priv *priv, | ||||||
|  * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that |  * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that | ||||||
|  * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. |  * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. | ||||||
|  */ |  */ | ||||||
| int iwl_full_rxon_required(struct iwl_priv *priv, | static int iwl_full_rxon_required(struct iwl_priv *priv, | ||||||
| 				  struct iwl_rxon_context *ctx) | 				  struct iwl_rxon_context *ctx) | ||||||
| { | { | ||||||
| 	const struct iwl_rxon_cmd *staging = &ctx->staging; | 	const struct iwl_rxon_cmd *staging = &ctx->staging; | ||||||
|  | @ -1189,7 +1182,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | ||||||
| 	struct iwl_rxon_context *ctx; | 	struct iwl_rxon_context *ctx; | ||||||
| 	struct ieee80211_conf *conf = &hw->conf; | 	struct ieee80211_conf *conf = &hw->conf; | ||||||
| 	struct ieee80211_channel *channel = conf->channel; | 	struct ieee80211_channel *channel = conf->channel; | ||||||
| 	const struct iwl_channel_info *ch_info; |  | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
| 
 | 
 | ||||||
| 	IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed); | 	IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed); | ||||||
|  | @ -1223,14 +1215,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||||||
| 		ch_info = iwl_get_channel_info(priv, channel->band, |  | ||||||
| 					       channel->hw_value); |  | ||||||
| 		if (!is_channel_valid(ch_info)) { |  | ||||||
| 			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); |  | ||||||
| 			ret = -EINVAL; |  | ||||||
| 			goto out; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		for_each_context(priv, ctx) { | 		for_each_context(priv, ctx) { | ||||||
| 			/* Configure HT40 channels */ | 			/* Configure HT40 channels */ | ||||||
| 			if (ctx->ht.enabled != conf_is_ht(conf)) | 			if (ctx->ht.enabled != conf_is_ht(conf)) | ||||||
|  | @ -1294,7 +1278,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_check_needed_chains(struct iwl_priv *priv, | static void iwlagn_check_needed_chains(struct iwl_priv *priv, | ||||||
| 				       struct iwl_rxon_context *ctx, | 				       struct iwl_rxon_context *ctx, | ||||||
| 				       struct ieee80211_bss_conf *bss_conf) | 				       struct ieee80211_bss_conf *bss_conf) | ||||||
| { | { | ||||||
|  | @ -1388,7 +1372,7 @@ void iwlagn_check_needed_chains(struct iwl_priv *priv, | ||||||
| 	ht_conf->single_chain_sufficient = !need_multiple; | 	ht_conf->single_chain_sufficient = !need_multiple; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwlagn_chain_noise_reset(struct iwl_priv *priv) | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 	struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -30,11 +30,8 @@ | ||||||
| #include <linux/etherdevice.h> | #include <linux/etherdevice.h> | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| 
 | 
 | ||||||
| #include "iwl-eeprom.h" | #include "dev.h" | ||||||
| #include "iwl-dev.h" | #include "agn.h" | ||||||
| #include "iwl-io.h" |  | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-trans.h" |  | ||||||
| 
 | 
 | ||||||
| /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
 | /* 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 |  * sending probe req.  This should be set long enough to hear probe responses | ||||||
|  | @ -67,7 +64,6 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) | ||||||
| 	 * to receive scan abort command or it does not perform | 	 * to receive scan abort command or it does not perform | ||||||
| 	 * hardware scan currently */ | 	 * hardware scan currently */ | ||||||
| 	if (!test_bit(STATUS_READY, &priv->status) || | 	if (!test_bit(STATUS_READY, &priv->status) || | ||||||
| 	    !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || |  | ||||||
| 	    !test_bit(STATUS_SCAN_HW, &priv->status) || | 	    !test_bit(STATUS_SCAN_HW, &priv->status) || | ||||||
| 	    test_bit(STATUS_FW_ERROR, &priv->status)) | 	    test_bit(STATUS_FW_ERROR, &priv->status)) | ||||||
| 		return -EIO; | 		return -EIO; | ||||||
|  | @ -101,11 +97,8 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) | ||||||
| 		ieee80211_scan_completed(priv->hw, aborted); | 		ieee80211_scan_completed(priv->hw, aborted); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (priv->scan_type == IWL_SCAN_ROC) { | 	if (priv->scan_type == IWL_SCAN_ROC) | ||||||
| 		ieee80211_remain_on_channel_expired(priv->hw); | 		iwl_scan_roc_expired(priv); | ||||||
| 		priv->hw_roc_channel = NULL; |  | ||||||
| 		schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	priv->scan_type = IWL_SCAN_NORMAL; | 	priv->scan_type = IWL_SCAN_NORMAL; | ||||||
| 	priv->scan_vif = NULL; | 	priv->scan_vif = NULL; | ||||||
|  | @ -134,11 +127,8 @@ static void iwl_process_scan_complete(struct iwl_priv *priv) | ||||||
| 		goto out_settings; | 		goto out_settings; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (priv->scan_type == IWL_SCAN_ROC) { | 	if (priv->scan_type == IWL_SCAN_ROC) | ||||||
| 		ieee80211_remain_on_channel_expired(priv->hw); | 		iwl_scan_roc_expired(priv); | ||||||
| 		priv->hw_roc_channel = NULL; |  | ||||||
| 		schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { | 	if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { | ||||||
| 		int err; | 		int err; | ||||||
|  | @ -455,25 +445,15 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | ||||||
| static u8 iwl_get_single_channel_number(struct iwl_priv *priv, | static u8 iwl_get_single_channel_number(struct iwl_priv *priv, | ||||||
| 					enum ieee80211_band band) | 					enum ieee80211_band band) | ||||||
| { | { | ||||||
| 	const struct iwl_channel_info *ch_info; | 	struct ieee80211_supported_band *sband = priv->hw->wiphy->bands[band]; | ||||||
| 	int i; |  | ||||||
| 	u8 channel = 0; |  | ||||||
| 	u8 min, max; |  | ||||||
| 	struct iwl_rxon_context *ctx; | 	struct iwl_rxon_context *ctx; | ||||||
|  | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (band == IEEE80211_BAND_5GHZ) { | 	for (i = 0; i < sband->n_channels; i++) { | ||||||
| 		min = 14; |  | ||||||
| 		max = priv->channel_count; |  | ||||||
| 	} else { |  | ||||||
| 		min = 0; |  | ||||||
| 		max = 14; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for (i = min; i < max; i++) { |  | ||||||
| 		bool busy = false; | 		bool busy = false; | ||||||
| 
 | 
 | ||||||
| 		for_each_context(priv, ctx) { | 		for_each_context(priv, ctx) { | ||||||
| 			busy = priv->channel_info[i].channel == | 			busy = sband->channels[i].hw_value == | ||||||
| 				le16_to_cpu(ctx->staging.channel); | 				le16_to_cpu(ctx->staging.channel); | ||||||
| 			if (busy) | 			if (busy) | ||||||
| 				break; | 				break; | ||||||
|  | @ -482,13 +462,11 @@ static u8 iwl_get_single_channel_number(struct iwl_priv *priv, | ||||||
| 		if (busy) | 		if (busy) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		channel = priv->channel_info[i].channel; | 		if (!(sband->channels[i].flags & IEEE80211_CHAN_DISABLED)) | ||||||
| 		ch_info = iwl_get_channel_info(priv, band, channel); | 			return sband->channels[i].hw_value; | ||||||
| 		if (is_channel_valid(ch_info)) |  | ||||||
| 			break; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return channel; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | ||||||
|  | @ -540,7 +518,6 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | ||||||
| { | { | ||||||
| 	struct ieee80211_channel *chan; | 	struct ieee80211_channel *chan; | ||||||
| 	const struct ieee80211_supported_band *sband; | 	const struct ieee80211_supported_band *sband; | ||||||
| 	const struct iwl_channel_info *ch_info; |  | ||||||
| 	u16 passive_dwell = 0; | 	u16 passive_dwell = 0; | ||||||
| 	u16 active_dwell = 0; | 	u16 active_dwell = 0; | ||||||
| 	int added, i; | 	int added, i; | ||||||
|  | @ -565,16 +542,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | ||||||
| 		channel = chan->hw_value; | 		channel = chan->hw_value; | ||||||
| 		scan_ch->channel = cpu_to_le16(channel); | 		scan_ch->channel = cpu_to_le16(channel); | ||||||
| 
 | 
 | ||||||
| 		ch_info = iwl_get_channel_info(priv, band, channel); | 		if (!is_active || (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) | ||||||
| 		if (!is_channel_valid(ch_info)) { |  | ||||||
| 			IWL_DEBUG_SCAN(priv, |  | ||||||
| 				       "Channel %d is INVALID for this band.\n", |  | ||||||
| 				       channel); |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (!is_active || is_channel_passive(ch_info) || |  | ||||||
| 		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) |  | ||||||
| 			scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | 			scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||||||
| 		else | 		else | ||||||
| 			scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | 			scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | ||||||
|  | @ -678,12 +646,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | ||||||
| 	u16 rx_chain = 0; | 	u16 rx_chain = 0; | ||||||
| 	enum ieee80211_band band; | 	enum ieee80211_band band; | ||||||
| 	u8 n_probes = 0; | 	u8 n_probes = 0; | ||||||
| 	u8 rx_ant = priv->hw_params.valid_rx_ant; | 	u8 rx_ant = priv->eeprom_data->valid_rx_ant; | ||||||
| 	u8 rate; | 	u8 rate; | ||||||
| 	bool is_active = false; | 	bool is_active = false; | ||||||
| 	int  chan_mod; | 	int  chan_mod; | ||||||
| 	u8 active_chains; | 	u8 active_chains; | ||||||
| 	u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; | 	u8 scan_tx_antennas = priv->eeprom_data->valid_tx_ant; | ||||||
| 	int ret; | 	int ret; | ||||||
| 	int scan_cmd_size = sizeof(struct iwl_scan_cmd) + | 	int scan_cmd_size = sizeof(struct iwl_scan_cmd) + | ||||||
| 			    MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + | 			    MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + | ||||||
|  | @ -893,7 +861,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | ||||||
| 
 | 
 | ||||||
| 	/* MIMO is not used here, but value is required */ | 	/* MIMO is not used here, but value is required */ | ||||||
| 	rx_chain |= | 	rx_chain |= | ||||||
| 		priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | 		priv->eeprom_data->valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | ||||||
| 	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | 	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | ||||||
| 	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | 	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | ||||||
| 	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | 	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | ||||||
|  | @ -994,8 +962,10 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | ||||||
| 	set_bit(STATUS_SCAN_HW, &priv->status); | 	set_bit(STATUS_SCAN_HW, &priv->status); | ||||||
| 
 | 
 | ||||||
| 	ret = iwlagn_set_pan_params(priv); | 	ret = iwlagn_set_pan_params(priv); | ||||||
| 	if (ret) | 	if (ret) { | ||||||
|  | 		clear_bit(STATUS_SCAN_HW, &priv->status); | ||||||
| 		return ret; | 		return ret; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	ret = iwl_dvm_send_cmd(priv, &cmd); | 	ret = iwl_dvm_send_cmd(priv, &cmd); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
|  | @ -1008,7 +978,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | ||||||
| 
 | 
 | ||||||
| void iwl_init_scan_params(struct iwl_priv *priv) | void iwl_init_scan_params(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; | 	u8 ant_idx = fls(priv->eeprom_data->valid_tx_ant) - 1; | ||||||
| 	if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) | 	if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) | ||||||
| 		priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; | 		priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; | ||||||
| 	if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) | 	if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) | ||||||
|  | @ -1158,3 +1128,40 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv) | ||||||
| 		mutex_unlock(&priv->mutex); | 		mutex_unlock(&priv->mutex); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void iwl_scan_roc_expired(struct iwl_priv *priv) | ||||||
|  | { | ||||||
|  | 	/*
 | ||||||
|  | 	 * The status bit should be set here, to prevent a race | ||||||
|  | 	 * where the atomic_read returns 1, but before the execution continues | ||||||
|  | 	 * iwl_scan_offchannel_skb_status() checks if the status bit is set | ||||||
|  | 	 */ | ||||||
|  | 	set_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status); | ||||||
|  | 
 | ||||||
|  | 	if (atomic_read(&priv->num_aux_in_flight) == 0) { | ||||||
|  | 		ieee80211_remain_on_channel_expired(priv->hw); | ||||||
|  | 		priv->hw_roc_channel = NULL; | ||||||
|  | 		schedule_delayed_work(&priv->hw_roc_disable_work, | ||||||
|  | 				      10 * HZ); | ||||||
|  | 
 | ||||||
|  | 		clear_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status); | ||||||
|  | 	} else { | ||||||
|  | 		IWL_DEBUG_SCAN(priv, "ROC done with %d frames in aux\n", | ||||||
|  | 			       atomic_read(&priv->num_aux_in_flight)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void iwl_scan_offchannel_skb(struct iwl_priv *priv) | ||||||
|  | { | ||||||
|  | 	WARN_ON(!priv->hw_roc_start_notified); | ||||||
|  | 	atomic_inc(&priv->num_aux_in_flight); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void iwl_scan_offchannel_skb_status(struct iwl_priv *priv) | ||||||
|  | { | ||||||
|  | 	if (atomic_dec_return(&priv->num_aux_in_flight) == 0 && | ||||||
|  | 	    test_bit(STATUS_SCAN_ROC_EXPIRED, &priv->status)) { | ||||||
|  | 		IWL_DEBUG_SCAN(priv, "0 aux frames. Calling ROC expired\n"); | ||||||
|  | 		iwl_scan_roc_expired(priv); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -28,10 +28,9 @@ | ||||||
|  *****************************************************************************/ |  *****************************************************************************/ | ||||||
| #include <linux/etherdevice.h> | #include <linux/etherdevice.h> | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| 
 |  | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
|  | #include "dev.h" | ||||||
|  | #include "agn.h" | ||||||
| 
 | 
 | ||||||
| const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | ||||||
| 
 | 
 | ||||||
|  | @ -171,26 +170,6 @@ int iwl_send_add_sta(struct iwl_priv *priv, | ||||||
| 	return cmd.handler_status; | 	return cmd.handler_status; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool iwl_is_channel_extension(struct iwl_priv *priv, |  | ||||||
| 				     enum ieee80211_band band, |  | ||||||
| 				     u16 channel, u8 extension_chan_offset) |  | ||||||
| { |  | ||||||
| 	const struct iwl_channel_info *ch_info; |  | ||||||
| 
 |  | ||||||
| 	ch_info = iwl_get_channel_info(priv, band, channel); |  | ||||||
| 	if (!is_channel_valid(ch_info)) |  | ||||||
| 		return false; |  | ||||||
| 
 |  | ||||||
| 	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) |  | ||||||
| 		return !(ch_info->ht40_extension_channel & |  | ||||||
| 					IEEE80211_CHAN_NO_HT40PLUS); |  | ||||||
| 	else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) |  | ||||||
| 		return !(ch_info->ht40_extension_channel & |  | ||||||
| 					IEEE80211_CHAN_NO_HT40MINUS); |  | ||||||
| 
 |  | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | ||||||
| 			    struct iwl_rxon_context *ctx, | 			    struct iwl_rxon_context *ctx, | ||||||
| 			    struct ieee80211_sta_ht_cap *ht_cap) | 			    struct ieee80211_sta_ht_cap *ht_cap) | ||||||
|  | @ -198,21 +177,25 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | ||||||
| 	if (!ctx->ht.enabled || !ctx->ht.is_40mhz) | 	if (!ctx->ht.enabled || !ctx->ht.is_40mhz) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	/*
 |  | ||||||
| 	 * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 |  | ||||||
| 	 * the bit will not set if it is pure 40MHz case |  | ||||||
| 	 */ |  | ||||||
| 	if (ht_cap && !ht_cap->ht_supported) |  | ||||||
| 		return false; |  | ||||||
| 
 |  | ||||||
| #ifdef CONFIG_IWLWIFI_DEBUGFS | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||||||
| 	if (priv->disable_ht40) | 	if (priv->disable_ht40) | ||||||
| 		return false; | 		return false; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	return iwl_is_channel_extension(priv, priv->band, | 	/*
 | ||||||
| 			le16_to_cpu(ctx->staging.channel), | 	 * Remainder of this function checks ht_cap, but if it's | ||||||
| 			ctx->ht.extension_chan_offset); | 	 * NULL then we can do HT40 (special case for RXON) | ||||||
|  | 	 */ | ||||||
|  | 	if (!ht_cap) | ||||||
|  | 		return true; | ||||||
|  | 
 | ||||||
|  | 	if (!ht_cap->ht_supported) | ||||||
|  | 		return false; | ||||||
|  | 
 | ||||||
|  | 	if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) | ||||||
|  | 		return false; | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, | static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, | ||||||
|  | @ -650,23 +633,23 @@ static void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | ||||||
| 	if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | 	if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) | ||||||
| 		rate_flags |= RATE_MCS_CCK_MSK; | 		rate_flags |= RATE_MCS_CCK_MSK; | ||||||
| 
 | 
 | ||||||
| 	rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << | 	rate_flags |= first_antenna(priv->eeprom_data->valid_tx_ant) << | ||||||
| 				RATE_MCS_ANT_POS; | 				RATE_MCS_ANT_POS; | ||||||
| 	rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | 	rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | ||||||
| 	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) | 	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) | ||||||
| 		link_cmd->rs_table[i].rate_n_flags = rate_n_flags; | 		link_cmd->rs_table[i].rate_n_flags = rate_n_flags; | ||||||
| 
 | 
 | ||||||
| 	link_cmd->general_params.single_stream_ant_msk = | 	link_cmd->general_params.single_stream_ant_msk = | ||||||
| 			first_antenna(priv->hw_params.valid_tx_ant); | 			first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 
 | 
 | ||||||
| 	link_cmd->general_params.dual_stream_ant_msk = | 	link_cmd->general_params.dual_stream_ant_msk = | ||||||
| 		priv->hw_params.valid_tx_ant & | 		priv->eeprom_data->valid_tx_ant & | ||||||
| 		~first_antenna(priv->hw_params.valid_tx_ant); | 		~first_antenna(priv->eeprom_data->valid_tx_ant); | ||||||
| 	if (!link_cmd->general_params.dual_stream_ant_msk) { | 	if (!link_cmd->general_params.dual_stream_ant_msk) { | ||||||
| 		link_cmd->general_params.dual_stream_ant_msk = ANT_AB; | 		link_cmd->general_params.dual_stream_ant_msk = ANT_AB; | ||||||
| 	} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | 	} else if (num_of_ant(priv->eeprom_data->valid_tx_ant) == 2) { | ||||||
| 		link_cmd->general_params.dual_stream_ant_msk = | 		link_cmd->general_params.dual_stream_ant_msk = | ||||||
| 			priv->hw_params.valid_tx_ant; | 			priv->eeprom_data->valid_tx_ant; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	link_cmd->agg_params.agg_dis_start_th = | 	link_cmd->agg_params.agg_dis_start_th = | ||||||
|  | @ -69,15 +69,14 @@ | ||||||
| #include <net/cfg80211.h> | #include <net/cfg80211.h> | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| #include <net/netlink.h> | #include <net/netlink.h> | ||||||
| 
 |  | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-debug.h" | #include "iwl-debug.h" | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-testmode.h" |  | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-fh.h" | #include "iwl-fh.h" | ||||||
| #include "iwl-prph.h" | #include "iwl-prph.h" | ||||||
|  | #include "dev.h" | ||||||
|  | #include "agn.h" | ||||||
|  | #include "testmode.h" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Periphery registers absolute lower bound. This is used in order to
 | /* Periphery registers absolute lower bound. This is used in order to
 | ||||||
|  | @ -89,7 +88,7 @@ | ||||||
| /* The TLVs used in the gnl message policy between the kernel module and
 | /* 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 |  * user space application. iwl_testmode_gnl_msg_policy is to be carried | ||||||
|  * through the NL80211_CMD_TESTMODE channel regulated by nl80211. |  * through the NL80211_CMD_TESTMODE channel regulated by nl80211. | ||||||
|  * See iwl-testmode.h |  * See testmode.h | ||||||
|  */ |  */ | ||||||
| static | static | ||||||
| struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { | struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { | ||||||
|  | @ -129,7 +128,7 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * See the struct iwl_rx_packet in iwl-commands.h for the format of the |  * See the struct iwl_rx_packet in commands.h for the format of the | ||||||
|  * received events from the device |  * received events from the device | ||||||
|  */ |  */ | ||||||
| static inline int get_event_length(struct iwl_rx_cmd_buffer *rxb) | static inline int get_event_length(struct iwl_rx_cmd_buffer *rxb) | ||||||
|  | @ -535,9 +534,9 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | ||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
| 	case IWL_TM_CMD_APP2DEV_GET_EEPROM: | 	case IWL_TM_CMD_APP2DEV_GET_EEPROM: | ||||||
| 		if (priv->eeprom) { | 		if (priv->eeprom_blob) { | ||||||
| 			skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | 			skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | ||||||
| 				priv->cfg->base_params->eeprom_size + 20); | 				priv->eeprom_blob_size + 20); | ||||||
| 			if (!skb) { | 			if (!skb) { | ||||||
| 				IWL_ERR(priv, "Memory allocation fail\n"); | 				IWL_ERR(priv, "Memory allocation fail\n"); | ||||||
| 				return -ENOMEM; | 				return -ENOMEM; | ||||||
|  | @ -545,15 +544,15 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | ||||||
| 			if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | 			if (nla_put_u32(skb, IWL_TM_ATTR_COMMAND, | ||||||
| 					IWL_TM_CMD_DEV2APP_EEPROM_RSP) || | 					IWL_TM_CMD_DEV2APP_EEPROM_RSP) || | ||||||
| 			    nla_put(skb, IWL_TM_ATTR_EEPROM, | 			    nla_put(skb, IWL_TM_ATTR_EEPROM, | ||||||
| 				    priv->cfg->base_params->eeprom_size, | 				    priv->eeprom_blob_size, | ||||||
| 				    priv->eeprom)) | 				    priv->eeprom_blob)) | ||||||
| 				goto nla_put_failure; | 				goto nla_put_failure; | ||||||
| 			status = cfg80211_testmode_reply(skb); | 			status = cfg80211_testmode_reply(skb); | ||||||
| 			if (status < 0) | 			if (status < 0) | ||||||
| 				IWL_ERR(priv, "Error sending msg : %d\n", | 				IWL_ERR(priv, "Error sending msg : %d\n", | ||||||
| 					status); | 					status); | ||||||
| 		} else | 		} else | ||||||
| 			return -EFAULT; | 			return -ENODATA; | ||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
| 	case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: | 	case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: | ||||||
|  | @ -31,17 +31,14 @@ | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
| 
 |  | ||||||
| #include <net/mac80211.h> | #include <net/mac80211.h> | ||||||
| 
 |  | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-eeprom.h" |  | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-commands.h" |  | ||||||
| #include "iwl-debug.h" |  | ||||||
| #include "iwl-agn-tt.h" |  | ||||||
| #include "iwl-modparams.h" | #include "iwl-modparams.h" | ||||||
|  | #include "iwl-debug.h" | ||||||
|  | #include "agn.h" | ||||||
|  | #include "dev.h" | ||||||
|  | #include "commands.h" | ||||||
|  | #include "tt.h" | ||||||
| 
 | 
 | ||||||
| /* default Thermal Throttling transaction table
 | /* default Thermal Throttling transaction table
 | ||||||
|  * Current state   |         Throttling Down               |  Throttling Up |  * Current state   |         Throttling Down               |  Throttling Up | ||||||
|  | @ -28,7 +28,7 @@ | ||||||
| #ifndef __iwl_tt_setting_h__ | #ifndef __iwl_tt_setting_h__ | ||||||
| #define __iwl_tt_setting_h__ | #define __iwl_tt_setting_h__ | ||||||
| 
 | 
 | ||||||
| #include "iwl-commands.h" | #include "commands.h" | ||||||
| 
 | 
 | ||||||
| #define IWL_ABSOLUTE_ZERO		0 | #define IWL_ABSOLUTE_ZERO		0 | ||||||
| #define IWL_ABSOLUTE_MAX		0xFFFFFFFF | #define IWL_ABSOLUTE_MAX		0xFFFFFFFF | ||||||
|  | @ -32,12 +32,11 @@ | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
| #include <linux/sched.h> | #include <linux/sched.h> | ||||||
| #include <linux/ieee80211.h> | #include <linux/ieee80211.h> | ||||||
| 
 |  | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-agn-hw.h" |  | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
|  | #include "iwl-agn-hw.h" | ||||||
|  | #include "dev.h" | ||||||
|  | #include "agn.h" | ||||||
| 
 | 
 | ||||||
| static const u8 tid_to_ac[] = { | static const u8 tid_to_ac[] = { | ||||||
| 	IEEE80211_AC_BE, | 	IEEE80211_AC_BE, | ||||||
|  | @ -187,7 +186,8 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | ||||||
| 	rate_idx = info->control.rates[0].idx; | 	rate_idx = info->control.rates[0].idx; | ||||||
| 	if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | 	if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | ||||||
| 			(rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | 			(rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | ||||||
| 		rate_idx = rate_lowest_index(&priv->bands[info->band], | 		rate_idx = rate_lowest_index( | ||||||
|  | 				&priv->eeprom_data->bands[info->band], | ||||||
| 				info->control.sta); | 				info->control.sta); | ||||||
| 	/* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | 	/* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | ||||||
| 	if (info->band == IEEE80211_BAND_5GHZ) | 	if (info->band == IEEE80211_BAND_5GHZ) | ||||||
|  | @ -207,10 +207,11 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | ||||||
| 	     priv->bt_full_concurrent) { | 	     priv->bt_full_concurrent) { | ||||||
| 		/* operated as 1x1 in full concurrency mode */ | 		/* operated as 1x1 in full concurrency mode */ | ||||||
| 		priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 		priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | ||||||
| 				first_antenna(priv->hw_params.valid_tx_ant)); | 				first_antenna(priv->eeprom_data->valid_tx_ant)); | ||||||
| 	} else | 	} else | ||||||
| 		priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant, | 		priv->mgmt_tx_ant = iwl_toggle_tx_ant( | ||||||
| 						priv->hw_params.valid_tx_ant); | 					priv, priv->mgmt_tx_ant, | ||||||
|  | 					priv->eeprom_data->valid_tx_ant); | ||||||
| 	rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | 	rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||||||
| 
 | 
 | ||||||
| 	/* Set the rate in the TX cmd */ | 	/* Set the rate in the TX cmd */ | ||||||
|  | @ -296,7 +297,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||||||
| 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||||||
| 	struct iwl_station_priv *sta_priv = NULL; | 	struct iwl_station_priv *sta_priv = NULL; | ||||||
| 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||||||
| 	struct iwl_device_cmd *dev_cmd = NULL; | 	struct iwl_device_cmd *dev_cmd; | ||||||
| 	struct iwl_tx_cmd *tx_cmd; | 	struct iwl_tx_cmd *tx_cmd; | ||||||
| 	__le16 fc; | 	__le16 fc; | ||||||
| 	u8 hdr_len; | 	u8 hdr_len; | ||||||
|  | @ -378,7 +379,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||||||
| 	if (info->flags & IEEE80211_TX_CTL_AMPDU) | 	if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||||||
| 		is_agg = true; | 		is_agg = true; | ||||||
| 
 | 
 | ||||||
| 	dev_cmd = kmem_cache_alloc(iwl_tx_cmd_pool, GFP_ATOMIC); | 	dev_cmd = iwl_trans_alloc_tx_cmd(priv->trans); | ||||||
| 
 | 
 | ||||||
| 	if (unlikely(!dev_cmd)) | 	if (unlikely(!dev_cmd)) | ||||||
| 		goto drop_unlock_priv; | 		goto drop_unlock_priv; | ||||||
|  | @ -486,11 +487,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||||||
| 	if (sta_priv && sta_priv->client && !is_agg) | 	if (sta_priv && sta_priv->client && !is_agg) | ||||||
| 		atomic_inc(&sta_priv->pending_frames); | 		atomic_inc(&sta_priv->pending_frames); | ||||||
| 
 | 
 | ||||||
|  | 	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||||||
|  | 		iwl_scan_offchannel_skb(priv); | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
| drop_unlock_sta: | drop_unlock_sta: | ||||||
| 	if (dev_cmd) | 	if (dev_cmd) | ||||||
| 		kmem_cache_free(iwl_tx_cmd_pool, dev_cmd); | 		iwl_trans_free_tx_cmd(priv->trans, dev_cmd); | ||||||
| 	spin_unlock(&priv->sta_lock); | 	spin_unlock(&priv->sta_lock); | ||||||
| drop_unlock_priv: | drop_unlock_priv: | ||||||
| 	return -1; | 	return -1; | ||||||
|  | @ -597,7 +601,7 @@ turn_off: | ||||||
| 		 * time, or we hadn't time to drain the AC queues. | 		 * time, or we hadn't time to drain the AC queues. | ||||||
| 		 */ | 		 */ | ||||||
| 		if (agg_state == IWL_AGG_ON) | 		if (agg_state == IWL_AGG_ON) | ||||||
| 			iwl_trans_tx_agg_disable(priv->trans, txq_id); | 			iwl_trans_txq_disable(priv->trans, txq_id); | ||||||
| 		else | 		else | ||||||
| 			IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | 			IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | ||||||
| 					    agg_state); | 					    agg_state); | ||||||
|  | @ -686,8 +690,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||||||
| 
 | 
 | ||||||
| 	fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; | 	fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; | ||||||
| 
 | 
 | ||||||
| 	iwl_trans_tx_agg_setup(priv->trans, q, fifo, | 	iwl_trans_txq_enable(priv->trans, q, fifo, sta_priv->sta_id, tid, | ||||||
| 			       sta_priv->sta_id, tid, |  | ||||||
| 			     buf_size, ssn); | 			     buf_size, ssn); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
|  | @ -753,7 +756,7 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) | ||||||
| 			IWL_DEBUG_TX_QUEUES(priv, | 			IWL_DEBUG_TX_QUEUES(priv, | ||||||
| 				"Can continue DELBA flow ssn = next_recl =" | 				"Can continue DELBA flow ssn = next_recl =" | ||||||
| 				" %d", tid_data->next_reclaimed); | 				" %d", tid_data->next_reclaimed); | ||||||
| 			iwl_trans_tx_agg_disable(priv->trans, | 			iwl_trans_txq_disable(priv->trans, | ||||||
| 					      tid_data->agg.txq_id); | 					      tid_data->agg.txq_id); | ||||||
| 			iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); | 			iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); | ||||||
| 			tid_data->agg.state = IWL_AGG_OFF; | 			tid_data->agg.state = IWL_AGG_OFF; | ||||||
|  | @ -1136,6 +1139,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | ||||||
| 	struct sk_buff *skb; | 	struct sk_buff *skb; | ||||||
| 	struct iwl_rxon_context *ctx; | 	struct iwl_rxon_context *ctx; | ||||||
| 	bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); | 	bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); | ||||||
|  | 	bool is_offchannel_skb; | ||||||
| 
 | 
 | ||||||
| 	tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> | 	tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >> | ||||||
| 		IWLAGN_TX_RES_TID_POS; | 		IWLAGN_TX_RES_TID_POS; | ||||||
|  | @ -1149,6 +1153,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | ||||||
| 
 | 
 | ||||||
| 	__skb_queue_head_init(&skbs); | 	__skb_queue_head_init(&skbs); | ||||||
| 
 | 
 | ||||||
|  | 	is_offchannel_skb = false; | ||||||
|  | 
 | ||||||
| 	if (tx_resp->frame_count == 1) { | 	if (tx_resp->frame_count == 1) { | ||||||
| 		u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); | 		u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); | ||||||
| 		next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); | 		next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); | ||||||
|  | @ -1189,8 +1195,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | ||||||
| 
 | 
 | ||||||
| 			info = IEEE80211_SKB_CB(skb); | 			info = IEEE80211_SKB_CB(skb); | ||||||
| 			ctx = info->driver_data[0]; | 			ctx = info->driver_data[0]; | ||||||
| 			kmem_cache_free(iwl_tx_cmd_pool, | 			iwl_trans_free_tx_cmd(priv->trans, | ||||||
| 					(info->driver_data[1])); | 					      info->driver_data[1]); | ||||||
| 
 | 
 | ||||||
| 			memset(&info->status, 0, sizeof(info->status)); | 			memset(&info->status, 0, sizeof(info->status)); | ||||||
| 
 | 
 | ||||||
|  | @ -1225,10 +1231,19 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | ||||||
| 			if (!is_agg) | 			if (!is_agg) | ||||||
| 				iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); | 				iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); | ||||||
| 
 | 
 | ||||||
|  | 			is_offchannel_skb = | ||||||
|  | 				(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); | ||||||
| 			freed++; | 			freed++; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		WARN_ON(!is_agg && freed != 1); | 		WARN_ON(!is_agg && freed != 1); | ||||||
|  | 
 | ||||||
|  | 		/*
 | ||||||
|  | 		 * An offchannel frame can be send only on the AUX queue, where | ||||||
|  | 		 * there is no aggregation (and reordering) so it only is single | ||||||
|  | 		 * skb is expected to be processed. | ||||||
|  | 		 */ | ||||||
|  | 		WARN_ON(is_offchannel_skb && freed != 1); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	iwl_check_abort_status(priv, tx_resp->frame_count, status); | 	iwl_check_abort_status(priv, tx_resp->frame_count, status); | ||||||
|  | @ -1239,6 +1254,9 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | ||||||
| 		ieee80211_tx_status(priv->hw, skb); | 		ieee80211_tx_status(priv->hw, skb); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (is_offchannel_skb) | ||||||
|  | 		iwl_scan_offchannel_skb_status(priv); | ||||||
|  | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1341,7 +1359,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | ||||||
| 			WARN_ON_ONCE(1); | 			WARN_ON_ONCE(1); | ||||||
| 
 | 
 | ||||||
| 		info = IEEE80211_SKB_CB(skb); | 		info = IEEE80211_SKB_CB(skb); | ||||||
| 		kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1])); | 		iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); | ||||||
| 
 | 
 | ||||||
| 		if (freed == 1) { | 		if (freed == 1) { | ||||||
| 			/* this is the first skb we deliver in this batch */ | 			/* this is the first skb we deliver in this batch */ | ||||||
|  | @ -30,15 +30,16 @@ | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
| 
 | 
 | ||||||
| #include "iwl-dev.h" |  | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-agn-hw.h" | #include "iwl-agn-hw.h" | ||||||
| #include "iwl-agn.h" |  | ||||||
| #include "iwl-agn-calib.h" |  | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-fh.h" | #include "iwl-fh.h" | ||||||
| #include "iwl-op-mode.h" | #include "iwl-op-mode.h" | ||||||
| 
 | 
 | ||||||
|  | #include "dev.h" | ||||||
|  | #include "agn.h" | ||||||
|  | #include "calib.h" | ||||||
|  | 
 | ||||||
| /******************************************************************************
 | /******************************************************************************
 | ||||||
|  * |  * | ||||||
|  * uCode download functions |  * uCode download functions | ||||||
|  | @ -60,8 +61,7 @@ iwl_get_ucode_image(struct iwl_priv *priv, enum iwl_ucode_type ucode_type) | ||||||
| static int iwl_set_Xtal_calib(struct iwl_priv *priv) | static int iwl_set_Xtal_calib(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	struct iwl_calib_xtal_freq_cmd cmd; | 	struct iwl_calib_xtal_freq_cmd cmd; | ||||||
| 	__le16 *xtal_calib = | 	__le16 *xtal_calib = priv->eeprom_data->xtal_calib; | ||||||
| 		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL); |  | ||||||
| 
 | 
 | ||||||
| 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); | 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); | ||||||
| 	cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | 	cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | ||||||
|  | @ -72,12 +72,10 @@ static int iwl_set_Xtal_calib(struct iwl_priv *priv) | ||||||
| static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	struct iwl_calib_temperature_offset_cmd cmd; | 	struct iwl_calib_temperature_offset_cmd cmd; | ||||||
| 	__le16 *offset_calib = |  | ||||||
| 		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); |  | ||||||
| 
 | 
 | ||||||
| 	memset(&cmd, 0, sizeof(cmd)); | 	memset(&cmd, 0, sizeof(cmd)); | ||||||
| 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | ||||||
| 	memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib)); | 	cmd.radio_sensor_offset = priv->eeprom_data->raw_temperature; | ||||||
| 	if (!(cmd.radio_sensor_offset)) | 	if (!(cmd.radio_sensor_offset)) | ||||||
| 		cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; | 		cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; | ||||||
| 
 | 
 | ||||||
|  | @ -89,27 +87,17 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) | ||||||
| static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) | static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	struct iwl_calib_temperature_offset_v2_cmd cmd; | 	struct iwl_calib_temperature_offset_v2_cmd cmd; | ||||||
| 	__le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, |  | ||||||
| 				     EEPROM_KELVIN_TEMPERATURE); |  | ||||||
| 	__le16 *offset_calib_low = |  | ||||||
| 		(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE); |  | ||||||
| 	struct iwl_eeprom_calib_hdr *hdr; |  | ||||||
| 
 | 
 | ||||||
| 	memset(&cmd, 0, sizeof(cmd)); | 	memset(&cmd, 0, sizeof(cmd)); | ||||||
| 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); | ||||||
| 	hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | 	cmd.radio_sensor_offset_high = priv->eeprom_data->kelvin_temperature; | ||||||
| 							EEPROM_CALIB_ALL); | 	cmd.radio_sensor_offset_low = priv->eeprom_data->raw_temperature; | ||||||
| 	memcpy(&cmd.radio_sensor_offset_high, offset_calib_high, | 	if (!cmd.radio_sensor_offset_low) { | ||||||
| 		sizeof(*offset_calib_high)); |  | ||||||
| 	memcpy(&cmd.radio_sensor_offset_low, offset_calib_low, |  | ||||||
| 		sizeof(*offset_calib_low)); |  | ||||||
| 	if (!(cmd.radio_sensor_offset_low)) { |  | ||||||
| 		IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); | 		IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); | ||||||
| 		cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; | 		cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; | ||||||
| 		cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; | 		cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; | ||||||
| 	} | 	} | ||||||
| 	memcpy(&cmd.burntVoltageRef, &hdr->voltage, | 	cmd.burntVoltageRef = priv->eeprom_data->calib_voltage; | ||||||
| 		sizeof(hdr->voltage)); |  | ||||||
| 
 | 
 | ||||||
| 	IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", | 	IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", | ||||||
| 			le16_to_cpu(cmd.radio_sensor_offset_high)); | 			le16_to_cpu(cmd.radio_sensor_offset_high)); | ||||||
|  | @ -177,7 +165,7 @@ int iwl_init_alive_start(struct iwl_priv *priv) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int iwl_send_wimax_coex(struct iwl_priv *priv) | static int iwl_send_wimax_coex(struct iwl_priv *priv) | ||||||
| { | { | ||||||
| 	struct iwl_wimax_coex_cmd coex_cmd; | 	struct iwl_wimax_coex_cmd coex_cmd; | ||||||
| 
 | 
 | ||||||
|  | @ -113,7 +113,7 @@ enum iwl_led_mode { | ||||||
| #define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE	0 | #define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE	0 | ||||||
| 
 | 
 | ||||||
| /* TX queue watchdog timeouts in mSecs */ | /* TX queue watchdog timeouts in mSecs */ | ||||||
| #define IWL_WATCHHDOG_DISABLED	0 | #define IWL_WATCHDOG_DISABLED	0 | ||||||
| #define IWL_DEF_WD_TIMEOUT	2000 | #define IWL_DEF_WD_TIMEOUT	2000 | ||||||
| #define IWL_LONG_WD_TIMEOUT	10000 | #define IWL_LONG_WD_TIMEOUT	10000 | ||||||
| #define IWL_MAX_WD_TIMEOUT	120000 | #define IWL_MAX_WD_TIMEOUT	120000 | ||||||
|  | @ -182,13 +182,34 @@ struct iwl_bt_params { | ||||||
| 	bool bt_sco_disable; | 	bool bt_sco_disable; | ||||||
| 	bool bt_session_2; | 	bool bt_session_2; | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * @use_rts_for_aggregation: use rts/cts protection for HT traffic |  * @use_rts_for_aggregation: use rts/cts protection for HT traffic | ||||||
|  |  * @ht40_bands: bitmap of bands (using %IEEE80211_BAND_*) that support HT40 | ||||||
|  */ |  */ | ||||||
| struct iwl_ht_params { | struct iwl_ht_params { | ||||||
|  | 	enum ieee80211_smps_mode smps_mode; | ||||||
| 	const bool ht_greenfield_support; /* if used set to true */ | 	const bool ht_greenfield_support; /* if used set to true */ | ||||||
| 	bool use_rts_for_aggregation; | 	bool use_rts_for_aggregation; | ||||||
| 	enum ieee80211_smps_mode smps_mode; | 	u8 ht40_bands; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * information on how to parse the EEPROM | ||||||
|  |  */ | ||||||
|  | #define EEPROM_REG_BAND_1_CHANNELS		0x08 | ||||||
|  | #define EEPROM_REG_BAND_2_CHANNELS		0x26 | ||||||
|  | #define EEPROM_REG_BAND_3_CHANNELS		0x42 | ||||||
|  | #define EEPROM_REG_BAND_4_CHANNELS		0x5C | ||||||
|  | #define EEPROM_REG_BAND_5_CHANNELS		0x74 | ||||||
|  | #define EEPROM_REG_BAND_24_HT40_CHANNELS	0x82 | ||||||
|  | #define EEPROM_REG_BAND_52_HT40_CHANNELS	0x92 | ||||||
|  | #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS	0x80 | ||||||
|  | #define EEPROM_REGULATORY_BAND_NO_HT40		0 | ||||||
|  | 
 | ||||||
|  | struct iwl_eeprom_params { | ||||||
|  | 	const u8 regulatory_bands[7]; | ||||||
|  | 	bool enhanced_txpower; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -243,6 +264,7 @@ struct iwl_cfg { | ||||||
| 	/* params likely to change within a device family */ | 	/* params likely to change within a device family */ | ||||||
| 	const struct iwl_ht_params *ht_params; | 	const struct iwl_ht_params *ht_params; | ||||||
| 	const struct iwl_bt_params *bt_params; | 	const struct iwl_bt_params *bt_params; | ||||||
|  | 	const struct iwl_eeprom_params *eeprom_params; | ||||||
| 	const bool need_temp_offset_calib; /* if used set to true */ | 	const bool need_temp_offset_calib; /* if used set to true */ | ||||||
| 	const bool no_xtal_calib; | 	const bool no_xtal_calib; | ||||||
| 	enum iwl_led_mode led_mode; | 	enum iwl_led_mode led_mode; | ||||||
|  |  | ||||||
|  | @ -97,13 +97,10 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Hardware revision info |  * Hardware revision info | ||||||
|  * Bit fields: |  * Bit fields: | ||||||
|  * 31-8:  Reserved |  * 31-16:  Reserved | ||||||
|  *  7-4:  Type of device:  see CSR_HW_REV_TYPE_xxx definitions |  *  15-4:  Type of device:  see CSR_HW_REV_TYPE_xxx definitions | ||||||
|  *  3-2:  Revision step:  0 = A, 1 = B, 2 = C, 3 = D |  *  3-2:  Revision step:  0 = A, 1 = B, 2 = C, 3 = D | ||||||
|  *  1-0:  "Dash" (-) value, as in A-1, etc. |  *  1-0:  "Dash" (-) value, as in A-1, etc. | ||||||
|  * |  | ||||||
|  * NOTE:  Revision step affects calculation of CCK txpower for 4965. |  | ||||||
|  * NOTE:  See also CSR_HW_REV_WA_REG (work-around for bug in 4965). |  | ||||||
|  */ |  */ | ||||||
| #define CSR_HW_REV              (CSR_BASE+0x028) | #define CSR_HW_REV              (CSR_BASE+0x028) | ||||||
| 
 | 
 | ||||||
|  | @ -155,9 +152,21 @@ | ||||||
| #define CSR_DBG_LINK_PWR_MGMT_REG	(CSR_BASE+0x250) | #define CSR_DBG_LINK_PWR_MGMT_REG	(CSR_BASE+0x250) | ||||||
| 
 | 
 | ||||||
| /* Bits for CSR_HW_IF_CONFIG_REG */ | /* Bits for CSR_HW_IF_CONFIG_REG */ | ||||||
| #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER	(0x00000C00) | #define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH	(0x00000003) | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP	(0x0000000C) | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER	(0x000000C0) | ||||||
| #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI		(0x00000100) | #define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI		(0x00000100) | ||||||
| #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI	(0x00000200) | #define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI	(0x00000200) | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE	(0x00000C00) | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH	(0x00003000) | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP	(0x0000C000) | ||||||
|  | 
 | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_POS_MAC_DASH	(0) | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_POS_MAC_STEP	(2) | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_POS_BOARD_VER	(6) | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE	(10) | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_POS_PHY_DASH	(12) | ||||||
|  | #define CSR_HW_IF_CONFIG_REG_POS_PHY_STEP	(14) | ||||||
| 
 | 
 | ||||||
| #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A	(0x00080000) | #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A	(0x00080000) | ||||||
| #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM	(0x00200000) | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM	(0x00200000) | ||||||
|  | @ -270,7 +279,10 @@ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* HW REV */ | /* HW REV */ | ||||||
| #define CSR_HW_REV_TYPE_MSK            (0x00001F0) | #define CSR_HW_REV_DASH(_val)          (((_val) & 0x0000003) >> 0) | ||||||
|  | #define CSR_HW_REV_STEP(_val)          (((_val) & 0x000000C) >> 2) | ||||||
|  | 
 | ||||||
|  | #define CSR_HW_REV_TYPE_MSK            (0x000FFF0) | ||||||
| #define CSR_HW_REV_TYPE_5300           (0x0000020) | #define CSR_HW_REV_TYPE_5300           (0x0000020) | ||||||
| #define CSR_HW_REV_TYPE_5350           (0x0000030) | #define CSR_HW_REV_TYPE_5350           (0x0000030) | ||||||
| #define CSR_HW_REV_TYPE_5100           (0x0000050) | #define CSR_HW_REV_TYPE_5100           (0x0000050) | ||||||
|  |  | ||||||
|  | @ -45,6 +45,7 @@ void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3); | ||||||
| 
 | 
 | ||||||
| /* No matter what is m (priv, bus, trans), this will work */ | /* No matter what is m (priv, bus, trans), this will work */ | ||||||
| #define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a) | #define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a) | ||||||
|  | #define IWL_ERR_DEV(d, f, a...) __iwl_err((d), false, false, f, ## a) | ||||||
| #define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a) | #define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a) | ||||||
| #define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a) | #define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a) | ||||||
| #define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a) | #define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a) | ||||||
|  | @ -69,6 +70,8 @@ do {									\ | ||||||
| 
 | 
 | ||||||
| #define IWL_DEBUG(m, level, fmt, args...)				\ | #define IWL_DEBUG(m, level, fmt, args...)				\ | ||||||
| 	__iwl_dbg((m)->dev, level, false, __func__, fmt, ##args) | 	__iwl_dbg((m)->dev, level, false, __func__, fmt, ##args) | ||||||
|  | #define IWL_DEBUG_DEV(dev, level, fmt, args...)				\ | ||||||
|  | 	__iwl_dbg((dev), level, false, __func__, fmt, ##args) | ||||||
| #define IWL_DEBUG_LIMIT(m, level, fmt, args...)				\ | #define IWL_DEBUG_LIMIT(m, level, fmt, args...)				\ | ||||||
| 	__iwl_dbg((m)->dev, level, true, __func__, fmt, ##args) | 	__iwl_dbg((m)->dev, level, true, __func__, fmt, ##args) | ||||||
| 
 | 
 | ||||||
|  | @ -153,7 +156,7 @@ do {                                            			\ | ||||||
| #define IWL_DEBUG_LED(p, f, a...)	IWL_DEBUG(p, IWL_DL_LED, f, ## a) | #define IWL_DEBUG_LED(p, f, a...)	IWL_DEBUG(p, IWL_DL_LED, f, ## a) | ||||||
| #define IWL_DEBUG_WEP(p, f, a...)	IWL_DEBUG(p, IWL_DL_WEP, f, ## a) | #define IWL_DEBUG_WEP(p, f, a...)	IWL_DEBUG(p, IWL_DL_WEP, f, ## a) | ||||||
| #define IWL_DEBUG_HC(p, f, a...)	IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) | #define IWL_DEBUG_HC(p, f, a...)	IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) | ||||||
| #define IWL_DEBUG_EEPROM(p, f, a...)	IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a) | #define IWL_DEBUG_EEPROM(d, f, a...)	IWL_DEBUG_DEV(d, IWL_DL_EEPROM, f, ## a) | ||||||
| #define IWL_DEBUG_CALIB(p, f, a...)	IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) | #define IWL_DEBUG_CALIB(p, f, a...)	IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) | ||||||
| #define IWL_DEBUG_FW(p, f, a...)	IWL_DEBUG(p, IWL_DL_FW, f, ## a) | #define IWL_DEBUG_FW(p, f, a...)	IWL_DEBUG(p, IWL_DL_FW, f, ## a) | ||||||
| #define IWL_DEBUG_RF_KILL(p, f, a...)	IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) | #define IWL_DEBUG_RF_KILL(p, f, a...)	IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) | ||||||
|  |  | ||||||
|  | @ -28,6 +28,7 @@ | ||||||
| #define __IWLWIFI_DEVICE_TRACE | #define __IWLWIFI_DEVICE_TRACE | ||||||
| 
 | 
 | ||||||
| #include <linux/tracepoint.h> | #include <linux/tracepoint.h> | ||||||
|  | #include <linux/device.h> | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) | #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) | ||||||
|  |  | ||||||
							
								
								
									
										900
									
								
								drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										900
									
								
								drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,900 @@ | ||||||
|  | /******************************************************************************
 | ||||||
|  |  * | ||||||
|  |  * 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) 2008 - 2012 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 - 2012 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/types.h> | ||||||
|  | #include <linux/slab.h> | ||||||
|  | #include <linux/export.h> | ||||||
|  | #include "iwl-modparams.h" | ||||||
|  | #include "iwl-eeprom-parse.h" | ||||||
|  | 
 | ||||||
|  | /* EEPROM offset definitions */ | ||||||
|  | 
 | ||||||
|  | /* indirect access definitions */ | ||||||
|  | #define ADDRESS_MSK                 0x0000FFFF | ||||||
|  | #define INDIRECT_TYPE_MSK           0x000F0000 | ||||||
|  | #define INDIRECT_HOST               0x00010000 | ||||||
|  | #define INDIRECT_GENERAL            0x00020000 | ||||||
|  | #define INDIRECT_REGULATORY         0x00030000 | ||||||
|  | #define INDIRECT_CALIBRATION        0x00040000 | ||||||
|  | #define INDIRECT_PROCESS_ADJST      0x00050000 | ||||||
|  | #define INDIRECT_OTHERS             0x00060000 | ||||||
|  | #define INDIRECT_TXP_LIMIT          0x00070000 | ||||||
|  | #define INDIRECT_TXP_LIMIT_SIZE     0x00080000 | ||||||
|  | #define INDIRECT_ADDRESS            0x00100000 | ||||||
|  | 
 | ||||||
|  | /* corresponding link offsets in EEPROM */ | ||||||
|  | #define EEPROM_LINK_HOST             (2*0x64) | ||||||
|  | #define EEPROM_LINK_GENERAL          (2*0x65) | ||||||
|  | #define EEPROM_LINK_REGULATORY       (2*0x66) | ||||||
|  | #define EEPROM_LINK_CALIBRATION      (2*0x67) | ||||||
|  | #define EEPROM_LINK_PROCESS_ADJST    (2*0x68) | ||||||
|  | #define EEPROM_LINK_OTHERS           (2*0x69) | ||||||
|  | #define EEPROM_LINK_TXP_LIMIT        (2*0x6a) | ||||||
|  | #define EEPROM_LINK_TXP_LIMIT_SIZE   (2*0x6b) | ||||||
|  | 
 | ||||||
|  | /* 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_RADIO_CONFIG                 (2*0x48)	/* 2  bytes */ | ||||||
|  | #define EEPROM_NUM_MAC_ADDRESS              (2*0x4C)	/* 2  bytes */ | ||||||
|  | 
 | ||||||
|  | /* calibration */ | ||||||
|  | struct iwl_eeprom_calib_hdr { | ||||||
|  | 	u8 version; | ||||||
|  | 	u8 pa_type; | ||||||
|  | 	__le16 voltage; | ||||||
|  | } __packed; | ||||||
|  | 
 | ||||||
|  | #define EEPROM_CALIB_ALL	(INDIRECT_ADDRESS | INDIRECT_CALIBRATION) | ||||||
|  | #define EEPROM_XTAL		((2*0x128) | EEPROM_CALIB_ALL) | ||||||
|  | 
 | ||||||
|  | /* temperature */ | ||||||
|  | #define EEPROM_KELVIN_TEMPERATURE	((2*0x12A) | EEPROM_CALIB_ALL) | ||||||
|  | #define EEPROM_RAW_TEMPERATURE		((2*0x12B) | EEPROM_CALIB_ALL) | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * EEPROM bands | ||||||
|  |  * These are the channel numbers from each band in the order | ||||||
|  |  * that they are stored in the EEPROM band information. Note | ||||||
|  |  * that EEPROM bands aren't the same as mac80211 bands, and | ||||||
|  |  * there are even special "ht40 bands" in the EEPROM. | ||||||
|  |  */ | ||||||
|  | static const u8 iwl_eeprom_band_1[14] = { /* 2.4 GHz */ | ||||||
|  | 	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const u8 iwl_eeprom_band_2[] = {	/* 4915-5080MHz */ | ||||||
|  | 	183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const u8 iwl_eeprom_band_3[] = {	/* 5170-5320MHz */ | ||||||
|  | 	34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const u8 iwl_eeprom_band_4[] = {	/* 5500-5700MHz */ | ||||||
|  | 	100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const u8 iwl_eeprom_band_5[] = {	/* 5725-5825MHz */ | ||||||
|  | 	145, 149, 153, 157, 161, 165 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const u8 iwl_eeprom_band_6[] = {	/* 2.4 ht40 channel */ | ||||||
|  | 	1, 2, 3, 4, 5, 6, 7 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const u8 iwl_eeprom_band_7[] = {	/* 5.2 ht40 channel */ | ||||||
|  | 	36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define IWL_NUM_CHANNELS	(ARRAY_SIZE(iwl_eeprom_band_1) + \ | ||||||
|  | 				 ARRAY_SIZE(iwl_eeprom_band_2) + \ | ||||||
|  | 				 ARRAY_SIZE(iwl_eeprom_band_3) + \ | ||||||
|  | 				 ARRAY_SIZE(iwl_eeprom_band_4) + \ | ||||||
|  | 				 ARRAY_SIZE(iwl_eeprom_band_5)) | ||||||
|  | 
 | ||||||
|  | /* rate data (static) */ | ||||||
|  | static struct ieee80211_rate iwl_cfg80211_rates[] = { | ||||||
|  | 	{ .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, }, | ||||||
|  | 	{ .bitrate = 2 * 10, .hw_value = 1, .hw_value_short = 1, | ||||||
|  | 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE, }, | ||||||
|  | 	{ .bitrate = 5.5 * 10, .hw_value = 2, .hw_value_short = 2, | ||||||
|  | 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE, }, | ||||||
|  | 	{ .bitrate = 11 * 10, .hw_value = 3, .hw_value_short = 3, | ||||||
|  | 	  .flags = IEEE80211_RATE_SHORT_PREAMBLE, }, | ||||||
|  | 	{ .bitrate = 6 * 10, .hw_value = 4, .hw_value_short = 4, }, | ||||||
|  | 	{ .bitrate = 9 * 10, .hw_value = 5, .hw_value_short = 5, }, | ||||||
|  | 	{ .bitrate = 12 * 10, .hw_value = 6, .hw_value_short = 6, }, | ||||||
|  | 	{ .bitrate = 18 * 10, .hw_value = 7, .hw_value_short = 7, }, | ||||||
|  | 	{ .bitrate = 24 * 10, .hw_value = 8, .hw_value_short = 8, }, | ||||||
|  | 	{ .bitrate = 36 * 10, .hw_value = 9, .hw_value_short = 9, }, | ||||||
|  | 	{ .bitrate = 48 * 10, .hw_value = 10, .hw_value_short = 10, }, | ||||||
|  | 	{ .bitrate = 54 * 10, .hw_value = 11, .hw_value_short = 11, }, | ||||||
|  | }; | ||||||
|  | #define RATES_24_OFFS	0 | ||||||
|  | #define N_RATES_24	ARRAY_SIZE(iwl_cfg80211_rates) | ||||||
|  | #define RATES_52_OFFS	4 | ||||||
|  | #define N_RATES_52	(N_RATES_24 - RATES_52_OFFS) | ||||||
|  | 
 | ||||||
|  | /* EEPROM reading functions */ | ||||||
|  | 
 | ||||||
|  | static u16 iwl_eeprom_query16(const u8 *eeprom, size_t eeprom_size, int offset) | ||||||
|  | { | ||||||
|  | 	if (WARN_ON(offset + sizeof(u16) > eeprom_size)) | ||||||
|  | 		return 0; | ||||||
|  | 	return le16_to_cpup((__le16 *)(eeprom + offset)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static u32 eeprom_indirect_address(const u8 *eeprom, size_t eeprom_size, | ||||||
|  | 				   u32 address) | ||||||
|  | { | ||||||
|  | 	u16 offset = 0; | ||||||
|  | 
 | ||||||
|  | 	if ((address & INDIRECT_ADDRESS) == 0) | ||||||
|  | 		return address; | ||||||
|  | 
 | ||||||
|  | 	switch (address & INDIRECT_TYPE_MSK) { | ||||||
|  | 	case INDIRECT_HOST: | ||||||
|  | 		offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 					    EEPROM_LINK_HOST); | ||||||
|  | 		break; | ||||||
|  | 	case INDIRECT_GENERAL: | ||||||
|  | 		offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 					    EEPROM_LINK_GENERAL); | ||||||
|  | 		break; | ||||||
|  | 	case INDIRECT_REGULATORY: | ||||||
|  | 		offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 					    EEPROM_LINK_REGULATORY); | ||||||
|  | 		break; | ||||||
|  | 	case INDIRECT_TXP_LIMIT: | ||||||
|  | 		offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 					    EEPROM_LINK_TXP_LIMIT); | ||||||
|  | 		break; | ||||||
|  | 	case INDIRECT_TXP_LIMIT_SIZE: | ||||||
|  | 		offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 					    EEPROM_LINK_TXP_LIMIT_SIZE); | ||||||
|  | 		break; | ||||||
|  | 	case INDIRECT_CALIBRATION: | ||||||
|  | 		offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 					    EEPROM_LINK_CALIBRATION); | ||||||
|  | 		break; | ||||||
|  | 	case INDIRECT_PROCESS_ADJST: | ||||||
|  | 		offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 					    EEPROM_LINK_PROCESS_ADJST); | ||||||
|  | 		break; | ||||||
|  | 	case INDIRECT_OTHERS: | ||||||
|  | 		offset = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 					    EEPROM_LINK_OTHERS); | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		WARN_ON(1); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* translate the offset from words to byte */ | ||||||
|  | 	return (address & ADDRESS_MSK) + (offset << 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const u8 *iwl_eeprom_query_addr(const u8 *eeprom, size_t eeprom_size, | ||||||
|  | 				       u32 offset) | ||||||
|  | { | ||||||
|  | 	u32 address = eeprom_indirect_address(eeprom, eeprom_size, offset); | ||||||
|  | 
 | ||||||
|  | 	if (WARN_ON(address >= eeprom_size)) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	return &eeprom[address]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int iwl_eeprom_read_calib(const u8 *eeprom, size_t eeprom_size, | ||||||
|  | 				 struct iwl_eeprom_data *data) | ||||||
|  | { | ||||||
|  | 	struct iwl_eeprom_calib_hdr *hdr; | ||||||
|  | 
 | ||||||
|  | 	hdr = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||||||
|  | 					    EEPROM_CALIB_ALL); | ||||||
|  | 	if (!hdr) | ||||||
|  | 		return -ENODATA; | ||||||
|  | 	data->calib_version = hdr->version; | ||||||
|  | 	data->calib_voltage = hdr->voltage; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * enum iwl_eeprom_channel_flags - channel flags in EEPROM | ||||||
|  |  * @EEPROM_CHANNEL_VALID: channel is usable for this SKU/geo | ||||||
|  |  * @EEPROM_CHANNEL_IBSS: usable as an IBSS channel | ||||||
|  |  * @EEPROM_CHANNEL_ACTIVE: active scanning allowed | ||||||
|  |  * @EEPROM_CHANNEL_RADAR: radar detection required | ||||||
|  |  * @EEPROM_CHANNEL_WIDE: 20 MHz channel okay (?) | ||||||
|  |  * @EEPROM_CHANNEL_DFS: dynamic freq selection candidate | ||||||
|  |  */ | ||||||
|  | enum iwl_eeprom_channel_flags { | ||||||
|  | 	EEPROM_CHANNEL_VALID = BIT(0), | ||||||
|  | 	EEPROM_CHANNEL_IBSS = BIT(1), | ||||||
|  | 	EEPROM_CHANNEL_ACTIVE = BIT(3), | ||||||
|  | 	EEPROM_CHANNEL_RADAR = BIT(4), | ||||||
|  | 	EEPROM_CHANNEL_WIDE = BIT(5), | ||||||
|  | 	EEPROM_CHANNEL_DFS = BIT(7), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * struct iwl_eeprom_channel - EEPROM channel data | ||||||
|  |  * @flags: %EEPROM_CHANNEL_* flags | ||||||
|  |  * @max_power_avg: max power (in dBm) on this channel, at most 31 dBm | ||||||
|  |  */ | ||||||
|  | struct iwl_eeprom_channel { | ||||||
|  | 	u8 flags; | ||||||
|  | 	s8 max_power_avg; | ||||||
|  | } __packed; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | enum iwl_eeprom_enhanced_txpwr_flags { | ||||||
|  | 	IWL_EEPROM_ENH_TXP_FL_VALID = BIT(0), | ||||||
|  | 	IWL_EEPROM_ENH_TXP_FL_BAND_52G = BIT(1), | ||||||
|  | 	IWL_EEPROM_ENH_TXP_FL_OFDM = BIT(2), | ||||||
|  | 	IWL_EEPROM_ENH_TXP_FL_40MHZ = BIT(3), | ||||||
|  | 	IWL_EEPROM_ENH_TXP_FL_HT_AP = BIT(4), | ||||||
|  | 	IWL_EEPROM_ENH_TXP_FL_RES1 = BIT(5), | ||||||
|  | 	IWL_EEPROM_ENH_TXP_FL_RES2 = BIT(6), | ||||||
|  | 	IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE = BIT(7), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * iwl_eeprom_enhanced_txpwr structure | ||||||
|  |  * @flags: entry flags | ||||||
|  |  * @channel: channel number | ||||||
|  |  * @chain_a_max_pwr: chain a max power in 1/2 dBm | ||||||
|  |  * @chain_b_max_pwr: chain b max power in 1/2 dBm | ||||||
|  |  * @chain_c_max_pwr: chain c max power in 1/2 dBm | ||||||
|  |  * @delta_20_in_40: 20-in-40 deltas (hi/lo) | ||||||
|  |  * @mimo2_max_pwr: mimo2 max power in 1/2 dBm | ||||||
|  |  * @mimo3_max_pwr: mimo3 max power in 1/2 dBm | ||||||
|  |  * | ||||||
|  |  * This structure presents the enhanced regulatory tx power limit layout | ||||||
|  |  * in an EEPROM image. | ||||||
|  |  */ | ||||||
|  | struct iwl_eeprom_enhanced_txpwr { | ||||||
|  | 	u8 flags; | ||||||
|  | 	u8 channel; | ||||||
|  | 	s8 chain_a_max; | ||||||
|  | 	s8 chain_b_max; | ||||||
|  | 	s8 chain_c_max; | ||||||
|  | 	u8 delta_20_in_40; | ||||||
|  | 	s8 mimo2_max; | ||||||
|  | 	s8 mimo3_max; | ||||||
|  | } __packed; | ||||||
|  | 
 | ||||||
|  | static s8 iwl_get_max_txpwr_half_dbm(const struct iwl_eeprom_data *data, | ||||||
|  | 				     struct iwl_eeprom_enhanced_txpwr *txp) | ||||||
|  | { | ||||||
|  | 	s8 result = 0; /* (.5 dBm) */ | ||||||
|  | 
 | ||||||
|  | 	/* Take the highest tx power from any valid chains */ | ||||||
|  | 	if (data->valid_tx_ant & ANT_A && txp->chain_a_max > result) | ||||||
|  | 		result = txp->chain_a_max; | ||||||
|  | 
 | ||||||
|  | 	if (data->valid_tx_ant & ANT_B && txp->chain_b_max > result) | ||||||
|  | 		result = txp->chain_b_max; | ||||||
|  | 
 | ||||||
|  | 	if (data->valid_tx_ant & ANT_C && txp->chain_c_max > result) | ||||||
|  | 		result = txp->chain_c_max; | ||||||
|  | 
 | ||||||
|  | 	if ((data->valid_tx_ant == ANT_AB || | ||||||
|  | 	     data->valid_tx_ant == ANT_BC || | ||||||
|  | 	     data->valid_tx_ant == ANT_AC) && txp->mimo2_max > result) | ||||||
|  | 		result = txp->mimo2_max; | ||||||
|  | 
 | ||||||
|  | 	if (data->valid_tx_ant == ANT_ABC && txp->mimo3_max > result) | ||||||
|  | 		result = txp->mimo3_max; | ||||||
|  | 
 | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define EEPROM_TXP_OFFS	(0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT) | ||||||
|  | #define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr) | ||||||
|  | #define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE) | ||||||
|  | 
 | ||||||
|  | #define TXP_CHECK_AND_PRINT(x) \ | ||||||
|  | 	((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) ? # x " " : "") | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | iwl_eeprom_enh_txp_read_element(struct iwl_eeprom_data *data, | ||||||
|  | 				struct iwl_eeprom_enhanced_txpwr *txp, | ||||||
|  | 				int n_channels, s8 max_txpower_avg) | ||||||
|  | { | ||||||
|  | 	int ch_idx; | ||||||
|  | 	enum ieee80211_band band; | ||||||
|  | 
 | ||||||
|  | 	band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ? | ||||||
|  | 		IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; | ||||||
|  | 
 | ||||||
|  | 	for (ch_idx = 0; ch_idx < n_channels; ch_idx++) { | ||||||
|  | 		struct ieee80211_channel *chan = &data->channels[ch_idx]; | ||||||
|  | 
 | ||||||
|  | 		/* update matching channel or from common data only */ | ||||||
|  | 		if (txp->channel != 0 && chan->hw_value != txp->channel) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		/* update matching band only */ | ||||||
|  | 		if (band != chan->band) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		if (chan->max_power < max_txpower_avg && | ||||||
|  | 		    !(txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ)) | ||||||
|  | 			chan->max_power = max_txpower_avg; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void iwl_eeprom_enhanced_txpower(struct device *dev, | ||||||
|  | 					struct iwl_eeprom_data *data, | ||||||
|  | 					const u8 *eeprom, size_t eeprom_size, | ||||||
|  | 					int n_channels) | ||||||
|  | { | ||||||
|  | 	struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; | ||||||
|  | 	int idx, entries; | ||||||
|  | 	__le16 *txp_len; | ||||||
|  | 	s8 max_txp_avg_halfdbm; | ||||||
|  | 
 | ||||||
|  | 	BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8); | ||||||
|  | 
 | ||||||
|  | 	/* the length is in 16-bit words, but we want entries */ | ||||||
|  | 	txp_len = (__le16 *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||||||
|  | 						  EEPROM_TXP_SZ_OFFS); | ||||||
|  | 	entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN; | ||||||
|  | 
 | ||||||
|  | 	txp_array = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, | ||||||
|  | 						  EEPROM_TXP_OFFS); | ||||||
|  | 
 | ||||||
|  | 	for (idx = 0; idx < entries; idx++) { | ||||||
|  | 		txp = &txp_array[idx]; | ||||||
|  | 		/* skip invalid entries */ | ||||||
|  | 		if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		IWL_DEBUG_EEPROM(dev, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n", | ||||||
|  | 				 (txp->channel && (txp->flags & | ||||||
|  | 					IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ? | ||||||
|  | 					"Common " : (txp->channel) ? | ||||||
|  | 					"Channel" : "Common", | ||||||
|  | 				 (txp->channel), | ||||||
|  | 				 TXP_CHECK_AND_PRINT(VALID), | ||||||
|  | 				 TXP_CHECK_AND_PRINT(BAND_52G), | ||||||
|  | 				 TXP_CHECK_AND_PRINT(OFDM), | ||||||
|  | 				 TXP_CHECK_AND_PRINT(40MHZ), | ||||||
|  | 				 TXP_CHECK_AND_PRINT(HT_AP), | ||||||
|  | 				 TXP_CHECK_AND_PRINT(RES1), | ||||||
|  | 				 TXP_CHECK_AND_PRINT(RES2), | ||||||
|  | 				 TXP_CHECK_AND_PRINT(COMMON_TYPE), | ||||||
|  | 				 txp->flags); | ||||||
|  | 		IWL_DEBUG_EEPROM(dev, | ||||||
|  | 				 "\t\t chain_A: 0x%02x chain_B: 0X%02x chain_C: 0X%02x\n", | ||||||
|  | 				 txp->chain_a_max, txp->chain_b_max, | ||||||
|  | 				 txp->chain_c_max); | ||||||
|  | 		IWL_DEBUG_EEPROM(dev, | ||||||
|  | 				 "\t\t MIMO2: 0x%02x MIMO3: 0x%02x High 20_on_40: 0x%02x Low 20_on_40: 0x%02x\n", | ||||||
|  | 				 txp->mimo2_max, txp->mimo3_max, | ||||||
|  | 				 ((txp->delta_20_in_40 & 0xf0) >> 4), | ||||||
|  | 				 (txp->delta_20_in_40 & 0x0f)); | ||||||
|  | 
 | ||||||
|  | 		max_txp_avg_halfdbm = iwl_get_max_txpwr_half_dbm(data, txp); | ||||||
|  | 
 | ||||||
|  | 		iwl_eeprom_enh_txp_read_element(data, txp, n_channels, | ||||||
|  | 				DIV_ROUND_UP(max_txp_avg_halfdbm, 2)); | ||||||
|  | 
 | ||||||
|  | 		if (max_txp_avg_halfdbm > data->max_tx_pwr_half_dbm) | ||||||
|  | 			data->max_tx_pwr_half_dbm = max_txp_avg_halfdbm; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void iwl_init_band_reference(const struct iwl_cfg *cfg, | ||||||
|  | 				    const u8 *eeprom, size_t eeprom_size, | ||||||
|  | 				    int eeprom_band, int *eeprom_ch_count, | ||||||
|  | 				    const struct iwl_eeprom_channel **ch_info, | ||||||
|  | 				    const u8 **eeprom_ch_array) | ||||||
|  | { | ||||||
|  | 	u32 offset = cfg->eeprom_params->regulatory_bands[eeprom_band - 1]; | ||||||
|  | 
 | ||||||
|  | 	offset |= INDIRECT_ADDRESS | INDIRECT_REGULATORY; | ||||||
|  | 
 | ||||||
|  | 	*ch_info = (void *)iwl_eeprom_query_addr(eeprom, eeprom_size, offset); | ||||||
|  | 
 | ||||||
|  | 	switch (eeprom_band) { | ||||||
|  | 	case 1:		/* 2.4GHz band */ | ||||||
|  | 		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); | ||||||
|  | 		*eeprom_ch_array = iwl_eeprom_band_1; | ||||||
|  | 		break; | ||||||
|  | 	case 2:		/* 4.9GHz band */ | ||||||
|  | 		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); | ||||||
|  | 		*eeprom_ch_array = iwl_eeprom_band_2; | ||||||
|  | 		break; | ||||||
|  | 	case 3:		/* 5.2GHz band */ | ||||||
|  | 		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); | ||||||
|  | 		*eeprom_ch_array = iwl_eeprom_band_3; | ||||||
|  | 		break; | ||||||
|  | 	case 4:		/* 5.5GHz band */ | ||||||
|  | 		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); | ||||||
|  | 		*eeprom_ch_array = iwl_eeprom_band_4; | ||||||
|  | 		break; | ||||||
|  | 	case 5:		/* 5.7GHz band */ | ||||||
|  | 		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); | ||||||
|  | 		*eeprom_ch_array = iwl_eeprom_band_5; | ||||||
|  | 		break; | ||||||
|  | 	case 6:		/* 2.4GHz ht40 channels */ | ||||||
|  | 		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); | ||||||
|  | 		*eeprom_ch_array = iwl_eeprom_band_6; | ||||||
|  | 		break; | ||||||
|  | 	case 7:		/* 5 GHz ht40 channels */ | ||||||
|  | 		*eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); | ||||||
|  | 		*eeprom_ch_array = iwl_eeprom_band_7; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		*eeprom_ch_count = 0; | ||||||
|  | 		*eeprom_ch_array = NULL; | ||||||
|  | 		WARN_ON(1); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define CHECK_AND_PRINT(x) \ | ||||||
|  | 	((eeprom_ch->flags & EEPROM_CHANNEL_##x) ? # x " " : "") | ||||||
|  | 
 | ||||||
|  | static void iwl_mod_ht40_chan_info(struct device *dev, | ||||||
|  | 				   struct iwl_eeprom_data *data, int n_channels, | ||||||
|  | 				   enum ieee80211_band band, u16 channel, | ||||||
|  | 				   const struct iwl_eeprom_channel *eeprom_ch, | ||||||
|  | 				   u8 clear_ht40_extension_channel) | ||||||
|  | { | ||||||
|  | 	struct ieee80211_channel *chan = NULL; | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < n_channels; i++) { | ||||||
|  | 		if (data->channels[i].band != band) | ||||||
|  | 			continue; | ||||||
|  | 		if (data->channels[i].hw_value != channel) | ||||||
|  | 			continue; | ||||||
|  | 		chan = &data->channels[i]; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!chan) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	IWL_DEBUG_EEPROM(dev, | ||||||
|  | 			 "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | ||||||
|  | 			 channel, | ||||||
|  | 			 band == IEEE80211_BAND_5GHZ ? "5.2" : "2.4", | ||||||
|  | 			 CHECK_AND_PRINT(IBSS), | ||||||
|  | 			 CHECK_AND_PRINT(ACTIVE), | ||||||
|  | 			 CHECK_AND_PRINT(RADAR), | ||||||
|  | 			 CHECK_AND_PRINT(WIDE), | ||||||
|  | 			 CHECK_AND_PRINT(DFS), | ||||||
|  | 			 eeprom_ch->flags, | ||||||
|  | 			 eeprom_ch->max_power_avg, | ||||||
|  | 			 ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) && | ||||||
|  | 			  !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? "" | ||||||
|  | 								      : "not "); | ||||||
|  | 
 | ||||||
|  | 	if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) | ||||||
|  | 		chan->flags &= ~clear_ht40_extension_channel; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define CHECK_AND_PRINT_I(x)	\ | ||||||
|  | 	((eeprom_ch_info[ch_idx].flags & EEPROM_CHANNEL_##x) ? # x " " : "") | ||||||
|  | 
 | ||||||
|  | static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | ||||||
|  | 				struct iwl_eeprom_data *data, | ||||||
|  | 				const u8 *eeprom, size_t eeprom_size) | ||||||
|  | { | ||||||
|  | 	int band, ch_idx; | ||||||
|  | 	const struct iwl_eeprom_channel *eeprom_ch_info; | ||||||
|  | 	const u8 *eeprom_ch_array; | ||||||
|  | 	int eeprom_ch_count; | ||||||
|  | 	int n_channels = 0; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Loop through the 5 EEPROM bands and add them to the parse list | ||||||
|  | 	 */ | ||||||
|  | 	for (band = 1; band <= 5; band++) { | ||||||
|  | 		struct ieee80211_channel *channel; | ||||||
|  | 
 | ||||||
|  | 		iwl_init_band_reference(cfg, eeprom, eeprom_size, band, | ||||||
|  | 					&eeprom_ch_count, &eeprom_ch_info, | ||||||
|  | 					&eeprom_ch_array); | ||||||
|  | 
 | ||||||
|  | 		/* Loop through each band adding each of the channels */ | ||||||
|  | 		for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) { | ||||||
|  | 			const struct iwl_eeprom_channel *eeprom_ch; | ||||||
|  | 
 | ||||||
|  | 			eeprom_ch = &eeprom_ch_info[ch_idx]; | ||||||
|  | 
 | ||||||
|  | 			if (!(eeprom_ch->flags & EEPROM_CHANNEL_VALID)) { | ||||||
|  | 				IWL_DEBUG_EEPROM(dev, | ||||||
|  | 						 "Ch. %d Flags %x [%sGHz] - No traffic\n", | ||||||
|  | 						 eeprom_ch_array[ch_idx], | ||||||
|  | 						 eeprom_ch_info[ch_idx].flags, | ||||||
|  | 						 (band != 1) ? "5.2" : "2.4"); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			channel = &data->channels[n_channels]; | ||||||
|  | 			n_channels++; | ||||||
|  | 
 | ||||||
|  | 			channel->hw_value = eeprom_ch_array[ch_idx]; | ||||||
|  | 			channel->band = (band == 1) ? IEEE80211_BAND_2GHZ | ||||||
|  | 						    : IEEE80211_BAND_5GHZ; | ||||||
|  | 			channel->center_freq = | ||||||
|  | 				ieee80211_channel_to_frequency( | ||||||
|  | 					channel->hw_value, channel->band); | ||||||
|  | 
 | ||||||
|  | 			/* set no-HT40, will enable as appropriate later */ | ||||||
|  | 			channel->flags = IEEE80211_CHAN_NO_HT40; | ||||||
|  | 
 | ||||||
|  | 			if (!(eeprom_ch->flags & EEPROM_CHANNEL_IBSS)) | ||||||
|  | 				channel->flags |= IEEE80211_CHAN_NO_IBSS; | ||||||
|  | 
 | ||||||
|  | 			if (!(eeprom_ch->flags & EEPROM_CHANNEL_ACTIVE)) | ||||||
|  | 				channel->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||||||
|  | 
 | ||||||
|  | 			if (eeprom_ch->flags & EEPROM_CHANNEL_RADAR) | ||||||
|  | 				channel->flags |= IEEE80211_CHAN_RADAR; | ||||||
|  | 
 | ||||||
|  | 			/* Initialize regulatory-based run-time data */ | ||||||
|  | 			channel->max_power = | ||||||
|  | 				eeprom_ch_info[ch_idx].max_power_avg; | ||||||
|  | 			IWL_DEBUG_EEPROM(dev, | ||||||
|  | 					 "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", | ||||||
|  | 					 channel->hw_value, | ||||||
|  | 					 (band != 1) ? "5.2" : "2.4", | ||||||
|  | 					 CHECK_AND_PRINT_I(VALID), | ||||||
|  | 					 CHECK_AND_PRINT_I(IBSS), | ||||||
|  | 					 CHECK_AND_PRINT_I(ACTIVE), | ||||||
|  | 					 CHECK_AND_PRINT_I(RADAR), | ||||||
|  | 					 CHECK_AND_PRINT_I(WIDE), | ||||||
|  | 					 CHECK_AND_PRINT_I(DFS), | ||||||
|  | 					 eeprom_ch_info[ch_idx].flags, | ||||||
|  | 					 eeprom_ch_info[ch_idx].max_power_avg, | ||||||
|  | 					 ((eeprom_ch_info[ch_idx].flags & | ||||||
|  | 							EEPROM_CHANNEL_IBSS) && | ||||||
|  | 					  !(eeprom_ch_info[ch_idx].flags & | ||||||
|  | 							EEPROM_CHANNEL_RADAR)) | ||||||
|  | 						? "" : "not "); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (cfg->eeprom_params->enhanced_txpower) { | ||||||
|  | 		/*
 | ||||||
|  | 		 * for newer device (6000 series and up) | ||||||
|  | 		 * EEPROM contain enhanced tx power information | ||||||
|  | 		 * driver need to process addition information | ||||||
|  | 		 * to determine the max channel tx power limits | ||||||
|  | 		 */ | ||||||
|  | 		iwl_eeprom_enhanced_txpower(dev, data, eeprom, eeprom_size, | ||||||
|  | 					    n_channels); | ||||||
|  | 	} else { | ||||||
|  | 		/* All others use data from channel map */ | ||||||
|  | 		int i; | ||||||
|  | 
 | ||||||
|  | 		data->max_tx_pwr_half_dbm = -128; | ||||||
|  | 
 | ||||||
|  | 		for (i = 0; i < n_channels; i++) | ||||||
|  | 			data->max_tx_pwr_half_dbm = | ||||||
|  | 				max_t(s8, data->max_tx_pwr_half_dbm, | ||||||
|  | 				      data->channels[i].max_power * 2); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Check if we do have HT40 channels */ | ||||||
|  | 	if (cfg->eeprom_params->regulatory_bands[5] == | ||||||
|  | 				EEPROM_REGULATORY_BAND_NO_HT40 && | ||||||
|  | 	    cfg->eeprom_params->regulatory_bands[6] == | ||||||
|  | 				EEPROM_REGULATORY_BAND_NO_HT40) | ||||||
|  | 		return n_channels; | ||||||
|  | 
 | ||||||
|  | 	/* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ | ||||||
|  | 	for (band = 6; band <= 7; band++) { | ||||||
|  | 		enum ieee80211_band ieeeband; | ||||||
|  | 
 | ||||||
|  | 		iwl_init_band_reference(cfg, eeprom, eeprom_size, band, | ||||||
|  | 					&eeprom_ch_count, &eeprom_ch_info, | ||||||
|  | 					&eeprom_ch_array); | ||||||
|  | 
 | ||||||
|  | 		/* EEPROM band 6 is 2.4, band 7 is 5 GHz */ | ||||||
|  | 		ieeeband = (band == 6) ? IEEE80211_BAND_2GHZ | ||||||
|  | 				       : IEEE80211_BAND_5GHZ; | ||||||
|  | 
 | ||||||
|  | 		/* Loop through each band adding each of the channels */ | ||||||
|  | 		for (ch_idx = 0; ch_idx < eeprom_ch_count; ch_idx++) { | ||||||
|  | 			/* Set up driver's info for lower half */ | ||||||
|  | 			iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband, | ||||||
|  | 					       eeprom_ch_array[ch_idx], | ||||||
|  | 					       &eeprom_ch_info[ch_idx], | ||||||
|  | 					       IEEE80211_CHAN_NO_HT40PLUS); | ||||||
|  | 
 | ||||||
|  | 			/* Set up driver's info for upper half */ | ||||||
|  | 			iwl_mod_ht40_chan_info(dev, data, n_channels, ieeeband, | ||||||
|  | 					       eeprom_ch_array[ch_idx] + 4, | ||||||
|  | 					       &eeprom_ch_info[ch_idx], | ||||||
|  | 					       IEEE80211_CHAN_NO_HT40MINUS); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return n_channels; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int iwl_init_sband_channels(struct iwl_eeprom_data *data, | ||||||
|  | 				   struct ieee80211_supported_band *sband, | ||||||
|  | 				   int n_channels, enum ieee80211_band band) | ||||||
|  | { | ||||||
|  | 	struct ieee80211_channel *chan = &data->channels[0]; | ||||||
|  | 	int n = 0, idx = 0; | ||||||
|  | 
 | ||||||
|  | 	while (chan->band != band && idx < n_channels) | ||||||
|  | 		chan = &data->channels[++idx]; | ||||||
|  | 
 | ||||||
|  | 	sband->channels = &data->channels[idx]; | ||||||
|  | 
 | ||||||
|  | 	while (chan->band == band && idx < n_channels) { | ||||||
|  | 		chan = &data->channels[++idx]; | ||||||
|  | 		n++; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sband->n_channels = n; | ||||||
|  | 
 | ||||||
|  | 	return n; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define MAX_BIT_RATE_40_MHZ	150 /* Mbps */ | ||||||
|  | #define MAX_BIT_RATE_20_MHZ	72 /* Mbps */ | ||||||
|  | 
 | ||||||
|  | static void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg, | ||||||
|  | 				 struct iwl_eeprom_data *data, | ||||||
|  | 				 struct ieee80211_sta_ht_cap *ht_info, | ||||||
|  | 				 enum ieee80211_band band) | ||||||
|  | { | ||||||
|  | 	int max_bit_rate = 0; | ||||||
|  | 	u8 rx_chains; | ||||||
|  | 	u8 tx_chains; | ||||||
|  | 
 | ||||||
|  | 	tx_chains = hweight8(data->valid_tx_ant); | ||||||
|  | 	if (cfg->rx_with_siso_diversity) | ||||||
|  | 		rx_chains = 1; | ||||||
|  | 	else | ||||||
|  | 		rx_chains = hweight8(data->valid_rx_ant); | ||||||
|  | 
 | ||||||
|  | 	if (!(data->sku & EEPROM_SKU_CAP_11N_ENABLE) || !cfg->ht_params) { | ||||||
|  | 		ht_info->ht_supported = false; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ht_info->ht_supported = true; | ||||||
|  | 	ht_info->cap = 0; | ||||||
|  | 
 | ||||||
|  | 	if (iwlwifi_mod_params.amsdu_size_8K) | ||||||
|  | 		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||||||
|  | 
 | ||||||
|  | 	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | ||||||
|  | 	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; | ||||||
|  | 
 | ||||||
|  | 	ht_info->mcs.rx_mask[0] = 0xFF; | ||||||
|  | 	if (rx_chains >= 2) | ||||||
|  | 		ht_info->mcs.rx_mask[1] = 0xFF; | ||||||
|  | 	if (rx_chains >= 3) | ||||||
|  | 		ht_info->mcs.rx_mask[2] = 0xFF; | ||||||
|  | 
 | ||||||
|  | 	if (cfg->ht_params->ht_greenfield_support) | ||||||
|  | 		ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||||||
|  | 	ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||||||
|  | 
 | ||||||
|  | 	max_bit_rate = MAX_BIT_RATE_20_MHZ; | ||||||
|  | 
 | ||||||
|  | 	if (cfg->ht_params->ht40_bands & BIT(band)) { | ||||||
|  | 		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||||||
|  | 		ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||||||
|  | 		ht_info->mcs.rx_mask[4] = 0x01; | ||||||
|  | 		max_bit_rate = MAX_BIT_RATE_40_MHZ; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Highest supported Rx data rate */ | ||||||
|  | 	max_bit_rate *= rx_chains; | ||||||
|  | 	WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); | ||||||
|  | 	ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); | ||||||
|  | 
 | ||||||
|  | 	/* Tx MCS capabilities */ | ||||||
|  | 	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||||||
|  | 	if (tx_chains != rx_chains) { | ||||||
|  | 		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||||||
|  | 		ht_info->mcs.tx_params |= ((tx_chains - 1) << | ||||||
|  | 				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | ||||||
|  | 			    struct iwl_eeprom_data *data, | ||||||
|  | 			    const u8 *eeprom, size_t eeprom_size) | ||||||
|  | { | ||||||
|  | 	int n_channels = iwl_init_channel_map(dev, cfg, data, | ||||||
|  | 					      eeprom, eeprom_size); | ||||||
|  | 	int n_used = 0; | ||||||
|  | 	struct ieee80211_supported_band *sband; | ||||||
|  | 
 | ||||||
|  | 	sband = &data->bands[IEEE80211_BAND_2GHZ]; | ||||||
|  | 	sband->band = IEEE80211_BAND_2GHZ; | ||||||
|  | 	sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; | ||||||
|  | 	sband->n_bitrates = N_RATES_24; | ||||||
|  | 	n_used += iwl_init_sband_channels(data, sband, n_channels, | ||||||
|  | 					  IEEE80211_BAND_2GHZ); | ||||||
|  | 	iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_2GHZ); | ||||||
|  | 
 | ||||||
|  | 	sband = &data->bands[IEEE80211_BAND_5GHZ]; | ||||||
|  | 	sband->band = IEEE80211_BAND_5GHZ; | ||||||
|  | 	sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS]; | ||||||
|  | 	sband->n_bitrates = N_RATES_52; | ||||||
|  | 	n_used += iwl_init_sband_channels(data, sband, n_channels, | ||||||
|  | 					  IEEE80211_BAND_5GHZ); | ||||||
|  | 	iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ); | ||||||
|  | 
 | ||||||
|  | 	if (n_channels != n_used) | ||||||
|  | 		IWL_ERR_DEV(dev, "EEPROM: used only %d of %d channels\n", | ||||||
|  | 			    n_used, n_channels); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* EEPROM data functions */ | ||||||
|  | 
 | ||||||
|  | struct iwl_eeprom_data * | ||||||
|  | iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | ||||||
|  | 		      const u8 *eeprom, size_t eeprom_size) | ||||||
|  | { | ||||||
|  | 	struct iwl_eeprom_data *data; | ||||||
|  | 	const void *tmp; | ||||||
|  | 
 | ||||||
|  | 	if (WARN_ON(!cfg || !cfg->eeprom_params)) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	data = kzalloc(sizeof(*data) + | ||||||
|  | 		       sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, | ||||||
|  | 		       GFP_KERNEL); | ||||||
|  | 	if (!data) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	/* get MAC address(es) */ | ||||||
|  | 	tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_MAC_ADDRESS); | ||||||
|  | 	if (!tmp) | ||||||
|  | 		goto err_free; | ||||||
|  | 	memcpy(data->hw_addr, tmp, ETH_ALEN); | ||||||
|  | 	data->n_hw_addrs = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 					      EEPROM_NUM_MAC_ADDRESS); | ||||||
|  | 
 | ||||||
|  | 	if (iwl_eeprom_read_calib(eeprom, eeprom_size, data)) | ||||||
|  | 		goto err_free; | ||||||
|  | 
 | ||||||
|  | 	tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, EEPROM_XTAL); | ||||||
|  | 	if (!tmp) | ||||||
|  | 		goto err_free; | ||||||
|  | 	memcpy(data->xtal_calib, tmp, sizeof(data->xtal_calib)); | ||||||
|  | 
 | ||||||
|  | 	tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, | ||||||
|  | 				    EEPROM_RAW_TEMPERATURE); | ||||||
|  | 	if (!tmp) | ||||||
|  | 		goto err_free; | ||||||
|  | 	data->raw_temperature = *(__le16 *)tmp; | ||||||
|  | 
 | ||||||
|  | 	tmp = iwl_eeprom_query_addr(eeprom, eeprom_size, | ||||||
|  | 				    EEPROM_KELVIN_TEMPERATURE); | ||||||
|  | 	if (!tmp) | ||||||
|  | 		goto err_free; | ||||||
|  | 	data->kelvin_temperature = *(__le16 *)tmp; | ||||||
|  | 	data->kelvin_voltage = *((__le16 *)tmp + 1); | ||||||
|  | 
 | ||||||
|  | 	data->radio_cfg = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 					     EEPROM_RADIO_CONFIG); | ||||||
|  | 	data->sku = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 				       EEPROM_SKU_CAP); | ||||||
|  | 	data->eeprom_version = iwl_eeprom_query16(eeprom, eeprom_size, | ||||||
|  | 						  EEPROM_VERSION); | ||||||
|  | 
 | ||||||
|  | 	data->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(data->radio_cfg); | ||||||
|  | 	data->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(data->radio_cfg); | ||||||
|  | 
 | ||||||
|  | 	/* check overrides (some devices have wrong EEPROM) */ | ||||||
|  | 	if (cfg->valid_tx_ant) | ||||||
|  | 		data->valid_tx_ant = cfg->valid_tx_ant; | ||||||
|  | 	if (cfg->valid_rx_ant) | ||||||
|  | 		data->valid_rx_ant = cfg->valid_rx_ant; | ||||||
|  | 
 | ||||||
|  | 	if (!data->valid_tx_ant || !data->valid_rx_ant) { | ||||||
|  | 		IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n", | ||||||
|  | 			    data->valid_tx_ant, data->valid_rx_ant); | ||||||
|  | 		goto err_free; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	iwl_init_sbands(dev, cfg, data, eeprom, eeprom_size); | ||||||
|  | 
 | ||||||
|  | 	return data; | ||||||
|  |  err_free: | ||||||
|  | 	kfree(data); | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(iwl_parse_eeprom_data); | ||||||
|  | 
 | ||||||
|  | /* helper functions */ | ||||||
|  | int iwl_eeprom_check_version(struct iwl_eeprom_data *data, | ||||||
|  | 			     struct iwl_trans *trans) | ||||||
|  | { | ||||||
|  | 	if (data->eeprom_version >= trans->cfg->eeprom_ver || | ||||||
|  | 	    data->calib_version >= trans->cfg->eeprom_calib_ver) { | ||||||
|  | 		IWL_INFO(trans, "device EEPROM VER=0x%x, CALIB=0x%x\n", | ||||||
|  | 			 data->eeprom_version, data->calib_version); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	IWL_ERR(trans, | ||||||
|  | 		"Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", | ||||||
|  | 		data->eeprom_version, trans->cfg->eeprom_ver, | ||||||
|  | 		data->calib_version,  trans->cfg->eeprom_calib_ver); | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(iwl_eeprom_check_version); | ||||||
							
								
								
									
										138
									
								
								drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,138 @@ | ||||||
|  | /******************************************************************************
 | ||||||
|  |  * | ||||||
|  |  * 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) 2008 - 2012 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 - 2012 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_eeprom_parse_h__ | ||||||
|  | #define __iwl_eeprom_parse_h__ | ||||||
|  | 
 | ||||||
|  | #include <linux/types.h> | ||||||
|  | #include <linux/if_ether.h> | ||||||
|  | #include "iwl-trans.h" | ||||||
|  | 
 | ||||||
|  | /* SKU Capabilities (actual values from EEPROM definition) */ | ||||||
|  | #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_IPAN_ENABLE	(1 << 8) | ||||||
|  | 
 | ||||||
|  | /* radio config bits (actual values from EEPROM definition) */ | ||||||
|  | #define EEPROM_RF_CFG_TYPE_MSK(x)   (x & 0x3)         /* bits 0-1   */ | ||||||
|  | #define EEPROM_RF_CFG_STEP_MSK(x)   ((x >> 2)  & 0x3) /* bits 2-3   */ | ||||||
|  | #define EEPROM_RF_CFG_DASH_MSK(x)   ((x >> 4)  & 0x3) /* bits 4-5   */ | ||||||
|  | #define EEPROM_RF_CFG_PNUM_MSK(x)   ((x >> 6)  & 0x3) /* bits 6-7   */ | ||||||
|  | #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8)  & 0xF) /* bits 8-11  */ | ||||||
|  | #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ | ||||||
|  | 
 | ||||||
|  | struct iwl_eeprom_data { | ||||||
|  | 	int n_hw_addrs; | ||||||
|  | 	u8 hw_addr[ETH_ALEN]; | ||||||
|  | 
 | ||||||
|  | 	u16 radio_config; | ||||||
|  | 
 | ||||||
|  | 	u8 calib_version; | ||||||
|  | 	__le16 calib_voltage; | ||||||
|  | 
 | ||||||
|  | 	__le16 raw_temperature; | ||||||
|  | 	__le16 kelvin_temperature; | ||||||
|  | 	__le16 kelvin_voltage; | ||||||
|  | 	__le16 xtal_calib[2]; | ||||||
|  | 
 | ||||||
|  | 	u16 sku; | ||||||
|  | 	u16 radio_cfg; | ||||||
|  | 	u16 eeprom_version; | ||||||
|  | 	s8 max_tx_pwr_half_dbm; | ||||||
|  | 
 | ||||||
|  | 	u8 valid_tx_ant, valid_rx_ant; | ||||||
|  | 
 | ||||||
|  | 	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | ||||||
|  | 	struct ieee80211_channel channels[]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * iwl_parse_eeprom_data - parse EEPROM data and return values | ||||||
|  |  * | ||||||
|  |  * @dev: device pointer we're parsing for, for debug only | ||||||
|  |  * @cfg: device configuration for parsing and overrides | ||||||
|  |  * @eeprom: the EEPROM data | ||||||
|  |  * @eeprom_size: length of the EEPROM data | ||||||
|  |  * | ||||||
|  |  * This function parses all EEPROM values we need and then | ||||||
|  |  * returns a (newly allocated) struct containing all the | ||||||
|  |  * relevant values for driver use. The struct must be freed | ||||||
|  |  * later with iwl_free_eeprom_data(). | ||||||
|  |  */ | ||||||
|  | struct iwl_eeprom_data * | ||||||
|  | iwl_parse_eeprom_data(struct device *dev, const struct iwl_cfg *cfg, | ||||||
|  | 		      const u8 *eeprom, size_t eeprom_size); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * iwl_free_eeprom_data - free EEPROM data | ||||||
|  |  * @data: the data to free | ||||||
|  |  */ | ||||||
|  | static inline void iwl_free_eeprom_data(struct iwl_eeprom_data *data) | ||||||
|  | { | ||||||
|  | 	kfree(data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int iwl_eeprom_check_version(struct iwl_eeprom_data *data, | ||||||
|  | 			     struct iwl_trans *trans); | ||||||
|  | 
 | ||||||
|  | #endif /* __iwl_eeprom_parse_h__ */ | ||||||
							
								
								
									
										463
									
								
								drivers/net/wireless/iwlwifi/iwl-eeprom-read.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										463
									
								
								drivers/net/wireless/iwlwifi/iwl-eeprom-read.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,463 @@ | ||||||
|  | /******************************************************************************
 | ||||||
|  |  * | ||||||
|  |  * 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) 2008 - 2012 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 - 2012 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/types.h> | ||||||
|  | #include <linux/slab.h> | ||||||
|  | #include <linux/export.h> | ||||||
|  | 
 | ||||||
|  | #include "iwl-debug.h" | ||||||
|  | #include "iwl-eeprom-read.h" | ||||||
|  | #include "iwl-io.h" | ||||||
|  | #include "iwl-prph.h" | ||||||
|  | #include "iwl-csr.h" | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * EEPROM access time values: | ||||||
|  |  * | ||||||
|  |  * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG. | ||||||
|  |  * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). | ||||||
|  |  * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. | ||||||
|  |  * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. | ||||||
|  |  */ | ||||||
|  | #define IWL_EEPROM_ACCESS_TIMEOUT	5000 /* uSec */ | ||||||
|  | 
 | ||||||
|  | #define IWL_EEPROM_SEM_TIMEOUT		10   /* microseconds */ | ||||||
|  | #define IWL_EEPROM_SEM_RETRY_LIMIT	1000 /* number of attempts (not time) */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * The device's EEPROM semaphore prevents conflicts between driver and uCode | ||||||
|  |  * when accessing the EEPROM; each access is a series of pulses to/from the | ||||||
|  |  * EEPROM chip, not a single event, so even reads could conflict if they | ||||||
|  |  * weren't arbitrated by the semaphore. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #define	EEPROM_SEM_TIMEOUT 10		/* milliseconds */ | ||||||
|  | #define EEPROM_SEM_RETRY_LIMIT 1000	/* number of attempts (not time) */ | ||||||
|  | 
 | ||||||
|  | static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans) | ||||||
|  | { | ||||||
|  | 	u16 count; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { | ||||||
|  | 		/* Request semaphore */ | ||||||
|  | 		iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, | ||||||
|  | 			    CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||||||
|  | 
 | ||||||
|  | 		/* See if we got it */ | ||||||
|  | 		ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG, | ||||||
|  | 				CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||||||
|  | 				CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||||||
|  | 				EEPROM_SEM_TIMEOUT); | ||||||
|  | 		if (ret >= 0) { | ||||||
|  | 			IWL_DEBUG_EEPROM(trans->dev, | ||||||
|  | 					 "Acquired semaphore after %d tries.\n", | ||||||
|  | 					 count+1); | ||||||
|  | 			return ret; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void iwl_eeprom_release_semaphore(struct iwl_trans *trans) | ||||||
|  | { | ||||||
|  | 	iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG, | ||||||
|  | 		      CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int iwl_eeprom_verify_signature(struct iwl_trans *trans, bool nvm_is_otp) | ||||||
|  | { | ||||||
|  | 	u32 gp = iwl_read32(trans, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; | ||||||
|  | 
 | ||||||
|  | 	IWL_DEBUG_EEPROM(trans->dev, "EEPROM signature=0x%08x\n", gp); | ||||||
|  | 
 | ||||||
|  | 	switch (gp) { | ||||||
|  | 	case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: | ||||||
|  | 		if (!nvm_is_otp) { | ||||||
|  | 			IWL_ERR(trans, "EEPROM with bad signature: 0x%08x\n", | ||||||
|  | 				gp); | ||||||
|  | 			return -ENOENT; | ||||||
|  | 		} | ||||||
|  | 		return 0; | ||||||
|  | 	case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: | ||||||
|  | 	case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: | ||||||
|  | 		if (nvm_is_otp) { | ||||||
|  | 			IWL_ERR(trans, "OTP with bad signature: 0x%08x\n", gp); | ||||||
|  | 			return -ENOENT; | ||||||
|  | 		} | ||||||
|  | 		return 0; | ||||||
|  | 	case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: | ||||||
|  | 	default: | ||||||
|  | 		IWL_ERR(trans, | ||||||
|  | 			"bad EEPROM/OTP signature, type=%s, EEPROM_GP=0x%08x\n", | ||||||
|  | 			nvm_is_otp ? "OTP" : "EEPROM", gp); | ||||||
|  | 		return -ENOENT; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /******************************************************************************
 | ||||||
|  |  * | ||||||
|  |  * OTP related functions | ||||||
|  |  * | ||||||
|  | ******************************************************************************/ | ||||||
|  | 
 | ||||||
|  | static void iwl_set_otp_access_absolute(struct iwl_trans *trans) | ||||||
|  | { | ||||||
|  | 	iwl_read32(trans, CSR_OTP_GP_REG); | ||||||
|  | 
 | ||||||
|  | 	iwl_clear_bit(trans, CSR_OTP_GP_REG, | ||||||
|  | 		      CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int iwl_nvm_is_otp(struct iwl_trans *trans) | ||||||
|  | { | ||||||
|  | 	u32 otpgp; | ||||||
|  | 
 | ||||||
|  | 	/* OTP only valid for CP/PP and after */ | ||||||
|  | 	switch (trans->hw_rev & CSR_HW_REV_TYPE_MSK) { | ||||||
|  | 	case CSR_HW_REV_TYPE_NONE: | ||||||
|  | 		IWL_ERR(trans, "Unknown hardware type\n"); | ||||||
|  | 		return -EIO; | ||||||
|  | 	case CSR_HW_REV_TYPE_5300: | ||||||
|  | 	case CSR_HW_REV_TYPE_5350: | ||||||
|  | 	case CSR_HW_REV_TYPE_5100: | ||||||
|  | 	case CSR_HW_REV_TYPE_5150: | ||||||
|  | 		return 0; | ||||||
|  | 	default: | ||||||
|  | 		otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||||||
|  | 		if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) | ||||||
|  | 			return 1; | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int iwl_init_otp_access(struct iwl_trans *trans) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	/* Enable 40MHz radio clock */ | ||||||
|  | 	iwl_write32(trans, CSR_GP_CNTRL, | ||||||
|  | 		    iwl_read32(trans, CSR_GP_CNTRL) | | ||||||
|  | 		    CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||||||
|  | 
 | ||||||
|  | 	/* wait for clock to be ready */ | ||||||
|  | 	ret = iwl_poll_bit(trans, CSR_GP_CNTRL, | ||||||
|  | 			   CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||||||
|  | 			   CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||||||
|  | 			   25000); | ||||||
|  | 	if (ret < 0) { | ||||||
|  | 		IWL_ERR(trans, "Time out access OTP\n"); | ||||||
|  | 	} else { | ||||||
|  | 		iwl_set_bits_prph(trans, APMG_PS_CTRL_REG, | ||||||
|  | 				  APMG_PS_CTRL_VAL_RESET_REQ); | ||||||
|  | 		udelay(5); | ||||||
|  | 		iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG, | ||||||
|  | 				    APMG_PS_CTRL_VAL_RESET_REQ); | ||||||
|  | 
 | ||||||
|  | 		/*
 | ||||||
|  | 		 * CSR auto clock gate disable bit - | ||||||
|  | 		 * this is only applicable for HW with OTP shadow RAM | ||||||
|  | 		 */ | ||||||
|  | 		if (trans->cfg->base_params->shadow_ram_support) | ||||||
|  | 			iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG, | ||||||
|  | 				    CSR_RESET_LINK_PWR_MGMT_DISABLED); | ||||||
|  | 	} | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr, | ||||||
|  | 			     __le16 *eeprom_data) | ||||||
|  | { | ||||||
|  | 	int ret = 0; | ||||||
|  | 	u32 r; | ||||||
|  | 	u32 otpgp; | ||||||
|  | 
 | ||||||
|  | 	iwl_write32(trans, CSR_EEPROM_REG, | ||||||
|  | 		    CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||||||
|  | 	ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||||||
|  | 				 CSR_EEPROM_REG_READ_VALID_MSK, | ||||||
|  | 				 CSR_EEPROM_REG_READ_VALID_MSK, | ||||||
|  | 				 IWL_EEPROM_ACCESS_TIMEOUT); | ||||||
|  | 	if (ret < 0) { | ||||||
|  | 		IWL_ERR(trans, "Time out reading OTP[%d]\n", addr); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 	r = iwl_read32(trans, CSR_EEPROM_REG); | ||||||
|  | 	/* check for ECC errors: */ | ||||||
|  | 	otpgp = iwl_read32(trans, CSR_OTP_GP_REG); | ||||||
|  | 	if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | ||||||
|  | 		/* stop in this case */ | ||||||
|  | 		/* set the uncorrectable OTP ECC bit for acknowledgement */ | ||||||
|  | 		iwl_set_bit(trans, CSR_OTP_GP_REG, | ||||||
|  | 			    CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||||||
|  | 		IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n"); | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	} | ||||||
|  | 	if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | ||||||
|  | 		/* continue in this case */ | ||||||
|  | 		/* set the correctable OTP ECC bit for acknowledgement */ | ||||||
|  | 		iwl_set_bit(trans, CSR_OTP_GP_REG, | ||||||
|  | 			    CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | ||||||
|  | 		IWL_ERR(trans, "Correctable OTP ECC error, continue read\n"); | ||||||
|  | 	} | ||||||
|  | 	*eeprom_data = cpu_to_le16(r >> 16); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * iwl_is_otp_empty: check for empty OTP | ||||||
|  |  */ | ||||||
|  | static bool iwl_is_otp_empty(struct iwl_trans *trans) | ||||||
|  | { | ||||||
|  | 	u16 next_link_addr = 0; | ||||||
|  | 	__le16 link_value; | ||||||
|  | 	bool is_empty = false; | ||||||
|  | 
 | ||||||
|  | 	/* locate the beginning of OTP link list */ | ||||||
|  | 	if (!iwl_read_otp_word(trans, next_link_addr, &link_value)) { | ||||||
|  | 		if (!link_value) { | ||||||
|  | 			IWL_ERR(trans, "OTP is empty\n"); | ||||||
|  | 			is_empty = true; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		IWL_ERR(trans, "Unable to read first block of OTP list.\n"); | ||||||
|  | 		is_empty = true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return is_empty; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * iwl_find_otp_image: find EEPROM image in OTP | ||||||
|  |  *   finding the OTP block that contains the EEPROM image. | ||||||
|  |  *   the last valid block on the link list (the block _before_ the last block) | ||||||
|  |  *   is the block we should read and used to configure the device. | ||||||
|  |  *   If all the available OTP blocks are full, the last block will be the block | ||||||
|  |  *   we should read and used to configure the device. | ||||||
|  |  *   only perform this operation if shadow RAM is disabled | ||||||
|  |  */ | ||||||
|  | static int iwl_find_otp_image(struct iwl_trans *trans, | ||||||
|  | 					u16 *validblockaddr) | ||||||
|  | { | ||||||
|  | 	u16 next_link_addr = 0, valid_addr; | ||||||
|  | 	__le16 link_value = 0; | ||||||
|  | 	int usedblocks = 0; | ||||||
|  | 
 | ||||||
|  | 	/* set addressing mode to absolute to traverse the link list */ | ||||||
|  | 	iwl_set_otp_access_absolute(trans); | ||||||
|  | 
 | ||||||
|  | 	/* checking for empty OTP or error */ | ||||||
|  | 	if (iwl_is_otp_empty(trans)) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * start traverse link list | ||||||
|  | 	 * until reach the max number of OTP blocks | ||||||
|  | 	 * different devices have different number of OTP blocks | ||||||
|  | 	 */ | ||||||
|  | 	do { | ||||||
|  | 		/* save current valid block address
 | ||||||
|  | 		 * check for more block on the link list | ||||||
|  | 		 */ | ||||||
|  | 		valid_addr = next_link_addr; | ||||||
|  | 		next_link_addr = le16_to_cpu(link_value) * sizeof(u16); | ||||||
|  | 		IWL_DEBUG_EEPROM(trans->dev, "OTP blocks %d addr 0x%x\n", | ||||||
|  | 				 usedblocks, next_link_addr); | ||||||
|  | 		if (iwl_read_otp_word(trans, next_link_addr, &link_value)) | ||||||
|  | 			return -EINVAL; | ||||||
|  | 		if (!link_value) { | ||||||
|  | 			/*
 | ||||||
|  | 			 * reach the end of link list, return success and | ||||||
|  | 			 * set address point to the starting address | ||||||
|  | 			 * of the image | ||||||
|  | 			 */ | ||||||
|  | 			*validblockaddr = valid_addr; | ||||||
|  | 			/* skip first 2 bytes (link list pointer) */ | ||||||
|  | 			*validblockaddr += 2; | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 		/* more in the link list, continue */ | ||||||
|  | 		usedblocks++; | ||||||
|  | 	} while (usedblocks <= trans->cfg->base_params->max_ll_items); | ||||||
|  | 
 | ||||||
|  | 	/* OTP has no valid blocks */ | ||||||
|  | 	IWL_DEBUG_EEPROM(trans->dev, "OTP has no valid blocks\n"); | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * iwl_read_eeprom - read EEPROM contents | ||||||
|  |  * | ||||||
|  |  * Load the EEPROM contents from adapter and return it | ||||||
|  |  * and its size. | ||||||
|  |  * | ||||||
|  |  * NOTE:  This routine uses the non-debug IO access functions. | ||||||
|  |  */ | ||||||
|  | int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size) | ||||||
|  | { | ||||||
|  | 	__le16 *e; | ||||||
|  | 	u32 gp = iwl_read32(trans, CSR_EEPROM_GP); | ||||||
|  | 	int sz; | ||||||
|  | 	int ret; | ||||||
|  | 	u16 addr; | ||||||
|  | 	u16 validblockaddr = 0; | ||||||
|  | 	u16 cache_addr = 0; | ||||||
|  | 	int nvm_is_otp; | ||||||
|  | 
 | ||||||
|  | 	if (!eeprom || !eeprom_size) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	nvm_is_otp = iwl_nvm_is_otp(trans); | ||||||
|  | 	if (nvm_is_otp < 0) | ||||||
|  | 		return nvm_is_otp; | ||||||
|  | 
 | ||||||
|  | 	sz = trans->cfg->base_params->eeprom_size; | ||||||
|  | 	IWL_DEBUG_EEPROM(trans->dev, "NVM size = %d\n", sz); | ||||||
|  | 
 | ||||||
|  | 	e = kmalloc(sz, GFP_KERNEL); | ||||||
|  | 	if (!e) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	ret = iwl_eeprom_verify_signature(trans, nvm_is_otp); | ||||||
|  | 	if (ret < 0) { | ||||||
|  | 		IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | ||||||
|  | 		goto err_free; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Make sure driver (instead of uCode) is allowed to read EEPROM */ | ||||||
|  | 	ret = iwl_eeprom_acquire_semaphore(trans); | ||||||
|  | 	if (ret < 0) { | ||||||
|  | 		IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n"); | ||||||
|  | 		goto err_free; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (nvm_is_otp) { | ||||||
|  | 		ret = iwl_init_otp_access(trans); | ||||||
|  | 		if (ret) { | ||||||
|  | 			IWL_ERR(trans, "Failed to initialize OTP access.\n"); | ||||||
|  | 			goto err_unlock; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		iwl_write32(trans, CSR_EEPROM_GP, | ||||||
|  | 			    iwl_read32(trans, CSR_EEPROM_GP) & | ||||||
|  | 			    ~CSR_EEPROM_GP_IF_OWNER_MSK); | ||||||
|  | 
 | ||||||
|  | 		iwl_set_bit(trans, CSR_OTP_GP_REG, | ||||||
|  | 			    CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | ||||||
|  | 			    CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||||||
|  | 		/* traversing the linked list if no shadow ram supported */ | ||||||
|  | 		if (!trans->cfg->base_params->shadow_ram_support) { | ||||||
|  | 			ret = iwl_find_otp_image(trans, &validblockaddr); | ||||||
|  | 			if (ret) | ||||||
|  | 				goto err_unlock; | ||||||
|  | 		} | ||||||
|  | 		for (addr = validblockaddr; addr < validblockaddr + sz; | ||||||
|  | 		     addr += sizeof(u16)) { | ||||||
|  | 			__le16 eeprom_data; | ||||||
|  | 
 | ||||||
|  | 			ret = iwl_read_otp_word(trans, addr, &eeprom_data); | ||||||
|  | 			if (ret) | ||||||
|  | 				goto err_unlock; | ||||||
|  | 			e[cache_addr / 2] = eeprom_data; | ||||||
|  | 			cache_addr += sizeof(u16); | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		/* eeprom is an array of 16bit values */ | ||||||
|  | 		for (addr = 0; addr < sz; addr += sizeof(u16)) { | ||||||
|  | 			u32 r; | ||||||
|  | 
 | ||||||
|  | 			iwl_write32(trans, CSR_EEPROM_REG, | ||||||
|  | 				    CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||||||
|  | 
 | ||||||
|  | 			ret = iwl_poll_bit(trans, CSR_EEPROM_REG, | ||||||
|  | 					   CSR_EEPROM_REG_READ_VALID_MSK, | ||||||
|  | 					   CSR_EEPROM_REG_READ_VALID_MSK, | ||||||
|  | 					   IWL_EEPROM_ACCESS_TIMEOUT); | ||||||
|  | 			if (ret < 0) { | ||||||
|  | 				IWL_ERR(trans, | ||||||
|  | 					"Time out reading EEPROM[%d]\n", addr); | ||||||
|  | 				goto err_unlock; | ||||||
|  | 			} | ||||||
|  | 			r = iwl_read32(trans, CSR_EEPROM_REG); | ||||||
|  | 			e[addr / 2] = cpu_to_le16(r >> 16); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	IWL_DEBUG_EEPROM(trans->dev, "NVM Type: %s\n", | ||||||
|  | 			 nvm_is_otp ? "OTP" : "EEPROM"); | ||||||
|  | 
 | ||||||
|  | 	iwl_eeprom_release_semaphore(trans); | ||||||
|  | 
 | ||||||
|  | 	*eeprom_size = sz; | ||||||
|  | 	*eeprom = (u8 *)e; | ||||||
|  | 	return 0; | ||||||
|  | 
 | ||||||
|  |  err_unlock: | ||||||
|  | 	iwl_eeprom_release_semaphore(trans); | ||||||
|  |  err_free: | ||||||
|  | 	kfree(e); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(iwl_read_eeprom); | ||||||
							
								
								
									
										70
									
								
								drivers/net/wireless/iwlwifi/iwl-eeprom-read.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								drivers/net/wireless/iwlwifi/iwl-eeprom-read.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,70 @@ | ||||||
|  | /******************************************************************************
 | ||||||
|  |  * | ||||||
|  |  * 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) 2008 - 2012 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 - 2012 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_eeprom_h__ | ||||||
|  | #define __iwl_eeprom_h__ | ||||||
|  | 
 | ||||||
|  | #include "iwl-trans.h" | ||||||
|  | 
 | ||||||
|  | int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size); | ||||||
|  | 
 | ||||||
|  | #endif  /* __iwl_eeprom_h__ */ | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,269 +0,0 @@ | ||||||
| /******************************************************************************
 |  | ||||||
|  * |  | ||||||
|  * 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) 2008 - 2012 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 - 2012 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_eeprom_h__ |  | ||||||
| #define __iwl_eeprom_h__ |  | ||||||
| 
 |  | ||||||
| #include <net/mac80211.h> |  | ||||||
| 
 |  | ||||||
| struct iwl_priv; |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * EEPROM access time values: |  | ||||||
|  * |  | ||||||
|  * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG. |  | ||||||
|  * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). |  | ||||||
|  * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. |  | ||||||
|  * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. |  | ||||||
|  */ |  | ||||||
| #define IWL_EEPROM_ACCESS_TIMEOUT	5000 /* uSec */ |  | ||||||
| 
 |  | ||||||
| #define IWL_EEPROM_SEM_TIMEOUT 		10   /* microseconds */ |  | ||||||
| #define IWL_EEPROM_SEM_RETRY_LIMIT	1000 /* number of attempts (not time) */ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags. |  | ||||||
|  * |  | ||||||
|  * IBSS and/or AP operation is allowed *only* on those channels with |  | ||||||
|  * (VALID && IBSS && ACTIVE && !RADAR).  This restriction is in place because |  | ||||||
|  * RADAR detection is not supported by the 4965 driver, but is a |  | ||||||
|  * requirement for establishing a new network for legal operation on channels |  | ||||||
|  * requiring RADAR detection or restricting ACTIVE scanning. |  | ||||||
|  * |  | ||||||
|  * NOTE:  "WIDE" flag does not indicate anything about "HT40" 40 MHz channels. |  | ||||||
|  *        It only indicates that 20 MHz channel use is supported; HT40 channel |  | ||||||
|  *        usage is indicated by a separate set of regulatory flags for each |  | ||||||
|  *        HT40 channel pair. |  | ||||||
|  * |  | ||||||
|  * NOTE:  Using a channel inappropriately will result in a uCode error! |  | ||||||
|  */ |  | ||||||
| #define IWL_NUM_TX_CALIB_GROUPS 5 |  | ||||||
| enum { |  | ||||||
| 	EEPROM_CHANNEL_VALID = (1 << 0),	/* usable for this SKU/geo */ |  | ||||||
| 	EEPROM_CHANNEL_IBSS = (1 << 1),		/* usable as an IBSS channel */ |  | ||||||
| 	/* Bit 2 Reserved */ |  | ||||||
| 	EEPROM_CHANNEL_ACTIVE = (1 << 3),	/* active scanning allowed */ |  | ||||||
| 	EEPROM_CHANNEL_RADAR = (1 << 4),	/* radar detection required */ |  | ||||||
| 	EEPROM_CHANNEL_WIDE = (1 << 5),		/* 20 MHz channel okay */ |  | ||||||
| 	/* Bit 6 Reserved (was Narrow Channel) */ |  | ||||||
| 	EEPROM_CHANNEL_DFS = (1 << 7),	/* dynamic freq selection candidate */ |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /* SKU Capabilities */ |  | ||||||
| #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_IPAN_ENABLE	                (1 << 8) |  | ||||||
| 
 |  | ||||||
| /* *regulatory* channel data format in eeprom, one for each channel.
 |  | ||||||
|  * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */ |  | ||||||
| struct iwl_eeprom_channel { |  | ||||||
| 	u8 flags;		/* EEPROM_CHANNEL_* flags copied from EEPROM */ |  | ||||||
| 	s8 max_power_avg;	/* max power (dBm) on this chnl, limit 31 */ |  | ||||||
| } __packed; |  | ||||||
| 
 |  | ||||||
| enum iwl_eeprom_enhanced_txpwr_flags { |  | ||||||
| 	IWL_EEPROM_ENH_TXP_FL_VALID		= BIT(0), |  | ||||||
| 	IWL_EEPROM_ENH_TXP_FL_BAND_52G		= BIT(1), |  | ||||||
| 	IWL_EEPROM_ENH_TXP_FL_OFDM		= BIT(2), |  | ||||||
| 	IWL_EEPROM_ENH_TXP_FL_40MHZ		= BIT(3), |  | ||||||
| 	IWL_EEPROM_ENH_TXP_FL_HT_AP		= BIT(4), |  | ||||||
| 	IWL_EEPROM_ENH_TXP_FL_RES1		= BIT(5), |  | ||||||
| 	IWL_EEPROM_ENH_TXP_FL_RES2		= BIT(6), |  | ||||||
| 	IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE	= BIT(7), |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /**
 |  | ||||||
|  * iwl_eeprom_enhanced_txpwr structure |  | ||||||
|  *    This structure presents the enhanced regulatory tx power limit layout |  | ||||||
|  *    in eeprom image |  | ||||||
|  *    Enhanced regulatory tx power portion of eeprom image can be broken down |  | ||||||
|  *    into individual structures; each one is 8 bytes in size and contain the |  | ||||||
|  *    following information |  | ||||||
|  * @flags: entry flags |  | ||||||
|  * @channel: channel number |  | ||||||
|  * @chain_a_max_pwr: chain a max power in 1/2 dBm |  | ||||||
|  * @chain_b_max_pwr: chain b max power in 1/2 dBm |  | ||||||
|  * @chain_c_max_pwr: chain c max power in 1/2 dBm |  | ||||||
|  * @delta_20_in_40: 20-in-40 deltas (hi/lo) |  | ||||||
|  * @mimo2_max_pwr: mimo2 max power in 1/2 dBm |  | ||||||
|  * @mimo3_max_pwr: mimo3 max power in 1/2 dBm |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| struct iwl_eeprom_enhanced_txpwr { |  | ||||||
| 	u8 flags; |  | ||||||
| 	u8 channel; |  | ||||||
| 	s8 chain_a_max; |  | ||||||
| 	s8 chain_b_max; |  | ||||||
| 	s8 chain_c_max; |  | ||||||
| 	u8 delta_20_in_40; |  | ||||||
| 	s8 mimo2_max; |  | ||||||
| 	s8 mimo3_max; |  | ||||||
| } __packed; |  | ||||||
| 
 |  | ||||||
| /* calibration */ |  | ||||||
| struct iwl_eeprom_calib_hdr { |  | ||||||
| 	u8 version; |  | ||||||
| 	u8 pa_type; |  | ||||||
| 	__le16 voltage; |  | ||||||
| } __packed; |  | ||||||
| 
 |  | ||||||
| #define EEPROM_CALIB_ALL	(INDIRECT_ADDRESS | INDIRECT_CALIBRATION) |  | ||||||
| #define EEPROM_XTAL		((2*0x128) | EEPROM_CALIB_ALL) |  | ||||||
| 
 |  | ||||||
| /* temperature */ |  | ||||||
| #define EEPROM_KELVIN_TEMPERATURE	((2*0x12A) | EEPROM_CALIB_ALL) |  | ||||||
| #define EEPROM_RAW_TEMPERATURE		((2*0x12B) | EEPROM_CALIB_ALL) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* agn links */ |  | ||||||
| #define EEPROM_LINK_HOST             (2*0x64) |  | ||||||
| #define EEPROM_LINK_GENERAL          (2*0x65) |  | ||||||
| #define EEPROM_LINK_REGULATORY       (2*0x66) |  | ||||||
| #define EEPROM_LINK_CALIBRATION      (2*0x67) |  | ||||||
| #define EEPROM_LINK_PROCESS_ADJST    (2*0x68) |  | ||||||
| #define EEPROM_LINK_OTHERS           (2*0x69) |  | ||||||
| #define EEPROM_LINK_TXP_LIMIT        (2*0x6a) |  | ||||||
| #define EEPROM_LINK_TXP_LIMIT_SIZE   (2*0x6b) |  | ||||||
| 
 |  | ||||||
| /* agn regulatory - indirect access */ |  | ||||||
| #define EEPROM_REG_BAND_1_CHANNELS       ((0x08)\ |  | ||||||
| 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 28 bytes */ |  | ||||||
| #define EEPROM_REG_BAND_2_CHANNELS       ((0x26)\ |  | ||||||
| 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 26 bytes */ |  | ||||||
| #define EEPROM_REG_BAND_3_CHANNELS       ((0x42)\ |  | ||||||
| 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 24 bytes */ |  | ||||||
| #define EEPROM_REG_BAND_4_CHANNELS       ((0x5C)\ |  | ||||||
| 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 22 bytes */ |  | ||||||
| #define EEPROM_REG_BAND_5_CHANNELS       ((0x74)\ |  | ||||||
| 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 12 bytes */ |  | ||||||
| #define EEPROM_REG_BAND_24_HT40_CHANNELS  ((0x82)\ |  | ||||||
| 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 14  bytes */ |  | ||||||
| #define EEPROM_REG_BAND_52_HT40_CHANNELS  ((0x92)\ |  | ||||||
| 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 22  bytes */ |  | ||||||
| 
 |  | ||||||
| /* 6000 regulatory - indirect access */ |  | ||||||
| #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS  ((0x80)\ |  | ||||||
| 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 14  bytes */ |  | ||||||
| /* 2.4 GHz */ |  | ||||||
| extern const u8 iwl_eeprom_band_1[14]; |  | ||||||
| 
 |  | ||||||
| #define ADDRESS_MSK                 0x0000FFFF |  | ||||||
| #define INDIRECT_TYPE_MSK           0x000F0000 |  | ||||||
| #define INDIRECT_HOST               0x00010000 |  | ||||||
| #define INDIRECT_GENERAL            0x00020000 |  | ||||||
| #define INDIRECT_REGULATORY         0x00030000 |  | ||||||
| #define INDIRECT_CALIBRATION        0x00040000 |  | ||||||
| #define INDIRECT_PROCESS_ADJST      0x00050000 |  | ||||||
| #define INDIRECT_OTHERS             0x00060000 |  | ||||||
| #define INDIRECT_TXP_LIMIT          0x00070000 |  | ||||||
| #define INDIRECT_TXP_LIMIT_SIZE     0x00080000 |  | ||||||
| #define INDIRECT_ADDRESS            0x00100000 |  | ||||||
| 
 |  | ||||||
| /* 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_RADIO_CONFIG                 (2*0x48)	/* 2  bytes */ |  | ||||||
| #define EEPROM_NUM_MAC_ADDRESS              (2*0x4C)	/* 2  bytes */ |  | ||||||
| 
 |  | ||||||
| /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ |  | ||||||
| #define EEPROM_RF_CFG_TYPE_MSK(x)   (x & 0x3)         /* bits 0-1   */ |  | ||||||
| #define EEPROM_RF_CFG_STEP_MSK(x)   ((x >> 2)  & 0x3) /* bits 2-3   */ |  | ||||||
| #define EEPROM_RF_CFG_DASH_MSK(x)   ((x >> 4)  & 0x3) /* bits 4-5   */ |  | ||||||
| #define EEPROM_RF_CFG_PNUM_MSK(x)   ((x >> 6)  & 0x3) /* bits 6-7   */ |  | ||||||
| #define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8)  & 0xF) /* bits 8-11  */ |  | ||||||
| #define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ |  | ||||||
| 
 |  | ||||||
| #define EEPROM_RF_CONFIG_TYPE_MAX	0x3 |  | ||||||
| 
 |  | ||||||
| #define EEPROM_REGULATORY_BAND_NO_HT40			(0) |  | ||||||
| 
 |  | ||||||
| struct iwl_eeprom_ops { |  | ||||||
| 	const u32 regulatory_bands[7]; |  | ||||||
| 	bool enhanced_txpower; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev); |  | ||||||
| void iwl_eeprom_free(struct iwl_priv *priv); |  | ||||||
| int iwl_eeprom_check_version(struct iwl_priv *priv); |  | ||||||
| int iwl_eeprom_init_hw_params(struct iwl_priv *priv); |  | ||||||
| u16 iwl_eeprom_calib_version(struct iwl_priv *priv); |  | ||||||
| const u8 *iwl_eeprom_query_addr(struct iwl_priv *priv, size_t offset); |  | ||||||
| u16 iwl_eeprom_query16(struct iwl_priv *priv, size_t offset); |  | ||||||
| void iwl_eeprom_get_mac(struct iwl_priv *priv, u8 *mac); |  | ||||||
| int iwl_init_channel_map(struct iwl_priv *priv); |  | ||||||
| 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__ */ |  | ||||||
|  | @ -65,6 +65,24 @@ void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask) | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(iwl_clear_bit); | EXPORT_SYMBOL_GPL(iwl_clear_bit); | ||||||
| 
 | 
 | ||||||
|  | void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value) | ||||||
|  | { | ||||||
|  | 	unsigned long flags; | ||||||
|  | 	u32 v; | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_IWLWIFI_DEBUG | ||||||
|  | 	WARN_ON_ONCE(value & ~mask); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	spin_lock_irqsave(&trans->reg_lock, flags); | ||||||
|  | 	v = iwl_read32(trans, reg); | ||||||
|  | 	v &= ~mask; | ||||||
|  | 	v |= value; | ||||||
|  | 	iwl_write32(trans, reg, v); | ||||||
|  | 	spin_unlock_irqrestore(&trans->reg_lock, flags); | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(iwl_set_bits_mask); | ||||||
|  | 
 | ||||||
| int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | ||||||
| 		 u32 bits, u32 mask, int timeout) | 		 u32 bits, u32 mask, int timeout) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -54,6 +54,8 @@ static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) | ||||||
| void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); | void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask); | ||||||
| void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); | void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask); | ||||||
| 
 | 
 | ||||||
|  | void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value); | ||||||
|  | 
 | ||||||
| int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | int iwl_poll_bit(struct iwl_trans *trans, u32 addr, | ||||||
| 		 u32 bits, u32 mask, int timeout); | 		 u32 bits, u32 mask, int timeout); | ||||||
| int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask, | ||||||
|  |  | ||||||
|  | @ -221,9 +221,4 @@ static inline void iwl_op_mode_wimax_active(struct iwl_op_mode *op_mode) | ||||||
| 	op_mode->ops->wimax_active(op_mode); | 	op_mode->ops->wimax_active(op_mode); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*****************************************************
 |  | ||||||
| * Op mode layers implementations |  | ||||||
| ******************************************************/ |  | ||||||
| extern const struct iwl_op_mode_ops iwl_dvm_ops; |  | ||||||
| 
 |  | ||||||
| #endif /* __iwl_op_mode_h__ */ | #endif /* __iwl_op_mode_h__ */ | ||||||
|  |  | ||||||
|  | @ -187,7 +187,7 @@ | ||||||
| #define SCD_QUEUE_STTS_REG_POS_ACTIVE	(3) | #define SCD_QUEUE_STTS_REG_POS_ACTIVE	(3) | ||||||
| #define SCD_QUEUE_STTS_REG_POS_WSL	(4) | #define SCD_QUEUE_STTS_REG_POS_WSL	(4) | ||||||
| #define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) | #define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) | ||||||
| #define SCD_QUEUE_STTS_REG_MSK		(0x00FF0000) | #define SCD_QUEUE_STTS_REG_MSK		(0x017F0000) | ||||||
| 
 | 
 | ||||||
| #define SCD_QUEUE_CTX_REG1_CREDIT_POS		(8) | #define SCD_QUEUE_CTX_REG1_CREDIT_POS		(8) | ||||||
| #define SCD_QUEUE_CTX_REG1_CREDIT_MSK		(0x00FFFF00) | #define SCD_QUEUE_CTX_REG1_CREDIT_MSK		(0x00FFFF00) | ||||||
|  |  | ||||||
|  | @ -355,10 +355,10 @@ struct iwl_trans; | ||||||
|  *	Must be atomic |  *	Must be atomic | ||||||
|  * @reclaim: free packet until ssn. Returns a list of freed packets. |  * @reclaim: free packet until ssn. Returns a list of freed packets. | ||||||
|  *	Must be atomic |  *	Must be atomic | ||||||
|  * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is |  * @txq_enable: setup a tx queue for AMPDU - will be called once the HW is | ||||||
|  *	ready and a successful ADDBA response has been received. |  *	ready and a successful ADDBA response has been received. | ||||||
|  *	May sleep |  *	May sleep | ||||||
|  * @tx_agg_disable: de-configure a Tx queue to send AMPDUs |  * @txq_disable: de-configure a Tx queue to send AMPDUs | ||||||
|  *	Must be atomic |  *	Must be atomic | ||||||
|  * @wait_tx_queue_empty: wait until all tx queues are empty |  * @wait_tx_queue_empty: wait until all tx queues are empty | ||||||
|  *	May sleep |  *	May sleep | ||||||
|  | @ -391,9 +391,9 @@ struct iwl_trans_ops { | ||||||
| 	void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, | 	void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, | ||||||
| 			struct sk_buff_head *skbs); | 			struct sk_buff_head *skbs); | ||||||
| 
 | 
 | ||||||
| 	void (*tx_agg_setup)(struct iwl_trans *trans, int queue, int fifo, | 	void (*txq_enable)(struct iwl_trans *trans, int queue, int fifo, | ||||||
| 			   int sta_id, int tid, int frame_limit, u16 ssn); | 			   int sta_id, int tid, int frame_limit, u16 ssn); | ||||||
| 	void (*tx_agg_disable)(struct iwl_trans *trans, int queue); | 	void (*txq_disable)(struct iwl_trans *trans, int queue); | ||||||
| 
 | 
 | ||||||
| 	int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | 	int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | ||||||
| 	int (*wait_tx_queue_empty)(struct iwl_trans *trans); | 	int (*wait_tx_queue_empty)(struct iwl_trans *trans); | ||||||
|  | @ -433,6 +433,11 @@ enum iwl_trans_state { | ||||||
|  * @hw_id_str: a string with info about HW ID. Set during transport allocation. |  * @hw_id_str: a string with info about HW ID. Set during transport allocation. | ||||||
|  * @pm_support: set to true in start_hw if link pm is supported |  * @pm_support: set to true in start_hw if link pm is supported | ||||||
|  * @wait_command_queue: the wait_queue for SYNC host commands |  * @wait_command_queue: the wait_queue for SYNC host commands | ||||||
|  |  * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. | ||||||
|  |  *	The user should use iwl_trans_{alloc,free}_tx_cmd. | ||||||
|  |  * @dev_cmd_headroom: room needed for the transport's private use before the | ||||||
|  |  *	device_cmd for Tx - for internal use only | ||||||
|  |  *	The user should use iwl_trans_{alloc,free}_tx_cmd. | ||||||
|  */ |  */ | ||||||
| struct iwl_trans { | struct iwl_trans { | ||||||
| 	const struct iwl_trans_ops *ops; | 	const struct iwl_trans_ops *ops; | ||||||
|  | @ -450,6 +455,10 @@ struct iwl_trans { | ||||||
| 
 | 
 | ||||||
| 	wait_queue_head_t wait_command_queue; | 	wait_queue_head_t wait_command_queue; | ||||||
| 
 | 
 | ||||||
|  | 	/* The following fields are internal only */ | ||||||
|  | 	struct kmem_cache *dev_cmd_pool; | ||||||
|  | 	size_t dev_cmd_headroom; | ||||||
|  | 
 | ||||||
| 	/* pointer to trans specific struct */ | 	/* pointer to trans specific struct */ | ||||||
| 	/*Ensure that this pointer will always be aligned to sizeof pointer */ | 	/*Ensure that this pointer will always be aligned to sizeof pointer */ | ||||||
| 	char trans_specific[0] __aligned(sizeof(void *)); | 	char trans_specific[0] __aligned(sizeof(void *)); | ||||||
|  | @ -525,6 +534,26 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | ||||||
| 	return trans->ops->send_cmd(trans, cmd); | 	return trans->ops->send_cmd(trans, cmd); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static inline struct iwl_device_cmd * | ||||||
|  | iwl_trans_alloc_tx_cmd(struct iwl_trans *trans) | ||||||
|  | { | ||||||
|  | 	u8 *dev_cmd_ptr = kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC); | ||||||
|  | 
 | ||||||
|  | 	if (unlikely(dev_cmd_ptr == NULL)) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	return (struct iwl_device_cmd *) | ||||||
|  | 			(dev_cmd_ptr + trans->dev_cmd_headroom); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans, | ||||||
|  | 					 struct iwl_device_cmd *dev_cmd) | ||||||
|  | { | ||||||
|  | 	u8 *dev_cmd_ptr = (u8 *)dev_cmd - trans->dev_cmd_headroom; | ||||||
|  | 
 | ||||||
|  | 	kmem_cache_free(trans->dev_cmd_pool, dev_cmd_ptr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | ||||||
| 			       struct iwl_device_cmd *dev_cmd, int queue) | 			       struct iwl_device_cmd *dev_cmd, int queue) | ||||||
| { | { | ||||||
|  | @ -543,15 +572,15 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, | ||||||
| 	trans->ops->reclaim(trans, queue, ssn, skbs); | 	trans->ops->reclaim(trans, queue, ssn, skbs); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void iwl_trans_tx_agg_disable(struct iwl_trans *trans, int queue) | static inline void iwl_trans_txq_disable(struct iwl_trans *trans, int queue) | ||||||
| { | { | ||||||
| 	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | ||||||
| 		  "%s bad state = %d", __func__, trans->state); | 		  "%s bad state = %d", __func__, trans->state); | ||||||
| 
 | 
 | ||||||
| 	trans->ops->tx_agg_disable(trans, queue); | 	trans->ops->txq_disable(trans, queue); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, int queue, | static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue, | ||||||
| 					int fifo, int sta_id, int tid, | 					int fifo, int sta_id, int tid, | ||||||
| 					int frame_limit, u16 ssn) | 					int frame_limit, u16 ssn) | ||||||
| { | { | ||||||
|  | @ -560,7 +589,7 @@ static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, int queue, | ||||||
| 	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 	WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | ||||||
| 		  "%s bad state = %d", __func__, trans->state); | 		  "%s bad state = %d", __func__, trans->state); | ||||||
| 
 | 
 | ||||||
| 	trans->ops->tx_agg_setup(trans, queue, fifo, sta_id, tid, | 	trans->ops->txq_enable(trans, queue, fifo, sta_id, tid, | ||||||
| 				 frame_limit, ssn); | 				 frame_limit, ssn); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,9 +27,9 @@ | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/stringify.h> | #include <linux/stringify.h> | ||||||
| #include "iwl-config.h" | #include "iwl-config.h" | ||||||
| #include "iwl-cfg.h" |  | ||||||
| #include "iwl-csr.h" | #include "iwl-csr.h" | ||||||
| #include "iwl-agn-hw.h" | #include "iwl-agn-hw.h" | ||||||
|  | #include "cfg.h" | ||||||
| 
 | 
 | ||||||
| /* Highest firmware API version supported */ | /* Highest firmware API version supported */ | ||||||
| #define IWL1000_UCODE_API_MAX 5 | #define IWL1000_UCODE_API_MAX 5 | ||||||
|  | @ -64,13 +64,26 @@ static const struct iwl_base_params iwl1000_base_params = { | ||||||
| 	.support_ct_kill_exit = true, | 	.support_ct_kill_exit = true, | ||||||
| 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | ||||||
| 	.chain_noise_scale = 1000, | 	.chain_noise_scale = 1000, | ||||||
| 	.wd_timeout = IWL_WATCHHDOG_DISABLED, | 	.wd_timeout = IWL_WATCHDOG_DISABLED, | ||||||
| 	.max_event_log_size = 128, | 	.max_event_log_size = 128, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const struct iwl_ht_params iwl1000_ht_params = { | static const struct iwl_ht_params iwl1000_ht_params = { | ||||||
| 	.ht_greenfield_support = true, | 	.ht_greenfield_support = true, | ||||||
| 	.use_rts_for_aggregation = true, /* use rts/cts protection */ | 	.use_rts_for_aggregation = true, /* use rts/cts protection */ | ||||||
|  | 	.ht40_bands = BIT(IEEE80211_BAND_2GHZ), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const struct iwl_eeprom_params iwl1000_eeprom_params = { | ||||||
|  | 	.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_REG_BAND_24_HT40_CHANNELS, | ||||||
|  | 		EEPROM_REGULATORY_BAND_NO_HT40, | ||||||
|  | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define IWL_DEVICE_1000						\ | #define IWL_DEVICE_1000						\ | ||||||
|  | @ -84,6 +97,7 @@ static const struct iwl_ht_params iwl1000_ht_params = { | ||||||
| 	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,		\ | 	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,		\ | ||||||
| 	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl1000_base_params,			\ | 	.base_params = &iwl1000_base_params,			\ | ||||||
|  | 	.eeprom_params = &iwl1000_eeprom_params,		\ | ||||||
| 	.led_mode = IWL_LED_BLINK | 	.led_mode = IWL_LED_BLINK | ||||||
| 
 | 
 | ||||||
| const struct iwl_cfg iwl1000_bgn_cfg = { | const struct iwl_cfg iwl1000_bgn_cfg = { | ||||||
|  | @ -108,6 +122,7 @@ const struct iwl_cfg iwl1000_bg_cfg = { | ||||||
| 	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,		\ | 	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,		\ | ||||||
| 	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl1000_base_params,			\ | 	.base_params = &iwl1000_base_params,			\ | ||||||
|  | 	.eeprom_params = &iwl1000_eeprom_params,		\ | ||||||
| 	.led_mode = IWL_LED_RF_STATE,				\ | 	.led_mode = IWL_LED_RF_STATE,				\ | ||||||
| 	.rx_with_siso_diversity = true | 	.rx_with_siso_diversity = true | ||||||
| 
 | 
 | ||||||
|  | @ -27,9 +27,9 @@ | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/stringify.h> | #include <linux/stringify.h> | ||||||
| #include "iwl-config.h" | #include "iwl-config.h" | ||||||
| #include "iwl-cfg.h" |  | ||||||
| #include "iwl-agn-hw.h" | #include "iwl-agn-hw.h" | ||||||
| #include "iwl-commands.h" /* needed for BT for now */ | #include "cfg.h" | ||||||
|  | #include "dvm/commands.h" /* needed for BT for now */ | ||||||
| 
 | 
 | ||||||
| /* Highest firmware API version supported */ | /* Highest firmware API version supported */ | ||||||
| #define IWL2030_UCODE_API_MAX 6 | #define IWL2030_UCODE_API_MAX 6 | ||||||
|  | @ -104,6 +104,7 @@ static const struct iwl_base_params iwl2030_base_params = { | ||||||
| static const struct iwl_ht_params iwl2000_ht_params = { | static const struct iwl_ht_params iwl2000_ht_params = { | ||||||
| 	.ht_greenfield_support = true, | 	.ht_greenfield_support = true, | ||||||
| 	.use_rts_for_aggregation = true, /* use rts/cts protection */ | 	.use_rts_for_aggregation = true, /* use rts/cts protection */ | ||||||
|  | 	.ht40_bands = BIT(IEEE80211_BAND_2GHZ), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const struct iwl_bt_params iwl2030_bt_params = { | static const struct iwl_bt_params iwl2030_bt_params = { | ||||||
|  | @ -116,6 +117,19 @@ static const struct iwl_bt_params iwl2030_bt_params = { | ||||||
| 	.bt_session_2 = true, | 	.bt_session_2 = true, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static const struct iwl_eeprom_params iwl20x0_eeprom_params = { | ||||||
|  | 	.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, | ||||||
|  | 	}, | ||||||
|  | 	.enhanced_txpower = true, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| #define IWL_DEVICE_2000						\ | #define IWL_DEVICE_2000						\ | ||||||
| 	.fw_name_pre = IWL2000_FW_PRE,				\ | 	.fw_name_pre = IWL2000_FW_PRE,				\ | ||||||
| 	.ucode_api_max = IWL2000_UCODE_API_MAX,			\ | 	.ucode_api_max = IWL2000_UCODE_API_MAX,			\ | ||||||
|  | @ -127,6 +141,7 @@ static const struct iwl_bt_params iwl2030_bt_params = { | ||||||
| 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\ | 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\ | ||||||
| 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl2000_base_params,			\ | 	.base_params = &iwl2000_base_params,			\ | ||||||
|  | 	.eeprom_params = &iwl20x0_eeprom_params,		\ | ||||||
| 	.need_temp_offset_calib = true,				\ | 	.need_temp_offset_calib = true,				\ | ||||||
| 	.temp_offset_v2 = true,					\ | 	.temp_offset_v2 = true,					\ | ||||||
| 	.led_mode = IWL_LED_RF_STATE | 	.led_mode = IWL_LED_RF_STATE | ||||||
|  | @ -155,6 +170,7 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = { | ||||||
| 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl2030_base_params,			\ | 	.base_params = &iwl2030_base_params,			\ | ||||||
| 	.bt_params = &iwl2030_bt_params,			\ | 	.bt_params = &iwl2030_bt_params,			\ | ||||||
|  | 	.eeprom_params = &iwl20x0_eeprom_params,		\ | ||||||
| 	.need_temp_offset_calib = true,				\ | 	.need_temp_offset_calib = true,				\ | ||||||
| 	.temp_offset_v2 = true,					\ | 	.temp_offset_v2 = true,					\ | ||||||
| 	.led_mode = IWL_LED_RF_STATE,				\ | 	.led_mode = IWL_LED_RF_STATE,				\ | ||||||
|  | @ -177,6 +193,7 @@ const struct iwl_cfg iwl2030_2bgn_cfg = { | ||||||
| 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\ | 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\ | ||||||
| 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl2000_base_params,			\ | 	.base_params = &iwl2000_base_params,			\ | ||||||
|  | 	.eeprom_params = &iwl20x0_eeprom_params,		\ | ||||||
| 	.need_temp_offset_calib = true,				\ | 	.need_temp_offset_calib = true,				\ | ||||||
| 	.temp_offset_v2 = true,					\ | 	.temp_offset_v2 = true,					\ | ||||||
| 	.led_mode = IWL_LED_RF_STATE,				\ | 	.led_mode = IWL_LED_RF_STATE,				\ | ||||||
|  | @ -207,6 +224,7 @@ const struct iwl_cfg iwl105_bgn_d_cfg = { | ||||||
| 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl2030_base_params,			\ | 	.base_params = &iwl2030_base_params,			\ | ||||||
| 	.bt_params = &iwl2030_bt_params,			\ | 	.bt_params = &iwl2030_bt_params,			\ | ||||||
|  | 	.eeprom_params = &iwl20x0_eeprom_params,		\ | ||||||
| 	.need_temp_offset_calib = true,				\ | 	.need_temp_offset_calib = true,				\ | ||||||
| 	.temp_offset_v2 = true,					\ | 	.temp_offset_v2 = true,					\ | ||||||
| 	.led_mode = IWL_LED_RF_STATE,				\ | 	.led_mode = IWL_LED_RF_STATE,				\ | ||||||
|  | @ -27,9 +27,9 @@ | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/stringify.h> | #include <linux/stringify.h> | ||||||
| #include "iwl-config.h" | #include "iwl-config.h" | ||||||
| #include "iwl-cfg.h" |  | ||||||
| #include "iwl-agn-hw.h" | #include "iwl-agn-hw.h" | ||||||
| #include "iwl-csr.h" | #include "iwl-csr.h" | ||||||
|  | #include "cfg.h" | ||||||
| 
 | 
 | ||||||
| /* Highest firmware API version supported */ | /* Highest firmware API version supported */ | ||||||
| #define IWL5000_UCODE_API_MAX 5 | #define IWL5000_UCODE_API_MAX 5 | ||||||
|  | @ -62,13 +62,26 @@ static const struct iwl_base_params iwl5000_base_params = { | ||||||
| 	.led_compensation = 51, | 	.led_compensation = 51, | ||||||
| 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | ||||||
| 	.chain_noise_scale = 1000, | 	.chain_noise_scale = 1000, | ||||||
| 	.wd_timeout = IWL_WATCHHDOG_DISABLED, | 	.wd_timeout = IWL_WATCHDOG_DISABLED, | ||||||
| 	.max_event_log_size = 512, | 	.max_event_log_size = 512, | ||||||
| 	.no_idle_support = true, | 	.no_idle_support = true, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const struct iwl_ht_params iwl5000_ht_params = { | static const struct iwl_ht_params iwl5000_ht_params = { | ||||||
| 	.ht_greenfield_support = true, | 	.ht_greenfield_support = true, | ||||||
|  | 	.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const struct iwl_eeprom_params iwl5000_eeprom_params = { | ||||||
|  | 	.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_REG_BAND_24_HT40_CHANNELS, | ||||||
|  | 		EEPROM_REG_BAND_52_HT40_CHANNELS | ||||||
|  | 	}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define IWL_DEVICE_5000						\ | #define IWL_DEVICE_5000						\ | ||||||
|  | @ -82,6 +95,7 @@ static const struct iwl_ht_params iwl5000_ht_params = { | ||||||
| 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,		\ | 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,		\ | ||||||
| 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl5000_base_params,			\ | 	.base_params = &iwl5000_base_params,			\ | ||||||
|  | 	.eeprom_params = &iwl5000_eeprom_params,		\ | ||||||
| 	.led_mode = IWL_LED_BLINK | 	.led_mode = IWL_LED_BLINK | ||||||
| 
 | 
 | ||||||
| const struct iwl_cfg iwl5300_agn_cfg = { | const struct iwl_cfg iwl5300_agn_cfg = { | ||||||
|  | @ -128,6 +142,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { | ||||||
| 	.eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 	.eeprom_ver = EEPROM_5050_EEPROM_VERSION, | ||||||
| 	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | ||||||
| 	.base_params = &iwl5000_base_params, | 	.base_params = &iwl5000_base_params, | ||||||
|  | 	.eeprom_params = &iwl5000_eeprom_params, | ||||||
| 	.ht_params = &iwl5000_ht_params, | 	.ht_params = &iwl5000_ht_params, | ||||||
| 	.led_mode = IWL_LED_BLINK, | 	.led_mode = IWL_LED_BLINK, | ||||||
| 	.internal_wimax_coex = true, | 	.internal_wimax_coex = true, | ||||||
|  | @ -144,6 +159,7 @@ const struct iwl_cfg iwl5350_agn_cfg = { | ||||||
| 	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,		\ | 	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,		\ | ||||||
| 	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl5000_base_params,			\ | 	.base_params = &iwl5000_base_params,			\ | ||||||
|  | 	.eeprom_params = &iwl5000_eeprom_params,		\ | ||||||
| 	.no_xtal_calib = true,					\ | 	.no_xtal_calib = true,					\ | ||||||
| 	.led_mode = IWL_LED_BLINK,				\ | 	.led_mode = IWL_LED_BLINK,				\ | ||||||
| 	.internal_wimax_coex = true | 	.internal_wimax_coex = true | ||||||
|  | @ -27,9 +27,9 @@ | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/stringify.h> | #include <linux/stringify.h> | ||||||
| #include "iwl-config.h" | #include "iwl-config.h" | ||||||
| #include "iwl-cfg.h" |  | ||||||
| #include "iwl-agn-hw.h" | #include "iwl-agn-hw.h" | ||||||
| #include "iwl-commands.h" /* needed for BT for now */ | #include "cfg.h" | ||||||
|  | #include "dvm/commands.h" /* needed for BT for now */ | ||||||
| 
 | 
 | ||||||
| /* Highest firmware API version supported */ | /* Highest firmware API version supported */ | ||||||
| #define IWL6000_UCODE_API_MAX 6 | #define IWL6000_UCODE_API_MAX 6 | ||||||
|  | @ -124,6 +124,7 @@ static const struct iwl_base_params iwl6000_g2_base_params = { | ||||||
| static const struct iwl_ht_params iwl6000_ht_params = { | static const struct iwl_ht_params iwl6000_ht_params = { | ||||||
| 	.ht_greenfield_support = true, | 	.ht_greenfield_support = true, | ||||||
| 	.use_rts_for_aggregation = true, /* use rts/cts protection */ | 	.use_rts_for_aggregation = true, /* use rts/cts protection */ | ||||||
|  | 	.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const struct iwl_bt_params iwl6000_bt_params = { | static const struct iwl_bt_params iwl6000_bt_params = { | ||||||
|  | @ -135,6 +136,19 @@ static const struct iwl_bt_params iwl6000_bt_params = { | ||||||
| 	.bt_sco_disable = true, | 	.bt_sco_disable = true, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static const struct iwl_eeprom_params iwl6000_eeprom_params = { | ||||||
|  | 	.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_REG_BAND_52_HT40_CHANNELS | ||||||
|  | 	}, | ||||||
|  | 	.enhanced_txpower = true, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| #define IWL_DEVICE_6005						\ | #define IWL_DEVICE_6005						\ | ||||||
| 	.fw_name_pre = IWL6005_FW_PRE,				\ | 	.fw_name_pre = IWL6005_FW_PRE,				\ | ||||||
| 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\ | 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\ | ||||||
|  | @ -146,6 +160,7 @@ static const struct iwl_bt_params iwl6000_bt_params = { | ||||||
| 	.eeprom_ver = EEPROM_6005_EEPROM_VERSION,		\ | 	.eeprom_ver = EEPROM_6005_EEPROM_VERSION,		\ | ||||||
| 	.eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl6000_g2_base_params,			\ | 	.base_params = &iwl6000_g2_base_params,			\ | ||||||
|  | 	.eeprom_params = &iwl6000_eeprom_params,		\ | ||||||
| 	.need_temp_offset_calib = true,				\ | 	.need_temp_offset_calib = true,				\ | ||||||
| 	.led_mode = IWL_LED_RF_STATE | 	.led_mode = IWL_LED_RF_STATE | ||||||
| 
 | 
 | ||||||
|  | @ -201,6 +216,7 @@ const struct iwl_cfg iwl6005_2agn_mow2_cfg = { | ||||||
| 	.eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl6000_g2_base_params,			\ | 	.base_params = &iwl6000_g2_base_params,			\ | ||||||
| 	.bt_params = &iwl6000_bt_params,			\ | 	.bt_params = &iwl6000_bt_params,			\ | ||||||
|  | 	.eeprom_params = &iwl6000_eeprom_params,		\ | ||||||
| 	.need_temp_offset_calib = true,				\ | 	.need_temp_offset_calib = true,				\ | ||||||
| 	.led_mode = IWL_LED_RF_STATE,				\ | 	.led_mode = IWL_LED_RF_STATE,				\ | ||||||
| 	.adv_pm = true						\ | 	.adv_pm = true						\ | ||||||
|  | @ -273,6 +289,7 @@ const struct iwl_cfg iwl130_bg_cfg = { | ||||||
| 	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,		\ | 	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,		\ | ||||||
| 	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl6000_base_params,			\ | 	.base_params = &iwl6000_base_params,			\ | ||||||
|  | 	.eeprom_params = &iwl6000_eeprom_params,		\ | ||||||
| 	.led_mode = IWL_LED_BLINK | 	.led_mode = IWL_LED_BLINK | ||||||
| 
 | 
 | ||||||
| const struct iwl_cfg iwl6000i_2agn_cfg = { | const struct iwl_cfg iwl6000i_2agn_cfg = { | ||||||
|  | @ -303,6 +320,7 @@ const struct iwl_cfg iwl6000i_2bg_cfg = { | ||||||
| 	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,		\ | 	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,		\ | ||||||
| 	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl6050_base_params,			\ | 	.base_params = &iwl6050_base_params,			\ | ||||||
|  | 	.eeprom_params = &iwl6000_eeprom_params,		\ | ||||||
| 	.led_mode = IWL_LED_BLINK,				\ | 	.led_mode = IWL_LED_BLINK,				\ | ||||||
| 	.internal_wimax_coex = true | 	.internal_wimax_coex = true | ||||||
| 
 | 
 | ||||||
|  | @ -327,6 +345,7 @@ const struct iwl_cfg iwl6050_2abg_cfg = { | ||||||
| 	.eeprom_ver = EEPROM_6150_EEPROM_VERSION,		\ | 	.eeprom_ver = EEPROM_6150_EEPROM_VERSION,		\ | ||||||
| 	.eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION,	\ | 	.eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION,	\ | ||||||
| 	.base_params = &iwl6050_base_params,			\ | 	.base_params = &iwl6050_base_params,			\ | ||||||
|  | 	.eeprom_params = &iwl6000_eeprom_params,		\ | ||||||
| 	.led_mode = IWL_LED_BLINK,				\ | 	.led_mode = IWL_LED_BLINK,				\ | ||||||
| 	.internal_wimax_coex = true | 	.internal_wimax_coex = true | ||||||
| 
 | 
 | ||||||
|  | @ -353,6 +372,7 @@ const struct iwl_cfg iwl6000_3agn_cfg = { | ||||||
| 	.eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 	.eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||||||
| 	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | 	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | ||||||
| 	.base_params = &iwl6000_base_params, | 	.base_params = &iwl6000_base_params, | ||||||
|  | 	.eeprom_params = &iwl6000_eeprom_params, | ||||||
| 	.ht_params = &iwl6000_ht_params, | 	.ht_params = &iwl6000_ht_params, | ||||||
| 	.led_mode = IWL_LED_BLINK, | 	.led_mode = IWL_LED_BLINK, | ||||||
| }; | }; | ||||||
|  | @ -68,10 +68,11 @@ | ||||||
| #include <linux/pci-aspm.h> | #include <linux/pci-aspm.h> | ||||||
| 
 | 
 | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-cfg.h" |  | ||||||
| #include "iwl-drv.h" | #include "iwl-drv.h" | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-trans-pcie-int.h" | 
 | ||||||
|  | #include "cfg.h" | ||||||
|  | #include "internal.h" | ||||||
| 
 | 
 | ||||||
| #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | #define IWL_PCI_DEVICE(dev, subdev, cfg) \ | ||||||
| 	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \ | 	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \ | ||||||
|  | @ -339,12 +339,15 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, | ||||||
| void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, | ||||||
| 				       struct iwl_tx_queue *txq, | 				       struct iwl_tx_queue *txq, | ||||||
| 				       u16 byte_cnt); | 				       u16 byte_cnt); | ||||||
| void iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int queue); | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int queue); | ||||||
| void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); | ||||||
| void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | ||||||
| 				   struct iwl_tx_queue *txq, | 				   struct iwl_tx_queue *txq, | ||||||
| 				   int tx_fifo_id, bool active); | 				   int tx_fifo_id, bool active); | ||||||
| void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int queue, int fifo, | void __iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, | ||||||
|  | 					int fifo, int sta_id, int tid, | ||||||
|  | 					int frame_limit, u16 ssn); | ||||||
|  | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, | ||||||
| 			       int sta_id, int tid, int frame_limit, u16 ssn); | 			       int sta_id, int tid, int frame_limit, u16 ssn); | ||||||
| void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | ||||||
| 		      enum dma_data_direction dma_dir); | 		      enum dma_data_direction dma_dir); | ||||||
|  | @ -32,7 +32,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "iwl-prph.h" | #include "iwl-prph.h" | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-trans-pcie-int.h" | #include "internal.h" | ||||||
| #include "iwl-op-mode.h" | #include "iwl-op-mode.h" | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_IWLWIFI_IDI | #ifdef CONFIG_IWLWIFI_IDI | ||||||
|  | @ -70,13 +70,12 @@ | ||||||
| 
 | 
 | ||||||
| #include "iwl-drv.h" | #include "iwl-drv.h" | ||||||
| #include "iwl-trans.h" | #include "iwl-trans.h" | ||||||
| #include "iwl-trans-pcie-int.h" |  | ||||||
| #include "iwl-csr.h" | #include "iwl-csr.h" | ||||||
| #include "iwl-prph.h" | #include "iwl-prph.h" | ||||||
| #include "iwl-eeprom.h" |  | ||||||
| #include "iwl-agn-hw.h" | #include "iwl-agn-hw.h" | ||||||
|  | #include "internal.h" | ||||||
| /* FIXME: need to abstract out TX command (once we know what it looks like) */ | /* FIXME: need to abstract out TX command (once we know what it looks like) */ | ||||||
| #include "iwl-commands.h" | #include "dvm/commands.h" | ||||||
| 
 | 
 | ||||||
| #define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie)	\ | #define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie)	\ | ||||||
| 	(((1<<trans->cfg->base_params->num_of_queues) - 1) &\ | 	(((1<<trans->cfg->base_params->num_of_queues) - 1) &\ | ||||||
|  | @ -1031,6 +1030,10 @@ static void iwl_tx_start(struct iwl_trans *trans) | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 	spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||||||
| 
 | 
 | ||||||
|  | 	/* make sure all queue are not stopped/used */ | ||||||
|  | 	memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); | ||||||
|  | 	memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); | ||||||
|  | 
 | ||||||
| 	trans_pcie->scd_base_addr = | 	trans_pcie->scd_base_addr = | ||||||
| 		iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); | 		iwl_read_prph(trans, SCD_SRAM_BASE_ADDR); | ||||||
| 	a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; | 	a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND; | ||||||
|  | @ -1051,6 +1054,17 @@ static void iwl_tx_start(struct iwl_trans *trans) | ||||||
| 	iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, | 	iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, | ||||||
| 		       trans_pcie->scd_bc_tbls.dma >> 10); | 		       trans_pcie->scd_bc_tbls.dma >> 10); | ||||||
| 
 | 
 | ||||||
|  | 	for (i = 0; i < trans_pcie->n_q_to_fifo; i++) { | ||||||
|  | 		int fifo = trans_pcie->setup_q_to_fifo[i]; | ||||||
|  | 
 | ||||||
|  | 		__iwl_trans_pcie_txq_enable(trans, i, fifo, IWL_INVALID_STATION, | ||||||
|  | 					    IWL_TID_NON_QOS, | ||||||
|  | 					    SCD_FRAME_LIMIT, 0); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Activate all Tx DMA/FIFO channels */ | ||||||
|  | 	iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); | ||||||
|  | 
 | ||||||
| 	/* Enable DMA channel */ | 	/* Enable DMA channel */ | ||||||
| 	for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) | 	for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) | ||||||
| 		iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | 		iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||||||
|  | @ -1062,48 +1076,6 @@ static void iwl_tx_start(struct iwl_trans *trans) | ||||||
| 	iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, | 	iwl_write_direct32(trans, FH_TX_CHICKEN_BITS_REG, | ||||||
| 			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | 			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||||||
| 
 | 
 | ||||||
| 	iwl_write_prph(trans, SCD_QUEUECHAIN_SEL, |  | ||||||
| 		       SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie)); |  | ||||||
| 	iwl_write_prph(trans, SCD_AGGR_SEL, 0); |  | ||||||
| 
 |  | ||||||
| 	/* initiate the queues */ |  | ||||||
| 	for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { |  | ||||||
| 		iwl_write_prph(trans, SCD_QUEUE_RDPTR(i), 0); |  | ||||||
| 		iwl_write_direct32(trans, HBUS_TARG_WRPTR, 0 | (i << 8)); |  | ||||||
| 		iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + |  | ||||||
| 				SCD_CONTEXT_QUEUE_OFFSET(i), 0); |  | ||||||
| 		iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + |  | ||||||
| 				SCD_CONTEXT_QUEUE_OFFSET(i) + |  | ||||||
| 				sizeof(u32), |  | ||||||
| 				((SCD_WIN_SIZE << |  | ||||||
| 				SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & |  | ||||||
| 				SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | |  | ||||||
| 				((SCD_FRAME_LIMIT << |  | ||||||
| 				SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & |  | ||||||
| 				SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	iwl_write_prph(trans, SCD_INTERRUPT_MASK, |  | ||||||
| 		       IWL_MASK(0, trans->cfg->base_params->num_of_queues)); |  | ||||||
| 
 |  | ||||||
| 	/* Activate all Tx DMA/FIFO channels */ |  | ||||||
| 	iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); |  | ||||||
| 
 |  | ||||||
| 	iwl_trans_set_wr_ptrs(trans, trans_pcie->cmd_queue, 0); |  | ||||||
| 
 |  | ||||||
| 	/* make sure all queue are not stopped/used */ |  | ||||||
| 	memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); |  | ||||||
| 	memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); |  | ||||||
| 
 |  | ||||||
| 	for (i = 0; i < trans_pcie->n_q_to_fifo; i++) { |  | ||||||
| 		int fifo = trans_pcie->setup_q_to_fifo[i]; |  | ||||||
| 
 |  | ||||||
| 		set_bit(i, trans_pcie->queue_used); |  | ||||||
| 
 |  | ||||||
| 		iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i], |  | ||||||
| 					      fifo, true); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||||||
| 
 | 
 | ||||||
| 	/* Enable L1-Active */ | 	/* Enable L1-Active */ | ||||||
|  | @ -1556,6 +1528,7 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) | ||||||
| 	iounmap(trans_pcie->hw_base); | 	iounmap(trans_pcie->hw_base); | ||||||
| 	pci_release_regions(trans_pcie->pci_dev); | 	pci_release_regions(trans_pcie->pci_dev); | ||||||
| 	pci_disable_device(trans_pcie->pci_dev); | 	pci_disable_device(trans_pcie->pci_dev); | ||||||
|  | 	kmem_cache_destroy(trans->dev_cmd_pool); | ||||||
| 
 | 
 | ||||||
| 	kfree(trans); | 	kfree(trans); | ||||||
| } | } | ||||||
|  | @ -2046,8 +2019,8 @@ static const struct iwl_trans_ops trans_ops_pcie = { | ||||||
| 	.tx = iwl_trans_pcie_tx, | 	.tx = iwl_trans_pcie_tx, | ||||||
| 	.reclaim = iwl_trans_pcie_reclaim, | 	.reclaim = iwl_trans_pcie_reclaim, | ||||||
| 
 | 
 | ||||||
| 	.tx_agg_disable = iwl_trans_pcie_tx_agg_disable, | 	.txq_disable = iwl_trans_pcie_txq_disable, | ||||||
| 	.tx_agg_setup = iwl_trans_pcie_tx_agg_setup, | 	.txq_enable = iwl_trans_pcie_txq_enable, | ||||||
| 
 | 
 | ||||||
| 	.dbgfs_register = iwl_trans_pcie_dbgfs_register, | 	.dbgfs_register = iwl_trans_pcie_dbgfs_register, | ||||||
| 
 | 
 | ||||||
|  | @ -2070,6 +2043,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | ||||||
| { | { | ||||||
| 	struct iwl_trans_pcie *trans_pcie; | 	struct iwl_trans_pcie *trans_pcie; | ||||||
| 	struct iwl_trans *trans; | 	struct iwl_trans *trans; | ||||||
|  | 	char cmd_pool_name[100]; | ||||||
| 	u16 pci_cmd; | 	u16 pci_cmd; | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
|  | @ -2166,8 +2140,25 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | ||||||
| 	init_waitqueue_head(&trans->wait_command_queue); | 	init_waitqueue_head(&trans->wait_command_queue); | ||||||
| 	spin_lock_init(&trans->reg_lock); | 	spin_lock_init(&trans->reg_lock); | ||||||
| 
 | 
 | ||||||
|  | 	snprintf(cmd_pool_name, sizeof(cmd_pool_name), "iwl_cmd_pool:%s", | ||||||
|  | 		 dev_name(trans->dev)); | ||||||
|  | 
 | ||||||
|  | 	trans->dev_cmd_headroom = 0; | ||||||
|  | 	trans->dev_cmd_pool = | ||||||
|  | 		kmem_cache_create(cmd_pool_name, | ||||||
|  | 				  sizeof(struct iwl_device_cmd) | ||||||
|  | 				  + trans->dev_cmd_headroom, | ||||||
|  | 				  sizeof(void *), | ||||||
|  | 				  SLAB_HWCACHE_ALIGN, | ||||||
|  | 				  NULL); | ||||||
|  | 
 | ||||||
|  | 	if (!trans->dev_cmd_pool) | ||||||
|  | 		goto out_pci_disable_msi; | ||||||
|  | 
 | ||||||
| 	return trans; | 	return trans; | ||||||
| 
 | 
 | ||||||
|  | out_pci_disable_msi: | ||||||
|  | 	pci_disable_msi(pdev); | ||||||
| out_pci_release_regions: | out_pci_release_regions: | ||||||
| 	pci_release_regions(pdev); | 	pci_release_regions(pdev); | ||||||
| out_pci_disable_device: | out_pci_disable_device: | ||||||
|  | @ -34,11 +34,10 @@ | ||||||
| #include "iwl-csr.h" | #include "iwl-csr.h" | ||||||
| #include "iwl-prph.h" | #include "iwl-prph.h" | ||||||
| #include "iwl-io.h" | #include "iwl-io.h" | ||||||
| #include "iwl-agn-hw.h" |  | ||||||
| #include "iwl-op-mode.h" | #include "iwl-op-mode.h" | ||||||
| #include "iwl-trans-pcie-int.h" | #include "internal.h" | ||||||
| /* FIXME: need to abstract out TX command (once we know what it looks like) */ | /* FIXME: need to abstract out TX command (once we know what it looks like) */ | ||||||
| #include "iwl-commands.h" | #include "dvm/commands.h" | ||||||
| 
 | 
 | ||||||
| #define IWL_TX_CRC_SIZE 4 | #define IWL_TX_CRC_SIZE 4 | ||||||
| #define IWL_TX_DELIMITER_SIZE 4 | #define IWL_TX_DELIMITER_SIZE 4 | ||||||
|  | @ -443,29 +442,34 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | ||||||
| 		IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); | 		IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int txq_id, int fifo, | void __iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, | ||||||
| 				 int sta_id, int tid, int frame_limit, u16 ssn) | 					int fifo, int sta_id, int tid, | ||||||
|  | 					int frame_limit, u16 ssn) | ||||||
| { | { | ||||||
| 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||||||
| 	unsigned long flags; | 
 | ||||||
| 	u16 ra_tid = BUILD_RAxTID(sta_id, tid); | 	lockdep_assert_held(&trans_pcie->irq_lock); | ||||||
| 
 | 
 | ||||||
| 	if (test_and_set_bit(txq_id, trans_pcie->queue_used)) | 	if (test_and_set_bit(txq_id, trans_pcie->queue_used)) | ||||||
| 		WARN_ONCE(1, "queue %d already used - expect issues", txq_id); | 		WARN_ONCE(1, "queue %d already used - expect issues", txq_id); | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(&trans_pcie->irq_lock, flags); |  | ||||||
| 
 |  | ||||||
| 	/* Stop this Tx queue before configuring it */ | 	/* Stop this Tx queue before configuring it */ | ||||||
| 	iwlagn_tx_queue_stop_scheduler(trans, txq_id); | 	iwlagn_tx_queue_stop_scheduler(trans, txq_id); | ||||||
| 
 | 
 | ||||||
|  | 	/* Set this queue as a chain-building queue unless it is CMD queue */ | ||||||
|  | 	if (txq_id != trans_pcie->cmd_queue) | ||||||
|  | 		iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); | ||||||
|  | 
 | ||||||
|  | 	/* If this queue is mapped to a certain station: it is an AGG queue */ | ||||||
|  | 	if (sta_id != IWL_INVALID_STATION) { | ||||||
|  | 		u16 ra_tid = BUILD_RAxTID(sta_id, tid); | ||||||
|  | 
 | ||||||
| 		/* Map receiver-address / traffic-ID to this queue */ | 		/* Map receiver-address / traffic-ID to this queue */ | ||||||
| 		iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); | 		iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); | ||||||
| 
 | 
 | ||||||
| 	/* Set this queue as a chain-building queue */ |  | ||||||
| 	iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); |  | ||||||
| 
 |  | ||||||
| 		/* enable aggregations for the queue */ | 		/* enable aggregations for the queue */ | ||||||
| 		iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); | 		iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Place first TFD at index corresponding to start sequence number.
 | 	/* Place first TFD at index corresponding to start sequence number.
 | ||||||
| 	 * Assumes that ssn_idx is valid (!= 0xFFF) */ | 	 * Assumes that ssn_idx is valid (!= 0xFFF) */ | ||||||
|  | @ -474,6 +478,8 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int txq_id, int fifo, | ||||||
| 	iwl_trans_set_wr_ptrs(trans, txq_id, ssn); | 	iwl_trans_set_wr_ptrs(trans, txq_id, ssn); | ||||||
| 
 | 
 | ||||||
| 	/* Set up Tx window size and frame limit for this queue */ | 	/* Set up Tx window size and frame limit for this queue */ | ||||||
|  | 	iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | ||||||
|  | 			SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0); | ||||||
| 	iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | 	iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | ||||||
| 			SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), | 			SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), | ||||||
| 			((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | 			((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||||||
|  | @ -481,16 +487,26 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int txq_id, int fifo, | ||||||
| 			((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | 			((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||||||
| 				SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | 				SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||||||
| 
 | 
 | ||||||
| 	iwl_set_bits_prph(trans, SCD_INTERRUPT_MASK, (1 << txq_id)); |  | ||||||
| 
 |  | ||||||
| 	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | 	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | ||||||
| 	iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], | 	iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], | ||||||
| 				      fifo, true); | 				      fifo, true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, | ||||||
|  | 			       int sta_id, int tid, int frame_limit, u16 ssn) | ||||||
|  | { | ||||||
|  | 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||||||
|  | 	unsigned long flags; | ||||||
|  | 
 | ||||||
|  | 	spin_lock_irqsave(&trans_pcie->irq_lock, flags); | ||||||
|  | 
 | ||||||
|  | 	__iwl_trans_pcie_txq_enable(trans, txq_id, fifo, sta_id, | ||||||
|  | 				    tid, frame_limit, ssn); | ||||||
| 
 | 
 | ||||||
| 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int txq_id) | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) | ||||||
| { | { | ||||||
| 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||||||
| 
 | 
 | ||||||
|  | @ -507,8 +523,6 @@ void iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int txq_id) | ||||||
| 	trans_pcie->txq[txq_id].q.write_ptr = 0; | 	trans_pcie->txq[txq_id].q.write_ptr = 0; | ||||||
| 	iwl_trans_set_wr_ptrs(trans, txq_id, 0); | 	iwl_trans_set_wr_ptrs(trans, txq_id, 0); | ||||||
| 
 | 
 | ||||||
| 	iwl_clear_bits_prph(trans, SCD_INTERRUPT_MASK, BIT(txq_id)); |  | ||||||
| 
 |  | ||||||
| 	iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], | 	iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], | ||||||
| 				      0, false); | 				      0, false); | ||||||
| } | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 John W. Linville
				John W. Linville