Browse Source

Merge branch 'wireless-next' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi

John W. Linville 13 years ago
parent
commit
d896d463ee
35 changed files with 1112 additions and 611 deletions
  1. 1 1
      drivers/net/wireless/iwlwifi/Makefile
  2. 5 5
      drivers/net/wireless/iwlwifi/iwl-1000.c
  3. 9 5
      drivers/net/wireless/iwlwifi/iwl-2000.c
  4. 8 10
      drivers/net/wireless/iwlwifi/iwl-5000.c
  5. 13 4
      drivers/net/wireless/iwlwifi/iwl-6000.c
  6. 4 2
      drivers/net/wireless/iwlwifi/iwl-agn-calib.c
  7. 3 3
      drivers/net/wireless/iwlwifi/iwl-agn-lib.c
  8. 1 1
      drivers/net/wireless/iwlwifi/iwl-agn-rs.c
  9. 1 1
      drivers/net/wireless/iwlwifi/iwl-agn-rx.c
  10. 16 0
      drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
  11. 3 3
      drivers/net/wireless/iwlwifi/iwl-agn-tt.c
  12. 1 1
      drivers/net/wireless/iwlwifi/iwl-agn-tx.c
  13. 20 33
      drivers/net/wireless/iwlwifi/iwl-agn.c
  14. 3 7
      drivers/net/wireless/iwlwifi/iwl-agn.h
  15. 3 4
      drivers/net/wireless/iwlwifi/iwl-core.c
  16. 2 2
      drivers/net/wireless/iwlwifi/iwl-core.h
  17. 127 0
      drivers/net/wireless/iwlwifi/iwl-debug.c
  18. 42 41
      drivers/net/wireless/iwlwifi/iwl-debug.h
  19. 6 5
      drivers/net/wireless/iwlwifi/iwl-debugfs.c
  20. 5 16
      drivers/net/wireless/iwlwifi/iwl-dev.h
  21. 65 0
      drivers/net/wireless/iwlwifi/iwl-devtrace.h
  22. 12 8
      drivers/net/wireless/iwlwifi/iwl-mac80211.c
  23. 16 2
      drivers/net/wireless/iwlwifi/iwl-pci.c
  24. 5 5
      drivers/net/wireless/iwlwifi/iwl-scan.c
  25. 7 6
      drivers/net/wireless/iwlwifi/iwl-shared.h
  26. 239 172
      drivers/net/wireless/iwlwifi/iwl-testmode.c
  27. 36 28
      drivers/net/wireless/iwlwifi/iwl-testmode.h
  28. 1 0
      drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
  29. 33 37
      drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
  30. 2 2
      drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
  31. 24 15
      drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
  32. 157 33
      drivers/net/wireless/iwlwifi/iwl-trans.h
  33. 164 157
      drivers/net/wireless/iwlwifi/iwl-ucode.c
  34. 45 2
      drivers/net/wireless/iwlwifi/iwl-ucode.h
  35. 33 0
      drivers/net/wireless/iwlwifi/iwl-wifi.h

+ 1 - 1
drivers/net/wireless/iwlwifi/Makefile

@@ -1,7 +1,7 @@
 # WIFI
 obj-$(CONFIG_IWLWIFI)	+= iwlwifi.o
 iwlwifi-objs		:= iwl-agn.o iwl-agn-rs.o iwl-mac80211.o
-iwlwifi-objs		+= iwl-ucode.o iwl-agn-tx.o
+iwlwifi-objs		+= iwl-ucode.o iwl-agn-tx.o iwl-debug.o
 iwlwifi-objs		+= iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
 iwlwifi-objs		+= iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o
 

+ 5 - 5
drivers/net/wireless/iwlwifi/iwl-1000.c

@@ -120,7 +120,7 @@ static struct iwl_sensitivity_ranges iwl1000_sensitivity = {
 	.nrg_th_cca = 62,
 };
 
-static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
+static void iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 {
 	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
 	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
@@ -128,8 +128,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 			iwlagn_mod_params.num_of_queues;
 
 	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-	hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
-	hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE;
 
 	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ);
 
@@ -146,8 +144,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 
 	/* Set initial sensitivity parameters */
 	hw_params(priv).sens = &iwl1000_sensitivity;
-
-	return 0;
 }
 
 static struct iwl_lib_ops iwl1000_lib = {
@@ -193,6 +189,8 @@ static struct iwl_ht_params iwl1000_ht_params = {
 	.ucode_api_max = IWL1000_UCODE_API_MAX,			\
 	.ucode_api_ok = IWL1000_UCODE_API_OK,			\
 	.ucode_api_min = IWL1000_UCODE_API_MIN,			\
+	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
+	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
 	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
 	.lib = &iwl1000_lib,					\
@@ -215,6 +213,8 @@ struct iwl_cfg iwl1000_bg_cfg = {
 	.ucode_api_max = IWL100_UCODE_API_MAX,			\
 	.ucode_api_ok = IWL100_UCODE_API_OK,			\
 	.ucode_api_min = IWL100_UCODE_API_MIN,			\
+	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
+	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
 	.eeprom_ver = EEPROM_1000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,	\
 	.lib = &iwl1000_lib,					\

+ 9 - 5
drivers/net/wireless/iwlwifi/iwl-2000.c

@@ -116,7 +116,7 @@ static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
 	.nrg_th_cca = 62,
 };
 
-static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
+static void iwl2000_hw_set_hw_params(struct iwl_priv *priv)
 {
 	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
 	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
@@ -124,8 +124,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
 			iwlagn_mod_params.num_of_queues;
 
 	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-	hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
-	hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE;
 
 	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ);
 
@@ -142,8 +140,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
 
 	/* Set initial sensitivity parameters */
 	hw_params(priv).sens = &iwl2000_sensitivity;
-
-	return 0;
 }
 
 static struct iwl_lib_ops iwl2000_lib = {
@@ -242,6 +238,8 @@ static struct iwl_bt_params iwl2030_bt_params = {
 	.ucode_api_max = IWL2000_UCODE_API_MAX,			\
 	.ucode_api_ok = IWL2000_UCODE_API_OK,			\
 	.ucode_api_min = IWL2000_UCODE_API_MIN,			\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
 	.lib = &iwl2000_lib,					\
@@ -268,6 +266,8 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = {
 	.ucode_api_max = IWL2030_UCODE_API_MAX,			\
 	.ucode_api_ok = IWL2030_UCODE_API_OK,			\
 	.ucode_api_min = IWL2030_UCODE_API_MIN,			\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
 	.lib = &iwl2030_lib,					\
@@ -290,6 +290,8 @@ struct iwl_cfg iwl2030_2bgn_cfg = {
 	.ucode_api_max = IWL105_UCODE_API_MAX,			\
 	.ucode_api_ok = IWL105_UCODE_API_OK,			\
 	.ucode_api_min = IWL105_UCODE_API_MIN,			\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
 	.lib = &iwl2000_lib,					\
@@ -318,6 +320,8 @@ struct iwl_cfg iwl105_bgn_d_cfg = {
 	.ucode_api_max = IWL135_UCODE_API_MAX,			\
 	.ucode_api_ok = IWL135_UCODE_API_OK,			\
 	.ucode_api_min = IWL135_UCODE_API_MIN,			\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
 	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
 	.lib = &iwl2030_lib,					\

+ 8 - 10
drivers/net/wireless/iwlwifi/iwl-5000.c

@@ -162,7 +162,7 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
 	hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
 }
 
-static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
+static void iwl5000_hw_set_hw_params(struct iwl_priv *priv)
 {
 	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
 	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
@@ -170,8 +170,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
 			iwlagn_mod_params.num_of_queues;
 
 	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-	hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
-	hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE;
 
 	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
@@ -185,11 +183,9 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
 
 	/* Set initial sensitivity parameters */
 	hw_params(priv).sens = &iwl5000_sensitivity;
-
-	return 0;
 }
 
-static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
+static void iwl5150_hw_set_hw_params(struct iwl_priv *priv)
 {
 	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
 	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
@@ -197,8 +193,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
 			iwlagn_mod_params.num_of_queues;
 
 	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-	hw_params(priv).max_data_size = IWLAGN_RTC_DATA_SIZE;
-	hw_params(priv).max_inst_size = IWLAGN_RTC_INST_SIZE;
 
 	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
@@ -212,8 +206,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
 
 	/* Set initial sensitivity parameters */
 	hw_params(priv).sens = &iwl5150_sensitivity;
-
-	return 0;
 }
 
 static void iwl5150_temperature(struct iwl_priv *priv)
@@ -356,6 +348,8 @@ static struct iwl_ht_params iwl5000_ht_params = {
 	.fw_name_pre = IWL5000_FW_PRE,				\
 	.ucode_api_max = IWL5000_UCODE_API_MAX,			\
 	.ucode_api_min = IWL5000_UCODE_API_MIN,			\
+	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
+	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
 	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,	\
 	.lib = &iwl5000_lib,					\
@@ -399,6 +393,8 @@ struct iwl_cfg iwl5350_agn_cfg = {
 	.fw_name_pre = IWL5000_FW_PRE,
 	.ucode_api_max = IWL5000_UCODE_API_MAX,
 	.ucode_api_min = IWL5000_UCODE_API_MIN,
+	.max_inst_size = IWLAGN_RTC_INST_SIZE,
+	.max_data_size = IWLAGN_RTC_DATA_SIZE,
 	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
 	.lib = &iwl5000_lib,
@@ -412,6 +408,8 @@ struct iwl_cfg iwl5350_agn_cfg = {
 	.fw_name_pre = IWL5150_FW_PRE,				\
 	.ucode_api_max = IWL5150_UCODE_API_MAX,			\
 	.ucode_api_min = IWL5150_UCODE_API_MIN,			\
+	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
+	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
 	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,	\
 	.lib = &iwl5150_lib,					\

+ 13 - 4
drivers/net/wireless/iwlwifi/iwl-6000.c

@@ -137,7 +137,7 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
 	.nrg_th_cca = 62,
 };
 
-static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
+static void iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 {
 	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
 	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
@@ -145,8 +145,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 			iwlagn_mod_params.num_of_queues;
 
 	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
-	hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
-	hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE;
 
 	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
 					BIT(IEEE80211_BAND_5GHZ);
@@ -165,7 +163,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 	/* Set initial sensitivity parameters */
 	hw_params(priv).sens = &iwl6000_sensitivity;
 
-	return 0;
 }
 
 static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
@@ -349,6 +346,8 @@ static struct iwl_bt_params iwl6000_bt_params = {
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
 	.ucode_api_ok = IWL6000G2_UCODE_API_OK,			\
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
 	.eeprom_ver = EEPROM_6005_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION,	\
 	.lib = &iwl6000_lib,					\
@@ -389,6 +388,8 @@ struct iwl_cfg iwl6005_2agn_d_cfg = {
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
 	.ucode_api_ok = IWL6000G2_UCODE_API_OK,			\
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
 	.eeprom_ver = EEPROM_6030_EEPROM_VERSION,		\
 	.eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\
 	.lib = &iwl6030_lib,					\
@@ -458,6 +459,8 @@ struct iwl_cfg iwl130_bg_cfg = {
 	.ucode_api_max = IWL6000_UCODE_API_MAX,			\
 	.ucode_api_ok = IWL6000_UCODE_API_OK,			\
 	.ucode_api_min = IWL6000_UCODE_API_MIN,			\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
 	.valid_tx_ant = ANT_BC,		/* .cfg overwrite */	\
 	.valid_rx_ant = ANT_BC,		/* .cfg overwrite */	\
 	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,		\
@@ -487,6 +490,8 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
 	.fw_name_pre = IWL6050_FW_PRE,				\
 	.ucode_api_max = IWL6050_UCODE_API_MAX,			\
 	.ucode_api_min = IWL6050_UCODE_API_MIN,			\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
 	.valid_tx_ant = ANT_AB,		/* .cfg overwrite */	\
 	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */	\
 	.lib = &iwl6000_lib,					\
@@ -512,6 +517,8 @@ struct iwl_cfg iwl6050_2abg_cfg = {
 	.fw_name_pre = IWL6050_FW_PRE,				\
 	.ucode_api_max = IWL6050_UCODE_API_MAX,			\
 	.ucode_api_min = IWL6050_UCODE_API_MIN,			\
+	.max_inst_size = IWL60_RTC_INST_SIZE,			\
+	.max_data_size = IWL60_RTC_DATA_SIZE,			\
 	.lib = &iwl6000_lib,					\
 	.additional_nic_config = iwl6150_additional_nic_config,	\
 	.eeprom_ver = EEPROM_6150_EEPROM_VERSION,		\
@@ -537,6 +544,8 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 	.ucode_api_max = IWL6000_UCODE_API_MAX,
 	.ucode_api_ok = IWL6000_UCODE_API_OK,
 	.ucode_api_min = IWL6000_UCODE_API_MIN,
+	.max_inst_size = IWL60_RTC_INST_SIZE,
+	.max_data_size = IWL60_RTC_DATA_SIZE,
 	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
 	.lib = &iwl6000_lib,

+ 4 - 2
drivers/net/wireless/iwlwifi/iwl-agn-calib.c

@@ -68,6 +68,8 @@
 #include "iwl-agn-calib.h"
 #include "iwl-trans.h"
 #include "iwl-agn.h"
+#include "iwl-wifi.h"
+#include "iwl-ucode.h"
 
 /*****************************************************************************
  * INIT calibrations framework
@@ -634,7 +636,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
 	data->last_bad_plcp_cnt_cck = 0;
 	data->last_fa_cnt_cck = 0;
 
-	if (priv->enhance_sensitivity_table)
+	if (nic(priv)->fw.enhance_sensitivity_table)
 		ret |= iwl_enhance_sensitivity_write(priv);
 	else
 		ret |= iwl_sensitivity_write(priv);
@@ -745,7 +747,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
 
 	iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
 	iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
-	if (priv->enhance_sensitivity_table)
+	if (nic(priv)->fw.enhance_sensitivity_table)
 		iwl_enhance_sensitivity_write(priv);
 	else
 		iwl_sensitivity_write(priv);

+ 3 - 3
drivers/net/wireless/iwlwifi/iwl-agn-lib.c

@@ -77,7 +77,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
 	tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED;
 	tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO;
 
-	if (IWL_UCODE_API(priv->ucode_ver) == 1)
+	if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) == 1)
 		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
 	else
 		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
@@ -700,7 +700,7 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv,
 		priv->kill_cts_mask = bt_kill_cts_msg[kill_msk];
 
 		/* schedule to send runtime bt_config */
-		queue_work(priv->shrd->workqueue, &priv->bt_runtime_config);
+		queue_work(priv->workqueue, &priv->bt_runtime_config);
 	}
 }
 
@@ -745,7 +745,7 @@ int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
 					IWL_BT_COEX_TRAFFIC_LOAD_NONE;
 			}
 			priv->bt_status = coex->bt_status;
-			queue_work(priv->shrd->workqueue,
+			queue_work(priv->workqueue,
 				   &priv->bt_traffic_change_work);
 		}
 	}

+ 1 - 1
drivers/net/wireless/iwlwifi/iwl-agn-rs.c

@@ -892,7 +892,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 		rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
 		iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
 
-		queue_work(priv->shrd->workqueue, &priv->bt_full_concurrency);
+		queue_work(priv->workqueue, &priv->bt_full_concurrency);
 	}
 }
 

+ 1 - 1
drivers/net/wireless/iwlwifi/iwl-agn-rx.c

@@ -581,7 +581,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
 	if (unlikely(!test_bit(STATUS_SCANNING, &priv->shrd->status)) &&
 	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
 		iwlagn_rx_calc_noise(priv);
-		queue_work(priv->shrd->workqueue, &priv->run_time_calib_work);
+		queue_work(priv->workqueue, &priv->run_time_calib_work);
 	}
 	if (cfg(priv)->lib->temperature && change)
 		cfg(priv)->lib->temperature(priv);

+ 16 - 0
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c

@@ -900,6 +900,22 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 		}
 	}
 
+	/*
+	 * If the ucode decides to do beacon filtering before
+	 * association, it will lose beacons that are needed
+	 * before sending frames out on passive channels. This
+	 * causes association failures on those channels. Enable
+	 * receiving beacons in such cases.
+	 */
+
+	if (vif->type == NL80211_IFTYPE_STATION) {
+		if (!bss_conf->assoc)
+			ctx->staging.filter_flags |= RXON_FILTER_BCON_AWARE_MSK;
+		else
+			ctx->staging.filter_flags &=
+						    ~RXON_FILTER_BCON_AWARE_MSK;
+	}
+
 	if (force || memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
 		iwlagn_commit_rxon(priv, ctx);
 

+ 3 - 3
drivers/net/wireless/iwlwifi/iwl-agn-tt.c

@@ -568,7 +568,7 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
 		return;
 
 	IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
-	queue_work(priv->shrd->workqueue, &priv->ct_enter);
+	queue_work(priv->workqueue, &priv->ct_enter);
 }
 
 void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
@@ -577,7 +577,7 @@ void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
 		return;
 
 	IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
-	queue_work(priv->shrd->workqueue, &priv->ct_exit);
+	queue_work(priv->workqueue, &priv->ct_exit);
 }
 
 static void iwl_bg_tt_work(struct work_struct *work)
@@ -600,7 +600,7 @@ void iwl_tt_handler(struct iwl_priv *priv)
 		return;
 
 	IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
-	queue_work(priv->shrd->workqueue, &priv->tt_work);
+	queue_work(priv->workqueue, &priv->tt_work);
 }
 
 /* Thermal throttling initialization

+ 1 - 1
drivers/net/wireless/iwlwifi/iwl-agn-tx.c

@@ -983,7 +983,7 @@ static void iwl_check_abort_status(struct iwl_priv *priv,
 	if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
 		IWL_ERR(priv, "Tx flush command to flush out all frames\n");
 		if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
-			queue_work(priv->shrd->workqueue, &priv->tx_flush);
+			queue_work(priv->workqueue, &priv->tx_flush);
 	}
 }
 

+ 20 - 33
drivers/net/wireless/iwlwifi/iwl-agn.c

@@ -618,7 +618,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
 	  .valid = cpu_to_le32(valid_tx_ant),
 	};
 
-	if (IWL_UCODE_API(priv->ucode_ver) > 1) {
+	if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) > 1) {
 		IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
 		return iwl_trans_send_cmd_pdu(trans(priv),
 					TX_ANT_CONFIGURATION_CMD,
@@ -738,14 +738,14 @@ int iwl_alive_start(struct iwl_priv *priv)
 	return iwl_power_update_mode(priv, true);
 }
 
-static void iwl_cancel_deferred_work(struct iwl_priv *priv);
-
-void __iwl_down(struct iwl_priv *priv)
+void iwl_down(struct iwl_priv *priv)
 {
 	int exit_pending;
 
 	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
 
+	lockdep_assert_held(&priv->shrd->mutex);
+
 	iwl_scan_cancel_timeout(priv, 200);
 
 	/*
@@ -803,15 +803,6 @@ void __iwl_down(struct iwl_priv *priv)
 	priv->beacon_skb = NULL;
 }
 
-void iwl_down(struct iwl_priv *priv)
-{
-	mutex_lock(&priv->shrd->mutex);
-	__iwl_down(priv);
-	mutex_unlock(&priv->shrd->mutex);
-
-	iwl_cancel_deferred_work(priv);
-}
-
 /*****************************************************************************
  *
  * Workqueue callbacks
@@ -869,7 +860,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
 	bt_status = priv->bt_status;
 	bt_is_sco = priv->bt_is_sco;
 
-	__iwl_down(priv);
+	iwl_down(priv);
 
 	priv->bt_full_concurrent = bt_full_concurrent;
 	priv->bt_ci_compliance = bt_ci_compliance;
@@ -939,7 +930,7 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
 
 static void iwl_setup_deferred_work(struct iwl_priv *priv)
 {
-	priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME);
+	priv->workqueue = create_singlethread_workqueue(DRV_NAME);
 
 	init_waitqueue_head(&priv->shrd->wait_command_queue);
 
@@ -970,7 +961,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 	priv->watchdog.function = iwl_bg_watchdog;
 }
 
-static void iwl_cancel_deferred_work(struct iwl_priv *priv)
+void iwl_cancel_deferred_work(struct iwl_priv *priv)
 {
 	if (cfg(priv)->lib->cancel_deferred_work)
 		cfg(priv)->lib->cancel_deferred_work(priv);
@@ -1091,7 +1082,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
 #define IWL_RX_BUF_SIZE_4K (4 * 1024)
 #define IWL_RX_BUF_SIZE_8K (8 * 1024)
 
-static int iwl_set_hw_params(struct iwl_priv *priv)
+static void iwl_set_hw_params(struct iwl_priv *priv)
 {
 	if (iwlagn_mod_params.amsdu_size_8K)
 		hw_params(priv).rx_page_order =
@@ -1111,7 +1102,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
 	hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
 
 	/* Device-specific setup */
-	return cfg(priv)->lib->set_hw_params(priv);
+	cfg(priv)->lib->set_hw_params(priv);
 }
 
 
@@ -1248,11 +1239,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
 	/************************
 	 * 5. Setup HW constants
 	 ************************/
-	if (iwl_set_hw_params(priv)) {
-		err = -ENOENT;
-		IWL_ERR(priv, "failed to set hw parameters\n");
-		goto out_free_eeprom;
-	}
+	iwl_set_hw_params(priv);
 
 	/*******************
 	 * 6. Setup priv
@@ -1273,17 +1260,17 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
 	iwl_power_initialize(priv);
 	iwl_tt_initialize(priv);
 
-	init_completion(&priv->firmware_loading_complete);
+	init_completion(&nic(priv)->request_firmware_complete);
 
-	err = iwl_request_firmware(priv, true);
+	err = iwl_request_firmware(nic(priv), true);
 	if (err)
 		goto out_destroy_workqueue;
 
 	return 0;
 
 out_destroy_workqueue:
-	destroy_workqueue(priv->shrd->workqueue);
-	priv->shrd->workqueue = NULL;
+	destroy_workqueue(priv->workqueue);
+	priv->workqueue = NULL;
 	iwl_uninit_drv(priv);
 out_free_eeprom:
 	iwl_eeprom_free(priv->shrd);
@@ -1296,7 +1283,7 @@ out:
 
 void __devexit iwl_remove(struct iwl_priv * priv)
 {
-	wait_for_completion(&priv->firmware_loading_complete);
+	wait_for_completion(&nic(priv)->request_firmware_complete);
 
 	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
@@ -1316,18 +1303,18 @@ void __devexit iwl_remove(struct iwl_priv * priv)
 	/*This will stop the queues, move the device to low power state */
 	iwl_trans_stop_device(trans(priv));
 
-	iwl_dealloc_ucode(trans(priv));
+	iwl_dealloc_ucode(nic(priv));
 
 	iwl_eeprom_free(priv->shrd);
 
 	/*netif_stop_queue(dev); */
-	flush_workqueue(priv->shrd->workqueue);
+	flush_workqueue(priv->workqueue);
 
 	/* ieee80211_unregister_hw calls iwlagn_mac_stop, which flushes
-	 * priv->shrd->workqueue... so we can't take down the workqueue
+	 * priv->workqueue... so we can't take down the workqueue
 	 * until now... */
-	destroy_workqueue(priv->shrd->workqueue);
-	priv->shrd->workqueue = NULL;
+	destroy_workqueue(priv->workqueue);
+	priv->workqueue = NULL;
 	iwl_free_traffic_mem(priv);
 
 	iwl_uninit_drv(priv);

+ 3 - 7
drivers/net/wireless/iwlwifi/iwl-agn.h

@@ -65,11 +65,7 @@
 
 #include "iwl-dev.h"
 
-struct iwlagn_ucode_capabilities {
-	u32 max_probe_length;
-	u32 standard_phy_calibration_size;
-	u32 flags;
-};
+struct iwl_ucode_capabilities;
 
 extern struct ieee80211_ops iwlagn_hw_ops;
 
@@ -81,14 +77,14 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
 	hdr->data_valid = 1;
 }
 
-void __iwl_down(struct iwl_priv *priv);
 void iwl_down(struct iwl_priv *priv);
+void iwl_cancel_deferred_work(struct iwl_priv *priv);
 void iwlagn_prepare_restart(struct iwl_priv *priv);
 
 /* MAC80211 */
 struct ieee80211_hw *iwl_alloc_all(void);
 int iwlagn_mac_setup_register(struct iwl_priv *priv,
-			      struct iwlagn_ucode_capabilities *capa);
+			      struct iwl_ucode_capabilities *capa);
 void iwlagn_mac_unregister(struct iwl_priv *priv);
 
 /* RXON */

+ 3 - 4
drivers/net/wireless/iwlwifi/iwl-core.c

@@ -643,7 +643,7 @@ u8 iwl_get_single_channel_number(struct iwl_priv *priv,
  * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
  * in the staging RXON flag structure based on the ch->band
  */
-int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
+void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
 			 struct iwl_rxon_context *ctx)
 {
 	enum ieee80211_band band = ch->band;
@@ -651,7 +651,7 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
 
 	if ((le16_to_cpu(ctx->staging.channel) == channel) &&
 	    (priv->band == band))
-		return 0;
+		return;
 
 	ctx->staging.channel = cpu_to_le16(channel);
 	if (band == IEEE80211_BAND_5GHZ)
@@ -663,7 +663,6 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
 
 	IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band);
 
-	return 0;
 }
 
 void iwl_set_flags_for_band(struct iwl_priv *priv,
@@ -875,7 +874,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
 		if (iwlagn_mod_params.restart_fw) {
 			IWL_DEBUG_FW_ERRORS(priv,
 				  "Restarting adapter due to uCode error.\n");
-			queue_work(priv->shrd->workqueue, &priv->restart);
+			queue_work(priv->workqueue, &priv->restart);
 		} else
 			IWL_DEBUG_FW_ERRORS(priv,
 				  "Detected FW error, but not restarting\n");

+ 2 - 2
drivers/net/wireless/iwlwifi/iwl-core.h

@@ -76,7 +76,7 @@ struct iwl_cmd;
 
 struct iwl_lib_ops {
 	/* set hw dependent parameters */
-	int (*set_hw_params)(struct iwl_priv *priv);
+	void (*set_hw_params)(struct iwl_priv *priv);
 	/* setup BT Rx handler */
 	void (*bt_rx_handler_setup)(struct iwl_priv *priv);
 	/* setup BT related deferred work */
@@ -169,7 +169,7 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 			   int hw_decrypt);
 int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
 int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
-int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
+void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
 			 struct iwl_rxon_context *ctx);
 void iwl_set_flags_for_band(struct iwl_priv *priv,
 			    struct iwl_rxon_context *ctx,

+ 127 - 0
drivers/net/wireless/iwlwifi/iwl-debug.c

@@ -0,0 +1,127 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+#include <linux/interrupt.h>
+#include "iwl-debug.h"
+
+#define __iwl_fn(fn)						\
+void __iwl_ ##fn(struct device *dev, const char *fmt, ...)	\
+{								\
+	struct va_format vaf = {				\
+		.fmt = fmt,					\
+	};							\
+	va_list args;						\
+								\
+	va_start(args, fmt);					\
+	vaf.va = &args;						\
+	dev_ ##fn(dev, "%pV", &vaf);				\
+	trace_iwlwifi_ ##fn(&vaf);				\
+	va_end(args);						\
+}
+
+__iwl_fn(warn)
+__iwl_fn(info)
+__iwl_fn(crit)
+
+void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only,
+		const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+	if (!trace_only) {
+		if (rfkill_prefix)
+			dev_err(dev, "(RFKILL) %pV", &vaf);
+		else
+			dev_err(dev, "%pV", &vaf);
+	}
+	trace_iwlwifi_err(&vaf);
+	va_end(args);
+}
+
+#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
+void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
+	       u32 level, bool limit, const char *function,
+	       const char *fmt, ...)
+{
+	struct va_format vaf = {
+		.fmt = fmt,
+	};
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.va = &args;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	if (iwl_get_debug_level(shared) & level &&
+	    (!limit || net_ratelimit()))
+		dev_err(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U',
+			function, &vaf);
+#endif
+	trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf);
+	va_end(args);
+}
+#endif

+ 42 - 41
drivers/net/wireless/iwlwifi/iwl-debug.h

@@ -31,14 +31,33 @@
 
 #include "iwl-bus.h"
 #include "iwl-shared.h"
+#include "iwl-devtrace.h"
 
 struct iwl_priv;
 
-/*No matter what is m (priv, bus, trans), this will work */
-#define IWL_ERR(m, f, a...) dev_err(trans(m)->dev, f, ## a)
-#define IWL_WARN(m, f, a...) dev_warn(trans(m)->dev, f, ## a)
-#define IWL_INFO(m, f, a...) dev_info(trans(m)->dev, f, ## a)
-#define IWL_CRIT(m, f, a...) dev_crit(trans(m)->dev, f, ## a)
+void __iwl_err(struct device *dev, bool rfkill_prefix, bool only_trace,
+		const char *fmt, ...);
+void __iwl_warn(struct device *dev, const char *fmt, ...);
+void __iwl_info(struct device *dev, const char *fmt, ...);
+void __iwl_crit(struct device *dev, const char *fmt, ...);
+
+/* No matter what is m (priv, bus, trans), this will work */
+#define IWL_ERR(m, f, a...) __iwl_err(trans(m)->dev, false, false, f, ## a)
+#define IWL_WARN(m, f, a...) __iwl_warn(trans(m)->dev, f, ## a)
+#define IWL_INFO(m, f, a...) __iwl_info(trans(m)->dev, f, ## a)
+#define IWL_CRIT(m, f, a...) __iwl_crit(trans(m)->dev, f, ## a)
+
+#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
+void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
+	       u32 level, bool limit, const char *function,
+	       const char *fmt, ...);
+#else
+static inline void
+__iwl_dbg(struct iwl_shared *shared, struct device *dev,
+	  u32 level, bool limit, const char *function,
+	  const char *fmt, ...)
+{}
+#endif
 
 #define iwl_print_hex_error(m, p, len)					\
 do {									\
@@ -46,53 +65,35 @@ do {									\
 		       DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);		\
 } while (0)
 
-#ifdef CONFIG_IWLWIFI_DEBUG
-#define IWL_DEBUG(m, level, fmt, ...)					\
-do {									\
-	if (iwl_get_debug_level((m)->shrd) & (level))			\
-		dev_err(trans(m)->dev, "%c %s " fmt,			\
-			in_interrupt() ? 'I' : 'U', __func__,		\
-			##__VA_ARGS__);					\
-} while (0)
-
-#define IWL_DEBUG_LIMIT(m, level, fmt, ...)				\
-do {									\
-	if (iwl_get_debug_level((m)->shrd) & (level) &&			\
-	    net_ratelimit())						\
-		dev_err(trans(m)->dev, "%c %s " fmt,			\
-			in_interrupt() ? 'I' : 'U', __func__,		\
-			##__VA_ARGS__);					\
-} while (0)
+#define IWL_DEBUG(m, level, fmt, args...)				\
+	__iwl_dbg((m)->shrd, trans(m)->dev, level, false, __func__, fmt, ##args)
+#define IWL_DEBUG_LIMIT(m, level, fmt, args...)				\
+	__iwl_dbg((m)->shrd, trans(m)->dev, level, true, __func__, fmt, ##args)
 
+#ifdef CONFIG_IWLWIFI_DEBUG
 #define iwl_print_hex_dump(m, level, p, len)				\
 do {                                            			\
 	if (iwl_get_debug_level((m)->shrd) & level)			\
 		print_hex_dump(KERN_DEBUG, "iwl data: ",		\
 			       DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);	\
 } while (0)
-
-#define IWL_DEBUG_QUIET_RFKILL(p, fmt, ...)				\
+#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...)	\
 do {									\
-	if (!iwl_is_rfkill(p->shrd))					\
-		dev_err(trans(p)->dev, "%s%c %s " fmt,			\
-			"",						\
-			in_interrupt() ? 'I' : 'U', __func__,		\
-			##__VA_ARGS__);					\
-	else if	(iwl_get_debug_level(p->shrd) & IWL_DL_RADIO)		\
-		dev_err(trans(p)->dev, "%s%c %s " fmt,			\
-			"(RFKILL) ",					\
-			in_interrupt() ? 'I' : 'U', __func__,		\
-			##__VA_ARGS__);					\
+	if (!iwl_is_rfkill((m)->shrd))					\
+		IWL_ERR(m, fmt, ##args);				\
+	else								\
+		__iwl_err(trans(m)->dev, true,				\
+			  !(iwl_get_debug_level((m)->shrd) & IWL_DL_RADIO),\
+			  fmt, ##args);					\
 } while (0)
-
 #else
-#define IWL_DEBUG(m, level, fmt, args...)
-#define IWL_DEBUG_LIMIT(m, level, fmt, args...)
 #define iwl_print_hex_dump(m, level, p, len)
-#define IWL_DEBUG_QUIET_RFKILL(p, fmt, args...)	\
-do {							\
-	if (!iwl_is_rfkill(p->shrd))			\
-		IWL_ERR(p, fmt, ##args);		\
+#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...)	\
+do {									\
+	if (!iwl_is_rfkill((m)->shrd))					\
+		IWL_ERR(m, fmt, ##args);				\
+	else								\
+		__iwl_err(trans(m)->dev, true, true, fmt, ##args);	\
 } while (0)
 #endif				/* CONFIG_IWLWIFI_DEBUG */
 

+ 6 - 5
drivers/net/wireless/iwlwifi/iwl-debugfs.c

@@ -40,6 +40,7 @@
 #include "iwl-core.h"
 #include "iwl-io.h"
 #include "iwl-agn.h"
+#include "iwl-wifi.h"
 
 /* create and remove of files */
 #define DEBUGFS_ADD_FILE(name, parent, mode) do {			\
@@ -234,12 +235,12 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
 
 	/* default is to dump the entire data segment */
 	if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
-		struct iwl_trans *trans = trans(priv);
+		struct iwl_nic *nic = nic(priv);
 		priv->dbgfs_sram_offset = 0x800000;
-		if (trans->shrd->ucode_type == IWL_UCODE_INIT)
-			priv->dbgfs_sram_len = trans->ucode_init.data.len;
+		if (nic->shrd->ucode_type == IWL_UCODE_INIT)
+			priv->dbgfs_sram_len = nic->fw.ucode_init.data.len;
 		else
-			priv->dbgfs_sram_len = trans->ucode_rt.data.len;
+			priv->dbgfs_sram_len = nic->fw.ucode_rt.data.len;
 	}
 	len = priv->dbgfs_sram_len;
 
@@ -342,7 +343,7 @@ static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,
 
 	return simple_read_from_buffer(user_buf, count, ppos,
 				       priv->wowlan_sram,
-				       trans(priv)->ucode_wowlan.data.len);
+				       nic(priv)->fw.ucode_wowlan.data.len);
 }
 static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
 					size_t count, loff_t *ppos)

+ 5 - 16
drivers/net/wireless/iwlwifi/iwl-dev.h

@@ -696,11 +696,11 @@ struct iwl_testmode_trace {
 	dma_addr_t dma_addr;
 	bool trace_enabled;
 };
-struct iwl_testmode_sram {
+struct iwl_testmode_mem {
 	u32 buff_size;
 	u32 num_chunks;
 	u8 *buff_addr;
-	bool sram_readed;
+	bool read_in_progress;
 };
 #endif
 
@@ -721,6 +721,8 @@ struct iwl_priv {
 	struct ieee80211_rate *ieee_rates;
 	struct kmem_cache *tx_cmd_pool;
 
+	struct workqueue_struct *workqueue;
+
 	enum ieee80211_band band;
 
 	void (*pre_rx_handler)(struct iwl_priv *priv,
@@ -785,13 +787,6 @@ struct iwl_priv {
 	/* EEPROM MAC addresses */
 	struct mac_address addresses[2];
 
-	/* uCode images, save to reload in case of failure */
-	int fw_index;			/* firmware we're trying to load */
-	u32 ucode_ver;			/* version of ucode, copy of
-					   iwl_ucode.ver */
-
-	char firmware_name[25];
-
 	struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
 
 	__le16 switch_channel;
@@ -801,7 +796,6 @@ struct iwl_priv {
 	u8 start_calib;
 	struct iwl_sensitivity_data sensitivity_data;
 	struct iwl_chain_noise_data chain_noise_data;
-	bool enhance_sensitivity_table;
 	__le16 sensitivity_tbl[HD_TABLE_SIZE];
 	__le16 enhance_sensitivity_tbl[ENHANCE_HD_TABLE_ENTRIES];
 
@@ -869,11 +863,6 @@ struct iwl_priv {
 	struct iwl_rx_phy_res last_phy_res;
 	bool last_phy_res_valid;
 
-	struct completion firmware_loading_complete;
-
-	u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
-	u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
-
 	/*
 	 * chain noise reset and gain commands are the
 	 * two extra calibration commands follows the standard
@@ -964,7 +953,7 @@ struct iwl_priv {
 	bool led_registered;
 #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
 	struct iwl_testmode_trace testmode_trace;
-	struct iwl_testmode_sram testmode_sram;
+	struct iwl_testmode_mem testmode_mem;
 	u32 tm_fixed_rate;
 #endif
 

+ 65 - 0
drivers/net/wireless/iwlwifi/iwl-devtrace.h

@@ -34,6 +34,11 @@
 #undef TRACE_EVENT
 #define TRACE_EVENT(name, proto, ...) \
 static inline void trace_ ## name(proto) {}
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(...)
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(evt_class, name, proto, ...) \
+static inline void trace_ ## name(proto) {}
 #endif
 
 #define PRIV_ENTRY	__field(void *, priv)
@@ -163,6 +168,66 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
 		  __entry->p_entry)
 );
 
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_msg
+
+#define MAX_MSG_LEN	100
+
+DECLARE_EVENT_CLASS(iwlwifi_msg_event,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf),
+	TP_STRUCT__entry(
+		__dynamic_array(char, msg, MAX_MSG_LEN)
+	),
+	TP_fast_assign(
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       MAX_MSG_LEN, vaf->fmt,
+				       *vaf->va) >= MAX_MSG_LEN);
+	),
+	TP_printk("%s", (char *)__get_dynamic_array(msg))
+);
+
+DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_err,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_warn,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_info,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_crit,
+	TP_PROTO(struct va_format *vaf),
+	TP_ARGS(vaf)
+);
+
+TRACE_EVENT(iwlwifi_dbg,
+	TP_PROTO(u32 level, bool in_interrupt, const char *function,
+		 struct va_format *vaf),
+	TP_ARGS(level, in_interrupt, function, vaf),
+	TP_STRUCT__entry(
+		__field(u32, level)
+		__field(u8, in_interrupt)
+		__string(function, function)
+		__dynamic_array(char, msg, MAX_MSG_LEN)
+	),
+	TP_fast_assign(
+		__entry->level = level;
+		__entry->in_interrupt = in_interrupt;
+		__assign_str(function, function);
+		WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+				       MAX_MSG_LEN, vaf->fmt,
+				       *vaf->va) >= MAX_MSG_LEN);
+	),
+	TP_printk("%s", (char *)__get_dynamic_array(msg))
+);
+
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi
 

+ 12 - 8
drivers/net/wireless/iwlwifi/iwl-mac80211.c

@@ -136,7 +136,7 @@ iwlagn_iface_combinations_p2p[] = {
  * other mac80211 functions grouped here.
  */
 int iwlagn_mac_setup_register(struct iwl_priv *priv,
-				  struct iwlagn_ucode_capabilities *capa)
+				  struct iwl_ucode_capabilities *capa)
 {
 	int ret;
 	struct ieee80211_hw *hw = priv->hw;
@@ -195,7 +195,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
 			    WIPHY_FLAG_DISABLE_BEACON_HINTS |
 			    WIPHY_FLAG_IBSS_RSN;
 
-	if (trans(priv)->ucode_wowlan.code.len &&
+	if (nic(priv)->fw.ucode_wowlan.code.len &&
 	    device_can_wakeup(trans(priv)->dev)) {
 		hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
 					  WIPHY_WOWLAN_DISCONNECT |
@@ -296,7 +296,7 @@ static int __iwl_up(struct iwl_priv *priv)
 
  error:
 	set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
-	__iwl_down(priv);
+	iwl_down(priv);
 	clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
 
 	IWL_ERR(priv, "Unable to initialize device.\n");
@@ -341,9 +341,13 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
 
 	priv->is_open = 0;
 
+	mutex_lock(&priv->shrd->mutex);
 	iwl_down(priv);
+	mutex_unlock(&priv->shrd->mutex);
+
+	iwl_cancel_deferred_work(priv);
 
-	flush_workqueue(priv->shrd->workqueue);
+	flush_workqueue(priv->workqueue);
 
 	/* User space software may expect getting rfkill changes
 	 * even if interface is down, trans->down will leave the RF
@@ -453,17 +457,17 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 		if (ret == 0) {
-			struct iwl_trans *trans = trans(priv);
+			struct iwl_nic *nic = nic(priv);
 			if (!priv->wowlan_sram)
 				priv->wowlan_sram =
-					kzalloc(trans->ucode_wowlan.data.len,
+					kzalloc(nic->fw.ucode_wowlan.data.len,
 						GFP_KERNEL);
 
 			if (priv->wowlan_sram)
 				_iwl_read_targ_mem_words(
 					trans(priv), 0x800000,
 					priv->wowlan_sram,
-					trans->ucode_wowlan.data.len / 4);
+					nic->fw.ucode_wowlan.data.len / 4);
 		}
 #endif
 	}
@@ -1117,7 +1121,7 @@ static int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
 {
 	struct iwl_priv *priv = hw->priv;
 
-	queue_work(priv->shrd->workqueue, &priv->beacon_update);
+	queue_work(priv->workqueue, &priv->beacon_update);
 
 	return 0;
 }

+ 16 - 2
drivers/net/wireless/iwlwifi/iwl-pci.c

@@ -70,6 +70,7 @@
 #include "iwl-trans.h"
 #include "iwl-csr.h"
 #include "iwl-cfg.h"
+#include "iwl-wifi.h"
 
 #define IWL_PCI_DEVICE(dev, subdev, cfg) \
 	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
@@ -282,13 +283,23 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	bus->shrd->bus = bus;
 
+	/* temporarily create this here */
+	bus->shrd->nic = kzalloc(sizeof(*bus->shrd->nic), GFP_KERNEL);
+	if (!bus->shrd->nic) {
+		dev_printk(KERN_ERR, &pdev->dev,
+			   "Couldn't allocate iwl_nic");
+		err = -ENOMEM;
+		goto out_free_bus;
+	}
+	/* and initialize it as well, temporarily */
+	bus->shrd->nic->shrd = bus->shrd;
 	pci_set_drvdata(pdev, bus);
 
 #ifdef CONFIG_IWLWIFI_IDI
 	trans(bus) = iwl_trans_idi_alloc(bus->shrd, pdev, ent);
 	if (trans(bus) == NULL) {
 		err = -ENOMEM;
-		goto out_free_bus;
+		goto out_free_nic;
 	}
 
 	err = iwl_probe(bus, &trans_ops_idi, cfg);
@@ -296,7 +307,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	trans(bus) = iwl_trans_pcie_alloc(bus->shrd, pdev, ent);
 	if (trans(bus) == NULL) {
 		err = -ENOMEM;
-		goto out_free_bus;
+		goto out_free_nic;
 	}
 
 	err = iwl_probe(bus, &trans_ops_pcie, cfg);
@@ -309,6 +320,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 out_free_trans:
 	iwl_trans_free(trans(bus));
 	pci_set_drvdata(pdev, NULL);
+out_free_nic:
+	kfree(bus->shrd->nic);
 out_free_bus:
 	kfree(bus->shrd);
 	kfree(bus);
@@ -325,6 +338,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 
 	pci_set_drvdata(pdev, NULL);
 
+	kfree(bus->shrd->nic);
 	kfree(bus->shrd);
 	kfree(bus);
 }

+ 5 - 5
drivers/net/wireless/iwlwifi/iwl-scan.c

@@ -218,7 +218,7 @@ static void iwl_do_scan_abort(struct iwl_priv *priv)
 int iwl_scan_cancel(struct iwl_priv *priv)
 {
 	IWL_DEBUG_SCAN(priv, "Queuing abort scan\n");
-	queue_work(priv->shrd->workqueue, &priv->abort_scan);
+	queue_work(priv->workqueue, &priv->abort_scan);
 	return 0;
 }
 
@@ -354,7 +354,7 @@ static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 	 */
 	set_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
 	clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
-	queue_work(priv->shrd->workqueue, &priv->scan_completed);
+	queue_work(priv->workqueue, &priv->scan_completed);
 
 	if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
 	    iwl_advanced_bt_coexist(priv) &&
@@ -374,7 +374,7 @@ static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 				IWL_BT_COEX_TRAFFIC_LOAD_NONE;
 		}
 		priv->bt_status = scan_notif->bt_status;
-		queue_work(priv->shrd->workqueue,
+		queue_work(priv->workqueue,
 			   &priv->bt_traffic_change_work);
 	}
 	return 0;
@@ -950,7 +950,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
 		return ret;
 	}
 
-	queue_delayed_work(priv->shrd->workqueue, &priv->scan_check,
+	queue_delayed_work(priv->workqueue, &priv->scan_check,
 			   IWL_SCAN_CHECK_WATCHDOG);
 
 	return 0;
@@ -963,7 +963,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
  */
 void iwl_internal_short_hw_scan(struct iwl_priv *priv)
 {
-	queue_work(priv->shrd->workqueue, &priv->start_internal_scan);
+	queue_work(priv->workqueue, &priv->start_internal_scan);
 }
 
 static void iwl_bg_start_internal_scan(struct work_struct *work)

+ 7 - 6
drivers/net/wireless/iwlwifi/iwl-shared.h

@@ -173,8 +173,6 @@ struct iwl_mod_params {
  * @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX)
  * @sku: sku read from EEPROM
  * @rx_page_order: Rx buffer page order
- * @max_inst_size: for ucode use
- * @max_data_size: for ucode use
  * @ct_kill_threshold: temperature threshold - in hw dependent unit
  * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit
  *	relevant for 1000, 6000 and up
@@ -192,8 +190,6 @@ struct iwl_hw_params {
 	bool shadow_reg_enable;
 	u16 sku;
 	u32 rx_page_order;
-	u32 max_inst_size;
-	u32 max_data_size;
 	u32 ct_kill_threshold;
 	u32 ct_kill_exit_threshold;
 	unsigned int wd_timeout;
@@ -283,6 +279,8 @@ enum iwl_led_mode {
  * @ucode_api_ok: oldest version of the uCode API that is OK to load
  *	without a warning, for use in transitions
  * @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @max_inst_size: The maximal length of the fw inst section
+ * @max_data_size: The maximal length of the fw data section
  * @valid_tx_ant: valid transmit antenna
  * @valid_rx_ant: valid receive antenna
  * @sku: sku information from EEPROM
@@ -320,6 +318,8 @@ struct iwl_cfg {
 	const unsigned int ucode_api_max;
 	const unsigned int ucode_api_ok;
 	const unsigned int ucode_api_min;
+	const u32 max_data_size;
+	const u32 max_inst_size;
 	u8   valid_tx_ant;
 	u8   valid_rx_ant;
 	u16  sku;
@@ -358,8 +358,8 @@ struct iwl_cfg {
  * @cfg: see struct iwl_cfg
  * @priv: pointer to the upper layer data
  * @trans: pointer to the transport layer data
+ * @nic: pointer to the nic data
  * @hw_params: see struct iwl_hw_params
- * @workqueue: the workqueue used by all the layers of the driver
  * @lock: protect general shared data
  * @sta_lock: protects the station table.
  *	If lock and sta_lock are needed, lock must be acquired first.
@@ -389,9 +389,9 @@ struct iwl_shared {
 	struct iwl_cfg *cfg;
 	struct iwl_priv *priv;
 	struct iwl_trans *trans;
+	struct iwl_nic *nic;
 	struct iwl_hw_params hw_params;
 
-	struct workqueue_struct *workqueue;
 	spinlock_t lock;
 	spinlock_t sta_lock;
 	struct mutex mutex;
@@ -420,6 +420,7 @@ struct iwl_shared {
 #define priv(_m)	((_m)->shrd->priv)
 #define cfg(_m)		((_m)->shrd->cfg)
 #define bus(_m)		((_m)->shrd->bus)
+#define nic(_m)		((_m)->shrd->nic)
 #define trans(_m)	((_m)->shrd->trans)
 #define hw_params(_m)	((_m)->shrd->hw_params)
 

+ 239 - 172
drivers/net/wireless/iwlwifi/iwl-testmode.c

@@ -81,6 +81,13 @@
 #include "iwl-bus.h"
 #include "iwl-fh.h"
 
+
+/* Periphery registers absolute lower bound. This is used in order to
+ * differentiate registery access through HBUS_TARG_PRPH_* and
+ * HBUS_TARG_MEM_* accesses.
+ */
+#define IWL_TM_ABS_PRPH_START (0xA00000)
+
 /* 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
  * through the NL80211_CMD_TESTMODE channel regulated by nl80211.
@@ -110,9 +117,9 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
 
 	[IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, },
 
-	[IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, },
-	[IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, },
-	[IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, },
+	[IWL_TM_ATTR_MEM_ADDR] = { .type = NLA_U32, },
+	[IWL_TM_ATTR_BUFFER_SIZE] = { .type = NLA_U32, },
+	[IWL_TM_ATTR_BUFFER_DUMP] = { .type = NLA_UNSPEC, },
 
 	[IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, },
 	[IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, },
@@ -172,7 +179,7 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
 	skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length,
 								GFP_ATOMIC);
 	if (skb == NULL) {
-		IWL_DEBUG_INFO(priv,
+		IWL_ERR(priv,
 			 "Run out of memory for messages to user space ?\n");
 		return;
 	}
@@ -183,24 +190,24 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
 
 nla_put_failure:
 	kfree_skb(skb);
-	IWL_DEBUG_INFO(priv, "Ouch, overran buffer, check allocation!\n");
+	IWL_ERR(priv, "Ouch, overran buffer, check allocation!\n");
 }
 
 void iwl_testmode_init(struct iwl_priv *priv)
 {
 	priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
 	priv->testmode_trace.trace_enabled = false;
-	priv->testmode_sram.sram_readed = false;
+	priv->testmode_mem.read_in_progress = false;
 }
 
-static void iwl_sram_cleanup(struct iwl_priv *priv)
+static void iwl_mem_cleanup(struct iwl_priv *priv)
 {
-	if (priv->testmode_sram.sram_readed) {
-		kfree(priv->testmode_sram.buff_addr);
-		priv->testmode_sram.buff_addr = NULL;
-		priv->testmode_sram.buff_size = 0;
-		priv->testmode_sram.num_chunks = 0;
-		priv->testmode_sram.sram_readed = false;
+	if (priv->testmode_mem.read_in_progress) {
+		kfree(priv->testmode_mem.buff_addr);
+		priv->testmode_mem.buff_addr = NULL;
+		priv->testmode_mem.buff_size = 0;
+		priv->testmode_mem.num_chunks = 0;
+		priv->testmode_mem.read_in_progress = false;
 	}
 }
 
@@ -226,9 +233,10 @@ static void iwl_trace_cleanup(struct iwl_priv *priv)
 void iwl_testmode_cleanup(struct iwl_priv *priv)
 {
 	iwl_trace_cleanup(priv);
-	iwl_sram_cleanup(priv);
+	iwl_mem_cleanup(priv);
 }
 
+
 /*
  * This function handles the user application commands to the ucode.
  *
@@ -237,8 +245,10 @@ void iwl_testmode_cleanup(struct iwl_priv *priv)
  * host command to the ucode.
  *
  * If any mandatory field is missing, -ENOMSG is replied to the user space
- * application; otherwise, the actual execution result of the host command to
- * ucode is replied.
+ * application; otherwise, waits for the host command to be sent and checks
+ * the return code. In case or error, it is returned, otherwise a reply is
+ * allocated and the reply RX packet
+ * is returned.
  *
  * @hw: ieee80211_hw object that represents the device
  * @tb: gnl message fields from the user space
@@ -247,25 +257,68 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_host_cmd cmd;
+	struct iwl_rx_packet *pkt;
+	struct sk_buff *skb;
+	void *reply_buf;
+	u32 reply_len;
+	int ret;
+	bool cmd_want_skb;
 
 	memset(&cmd, 0, sizeof(struct iwl_host_cmd));
 
 	if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] ||
 	    !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) {
-		IWL_DEBUG_INFO(priv,
-			"Error finding ucode command mandatory fields\n");
+		IWL_ERR(priv, "Missing ucode command mandatory fields\n");
 		return -ENOMSG;
 	}
 
-	cmd.flags = CMD_ON_DEMAND;
+	cmd.flags = CMD_ON_DEMAND | CMD_SYNC;
+	cmd_want_skb = nla_get_flag(tb[IWL_TM_ATTR_UCODE_CMD_SKB]);
+	if (cmd_want_skb)
+		cmd.flags |= CMD_WANT_SKB;
+
 	cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
 	cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
 	cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
 	cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
-	IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
+	IWL_DEBUG_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
 				" len %d\n", cmd.id, cmd.flags, cmd.len[0]);
-	/* ok, let's submit the command to ucode */
-	return iwl_trans_send_cmd(trans(priv), &cmd);
+
+	ret = iwl_trans_send_cmd(trans(priv), &cmd);
+	if (ret) {
+		IWL_ERR(priv, "Failed to send hcmd\n");
+		return ret;
+	}
+	if (!cmd_want_skb)
+		return ret;
+
+	/* Handling return of SKB to the user */
+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	if (!pkt) {
+		IWL_ERR(priv, "HCMD received a null response packet\n");
+		return ret;
+	}
+
+	reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+	skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, reply_len + 20);
+	reply_buf = kmalloc(reply_len, GFP_KERNEL);
+	if (!skb || !reply_buf) {
+		kfree_skb(skb);
+		kfree(reply_buf);
+		return -ENOMEM;
+	}
+
+	/* The reply is in a page, that we cannot send to user space. */
+	memcpy(reply_buf, &(pkt->hdr), reply_len);
+	iwl_free_pages(priv->shrd, cmd.reply_page);
+
+	NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
+	NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf);
+	return cfg80211_testmode_reply(skb);
+
+nla_put_failure:
+	IWL_DEBUG_INFO(priv, "Failed creating NL attributes\n");
+	return -ENOMSG;
 }
 
 
@@ -295,7 +348,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
 	int status = 0;
 
 	if (!tb[IWL_TM_ATTR_REG_OFFSET]) {
-		IWL_DEBUG_INFO(priv, "Error finding register offset\n");
+		IWL_ERR(priv, "Missing register offset\n");
 		return -ENOMSG;
 	}
 	ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]);
@@ -309,7 +362,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
 		cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 ||
 		cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8) &&
 		(ofs >= FH_MEM_UPPER_BOUND)) {
-		IWL_DEBUG_INFO(priv, "offset out of segment (0x0 - 0x%x)\n",
+		IWL_ERR(priv, "offset out of segment (0x0 - 0x%x)\n",
 			FH_MEM_UPPER_BOUND);
 		return -EINVAL;
 	}
@@ -321,19 +374,17 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
 
 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
 		if (!skb) {
-			IWL_DEBUG_INFO(priv, "Error allocating memory\n");
+			IWL_ERR(priv, "Memory allocation fail\n");
 			return -ENOMEM;
 		}
 		NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32);
 		status = cfg80211_testmode_reply(skb);
 		if (status < 0)
-			IWL_DEBUG_INFO(priv,
-				       "Error sending msg : %d\n", status);
+			IWL_ERR(priv, "Error sending msg : %d\n", status);
 		break;
 	case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
 		if (!tb[IWL_TM_ATTR_REG_VALUE32]) {
-			IWL_DEBUG_INFO(priv,
-				       "Error finding value to write\n");
+			IWL_ERR(priv, "Missing value to write\n");
 			return -ENOMSG;
 		} else {
 			val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
@@ -343,7 +394,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
 		break;
 	case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
 		if (!tb[IWL_TM_ATTR_REG_VALUE8]) {
-			IWL_DEBUG_INFO(priv, "Error finding value to write\n");
+			IWL_ERR(priv, "Missing value to write\n");
 			return -ENOMSG;
 		} else {
 			val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]);
@@ -351,34 +402,8 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
 			iwl_write8(trans(priv), ofs, val8);
 		}
 		break;
-	case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32:
-		val32 = iwl_read_prph(trans(priv), ofs);
-		IWL_INFO(priv, "32bit value to read 0x%x\n", val32);
-
-		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
-		if (!skb) {
-			IWL_DEBUG_INFO(priv, "Error allocating memory\n");
-			return -ENOMEM;
-		}
-		NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32);
-		status = cfg80211_testmode_reply(skb);
-		if (status < 0)
-			IWL_DEBUG_INFO(priv,
-					"Error sending msg : %d\n", status);
-		break;
-	case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32:
-		if (!tb[IWL_TM_ATTR_REG_VALUE32]) {
-			IWL_DEBUG_INFO(priv,
-					"Error finding value to write\n");
-			return -ENOMSG;
-		} else {
-			val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
-			IWL_INFO(priv, "32bit value to write 0x%x\n", val32);
-			iwl_write_prph(trans(priv), ofs, val32);
-		}
-		break;
 	default:
-		IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n");
+		IWL_ERR(priv, "Unknown testmode register command ID\n");
 		return -ENOSYS;
 	}
 
@@ -400,14 +425,13 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
 				      NULL, NULL);
 	ret = iwl_init_alive_start(trans(priv));
 	if (ret) {
-		IWL_DEBUG_INFO(priv,
-			"Error configuring init calibration: %d\n", ret);
+		IWL_ERR(priv, "Fail init calibration: %d\n", ret);
 		goto cfg_init_calib_error;
 	}
 
 	ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ);
 	if (ret)
-		IWL_DEBUG_INFO(priv, "Error detecting"
+		IWL_ERR(priv, "Error detecting"
 			" CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
 	return ret;
 
@@ -448,8 +472,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
 							rsp_data_len + 20);
 		if (!skb) {
-			IWL_DEBUG_INFO(priv,
-				       "Error allocating memory\n");
+			IWL_ERR(priv, "Memory allocation fail\n");
 			return -ENOMEM;
 		}
 		NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
@@ -458,15 +481,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 			rsp_data_len, rsp_data_ptr);
 		status = cfg80211_testmode_reply(skb);
 		if (status < 0)
-			IWL_DEBUG_INFO(priv, "Error sending msg : %d\n",
-				       status);
+			IWL_ERR(priv, "Error sending msg : %d\n", status);
 		break;
 
 	case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
 		status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
 		if (status)
-			IWL_DEBUG_INFO(priv,
-				"Error loading init ucode: %d\n", status);
+			IWL_ERR(priv, "Error loading init ucode: %d\n", status);
 		break;
 
 	case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
@@ -477,13 +498,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 	case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
 		status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR);
 		if (status) {
-			IWL_DEBUG_INFO(priv,
+			IWL_ERR(priv,
 				"Error loading runtime ucode: %d\n", status);
 			break;
 		}
 		status = iwl_alive_start(priv);
 		if (status)
-			IWL_DEBUG_INFO(priv,
+			IWL_ERR(priv,
 				"Error starting the device: %d\n", status);
 		break;
 
@@ -492,13 +513,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 		iwl_trans_stop_device(trans);
 		status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN);
 		if (status) {
-			IWL_DEBUG_INFO(priv,
+			IWL_ERR(priv,
 				"Error loading WOWLAN ucode: %d\n", status);
 			break;
 		}
 		status = iwl_alive_start(priv);
 		if (status)
-			IWL_DEBUG_INFO(priv,
+			IWL_ERR(priv,
 				"Error starting the device: %d\n", status);
 		break;
 
@@ -507,8 +528,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 			skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
 				cfg(priv)->base_params->eeprom_size + 20);
 			if (!skb) {
-				IWL_DEBUG_INFO(priv,
-				       "Error allocating memory\n");
+				IWL_ERR(priv, "Memory allocation fail\n");
 				return -ENOMEM;
 			}
 			NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
@@ -518,35 +538,34 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 				priv->shrd->eeprom);
 			status = cfg80211_testmode_reply(skb);
 			if (status < 0)
-				IWL_DEBUG_INFO(priv,
-					       "Error sending msg : %d\n",
-					       status);
+				IWL_ERR(priv, "Error sending msg : %d\n",
+					status);
 		} else
 			return -EFAULT;
 		break;
 
 	case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
 		if (!tb[IWL_TM_ATTR_FIXRATE]) {
-			IWL_DEBUG_INFO(priv,
-				       "Error finding fixrate setting\n");
+			IWL_ERR(priv, "Missing fixrate setting\n");
 			return -ENOMSG;
 		}
 		priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
 		break;
 
 	case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
-		IWL_INFO(priv, "uCode version raw: 0x%x\n", priv->ucode_ver);
+		IWL_INFO(priv, "uCode version raw: 0x%x\n",
+			 nic(priv)->fw.ucode_ver);
 
 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
 		if (!skb) {
-			IWL_DEBUG_INFO(priv, "Error allocating memory\n");
+			IWL_ERR(priv, "Memory allocation fail\n");
 			return -ENOMEM;
 		}
-		NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION, priv->ucode_ver);
+		NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION,
+			    nic(priv)->fw.ucode_ver);
 		status = cfg80211_testmode_reply(skb);
 		if (status < 0)
-			IWL_DEBUG_INFO(priv,
-					"Error sending msg : %d\n", status);
+			IWL_ERR(priv, "Error sending msg : %d\n", status);
 		break;
 
 	case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
@@ -555,40 +574,39 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 
 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
 		if (!skb) {
-			IWL_DEBUG_INFO(priv, "Error allocating memory\n");
+			IWL_ERR(priv, "Memory allocation fail\n");
 			return -ENOMEM;
 		}
 		NLA_PUT_U32(skb, IWL_TM_ATTR_DEVICE_ID, devid);
 		status = cfg80211_testmode_reply(skb);
 		if (status < 0)
-			IWL_DEBUG_INFO(priv,
-					"Error sending msg : %d\n", status);
+			IWL_ERR(priv, "Error sending msg : %d\n", status);
 		break;
 
 	case IWL_TM_CMD_APP2DEV_GET_FW_INFO:
 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8);
 		if (!skb) {
-			IWL_DEBUG_INFO(priv, "Error allocating memory\n");
+			IWL_ERR(priv, "Memory allocation fail\n");
 			return -ENOMEM;
 		}
 		switch (priv->shrd->ucode_type) {
 		case IWL_UCODE_REGULAR:
-			inst_size = trans(priv)->ucode_rt.code.len;
-			data_size = trans(priv)->ucode_rt.data.len;
+			inst_size = nic(priv)->fw.ucode_rt.code.len;
+			data_size = nic(priv)->fw.ucode_rt.data.len;
 			break;
 		case IWL_UCODE_INIT:
-			inst_size = trans(priv)->ucode_init.code.len;
-			data_size = trans(priv)->ucode_init.data.len;
+			inst_size = nic(priv)->fw.ucode_init.code.len;
+			data_size = nic(priv)->fw.ucode_init.data.len;
 			break;
 		case IWL_UCODE_WOWLAN:
-			inst_size = trans(priv)->ucode_wowlan.code.len;
-			data_size = trans(priv)->ucode_wowlan.data.len;
+			inst_size = nic(priv)->fw.ucode_wowlan.code.len;
+			data_size = nic(priv)->fw.ucode_wowlan.data.len;
 			break;
 		case IWL_UCODE_NONE:
-			IWL_DEBUG_INFO(priv, "The uCode has not been loaded\n");
+			IWL_ERR(priv, "No uCode has not been loaded\n");
 			break;
 		default:
-			IWL_DEBUG_INFO(priv, "Unsupported uCode type\n");
+			IWL_ERR(priv, "Unsupported uCode type\n");
 			break;
 		}
 		NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type);
@@ -596,12 +614,11 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 		NLA_PUT_U32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size);
 		status = cfg80211_testmode_reply(skb);
 		if (status < 0)
-			IWL_DEBUG_INFO(priv,
-					"Error sending msg : %d\n", status);
+			IWL_ERR(priv, "Error sending msg : %d\n", status);
 		break;
 
 	default:
-		IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n");
+		IWL_ERR(priv, "Unknown testmode driver command ID\n");
 		return -ENOSYS;
 	}
 	return status;
@@ -664,8 +681,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
 		skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
 			sizeof(priv->testmode_trace.dma_addr) + 20);
 		if (!skb) {
-			IWL_DEBUG_INFO(priv,
-				"Error allocating memory\n");
+			IWL_ERR(priv, "Memory allocation fail\n");
 			iwl_trace_cleanup(priv);
 			return -ENOMEM;
 		}
@@ -674,9 +690,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
 			(u64 *)&priv->testmode_trace.dma_addr);
 		status = cfg80211_testmode_reply(skb);
 		if (status < 0) {
-			IWL_DEBUG_INFO(priv,
-				       "Error sending msg : %d\n",
-				       status);
+			IWL_ERR(priv, "Error sending msg : %d\n", status);
 		}
 		priv->testmode_trace.num_chunks =
 			DIV_ROUND_UP(priv->testmode_trace.buff_size,
@@ -687,7 +701,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
 		iwl_trace_cleanup(priv);
 		break;
 	default:
-		IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
+		IWL_ERR(priv, "Unknown testmode mem command ID\n");
 		return -ENOSYS;
 	}
 	return status;
@@ -752,7 +766,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
 	u8 owner;
 
 	if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
-		IWL_DEBUG_INFO(priv, "Error finding ucode owner\n");
+		IWL_ERR(priv, "Missing ucode owner\n");
 		return -ENOMSG;
 	}
 
@@ -760,12 +774,89 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
 	if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
 		priv->shrd->ucode_owner = owner;
 	else {
-		IWL_DEBUG_INFO(priv, "Invalid owner\n");
+		IWL_ERR(priv, "Invalid owner\n");
 		return -EINVAL;
 	}
 	return 0;
 }
 
+static int iwl_testmode_indirect_read(struct iwl_priv *priv, u32 addr, u32 size)
+{
+	struct iwl_trans *trans = trans(priv);
+	unsigned long flags;
+	int i;
+
+	if (size & 0x3)
+		return -EINVAL;
+	priv->testmode_mem.buff_size = size;
+	priv->testmode_mem.buff_addr =
+		kmalloc(priv->testmode_mem.buff_size, GFP_KERNEL);
+	if (priv->testmode_mem.buff_addr == NULL)
+		return -ENOMEM;
+
+	/* Hard-coded periphery absolute address */
+	if (IWL_TM_ABS_PRPH_START <= addr &&
+		addr < IWL_TM_ABS_PRPH_START + PRPH_END) {
+			spin_lock_irqsave(&trans->reg_lock, flags);
+			iwl_grab_nic_access(trans);
+			iwl_write32(trans, HBUS_TARG_PRPH_RADDR,
+				addr | (3 << 24));
+			for (i = 0; i < size; i += 4)
+				*(u32 *)(priv->testmode_mem.buff_addr + i) =
+					iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
+			iwl_release_nic_access(trans);
+			spin_unlock_irqrestore(&trans->reg_lock, flags);
+	} else { /* target memory (SRAM) */
+		_iwl_read_targ_mem_words(trans, addr,
+			priv->testmode_mem.buff_addr,
+			priv->testmode_mem.buff_size / 4);
+	}
+
+	priv->testmode_mem.num_chunks =
+		DIV_ROUND_UP(priv->testmode_mem.buff_size, DUMP_CHUNK_SIZE);
+	priv->testmode_mem.read_in_progress = true;
+	return 0;
+
+}
+
+static int iwl_testmode_indirect_write(struct iwl_priv *priv, u32 addr,
+	u32 size, unsigned char *buf)
+{
+	struct iwl_trans *trans = trans(priv);
+	u32 val, i;
+	unsigned long flags;
+
+	if (IWL_TM_ABS_PRPH_START <= addr &&
+		addr < IWL_TM_ABS_PRPH_START + PRPH_END) {
+			/* Periphery writes can be 1-3 bytes long, or DWORDs */
+			if (size < 4) {
+				memcpy(&val, buf, size);
+				spin_lock_irqsave(&trans->reg_lock, flags);
+				iwl_grab_nic_access(trans);
+				iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
+					    (addr & 0x0000FFFF) |
+					    ((size - 1) << 24));
+				iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
+				iwl_release_nic_access(trans);
+				/* needed after consecutive writes w/o read */
+				mmiowb();
+				spin_unlock_irqrestore(&trans->reg_lock, flags);
+			} else {
+				if (size % 4)
+					return -EINVAL;
+				for (i = 0; i < size; i += 4)
+					iwl_write_prph(trans, addr+i,
+						*(u32 *)(buf+i));
+			}
+	} else if (iwlagn_hw_valid_rtc_data_addr(addr) ||
+		(IWLAGN_RTC_INST_LOWER_BOUND <= addr &&
+		addr < IWLAGN_RTC_INST_UPPER_BOUND)) {
+			_iwl_write_targ_mem_words(trans, addr, buf, size/4);
+	} else
+		return -EINVAL;
+	return 0;
+}
+
 /*
  * This function handles the user application commands for SRAM data dump
  *
@@ -782,82 +873,60 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
  * @hw: ieee80211_hw object that represents the device
  * @tb: gnl message fields from the user space
  */
-static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb)
+static int iwl_testmode_indirect_mem(struct ieee80211_hw *hw,
+	struct nlattr **tb)
 {
 	struct iwl_priv *priv = hw->priv;
-	u32 ofs, size, maxsize;
+	u32 addr, size, cmd;
+	unsigned char *buf;
 
-	if (priv->testmode_sram.sram_readed)
+	/* Both read and write should be blocked, for atomicity */
+	if (priv->testmode_mem.read_in_progress)
 		return -EBUSY;
 
-	if (!tb[IWL_TM_ATTR_SRAM_ADDR]) {
-		IWL_DEBUG_INFO(priv, "Error finding SRAM offset address\n");
+	cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
+	if (!tb[IWL_TM_ATTR_MEM_ADDR]) {
+		IWL_ERR(priv, "Error finding memory offset address\n");
 		return -ENOMSG;
 	}
-	ofs = nla_get_u32(tb[IWL_TM_ATTR_SRAM_ADDR]);
-	if (!tb[IWL_TM_ATTR_SRAM_SIZE]) {
-		IWL_DEBUG_INFO(priv, "Error finding size for SRAM reading\n");
+	addr = nla_get_u32(tb[IWL_TM_ATTR_MEM_ADDR]);
+	if (!tb[IWL_TM_ATTR_BUFFER_SIZE]) {
+		IWL_ERR(priv, "Error finding size for memory reading\n");
 		return -ENOMSG;
 	}
-	size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]);
-	switch (priv->shrd->ucode_type) {
-	case IWL_UCODE_REGULAR:
-		maxsize = trans(priv)->ucode_rt.data.len;
-		break;
-	case IWL_UCODE_INIT:
-		maxsize = trans(priv)->ucode_init.data.len;
-		break;
-	case IWL_UCODE_WOWLAN:
-		maxsize = trans(priv)->ucode_wowlan.data.len;
-		break;
-	case IWL_UCODE_NONE:
-		IWL_ERR(priv, "Error, uCode does not been loaded\n");
-		return -ENOSYS;
-	default:
-		IWL_ERR(priv, "Error, unsupported uCode type\n");
-		return -ENOSYS;
-	}
-	if ((ofs + size) > (maxsize + SRAM_DATA_SEG_OFFSET)) {
-		IWL_ERR(priv, "Invalid offset/size: out of range\n");
-		return -EINVAL;
-	}
-	priv->testmode_sram.buff_size = (size / 4) * 4;
-	priv->testmode_sram.buff_addr =
-		kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL);
-	if (priv->testmode_sram.buff_addr == NULL) {
-		IWL_ERR(priv, "Error allocating memory\n");
-		return -ENOMEM;
+	size = nla_get_u32(tb[IWL_TM_ATTR_BUFFER_SIZE]);
+
+	if (cmd == IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ)
+		return iwl_testmode_indirect_read(priv, addr,  size);
+	else {
+		if (!tb[IWL_TM_ATTR_BUFFER_DUMP])
+			return -EINVAL;
+		buf = (unsigned char *) nla_data(tb[IWL_TM_ATTR_BUFFER_DUMP]);
+		return iwl_testmode_indirect_write(priv, addr, size, buf);
 	}
-	_iwl_read_targ_mem_words(trans(priv), ofs,
-					priv->testmode_sram.buff_addr,
-					priv->testmode_sram.buff_size / 4);
-	priv->testmode_sram.num_chunks =
-		DIV_ROUND_UP(priv->testmode_sram.buff_size, DUMP_CHUNK_SIZE);
-	priv->testmode_sram.sram_readed = true;
-	return 0;
 }
 
-static int iwl_testmode_sram_dump(struct ieee80211_hw *hw, struct nlattr **tb,
+static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb,
 				   struct sk_buff *skb,
 				   struct netlink_callback *cb)
 {
 	struct iwl_priv *priv = hw->priv;
 	int idx, length;
 
-	if (priv->testmode_sram.sram_readed) {
+	if (priv->testmode_mem.read_in_progress) {
 		idx = cb->args[4];
-		if (idx >= priv->testmode_sram.num_chunks) {
-			iwl_sram_cleanup(priv);
+		if (idx >= priv->testmode_mem.num_chunks) {
+			iwl_mem_cleanup(priv);
 			return -ENOENT;
 		}
 		length = DUMP_CHUNK_SIZE;
-		if (((idx + 1) == priv->testmode_sram.num_chunks) &&
-		    (priv->testmode_sram.buff_size % DUMP_CHUNK_SIZE))
-			length = priv->testmode_sram.buff_size %
+		if (((idx + 1) == priv->testmode_mem.num_chunks) &&
+		    (priv->testmode_mem.buff_size % DUMP_CHUNK_SIZE))
+			length = priv->testmode_mem.buff_size %
 				DUMP_CHUNK_SIZE;
 
-		NLA_PUT(skb, IWL_TM_ATTR_SRAM_DUMP, length,
-			priv->testmode_sram.buff_addr +
+		NLA_PUT(skb, IWL_TM_ATTR_BUFFER_DUMP, length,
+			priv->testmode_mem.buff_addr +
 			(DUMP_CHUNK_SIZE * idx));
 		idx++;
 		cb->args[4] = idx;
@@ -898,14 +967,13 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
 	result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
 			iwl_testmode_gnl_msg_policy);
 	if (result != 0) {
-		IWL_DEBUG_INFO(priv,
-			       "Error parsing the gnl message : %d\n", result);
+		IWL_ERR(priv, "Error parsing the gnl message : %d\n", result);
 		return result;
 	}
 
 	/* IWL_TM_ATTR_COMMAND is absolutely mandatory */
 	if (!tb[IWL_TM_ATTR_COMMAND]) {
-		IWL_DEBUG_INFO(priv, "Error finding testmode command type\n");
+		IWL_ERR(priv, "Missing testmode command type\n");
 		return -ENOMSG;
 	}
 	/* in case multiple accesses to the device happens */
@@ -919,8 +987,6 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
 	case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
 	case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
 	case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
-	case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32:
-	case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32:
 		IWL_DEBUG_INFO(priv, "testmode cmd to register\n");
 		result = iwl_testmode_reg(hw, tb);
 		break;
@@ -950,13 +1016,15 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
 		result = iwl_testmode_ownership(hw, tb);
 		break;
 
-	case IWL_TM_CMD_APP2DEV_READ_SRAM:
-		IWL_DEBUG_INFO(priv, "testmode sram read cmd to driver\n");
-		result = iwl_testmode_sram(hw, tb);
+	case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ:
+	case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE:
+		IWL_DEBUG_INFO(priv, "testmode indirect memory cmd "
+			"to driver\n");
+		result = iwl_testmode_indirect_mem(hw, tb);
 		break;
 
 	default:
-		IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
+		IWL_ERR(priv, "Unknown testmode command\n");
 		result = -ENOSYS;
 		break;
 	}
@@ -981,15 +1049,14 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
 		result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
 				iwl_testmode_gnl_msg_policy);
 		if (result) {
-			IWL_DEBUG_INFO(priv,
-			       "Error parsing the gnl message : %d\n", result);
+			IWL_ERR(priv,
+				"Error parsing the gnl message : %d\n", result);
 			return result;
 		}
 
 		/* IWL_TM_ATTR_COMMAND is absolutely mandatory */
 		if (!tb[IWL_TM_ATTR_COMMAND]) {
-			IWL_DEBUG_INFO(priv,
-				"Error finding testmode command type\n");
+			IWL_ERR(priv, "Missing testmode command type\n");
 			return -ENOMSG;
 		}
 		cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
@@ -1003,9 +1070,9 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
 		IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
 		result = iwl_testmode_trace_dump(hw, tb, skb, cb);
 		break;
-	case IWL_TM_CMD_APP2DEV_DUMP_SRAM:
+	case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP:
 		IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n");
-		result = iwl_testmode_sram_dump(hw, tb, skb, cb);
+		result = iwl_testmode_buffer_dump(hw, tb, skb, cb);
 		break;
 	default:
 		result = -EINVAL;

+ 36 - 28
drivers/net/wireless/iwlwifi/iwl-testmode.h

@@ -99,7 +99,7 @@
  *	to user application
  * @IWL_TM_CMD_DEV2APP_UCODE_RX_PKT:
  *	commands from kernel space to multicast the spontaneous messages
- *	to user application
+ *	to user application, or reply of host commands
  * @IWL_TM_CMD_DEV2APP_EEPROM_RSP:
  *	commands from kernel space to carry the eeprom response
  *	to user application
@@ -109,20 +109,19 @@
  *	if application has the ownership, the only host command from
  *	testmode will deliver to uCode. Default owner is driver
  *
- * @IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32:
- * @IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32:
- *	commands from user application to indirectly access peripheral register
- *
- * @IWL_TM_CMD_APP2DEV_READ_SRAM:
- * @IWL_TM_CMD_APP2DEV_DUMP_SRAM:
- *	commands from user application to read data in sram
- *
  * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Wake On Wireless LAN uCode image
  * @IWL_TM_CMD_APP2DEV_GET_FW_VERSION: retrieve uCode version
  * @IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: retrieve ID information in device
  * @IWL_TM_CMD_APP2DEV_GET_FW_INFO:
  *	retrieve information of existing loaded uCode image
  *
+ * @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ:
+ * @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP:
+ * @IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE:
+ *	Commands to read/write data from periphery or SRAM memory ranges.
+ *	Fore reading, a READ command is sent from the userspace and the data
+ *	is returned when the user calls a DUMP command.
+ *	For writing, only a WRITE command is used.
  */
 enum iwl_tm_cmd_t {
 	IWL_TM_CMD_APP2DEV_UCODE		= 1,
@@ -142,15 +141,18 @@ enum iwl_tm_cmd_t {
 	IWL_TM_CMD_DEV2APP_UCODE_RX_PKT		= 15,
 	IWL_TM_CMD_DEV2APP_EEPROM_RSP		= 16,
 	IWL_TM_CMD_APP2DEV_OWNERSHIP		= 17,
-	IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32	= 18,
-	IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32	= 19,
-	IWL_TM_CMD_APP2DEV_READ_SRAM		= 20,
-	IWL_TM_CMD_APP2DEV_DUMP_SRAM		= 21,
+	RESERVED_18				= 18,
+	RESERVED_19				= 19,
+	RESERVED_20				= 20,
+	RESERVED_21				= 21,
 	IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW	= 22,
 	IWL_TM_CMD_APP2DEV_GET_FW_VERSION	= 23,
 	IWL_TM_CMD_APP2DEV_GET_DEVICE_ID	= 24,
 	IWL_TM_CMD_APP2DEV_GET_FW_INFO		= 25,
-	IWL_TM_CMD_MAX				= 26,
+	IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ = 26,
+	IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP = 27,
+	IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE = 28,
+	IWL_TM_CMD_MAX				= 29,
 };
 
 /*
@@ -171,8 +173,6 @@ enum iwl_tm_cmd_t {
  *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE,
  *	The mandatory fields are :
  *	IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID;
- *	IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands;
- *	The optional fields are:
  *	IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload
  *	to the ucode
  *
@@ -221,16 +221,19 @@ enum iwl_tm_cmd_t {
  *	The mandatory fields are:
  *	IWL_TM_ATTR_UCODE_OWNER for the new owner
  *
- * @IWL_TM_ATTR_SRAM_ADDR:
- * @IWL_TM_ATTR_SRAM_SIZE:
- *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_READ_SRAM,
+ * @IWL_TM_ATTR_MEM_ADDR:
+ * @IWL_TM_ATTR_BUFFER_SIZE:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ
+ *	or IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE.
  *	The mandatory fields are:
- *	IWL_TM_ATTR_SRAM_ADDR for the address in sram
- *	IWL_TM_ATTR_SRAM_SIZE for the buffer size of data reading
+ *	IWL_TM_ATTR_MEM_ADDR for the address in SRAM/periphery to read/write
+ *	IWL_TM_ATTR_BUFFER_SIZE for the buffer size of data to read/write.
  *
- * @IWL_TM_ATTR_SRAM_DUMP:
- *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_DUMP_SRAM,
- *	IWL_TM_ATTR_SRAM_DUMP for the data in sram
+ * @IWL_TM_ATTR_BUFFER_DUMP:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP,
+ *	IWL_TM_ATTR_BUFFER_DUMP is used for the data that was read.
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE,
+ *	this attribute contains the data to write.
  *
  * @IWL_TM_ATTR_FW_VERSION:
  *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_VERSION,
@@ -249,6 +252,10 @@ enum iwl_tm_cmd_t {
  *	IWL_TM_ATTR_FW_INST_SIZE for the size of instruction section
  *	IWL_TM_ATTR_FW_DATA_SIZE for the size of data section
  *
+ * @IWL_TM_ATTR_UCODE_CMD_SKB:
+ *	When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE this flag
+ *	indicates that the user wants to receive the response of the command
+ *	in a reply SKB. If it's not present, the response is not returned.
  */
 enum iwl_tm_attr_t {
 	IWL_TM_ATTR_NOT_APPLICABLE		= 0,
@@ -266,15 +273,16 @@ enum iwl_tm_attr_t {
 	IWL_TM_ATTR_TRACE_DUMP			= 12,
 	IWL_TM_ATTR_FIXRATE			= 13,
 	IWL_TM_ATTR_UCODE_OWNER			= 14,
-	IWL_TM_ATTR_SRAM_ADDR			= 15,
-	IWL_TM_ATTR_SRAM_SIZE			= 16,
-	IWL_TM_ATTR_SRAM_DUMP			= 17,
+	IWL_TM_ATTR_MEM_ADDR			= 15,
+	IWL_TM_ATTR_BUFFER_SIZE			= 16,
+	IWL_TM_ATTR_BUFFER_DUMP			= 17,
 	IWL_TM_ATTR_FW_VERSION			= 18,
 	IWL_TM_ATTR_DEVICE_ID			= 19,
 	IWL_TM_ATTR_FW_TYPE			= 20,
 	IWL_TM_ATTR_FW_INST_SIZE		= 21,
 	IWL_TM_ATTR_FW_DATA_SIZE		= 22,
-	IWL_TM_ATTR_MAX				= 23,
+	IWL_TM_ATTR_UCODE_CMD_SKB		= 23,
+	IWL_TM_ATTR_MAX				= 24,
 };
 
 /* uCode trace buffer */

+ 1 - 0
drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h

@@ -230,6 +230,7 @@ struct iwl_trans_pcie {
 	struct tasklet_struct irq_tasklet;
 	struct isr_statistics isr_stats;
 
+	spinlock_t irq_lock;
 	u32 inta_mask;
 	u32 scd_base_addr;
 	struct iwl_dma_ptr scd_bc_tbls;

+ 33 - 37
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c

@@ -34,6 +34,7 @@
 #include "iwl-core.h"
 #include "iwl-io.h"
 #include "iwl-trans-pcie-int.h"
+#include "iwl-wifi.h"
 
 #ifdef CONFIG_IWLWIFI_IDI
 #include "iwl-amfh.h"
@@ -227,7 +228,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans)
 	/* If the pre-allocated buffer pool is dropping low, schedule to
 	 * refill it */
 	if (rxq->free_count <= RX_LOW_WATERMARK)
-		queue_work(trans->shrd->workqueue, &trans_pcie->rx_replenish);
+		schedule_work(&trans_pcie->rx_replenish);
 
 
 	/* If we've added more space for the firmware to place data, tell it.
@@ -331,13 +332,14 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority)
 
 void iwlagn_rx_replenish(struct iwl_trans *trans)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	unsigned long flags;
 
 	iwlagn_rx_allocate(trans, GFP_KERNEL);
 
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 	iwlagn_rx_queue_restock(trans);
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 }
 
 static void iwlagn_rx_replenish_now(struct iwl_trans *trans)
@@ -351,14 +353,8 @@ void iwl_bg_rx_replenish(struct work_struct *data)
 {
 	struct iwl_trans_pcie *trans_pcie =
 	    container_of(data, struct iwl_trans_pcie, rx_replenish);
-	struct iwl_trans *trans = trans_pcie->trans;
-
-	if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
-		return;
 
-	mutex_lock(&trans->shrd->mutex);
-	iwlagn_rx_replenish(trans);
-	mutex_unlock(&trans->shrd->mutex);
+	iwlagn_rx_replenish(trans_pcie->trans);
 }
 
 /**
@@ -594,17 +590,17 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
 {
 	u32 base;
 	struct iwl_error_event_table table;
-	struct iwl_priv *priv = priv(trans);
+	struct iwl_nic *nic = nic(trans);
 	struct iwl_trans_pcie *trans_pcie =
 		IWL_TRANS_GET_PCIE_TRANS(trans);
 
 	base = trans->shrd->device_pointers.error_event_table;
 	if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
 		if (!base)
-			base = priv->init_errlog_ptr;
+			base = nic->init_errlog_ptr;
 	} else {
 		if (!base)
-			base = priv->inst_errlog_ptr;
+			base = nic->inst_errlog_ptr;
 	}
 
 	if (!iwlagn_hw_valid_rtc_data_addr(base)) {
@@ -616,7 +612,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
 		return;
 	}
 
-	iwl_read_targ_mem_words(trans(priv), base, &table, sizeof(table));
+	iwl_read_targ_mem_words(trans, base, &table, sizeof(table));
 
 	if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
 		IWL_ERR(trans, "Start IWL Error Log Dump:\n");
@@ -626,7 +622,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
 
 	trans_pcie->isr_stats.err_code = table.error_id;
 
-	trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
+	trace_iwlwifi_dev_ucode_error(priv(nic), table.error_id, table.tsf_low,
 				      table.data1, table.data2, table.line,
 				      table.blink1, table.blink2, table.ilink1,
 				      table.ilink2, table.bcon_time, table.gp1,
@@ -723,7 +719,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
 	u32 ptr;        /* SRAM byte address of log data */
 	u32 ev, time, data; /* event log data */
 	unsigned long reg_flags;
-	struct iwl_priv *priv = priv(trans);
+	struct iwl_nic *nic = nic(trans);
 
 	if (num_events == 0)
 		return pos;
@@ -731,10 +727,10 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
 	base = trans->shrd->device_pointers.log_event_table;
 	if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
 		if (!base)
-			base = priv->init_evtlog_ptr;
+			base = nic->init_evtlog_ptr;
 	} else {
 		if (!base)
-			base = priv->inst_evtlog_ptr;
+			base = nic->inst_evtlog_ptr;
 	}
 
 	if (mode == 0)
@@ -764,7 +760,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
 						"EVT_LOG:0x%08x:%04u\n",
 						time, ev);
 			} else {
-				trace_iwlwifi_dev_ucode_event(priv, 0,
+				trace_iwlwifi_dev_ucode_event(priv(trans), 0,
 					time, ev);
 				IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n",
 					time, ev);
@@ -778,7 +774,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
 			} else {
 				IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n",
 					time, data, ev);
-				trace_iwlwifi_dev_ucode_event(priv, time,
+				trace_iwlwifi_dev_ucode_event(priv(trans), time,
 					data, ev);
 			}
 		}
@@ -840,17 +836,17 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
 	u32 logsize;
 	int pos = 0;
 	size_t bufsz = 0;
-	struct iwl_priv *priv = priv(trans);
+	struct iwl_nic *nic = nic(trans);
 
 	base = trans->shrd->device_pointers.log_event_table;
 	if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
-		logsize = priv->init_evtlog_size;
+		logsize = nic->init_evtlog_size;
 		if (!base)
-			base = priv->init_evtlog_ptr;
+			base = nic->init_evtlog_ptr;
 	} else {
-		logsize = priv->inst_evtlog_size;
+		logsize = nic->inst_evtlog_size;
 		if (!base)
-			base = priv->inst_evtlog_ptr;
+			base = nic->inst_evtlog_ptr;
 	}
 
 	if (!iwlagn_hw_valid_rtc_data_addr(base)) {
@@ -949,7 +945,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
 	struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
 
 
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
 	/* Ack/clear/reset pending uCode interrupts.
 	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
@@ -979,7 +975,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
 	/* saved interrupt in inta variable now we can reset trans_pcie->inta */
 	trans_pcie->inta = 0;
 
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	/* Now service all interrupt bits discovered above. */
 	if (inta & CSR_INT_BIT_HW_ERR) {
@@ -1232,7 +1228,7 @@ void iwl_reset_ict(struct iwl_trans *trans)
 	if (!trans_pcie->ict_tbl)
 		return;
 
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 	iwl_disable_interrupts(trans);
 
 	memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
@@ -1249,7 +1245,7 @@ void iwl_reset_ict(struct iwl_trans *trans)
 	trans_pcie->ict_index = 0;
 	iwl_write32(trans, CSR_INT, trans_pcie->inta_mask);
 	iwl_enable_interrupts(trans);
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 }
 
 /* Device is going down disable ict interrupt usage */
@@ -1260,9 +1256,9 @@ void iwl_disable_ict(struct iwl_trans *trans)
 
 	unsigned long flags;
 
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 	trans_pcie->use_ict = false;
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 }
 
 static irqreturn_t iwl_isr(int irq, void *data)
@@ -1281,7 +1277,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
 
 	trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
 	/* Disable (but don't clear!) interrupts here to avoid
 	 *    back-to-back ISRs and sporadic interrupts from our NIC.
@@ -1325,7 +1321,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
 		iwl_enable_interrupts(trans);
 
  unplugged:
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 	return IRQ_HANDLED;
 
  none:
@@ -1335,7 +1331,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
 		!trans_pcie->inta)
 		iwl_enable_interrupts(trans);
 
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 	return IRQ_NONE;
 }
 
@@ -1369,7 +1365,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
 
 	trace_iwlwifi_dev_irq(priv(trans));
 
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
 	/* Disable (but don't clear!) interrupts here to avoid
 	 * back-to-back ISRs and sporadic interrupts from our NIC.
@@ -1440,7 +1436,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
 		iwl_enable_interrupts(trans);
 	}
 
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 	return IRQ_HANDLED;
 
  none:
@@ -1451,6 +1447,6 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
 	    !trans_pcie->inta)
 		iwl_enable_interrupts(trans);
 
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 	return IRQ_NONE;
 }

+ 2 - 2
drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c

@@ -492,7 +492,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
 
 	ra_tid = BUILD_RAxTID(sta_id, tid);
 
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
 	/* Stop this Tx queue before configuring it */
 	iwlagn_tx_queue_stop_scheduler(trans, txq_id);
@@ -532,7 +532,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
 	trans_pcie->txq[txq_id].sta_id = sta_id;
 	trans_pcie->txq[txq_id].tid = tid;
 
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 }
 
 /*

+ 24 - 15
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c

@@ -219,10 +219,10 @@ static int iwl_rx_init(struct iwl_trans *trans)
 
 	iwl_trans_rx_hw_init(trans, rxq);
 
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 	rxq->need_update = 1;
 	iwl_rx_queue_update_write_ptr(trans, rxq);
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	return 0;
 }
@@ -585,7 +585,7 @@ static int iwl_tx_init(struct iwl_trans *trans)
 		alloc = true;
 	}
 
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
 	/* Turn off all Tx DMA fifos */
 	iwl_write_prph(trans, SCD_TXFACT, 0);
@@ -594,7 +594,7 @@ static int iwl_tx_init(struct iwl_trans *trans)
 	iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
 			   trans_pcie->kw.dma >> 4);
 
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
 	for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
@@ -803,17 +803,18 @@ static void iwl_apm_stop(struct iwl_trans *trans)
 
 static int iwl_nic_init(struct iwl_trans *trans)
 {
+	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	unsigned long flags;
 
 	/* nic_init */
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 	iwl_apm_init(trans);
 
 	/* Set interrupt coalescing calibration timer to default (512 usecs) */
 	iwl_write8(trans, CSR_INT_COALESCING,
 		IWL_HOST_INT_CALIB_TIMEOUT_DEF);
 
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	iwl_set_pwr_vmain(trans);
 
@@ -1078,10 +1079,15 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
 
 /*
  * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- * must be called under priv->shrd->lock and mac access
+ * must be called under the irq lock and with MAC access
  */
 static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
 {
+	struct iwl_trans_pcie __maybe_unused *trans_pcie =
+		IWL_TRANS_GET_PCIE_TRANS(trans);
+
+	lockdep_assert_held(&trans_pcie->irq_lock);
+
 	iwl_write_prph(trans, SCD_TXFACT, mask);
 }
 
@@ -1095,7 +1101,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
 	int i, chan;
 	u32 reg_val;
 
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
 	trans_pcie->scd_base_addr =
 		iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
@@ -1191,7 +1197,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
 					      fifo, 0);
 	}
 
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	/* Enable L1-Active */
 	iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
@@ -1214,7 +1220,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
 	/* Turn off all Tx DMA fifos */
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
 	iwl_trans_txq_set_sched(trans, 0);
 
@@ -1230,7 +1236,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
 			    iwl_read_direct32(trans,
 					      FH_TSSR_TX_STATUS_REG));
 	}
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	if (!trans_pcie->txq) {
 		IWL_WARN(trans, "Stopping tx queues that aren't allocated...");
@@ -1250,9 +1256,9 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
 	/* tell the device to stop sending interrupts */
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 	iwl_disable_interrupts(trans);
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	/* device going down, Stop using ICT table */
 	iwl_disable_ict(trans);
@@ -1285,14 +1291,16 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 	/* Upon stop, the APM issues an interrupt if HW RF kill is set.
 	 * Clean again the interrupt here
 	 */
-	spin_lock_irqsave(&trans->shrd->lock, flags);
+	spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 	iwl_disable_interrupts(trans);
-	spin_unlock_irqrestore(&trans->shrd->lock, flags);
+	spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 
 	/* wait to make sure we flush pending tasklet*/
 	synchronize_irq(trans->irq);
 	tasklet_kill(&trans_pcie->irq_tasklet);
 
+	cancel_work_sync(&trans_pcie->rx_replenish);
+
 	/* stop and reset the on-board processor */
 	iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 }
@@ -2259,6 +2267,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
 	trans->shrd = shrd;
 	trans_pcie->trans = trans;
 	spin_lock_init(&trans->hcmd_lock);
+	spin_lock_init(&trans_pcie->irq_lock);
 
 	/* W/A - seems to solve weird behavior. We need to remove this if we
 	 * don't want to stay in L1 all the time. This wastes a lot of power */

+ 157 - 33
drivers/net/wireless/iwlwifi/iwl-trans.h

@@ -68,18 +68,75 @@
 
 #include "iwl-shared.h"
 #include "iwl-commands.h"
+#include "iwl-ucode.h"
+#include "iwl-debug.h"
 
- /*This file includes the declaration that are exported from the transport
- * layer */
+/**
+ * DOC: Transport layer - what is it ?
+ *
+ * The tranport layer is the layer that deals with the HW directly. It provides
+ * an abstraction of the underlying HW to the upper layer. The transport layer
+ * doesn't provide any policy, algorithm or anything of this kind, but only
+ * mechanisms to make the HW do something.It is not completely stateless but
+ * close to it.
+ * We will have an implementation for each different supported bus.
+ */
+
+/**
+ * DOC: Life cycle of the transport layer
+ *
+ * The transport layer has a very precise life cycle.
+ *
+ *	1) A helper function is called during the module initialization and
+ *	   registers the bus driver's ops with the transport's alloc function.
+ *	2) Bus's probe calls to the transport layer's allocation functions.
+ *	   Of course this function is bus specific.
+ *	3) This allocation functions will spawn the upper layer which will
+ *	   register mac80211.
+ *
+ *	4) At some point (i.e. mac80211's start call), the op_mode will call
+ *	   the following sequence:
+ *	   start_hw
+ *	   start_fw
+ *
+ *	5) Then when finished (or reset):
+ *	   stop_fw (a.k.a. stop device for the moment)
+ *	   stop_hw
+ *
+ *	6) Eventually, the free function will be called.
+ */
+
+/**
+ * DOC: API needed by the transport layer from the op_mode
+ *
+ * TODO
+ */
 
 struct iwl_priv;
 struct iwl_shared;
 
+/**
+ * DOC: Host command section
+ *
+ * A host command is a commaned issued by the upper layer to the fw. There are
+ * several versions of fw that have several APIs. The transport layer is
+ * completely agnostic to these differences.
+ * The transport does provide helper functionnality (i.e. SYNC / ASYNC mode),
+ */
 #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
 #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
 #define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
 
-enum {
+/**
+ * enum CMD_MODE - how to send the host commands ?
+ *
+ * @CMD_SYNC: The caller will be stalled until the fw responds to the command
+ * @CMD_ASYNC: Return right away and don't want for the response
+ * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
+ *	response.
+ * @CMD_ON_DEMAND: This command is sent by the test mode pipe.
+ */
+enum CMD_MODE {
 	CMD_SYNC = 0,
 	CMD_ASYNC = BIT(0),
 	CMD_WANT_SKB = BIT(1),
@@ -104,20 +161,29 @@ struct iwl_device_cmd {
 
 #define IWL_MAX_CMD_TFDS	2
 
+/**
+ * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command
+ *
+ * IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's
+ *	ring. The transport layer doesn't map the command's buffer to DMA, but
+ *	rather copies it to an previously allocated DMA buffer. This flag tells
+ *	the transport layer not to copy the command, but to map the existing
+ *	buffer. This can save memcpy and is worth with very big comamnds.
+ */
 enum iwl_hcmd_dataflag {
 	IWL_HCMD_DFL_NOCOPY	= BIT(0),
 };
 
 /**
  * struct iwl_host_cmd - Host command to the uCode
+ *
  * @data: array of chunks that composes the data of the host command
  * @reply_page: pointer to the page that holds the response to the host command
  * @handler_status: return value of the handler of the command
  *	(put in setup_rx_handlers) - valid for SYNC mode only
- * @callback:
- * @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
+ * @flags: can be CMD_*
  * @len: array of the lenths of the chunks in data
- * @dataflags:
+ * @dataflags: IWL_HCMD_DFL_*
  * @id: id of the host command
  */
 struct iwl_host_cmd {
@@ -131,40 +197,45 @@ struct iwl_host_cmd {
 	u8 id;
 };
 
-/* one for each uCode image (inst/data, boot/init/runtime) */
-struct fw_desc {
-	dma_addr_t p_addr;	/* hardware address */
-	void *v_addr;		/* software address */
-	u32 len;		/* size in bytes */
-};
-
-struct fw_img {
-	struct fw_desc code;	/* firmware code image */
-	struct fw_desc data;	/* firmware data image */
-};
-
 /**
  * struct iwl_trans_ops - transport specific operations
+ *
+ * All the handlers MUST be implemented
+ *
  * @start_hw: starts the HW- from that point on, the HW can send interrupts
+ *	May sleep
  * @stop_hw: stops the HW- from that point on, the HW will be in low power but
  *	will still issue interrupt if the HW RF kill is triggered.
+ *	May sleep
  * @start_fw: allocates and inits all the resources for the transport
- *	layer. Also kick a fw image. This handler may sleep.
+ *	layer. Also kick a fw image.
+ *	May sleep
  * @fw_alive: called when the fw sends alive notification
+ *	May sleep
  * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
  * @stop_device:stops the whole device (embedded CPU put to reset)
+ *	May sleep
  * @send_cmd:send a host command
+ *	May sleep only if CMD_SYNC is set
  * @tx: send an skb
+ *	Must be atomic
  * @reclaim: free packet until ssn. Returns a list of freed packets.
+ *	Must be atomic
  * @tx_agg_alloc: allocate resources for a TX BA session
+ *	May sleep
  * @tx_agg_setup: 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
  * @tx_agg_disable: de-configure a Tx queue to send AMPDUs
+ *	May sleep
  * @free: release all the ressource for the transport layer itself such as
- *        irq, tasklet etc...
+ *	irq, tasklet etc... From this point on, the device may not issue
+ *	any interrupt (incl. RFKILL).
+ *	May sleep
  * @stop_queue: stop a specific queue
  * @check_stuck_queue: check if a specific queue is stuck
  * @wait_tx_queue_empty: wait until all tx queues are empty
+ *	May sleep
  * @dbgfs_register: add the dbgfs files under this directory. Files will be
  *	automatically deleted.
  * @suspend: stop the device unless WoWLAN is configured
@@ -226,8 +297,20 @@ struct iwl_calib_result {
 	/* data follows */
 };
 
+/**
+ * enum iwl_trans_state - state of the transport layer
+ *
+ * @IWL_TRANS_NO_FW: no fw has sent an alive response
+ * @IWL_TRANS_FW_ALIVE: a fw has sent an alive response
+ */
+enum iwl_trans_state {
+	IWL_TRANS_NO_FW = 0,
+	IWL_TRANS_FW_ALIVE	= 1,
+};
+
 /**
  * struct iwl_trans - transport common data
+ *
  * @ops - pointer to iwl_trans_ops
  * @shrd - pointer to iwl_shared which holds shared data from the upper layer
  * @hcmd_lock: protects HCMD
@@ -235,12 +318,9 @@ struct iwl_calib_result {
  * @dev - pointer to struct device * that represents the device
  * @irq - the irq number for the device
  * @hw_id: a u32 with the ID of the device / subdevice.
-  *	Set during transport alloaction.
+ *	Set during transport allocation.
  * @hw_id_str: a string with info about HW ID. Set during transport allocation.
  * @ucode_write_complete: indicates that the ucode has been copied.
- * @ucode_rt: run time ucode image
- * @ucode_init: init ucode image
- * @ucode_wowlan: wake on wireless ucode image (optional)
  * @nvm_device_type: indicates OTP or eeprom
  * @pm_support: set to true in start_hw if link pm is supported
  * @calib_results: list head for init calibration results
@@ -248,6 +328,7 @@ struct iwl_calib_result {
 struct iwl_trans {
 	const struct iwl_trans_ops *ops;
 	struct iwl_shared *shrd;
+	enum iwl_trans_state state;
 	spinlock_t hcmd_lock;
 	spinlock_t reg_lock;
 
@@ -257,16 +338,11 @@ struct iwl_trans {
 	u32 hw_id;
 	char hw_id_str[52];
 
-	u8 ucode_write_complete;	/* the image write is complete */
-	struct fw_img ucode_rt;
-	struct fw_img ucode_init;
-	struct fw_img ucode_wowlan;
+	u8 ucode_write_complete;
 
-	/* eeprom related variables */
 	int    nvm_device_type;
 	bool pm_support;
 
-	/* init calibration results */
 	struct list_head calib_results;
 
 	/* pointer to trans specific struct */
@@ -276,17 +352,27 @@ struct iwl_trans {
 
 static inline int iwl_trans_start_hw(struct iwl_trans *trans)
 {
+	might_sleep();
+
 	return trans->ops->start_hw(trans);
 }
 
 static inline void iwl_trans_stop_hw(struct iwl_trans *trans)
 {
+	might_sleep();
+
 	trans->ops->stop_hw(trans);
+
+	trans->state = IWL_TRANS_NO_FW;
 }
 
 static inline void iwl_trans_fw_alive(struct iwl_trans *trans)
 {
+	might_sleep();
+
 	trans->ops->fw_alive(trans);
+
+	trans->state = IWL_TRANS_FW_ALIVE;
 }
 
 static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw)
@@ -298,13 +384,20 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw)
 
 static inline void iwl_trans_stop_device(struct iwl_trans *trans)
 {
+	might_sleep();
+
 	trans->ops->stop_device(trans);
+
+	trans->state = IWL_TRANS_NO_FW;
 }
 
 static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
 					    enum iwl_rxon_context_id ctx,
 					    const char *msg)
 {
+	if (trans->state != IWL_TRANS_FW_ALIVE)
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+
 	trans->ops->wake_any_queue(trans, ctx, msg);
 }
 
@@ -312,6 +405,9 @@ static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
 static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
 				struct iwl_host_cmd *cmd)
 {
+	if (trans->state != IWL_TRANS_FW_ALIVE)
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+
 	return trans->ops->send_cmd(trans, cmd);
 }
 
@@ -322,6 +418,9 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
 		struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
 		u8 sta_id, u8 tid)
 {
+	if (trans->state != IWL_TRANS_FW_ALIVE)
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+
 	return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id, tid);
 }
 
@@ -329,6 +428,9 @@ static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
 				 int tid, int txq_id, int ssn, u32 status,
 				 struct sk_buff_head *skbs)
 {
+	if (trans->state != IWL_TRANS_FW_ALIVE)
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+
 	return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn,
 				   status, skbs);
 }
@@ -336,12 +438,22 @@ static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
 static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
 					    int sta_id, int tid)
 {
+	might_sleep();
+
+	if (trans->state != IWL_TRANS_FW_ALIVE)
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+
 	return trans->ops->tx_agg_disable(trans, sta_id, tid);
 }
 
 static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans,
 					 int sta_id, int tid)
 {
+	might_sleep();
+
+	if (trans->state != IWL_TRANS_FW_ALIVE)
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+
 	return trans->ops->tx_agg_alloc(trans, sta_id, tid);
 }
 
@@ -351,6 +463,11 @@ static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans,
 					   int sta_id, int tid,
 					   int frame_limit, u16 ssn)
 {
+	might_sleep();
+
+	if (trans->state != IWL_TRANS_FW_ALIVE)
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+
 	trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn);
 }
 
@@ -362,16 +479,25 @@ static inline void iwl_trans_free(struct iwl_trans *trans)
 static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q,
 					const char *msg)
 {
+	if (trans->state != IWL_TRANS_FW_ALIVE)
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+
 	trans->ops->stop_queue(trans, q, msg);
 }
 
 static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
 {
+	if (trans->state != IWL_TRANS_FW_ALIVE)
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+
 	return trans->ops->wait_tx_queue_empty(trans);
 }
 
 static inline int iwl_trans_check_stuck_queue(struct iwl_trans *trans, int q)
 {
+	if (trans->state != IWL_TRANS_FW_ALIVE)
+		IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+
 	return trans->ops->check_stuck_queue(trans, q);
 }
 static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
@@ -410,8 +536,6 @@ static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs)
 /*****************************************************
 * Utils functions
 ******************************************************/
-void iwl_dealloc_ucode(struct iwl_trans *trans);
-
 int iwl_send_calib_results(struct iwl_trans *trans);
 int iwl_calib_set(struct iwl_trans *trans,
 		  const struct iwl_calib_hdr *cmd, int len);

+ 164 - 157
drivers/net/wireless/iwlwifi/iwl-ucode.c

@@ -82,29 +82,29 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
  *
  ******************************************************************************/
 
-static void iwl_free_fw_desc(struct iwl_trans *trans, struct fw_desc *desc)
+static void iwl_free_fw_desc(struct iwl_nic *nic, struct fw_desc *desc)
 {
 	if (desc->v_addr)
-		dma_free_coherent(trans->dev, desc->len,
+		dma_free_coherent(trans(nic)->dev, desc->len,
 				  desc->v_addr, desc->p_addr);
 	desc->v_addr = NULL;
 	desc->len = 0;
 }
 
-static void iwl_free_fw_img(struct iwl_trans *trans, struct fw_img *img)
+static void iwl_free_fw_img(struct iwl_nic *nic, struct fw_img *img)
 {
-	iwl_free_fw_desc(trans, &img->code);
-	iwl_free_fw_desc(trans, &img->data);
+	iwl_free_fw_desc(nic, &img->code);
+	iwl_free_fw_desc(nic, &img->data);
 }
 
-void iwl_dealloc_ucode(struct iwl_trans *trans)
+void iwl_dealloc_ucode(struct iwl_nic *nic)
 {
-	iwl_free_fw_img(trans, &trans->ucode_rt);
-	iwl_free_fw_img(trans, &trans->ucode_init);
-	iwl_free_fw_img(trans, &trans->ucode_wowlan);
+	iwl_free_fw_img(nic, &nic->fw.ucode_rt);
+	iwl_free_fw_img(nic, &nic->fw.ucode_init);
+	iwl_free_fw_img(nic, &nic->fw.ucode_wowlan);
 }
 
-static int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc,
+static int iwl_alloc_fw_desc(struct iwl_nic *nic, struct fw_desc *desc,
 		      const void *data, size_t len)
 {
 	if (!len) {
@@ -112,7 +112,7 @@ static int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc,
 		return -EINVAL;
 	}
 
-	desc->v_addr = dma_alloc_coherent(trans->dev, len,
+	desc->v_addr = dma_alloc_coherent(trans(nic)->dev, len,
 					  &desc->p_addr, GFP_KERNEL);
 	if (!desc->v_addr)
 		return -ENOMEM;
@@ -122,16 +122,16 @@ static int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc,
 	return 0;
 }
 
-static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
+static inline struct fw_img *iwl_get_ucode_image(struct iwl_nic *nic,
 					enum iwl_ucode_type ucode_type)
 {
 	switch (ucode_type) {
 	case IWL_UCODE_INIT:
-		return &trans->ucode_init;
+		return &nic->fw.ucode_init;
 	case IWL_UCODE_WOWLAN:
-		return &trans->ucode_wowlan;
+		return &nic->fw.ucode_wowlan;
 	case IWL_UCODE_REGULAR:
-		return &trans->ucode_rt;
+		return &nic->fw.ucode_rt;
 	case IWL_UCODE_NONE:
 		break;
 	}
@@ -397,15 +397,16 @@ static int iwl_alive_notify(struct iwl_trans *trans)
  *   using sample data 100 bytes apart.  If these sample points are good,
  *   it's a pretty good bet that everything between them is good, too.
  */
-static int iwl_verify_inst_sparse(struct iwl_trans *trans,
+static int iwl_verify_inst_sparse(struct iwl_nic *nic,
 				      struct fw_desc *fw_desc)
 {
+	struct iwl_trans *trans = trans(nic);
 	__le32 *image = (__le32 *)fw_desc->v_addr;
 	u32 len = fw_desc->len;
 	u32 val;
 	u32 i;
 
-	IWL_DEBUG_FW(trans, "ucode inst image size is %u\n", len);
+	IWL_DEBUG_FW(nic, "ucode inst image size is %u\n", len);
 
 	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
 		/* read data comes through single port, auto-incr addr */
@@ -421,16 +422,17 @@ static int iwl_verify_inst_sparse(struct iwl_trans *trans,
 	return 0;
 }
 
-static void iwl_print_mismatch_inst(struct iwl_trans *trans,
+static void iwl_print_mismatch_inst(struct iwl_nic *nic,
 				    struct fw_desc *fw_desc)
 {
+	struct iwl_trans *trans = trans(nic);
 	__le32 *image = (__le32 *)fw_desc->v_addr;
 	u32 len = fw_desc->len;
 	u32 val;
 	u32 offs;
 	int errors = 0;
 
-	IWL_DEBUG_FW(trans, "ucode inst image size is %u\n", len);
+	IWL_DEBUG_FW(nic, "ucode inst image size is %u\n", len);
 
 	iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR,
 			   IWLAGN_RTC_INST_LOWER_BOUND);
@@ -441,7 +443,7 @@ static void iwl_print_mismatch_inst(struct iwl_trans *trans,
 		/* read data comes through single port, auto-incr addr */
 		val = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
 		if (val != le32_to_cpu(*image)) {
-			IWL_ERR(trans, "uCode INST section at "
+			IWL_ERR(nic, "uCode INST section at "
 				"offset 0x%x, is 0x%x, s/b 0x%x\n",
 				offs, val, le32_to_cpu(*image));
 			errors++;
@@ -453,24 +455,24 @@ static void iwl_print_mismatch_inst(struct iwl_trans *trans,
  * iwl_verify_ucode - determine which instruction image is in SRAM,
  *    and verify its contents
  */
-static int iwl_verify_ucode(struct iwl_trans *trans,
+static int iwl_verify_ucode(struct iwl_nic *nic,
 			    enum iwl_ucode_type ucode_type)
 {
-	struct fw_img *img = iwl_get_ucode_image(trans, ucode_type);
+	struct fw_img *img = iwl_get_ucode_image(nic, ucode_type);
 
 	if (!img) {
-		IWL_ERR(trans, "Invalid ucode requested (%d)\n", ucode_type);
+		IWL_ERR(nic, "Invalid ucode requested (%d)\n", ucode_type);
 		return -EINVAL;
 	}
 
-	if (!iwl_verify_inst_sparse(trans, &img->code)) {
-		IWL_DEBUG_FW(trans, "uCode is good in inst SRAM\n");
+	if (!iwl_verify_inst_sparse(nic, &img->code)) {
+		IWL_DEBUG_FW(nic, "uCode is good in inst SRAM\n");
 		return 0;
 	}
 
-	IWL_ERR(trans, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
+	IWL_ERR(nic, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
 
-	iwl_print_mismatch_inst(trans, &img->code);
+	iwl_print_mismatch_inst(nic, &img->code);
 	return -EIO;
 }
 
@@ -583,7 +585,7 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
 
 	old_type = trans->shrd->ucode_type;
 	trans->shrd->ucode_type = ucode_type;
-	fw = iwl_get_ucode_image(trans, ucode_type);
+	fw = iwl_get_ucode_image(nic(trans), ucode_type);
 
 	if (!fw)
 		return -EINVAL;
@@ -618,7 +620,7 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
 	 * skip it for WoWLAN.
 	 */
 	if (ucode_type != IWL_UCODE_WOWLAN) {
-		ret = iwl_verify_ucode(trans, ucode_type);
+		ret = iwl_verify_ucode(nic(trans), ucode_type);
 		if (ret) {
 			trans->shrd->ucode_type = old_type;
 			return ret;
@@ -647,7 +649,7 @@ int iwl_run_init_ucode(struct iwl_trans *trans)
 	lockdep_assert_held(&trans->shrd->mutex);
 
 	/* No init ucode required? Curious, but maybe ok */
-	if (!trans->ucode_init.code.len)
+	if (!nic(trans)->fw.ucode_init.code.len)
 		return 0;
 
 	if (trans->shrd->ucode_type != IWL_UCODE_NONE)
@@ -688,39 +690,40 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
 #define UCODE_EXPERIMENTAL_INDEX	100
 #define UCODE_EXPERIMENTAL_TAG		"exp"
 
-int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
+int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first)
 {
-	const char *name_pre = cfg(priv)->fw_name_pre;
+	struct iwl_cfg *cfg = cfg(nic);
+	const char *name_pre = cfg->fw_name_pre;
 	char tag[8];
 
 	if (first) {
 #ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
-		priv->fw_index = UCODE_EXPERIMENTAL_INDEX;
+		nic->fw_index = UCODE_EXPERIMENTAL_INDEX;
 		strcpy(tag, UCODE_EXPERIMENTAL_TAG);
-	} else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
+	} else if (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) {
 #endif
-		priv->fw_index = cfg(priv)->ucode_api_max;
-		sprintf(tag, "%d", priv->fw_index);
+		nic->fw_index = cfg->ucode_api_max;
+		sprintf(tag, "%d", nic->fw_index);
 	} else {
-		priv->fw_index--;
-		sprintf(tag, "%d", priv->fw_index);
+		nic->fw_index--;
+		sprintf(tag, "%d", nic->fw_index);
 	}
 
-	if (priv->fw_index < cfg(priv)->ucode_api_min) {
-		IWL_ERR(priv, "no suitable firmware found!\n");
+	if (nic->fw_index < cfg->ucode_api_min) {
+		IWL_ERR(nic, "no suitable firmware found!\n");
 		return -ENOENT;
 	}
 
-	sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
+	sprintf(nic->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
 
-	IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n",
-		       (priv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+	IWL_DEBUG_INFO(nic, "attempting to load firmware %s'%s'\n",
+		       (nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
 				? "EXPERIMENTAL " : "",
-		       priv->firmware_name);
+		       nic->firmware_name);
 
-	return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
-				       trans(priv)->dev,
-				       GFP_KERNEL, priv, iwl_ucode_callback);
+	return request_firmware_nowait(THIS_MODULE, 1, nic->firmware_name,
+				       trans(nic)->dev,
+				       GFP_KERNEL, nic, iwl_ucode_callback);
 }
 
 struct iwlagn_firmware_pieces {
@@ -734,7 +737,7 @@ struct iwlagn_firmware_pieces {
 	u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
 };
 
-static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
+static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic,
 				       const struct firmware *ucode_raw,
 				       struct iwlagn_firmware_pieces *pieces)
 {
@@ -742,14 +745,14 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
 	u32 api_ver, hdr_size;
 	const u8 *src;
 
-	priv->ucode_ver = le32_to_cpu(ucode->ver);
-	api_ver = IWL_UCODE_API(priv->ucode_ver);
+	nic->fw.ucode_ver = le32_to_cpu(ucode->ver);
+	api_ver = IWL_UCODE_API(nic->fw.ucode_ver);
 
 	switch (api_ver) {
 	default:
 		hdr_size = 28;
 		if (ucode_raw->size < hdr_size) {
-			IWL_ERR(priv, "File size too small!\n");
+			IWL_ERR(nic, "File size too small!\n");
 			return -EINVAL;
 		}
 		pieces->build = le32_to_cpu(ucode->u.v2.build);
@@ -764,7 +767,7 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
 	case 2:
 		hdr_size = 24;
 		if (ucode_raw->size < hdr_size) {
-			IWL_ERR(priv, "File size too small!\n");
+			IWL_ERR(nic, "File size too small!\n");
 			return -EINVAL;
 		}
 		pieces->build = 0;
@@ -781,7 +784,7 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
 				pieces->data_size + pieces->init_size +
 				pieces->init_data_size) {
 
-		IWL_ERR(priv,
+		IWL_ERR(nic,
 			"uCode file size %d does not match expected size\n",
 			(int)ucode_raw->size);
 		return -EINVAL;
@@ -799,10 +802,10 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
 	return 0;
 }
 
-static int iwlagn_load_firmware(struct iwl_priv *priv,
+static int iwl_parse_tlv_firmware(struct iwl_nic *nic,
 				const struct firmware *ucode_raw,
 				struct iwlagn_firmware_pieces *pieces,
-				struct iwlagn_ucode_capabilities *capa)
+				struct iwl_ucode_capabilities *capa)
 {
 	struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
 	struct iwl_ucode_tlv *tlv;
@@ -816,12 +819,12 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
 	const u8 *tlv_data;
 
 	if (len < sizeof(*ucode)) {
-		IWL_ERR(priv, "uCode has invalid length: %zd\n", len);
+		IWL_ERR(nic, "uCode has invalid length: %zd\n", len);
 		return -EINVAL;
 	}
 
 	if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) {
-		IWL_ERR(priv, "invalid uCode magic: 0X%x\n",
+		IWL_ERR(nic, "invalid uCode magic: 0X%x\n",
 			le32_to_cpu(ucode->magic));
 		return -EINVAL;
 	}
@@ -839,11 +842,11 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
 	while (wanted_alternative && !(alternatives & BIT(wanted_alternative)))
 		wanted_alternative--;
 	if (wanted_alternative && wanted_alternative != tmp)
-		IWL_WARN(priv,
+		IWL_WARN(nic,
 			 "uCode alternative %d not available, choosing %d\n",
 			 tmp, wanted_alternative);
 
-	priv->ucode_ver = le32_to_cpu(ucode->ver);
+	nic->fw.ucode_ver = le32_to_cpu(ucode->ver);
 	pieces->build = le32_to_cpu(ucode->build);
 	data = ucode->data;
 
@@ -861,7 +864,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
 		tlv_data = tlv->data;
 
 		if (len < tlv_len) {
-			IWL_ERR(priv, "invalid TLV len: %zd/%u\n",
+			IWL_ERR(nic, "invalid TLV len: %zd/%u\n",
 				len, tlv_len);
 			return -EINVAL;
 		}
@@ -894,7 +897,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
 			pieces->init_data_size = tlv_len;
 			break;
 		case IWL_UCODE_TLV_BOOT:
-			IWL_ERR(priv, "Found unexpected BOOT ucode\n");
+			IWL_ERR(nic, "Found unexpected BOOT ucode\n");
 			break;
 		case IWL_UCODE_TLV_PROBE_MAX_LEN:
 			if (tlv_len != sizeof(u32))
@@ -962,7 +965,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
 		case IWL_UCODE_TLV_ENHANCE_SENS_TBL:
 			if (tlv_len)
 				goto invalid_tlv_len;
-			priv->enhance_sensitivity_table = true;
+			nic->fw.enhance_sensitivity_table = true;
 			break;
 		case IWL_UCODE_TLV_WOWLAN_INST:
 			pieces->wowlan_inst = tlv_data;
@@ -979,22 +982,22 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
 					le32_to_cpup((__le32 *)tlv_data);
 			break;
 		default:
-			IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type);
+			IWL_DEBUG_INFO(nic, "unknown TLV: %d\n", tlv_type);
 			break;
 		}
 	}
 
 	if (len) {
-		IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len);
-		iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len);
+		IWL_ERR(nic, "invalid TLV after parsing: %zd\n", len);
+		iwl_print_hex_dump(nic, IWL_DL_FW, (u8 *)data, len);
 		return -EINVAL;
 	}
 
 	return 0;
 
  invalid_tlv_len:
-	IWL_ERR(priv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
-	iwl_print_hex_dump(priv, IWL_DL_FW, tlv_data, tlv_len);
+	IWL_ERR(nic, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
+	iwl_print_hex_dump(nic, IWL_DL_FW, tlv_data, tlv_len);
 
 	return -EINVAL;
 }
@@ -1007,21 +1010,23 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
  */
 static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 {
-	struct iwl_priv *priv = context;
+	struct iwl_nic *nic = context;
+	struct iwl_cfg *cfg = cfg(nic);
+	struct iwl_fw *fw = &nic->fw;
+	struct iwl_priv *priv = priv(nic); /* temporary */
 	struct iwl_ucode_header *ucode;
 	int err;
 	struct iwlagn_firmware_pieces pieces;
-	const unsigned int api_max = cfg(priv)->ucode_api_max;
-	unsigned int api_ok = cfg(priv)->ucode_api_ok;
-	const unsigned int api_min = cfg(priv)->ucode_api_min;
+	const unsigned int api_max = cfg->ucode_api_max;
+	unsigned int api_ok = cfg->ucode_api_ok;
+	const unsigned int api_min = cfg->ucode_api_min;
 	u32 api_ver;
 	char buildstr[25];
 	u32 build;
-	struct iwlagn_ucode_capabilities ucode_capa = {
-		.max_probe_length = 200,
-		.standard_phy_calibration_size =
-			IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE,
-	};
+
+	fw->ucode_capa.max_probe_length = 200;
+	fw->ucode_capa.standard_phy_calibration_size =
+			IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
 
 	if (!api_ok)
 		api_ok = api_max;
@@ -1029,19 +1034,19 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 	memset(&pieces, 0, sizeof(pieces));
 
 	if (!ucode_raw) {
-		if (priv->fw_index <= api_ok)
-			IWL_ERR(priv,
+		if (nic->fw_index <= api_ok)
+			IWL_ERR(nic,
 				"request for firmware file '%s' failed.\n",
-				priv->firmware_name);
+				nic->firmware_name);
 		goto try_again;
 	}
 
-	IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n",
-		       priv->firmware_name, ucode_raw->size);
+	IWL_DEBUG_INFO(nic, "Loaded firmware file '%s' (%zd bytes).\n",
+		       nic->firmware_name, ucode_raw->size);
 
 	/* Make sure that we got at least the API version number */
 	if (ucode_raw->size < 4) {
-		IWL_ERR(priv, "File size way too small!\n");
+		IWL_ERR(nic, "File size way too small!\n");
 		goto try_again;
 	}
 
@@ -1049,15 +1054,15 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 	ucode = (struct iwl_ucode_header *)ucode_raw->data;
 
 	if (ucode->ver)
-		err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces);
+		err = iwl_parse_v1_v2_firmware(nic, ucode_raw, &pieces);
 	else
-		err = iwlagn_load_firmware(priv, ucode_raw, &pieces,
-					   &ucode_capa);
+		err = iwl_parse_tlv_firmware(nic, ucode_raw, &pieces,
+					   &fw->ucode_capa);
 
 	if (err)
 		goto try_again;
 
-	api_ver = IWL_UCODE_API(priv->ucode_ver);
+	api_ver = IWL_UCODE_API(nic->fw.ucode_ver);
 	build = pieces.build;
 
 	/*
@@ -1066,9 +1071,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 	 * on the API version read from firmware header from here on forward
 	 */
 	/* no api version check required for experimental uCode */
-	if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) {
+	if (nic->fw_index != UCODE_EXPERIMENTAL_INDEX) {
 		if (api_ver < api_min || api_ver > api_max) {
-			IWL_ERR(priv,
+			IWL_ERR(nic,
 				"Driver unable to support your firmware API. "
 				"Driver supports v%u, firmware is v%u.\n",
 				api_max, api_ver);
@@ -1077,39 +1082,39 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 
 		if (api_ver < api_ok) {
 			if (api_ok != api_max)
-				IWL_ERR(priv, "Firmware has old API version, "
+				IWL_ERR(nic, "Firmware has old API version, "
 					"expected v%u through v%u, got v%u.\n",
 					api_ok, api_max, api_ver);
 			else
-				IWL_ERR(priv, "Firmware has old API version, "
+				IWL_ERR(nic, "Firmware has old API version, "
 					"expected v%u, got v%u.\n",
 					api_max, api_ver);
-			IWL_ERR(priv, "New firmware can be obtained from "
+			IWL_ERR(nic, "New firmware can be obtained from "
 				      "http://www.intellinuxwireless.org/.\n");
 		}
 	}
 
 	if (build)
 		sprintf(buildstr, " build %u%s", build,
-		       (priv->fw_index == UCODE_EXPERIMENTAL_INDEX)
+		       (nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
 				? " (EXP)" : "");
 	else
 		buildstr[0] = '\0';
 
-	IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n",
-		 IWL_UCODE_MAJOR(priv->ucode_ver),
-		 IWL_UCODE_MINOR(priv->ucode_ver),
-		 IWL_UCODE_API(priv->ucode_ver),
-		 IWL_UCODE_SERIAL(priv->ucode_ver),
+	IWL_INFO(nic, "loaded firmware version %u.%u.%u.%u%s\n",
+		 IWL_UCODE_MAJOR(nic->fw.ucode_ver),
+		 IWL_UCODE_MINOR(nic->fw.ucode_ver),
+		 IWL_UCODE_API(nic->fw.ucode_ver),
+		 IWL_UCODE_SERIAL(nic->fw.ucode_ver),
 		 buildstr);
 
 	snprintf(priv->hw->wiphy->fw_version,
 		 sizeof(priv->hw->wiphy->fw_version),
 		 "%u.%u.%u.%u%s",
-		 IWL_UCODE_MAJOR(priv->ucode_ver),
-		 IWL_UCODE_MINOR(priv->ucode_ver),
-		 IWL_UCODE_API(priv->ucode_ver),
-		 IWL_UCODE_SERIAL(priv->ucode_ver),
+		 IWL_UCODE_MAJOR(nic->fw.ucode_ver),
+		 IWL_UCODE_MINOR(nic->fw.ucode_ver),
+		 IWL_UCODE_API(nic->fw.ucode_ver),
+		 IWL_UCODE_SERIAL(nic->fw.ucode_ver),
 		 buildstr);
 
 	/*
@@ -1118,38 +1123,38 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 	 * user just got a corrupted version of the latest API.
 	 */
 
-	IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
-		       priv->ucode_ver);
-	IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n",
+	IWL_DEBUG_INFO(nic, "f/w package hdr ucode version raw = 0x%x\n",
+		       nic->fw.ucode_ver);
+	IWL_DEBUG_INFO(nic, "f/w package hdr runtime inst size = %Zd\n",
 		       pieces.inst_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n",
+	IWL_DEBUG_INFO(nic, "f/w package hdr runtime data size = %Zd\n",
 		       pieces.data_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n",
+	IWL_DEBUG_INFO(nic, "f/w package hdr init inst size = %Zd\n",
 		       pieces.init_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n",
+	IWL_DEBUG_INFO(nic, "f/w package hdr init data size = %Zd\n",
 		       pieces.init_data_size);
 
 	/* Verify that uCode images will fit in card's SRAM */
-	if (pieces.inst_size > hw_params(priv).max_inst_size) {
-		IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n",
+	if (pieces.inst_size > cfg->max_inst_size) {
+		IWL_ERR(nic, "uCode instr len %Zd too large to fit in\n",
 			pieces.inst_size);
 		goto try_again;
 	}
 
-	if (pieces.data_size > hw_params(priv).max_data_size) {
-		IWL_ERR(priv, "uCode data len %Zd too large to fit in\n",
+	if (pieces.data_size > cfg->max_data_size) {
+		IWL_ERR(nic, "uCode data len %Zd too large to fit in\n",
 			pieces.data_size);
 		goto try_again;
 	}
 
-	if (pieces.init_size > hw_params(priv).max_inst_size) {
-		IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n",
+	if (pieces.init_size > cfg->max_inst_size) {
+		IWL_ERR(nic, "uCode init instr len %Zd too large to fit in\n",
 			pieces.init_size);
 		goto try_again;
 	}
 
-	if (pieces.init_data_size > hw_params(priv).max_data_size) {
-		IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n",
+	if (pieces.init_data_size > cfg->max_data_size) {
+		IWL_ERR(nic, "uCode init data len %Zd too large to fit in\n",
 			pieces.init_data_size);
 		goto try_again;
 	}
@@ -1159,34 +1164,34 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 	/* Runtime instructions and 2 copies of data:
 	 * 1) unmodified from disk
 	 * 2) backup cache for save/restore during power-downs */
-	if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.code,
+	if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.code,
 			      pieces.inst, pieces.inst_size))
 		goto err_pci_alloc;
-	if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.data,
+	if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.data,
 			      pieces.data, pieces.data_size))
 		goto err_pci_alloc;
 
 	/* Initialization instructions and data */
 	if (pieces.init_size && pieces.init_data_size) {
-		if (iwl_alloc_fw_desc(trans(priv),
-				      &trans(priv)->ucode_init.code,
+		if (iwl_alloc_fw_desc(nic,
+				      &nic->fw.ucode_init.code,
 				      pieces.init, pieces.init_size))
 			goto err_pci_alloc;
-		if (iwl_alloc_fw_desc(trans(priv),
-				      &trans(priv)->ucode_init.data,
+		if (iwl_alloc_fw_desc(nic,
+				      &nic->fw.ucode_init.data,
 				      pieces.init_data, pieces.init_data_size))
 			goto err_pci_alloc;
 	}
 
 	/* WoWLAN instructions and data */
 	if (pieces.wowlan_inst_size && pieces.wowlan_data_size) {
-		if (iwl_alloc_fw_desc(trans(priv),
-				      &trans(priv)->ucode_wowlan.code,
+		if (iwl_alloc_fw_desc(nic,
+				      &nic->fw.ucode_wowlan.code,
 				      pieces.wowlan_inst,
 				      pieces.wowlan_inst_size))
 			goto err_pci_alloc;
-		if (iwl_alloc_fw_desc(trans(priv),
-				      &trans(priv)->ucode_wowlan.data,
+		if (iwl_alloc_fw_desc(nic,
+				      &nic->fw.ucode_wowlan.data,
 				      pieces.wowlan_data,
 				      pieces.wowlan_data_size))
 			goto err_pci_alloc;
@@ -1199,92 +1204,94 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 	 * for each event, which is of mode 1 (including timestamp) for all
 	 * new microcodes that include this information.
 	 */
-	priv->init_evtlog_ptr = pieces.init_evtlog_ptr;
+	nic->init_evtlog_ptr = pieces.init_evtlog_ptr;
 	if (pieces.init_evtlog_size)
-		priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
+		nic->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
 	else
-		priv->init_evtlog_size =
-			cfg(priv)->base_params->max_event_log_size;
-	priv->init_errlog_ptr = pieces.init_errlog_ptr;
-	priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
+		nic->init_evtlog_size =
+			cfg->base_params->max_event_log_size;
+	nic->init_errlog_ptr = pieces.init_errlog_ptr;
+	nic->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
 	if (pieces.inst_evtlog_size)
-		priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
+		nic->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
 	else
-		priv->inst_evtlog_size =
-			cfg(priv)->base_params->max_event_log_size;
-	priv->inst_errlog_ptr = pieces.inst_errlog_ptr;
+		nic->inst_evtlog_size =
+			cfg->base_params->max_event_log_size;
+	nic->inst_errlog_ptr = pieces.inst_errlog_ptr;
 #ifndef CONFIG_IWLWIFI_P2P
-	ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+	fw->ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
 #endif
 
 	priv->new_scan_threshold_behaviour =
-		!!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
+		!!(fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
 
-	if (!(cfg(priv)->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
-		ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+	if (!(cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
+		fw->ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
 
 	/*
 	 * if not PAN, then don't support P2P -- might be a uCode
 	 * packaging bug or due to the eeprom check above
 	 */
-	if (!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN))
-		ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
+	if (!(fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN))
+		fw->ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
 
-	if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
+	if (fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
 		priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
-		priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
+		nic->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
 	} else {
 		priv->sta_key_max_num = STA_KEY_MAX_NUM;
-		priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+		nic->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
 	}
 	/*
 	 * figure out the offset of chain noise reset and gain commands
 	 * base on the size of standard phy calibration commands table size
 	 */
-	if (ucode_capa.standard_phy_calibration_size >
+	if (fw->ucode_capa.standard_phy_calibration_size >
 	    IWL_MAX_PHY_CALIBRATE_TBL_SIZE)
-		ucode_capa.standard_phy_calibration_size =
+		fw->ucode_capa.standard_phy_calibration_size =
 			IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
 
 	priv->phy_calib_chain_noise_reset_cmd =
-		ucode_capa.standard_phy_calibration_size;
+		fw->ucode_capa.standard_phy_calibration_size;
 	priv->phy_calib_chain_noise_gain_cmd =
-		ucode_capa.standard_phy_calibration_size + 1;
+		fw->ucode_capa.standard_phy_calibration_size + 1;
 
 	/* initialize all valid contexts */
-	iwl_init_context(priv, ucode_capa.flags);
+	iwl_init_context(priv, fw->ucode_capa.flags);
 
 	/**************************************************
 	 * This is still part of probe() in a sense...
 	 *
 	 * 9. Setup and register with mac80211 and debugfs
 	 **************************************************/
-	err = iwlagn_mac_setup_register(priv, &ucode_capa);
+	err = iwlagn_mac_setup_register(priv, &fw->ucode_capa);
 	if (err)
 		goto out_unbind;
 
 	err = iwl_dbgfs_register(priv, DRV_NAME);
 	if (err)
-		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
+		IWL_ERR(nic,
+			"failed to create debugfs files. Ignoring error: %d\n",
+			err);
 
 	/* We have our copies now, allow OS release its copies */
 	release_firmware(ucode_raw);
-	complete(&priv->firmware_loading_complete);
+	complete(&nic->request_firmware_complete);
 	return;
 
  try_again:
 	/* try next, if any */
-	if (iwl_request_firmware(priv, false))
+	if (iwl_request_firmware(nic, false))
 		goto out_unbind;
 	release_firmware(ucode_raw);
 	return;
 
  err_pci_alloc:
-	IWL_ERR(priv, "failed to allocate pci memory\n");
-	iwl_dealloc_ucode(trans(priv));
+	IWL_ERR(nic, "failed to allocate pci memory\n");
+	iwl_dealloc_ucode(nic);
  out_unbind:
-	complete(&priv->firmware_loading_complete);
-	device_release_driver(trans(priv)->dev);
+	complete(&nic->request_firmware_complete);
+	device_release_driver(trans(nic)->dev);
 	release_firmware(ucode_raw);
 }
 

+ 45 - 2
drivers/net/wireless/iwlwifi/iwl-ucode.h

@@ -63,6 +63,8 @@
 #ifndef __iwl_ucode_h__
 #define __iwl_ucode_h__
 
+#include <linux/netdevice.h>
+
 /* v1/v2 uCode file layout */
 struct iwl_ucode_header {
 	__le32 ver;	/* major/minor/API/serial */
@@ -171,8 +173,49 @@ struct iwl_tlv_ucode_header {
 	u8 data[0];
 };
 
-struct iwl_priv;
+struct iwl_ucode_capabilities {
+	u32 max_probe_length;
+	u32 standard_phy_calibration_size;
+	u32 flags;
+};
+
+/* one for each uCode image (inst/data, boot/init/runtime) */
+struct fw_desc {
+	dma_addr_t p_addr;	/* hardware address */
+	void *v_addr;		/* software address */
+	u32 len;		/* size in bytes */
+};
 
-int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first);
+struct fw_img {
+	struct fw_desc code;	/* firmware code image */
+	struct fw_desc data;	/* firmware data image */
+};
+
+/**
+ * struct iwl_fw - variables associated with the firmware
+ *
+ * @ucode_ver: ucode version from the ucode file
+ * @fw_version: firmware version string
+ * @ucode_rt: run time ucode image
+ * @ucode_init: init ucode image
+ * @ucode_wowlan: wake on wireless ucode image (optional)
+ * @ucode_capa: capabilities parsed from the ucode file.
+ * @enhance_sensitivity_table: device can do enhanced sensitivity.
+ */
+struct iwl_fw {
+
+	/* ucode image and variables */
+	u32 ucode_ver;                  /* version of ucode, copy of
+					   iwl_ucode.ver */
+	char fw_version[ETHTOOL_BUSINFO_LEN];
+
+	/* ucode images */
+	struct fw_img ucode_rt;
+	struct fw_img ucode_init;
+	struct fw_img ucode_wowlan;
+
+	struct iwl_ucode_capabilities ucode_capa;
+	bool enhance_sensitivity_table;
+};
 
 #endif  /* __iwl_ucode_h__ */

+ 33 - 0
drivers/net/wireless/iwlwifi/iwl-wifi.h

@@ -64,6 +64,39 @@
 #define __iwl_wifi_h__
 
 #include "iwl-shared.h"
+#include "iwl-ucode.h"
+
+/**
+ * struct iwl_nic - nic common data
+ * @fw: the iwl_fw structure
+ * @shrd: pointer to common shared structure
+ * @fw_index: firmware revision to try loading
+ * @firmware_name: composite filename of ucode file to load
+ * @init_evtlog_ptr: event log offset for init ucode.
+ * @init_evtlog_size: event log size for init ucode.
+ * @init_errlog_ptr: error log offfset for init ucode.
+ * @inst_evtlog_ptr: event log offset for runtime ucode.
+ * @inst_evtlog_size: event log size for runtime ucode.
+ * @inst_errlog_ptr: error log offfset for runtime ucode.
+ * @request_firmware_complete: the firmware has been obtained from user space
+ */
+struct iwl_nic {
+	struct iwl_fw fw;
+
+	struct iwl_shared *shrd;
+
+	int fw_index;                   /* firmware we're trying to load */
+	char firmware_name[25];         /* name of firmware file to load */
+
+	u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
+	u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
+
+	struct completion request_firmware_complete;
+};
+
+
+int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first);
+void iwl_dealloc_ucode(struct iwl_nic *nic);
 
 int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type);
 void iwl_send_prio_tbl(struct iwl_trans *trans);