summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-2000.c14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c28
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c20
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tt.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c144
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-bus.h145
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-cfg.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c38
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.c127
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h84
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h33
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-devtrace.h65
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c103
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.h123
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c156
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-mac80211.c83
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-op-mode.h198
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-pci.c70
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-shared.h45
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.c432
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-testmode.h64
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c88
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c46
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h207
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-ucode.c394
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-ucode.h46
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-wifi.h37
42 files changed, 1902 insertions, 1048 deletions
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 9dc84a7354db..afa0bb8f3245 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/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
@@ -13,6 +13,7 @@ iwlwifi-objs += iwl-6000.o
iwlwifi-objs += iwl-1000.o
iwlwifi-objs += iwl-2000.o
iwlwifi-objs += iwl-pci.o
+iwlwifi-objs += iwl-drv.o
iwlwifi-objs += iwl-trans.o
iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 8c1466c907ff..605ee3df1d82 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/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, \
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index d4f5f3b87578..e6e8c79a80d8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/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, \
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index dc9317d0343e..1527dec7a267 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/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, \
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index c36fb858a45b..223e60a1b79d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/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, \
@@ -384,11 +383,24 @@ struct iwl_cfg iwl6005_2agn_d_cfg = {
.ht_params = &iwl6000_ht_params,
};
+struct iwl_cfg iwl6005_2agn_mow1_cfg = {
+ .name = "Intel(R) Centrino(R) Advanced-N 6206 AGN",
+ IWL_DEVICE_6005,
+ .ht_params = &iwl6000_ht_params,
+};
+struct iwl_cfg iwl6005_2agn_mow2_cfg = {
+ .name = "Intel(R) Centrino(R) Advanced-N 6207 AGN",
+ IWL_DEVICE_6005,
+ .ht_params = &iwl6000_ht_params,
+};
+
#define IWL_DEVICE_6030 \
.fw_name_pre = IWL6030_FW_PRE, \
.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 +470,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 +501,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 +528,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 +555,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,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index 6aa009827865..988ee454a944 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/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);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index a8f7689aaacf..5be0d3695d03 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/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);
}
}
@@ -959,7 +959,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
struct ieee80211_key_conf *key,
void *_data)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct wowlan_key_data *data = _data;
struct iwl_rxon_context *ctx = data->ctx;
struct aes_sc *aes_sc, *aes_tx_sc = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index b9ba404d15c1..a7d67135e3dc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -38,6 +38,7 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-agn.h"
+#include "iwl-op-mode.h"
#define RS_NAME "iwl-agn-rs"
@@ -892,7 +893,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);
}
}
@@ -909,7 +910,8 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
struct iwl_lq_sta *lq_sta = priv_sta;
struct iwl_link_quality_cmd *table;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct iwl_priv *priv = (struct iwl_priv *)priv_r;
+ struct iwl_op_mode *op_mode = (struct iwl_op_mode *)priv_r;
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
enum mac80211_rate_control_flags mac_flags;
u32 tx_rate;
@@ -2737,7 +2739,9 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb = txrc->skb;
struct ieee80211_supported_band *sband = txrc->sband;
- struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
+ struct iwl_op_mode *op_mode __maybe_unused =
+ (struct iwl_op_mode *)priv_r;
+ struct iwl_priv *priv __maybe_unused = IWL_OP_MODE_GET_DVM(op_mode);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_lq_sta *lq_sta = priv_sta;
int rate_idx;
@@ -2805,9 +2809,10 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
gfp_t gfp)
{
struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv;
- struct iwl_priv *priv;
+ struct iwl_op_mode *op_mode __maybe_unused =
+ (struct iwl_op_mode *)priv_rate;
+ struct iwl_priv *priv __maybe_unused = IWL_OP_MODE_GET_DVM(op_mode);
- priv = (struct iwl_priv *)priv_rate;
IWL_DEBUG_RATE(priv, "create station rate scale window\n");
return &sta_priv->lq_sta;
@@ -3074,7 +3079,8 @@ static void rs_free(void *priv_rate)
static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
void *priv_sta)
{
- struct iwl_priv *priv __maybe_unused = priv_r;
+ struct iwl_op_mode *op_mode __maybe_unused = priv_r;
+ struct iwl_priv *priv __maybe_unused = IWL_OP_MODE_GET_DVM(op_mode);
IWL_DEBUG_RATE(priv, "enter\n");
IWL_DEBUG_RATE(priv, "leave\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index a14ddab783ea..30bb5bbb0cd7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/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);
@@ -1141,10 +1141,11 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
}
-int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
+int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
int err = 0;
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 8ca9570ec365..73653a6cf32d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -549,7 +549,7 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx;
struct ieee80211_conf *conf = &hw->conf;
struct ieee80211_channel *channel = conf->channel;
@@ -805,7 +805,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *bss_conf,
u32 changes)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
int ret;
bool force = false;
@@ -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);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
index c728ed75584e..56d7c0e38163 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c
+++ b/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
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 64f8db685dc5..5f78567f4180 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -322,7 +322,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
sta_priv = (void *)info->control.sta->drv_priv;
if (sta_priv && sta_priv->asleep &&
- (info->flags & IEEE80211_TX_CTL_POLL_RESPONSE)) {
+ (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER)) {
/*
* This sends an asynchronous command to the device,
* but we can rely on it being processed before the
@@ -331,6 +331,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
* counter.
* For now set the counter to just 1 since we do not
* support uAPSD yet.
+ *
+ * FIXME: If we get two non-bufferable frames one
+ * after the other, we might only send out one of
+ * them because this is racy.
*/
iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
}
@@ -983,7 +987,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);
}
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 8837171ad553..e0fef9f257c2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -50,8 +50,8 @@
#include "iwl-agn-calib.h"
#include "iwl-agn.h"
#include "iwl-shared.h"
-#include "iwl-bus.h"
#include "iwl-trans.h"
+#include "iwl-op-mode.h"
/******************************************************************************
*
@@ -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);
}
@@ -1151,37 +1142,43 @@ static void iwl_debug_config(struct iwl_priv *priv)
#endif
}
-int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
- struct iwl_cfg *cfg)
+static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
{
+ struct iwl_fw *fw = &nic(trans)->fw;
int err = 0;
struct iwl_priv *priv;
struct ieee80211_hw *hw;
+ struct iwl_op_mode *op_mode;
u16 num_mac;
+ u32 ucode_flags;
/************************
* 1. Allocating HW data
************************/
hw = iwl_alloc_all();
if (!hw) {
- pr_err("%s: Cannot allocate network device\n", cfg->name);
+ pr_err("%s: Cannot allocate network device\n",
+ cfg(trans)->name);
err = -ENOMEM;
goto out;
}
- priv = hw->priv;
- priv->shrd = bus->shrd;
+ op_mode = hw->priv;
+ op_mode->ops = &iwl_dvm_ops;
+ priv = IWL_OP_MODE_GET_DVM(op_mode);
+ priv->shrd = trans->shrd;
priv->shrd->priv = priv;
+ iwl_trans_configure(trans(priv), op_mode);
+
/* At this point both hw and priv are allocated. */
- SET_IEEE80211_DEV(hw, trans(priv)->dev);
+ SET_IEEE80211_DEV(priv->hw, trans(priv)->dev);
/* show what debugging capabilities we have */
iwl_debug_config(priv);
IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
- cfg(priv) = cfg;
/* is antenna coupling more than 35dB ? */
priv->bt_ant_couple_ok =
@@ -1217,7 +1214,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
* 4. Read EEPROM
*****************/
/* Read the EEPROM */
- err = iwl_eeprom_init(priv, trans(priv)->hw_rev);
+ err = iwl_eeprom_init(trans(priv), trans(priv)->hw_rev);
/* Reset chip to save power until we load uCode during "up". */
iwl_trans_stop_hw(trans(priv));
if (err) {
@@ -1248,11 +1245,23 @@ 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);
+
+ ucode_flags = fw->ucode_capa.flags;
+
+#ifndef CONFIG_IWLWIFI_P2P
+ ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+#endif
+ if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE))
+ ucode_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_flags & IWL_UCODE_TLV_FLAGS_PAN))
+ ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
+
/*******************
* 6. Setup priv
@@ -1273,17 +1282,49 @@ 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);
+ snprintf(priv->hw->wiphy->fw_version,
+ sizeof(priv->hw->wiphy->fw_version),
+ "%s", fw->fw_version);
+
+ priv->new_scan_threshold_behaviour =
+ !!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
+
+ if (ucode_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;
+ } else {
+ priv->sta_key_max_num = STA_KEY_MAX_NUM;
+ priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+ }
+
+ priv->phy_calib_chain_noise_reset_cmd =
+ fw->ucode_capa.standard_phy_calibration_size;
+ priv->phy_calib_chain_noise_gain_cmd =
+ fw->ucode_capa.standard_phy_calibration_size + 1;
- err = iwl_request_firmware(priv, true);
+ /* initialize all valid contexts */
+ iwl_init_context(priv, ucode_flags);
+
+ /**************************************************
+ * This is still part of probe() in a sense...
+ *
+ * 9. Setup and register with mac80211 and debugfs
+ **************************************************/
+ err = iwlagn_mac_setup_register(priv, &fw->ucode_capa);
if (err)
goto out_destroy_workqueue;
- return 0;
+ err = iwl_dbgfs_register(priv, DRV_NAME);
+ if (err)
+ IWL_ERR(priv,
+ "failed to create debugfs files. Ignoring error: %d\n",
+ err);
+
+ return op_mode;
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);
@@ -1291,12 +1332,15 @@ out_free_traffic_mem:
iwl_free_traffic_mem(priv);
ieee80211_free_hw(priv->hw);
out:
- return err;
+ op_mode = NULL;
+ return op_mode;
}
-void __devexit iwl_remove(struct iwl_priv * priv)
+static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
{
- wait_for_completion(&priv->firmware_loading_complete);
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+ wait_for_completion(&nic(priv)->request_firmware_complete);
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
@@ -1316,18 +1360,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);
@@ -1337,6 +1381,16 @@ void __devexit iwl_remove(struct iwl_priv * priv)
ieee80211_free_hw(priv->hw);
}
+const struct iwl_op_mode_ops iwl_dvm_ops = {
+ .start = iwl_op_mode_dvm_start,
+ .stop = iwl_op_mode_dvm_stop,
+ .rx = iwl_rx_dispatch,
+ .queue_full = iwl_stop_sw_queue,
+ .queue_not_full = iwl_wake_sw_queue,
+ .hw_rf_kill = iwl_set_hw_rfkill_state,
+ .free_skb = iwl_free_skb,
+ .nic_error = iwl_nic_error,
+};
/*****************************************************************************
*
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 37c325ff6e8c..cb484e273b93 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/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,23 @@ 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);
+void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb);
+int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd);
+void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
+void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
+void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state);
+void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
+void iwl_nic_error(struct iwl_op_mode *op_mode);
/* 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 */
@@ -387,4 +392,14 @@ void iwl_testmode_cleanup(struct iwl_priv *priv)
}
#endif
+#ifdef CONFIG_IWLWIFI_DEBUG
+void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+ enum iwl_rxon_context_id ctxid);
+#else
+static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+ enum iwl_rxon_context_id ctxid)
+{
+}
+#endif
+
#endif /* __iwl_agn_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h
deleted file mode 100644
index 30965e0e8ab4..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-bus.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- * Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *****************************************************************************/
-#ifndef __iwl_bus_h__
-#define __iwl_bus_h__
-
-#include <linux/types.h>
-#include <linux/spinlock.h>
-
-/**
- * DOC: Bus layer - role and goal
- *
- * iwl-bus.h defines the API to the bus layer of the iwlwifi driver.
- * The bus layer is responsible for doing very basic bus operations that are
- * listed in the iwl_bus_ops structure.
- * The bus layer registers to the bus driver, advertises the supported HW and
- * gets notifications about enumeration, suspend, resume.
- * For the moment, the bus layer is not a linux kernel module as itself, and
- * the module_init function of the driver must call the bus specific
- * registration functions. These functions are listed at the end of this file.
- * For the moment, there is only one implementation of this interface: PCI-e.
- * This implementation is iwl-pci.c
- */
-
-/**
- * DOC: encapsulation and type safety
- *
- * The iwl_bus describes the data that is shared amongst all the bus layer
- * implementations. This data is visible to other layers. Data in the bus
- * specific area is not visible outside the bus specific implementation.
- * iwl_bus holds a pointer to iwl_shared which holds pointer to all the other
- * layers of the driver (iwl_priv, iwl_trans). In fact, this is the way to go
- * when the transport layer needs to call a function of another layer.
- *
- * In order to achieve encapsulation, iwl_priv cannot be dereferenced from the
- * bus layer. Type safety is still kept since functions that gets iwl_priv gets
- * a typed pointer (as opposed to void *).
- */
-
-/**
- * DOC: probe flow
- *
- * The module_init calls the bus specific registration function. The
- * registration to the bus layer will trigger an enumeration of the bus which
- * will call the bus specific probe function.
- * The first thing this function must do is to allocate the memory needed by
- * iwl_bus + the bus_specific data.
- * Once the bus specific probe function has configured the hardware, it
- * chooses the appropriate transport layer and calls iwl_probe that will run
- * the bus independent probe flow.
- *
- * Note: The bus specific code must set the following data in iwl_bus before it
- * calls iwl_probe:
- * * bus->dev
- * * bus->irq
- * * bus->ops
- */
-
-struct iwl_shared;
-struct iwl_bus;
-
-/**
- * struct iwl_bus - bus common data
- *
- * This data is common to all bus layer implementations.
- *
- * @ops - pointer to iwl_bus_ops
- * @shrd - pointer to iwl_shared which holds shared data from the upper layer
- * NB: for the time being this needs to be set by the upper layer since
- * it allocates the shared data
- */
-struct iwl_bus {
- struct iwl_shared *shrd;
-
- /* pointer to bus specific struct */
- /*Ensure that this pointer will always be aligned to sizeof pointer */
- char bus_specific[0] __attribute__((__aligned__(sizeof(void *))));
-};
-
-/*****************************************************
-* Bus layer registration functions
-******************************************************/
-int __must_check iwl_pci_register_driver(void);
-void iwl_pci_unregister_driver(void);
-
-#endif /* __iwl_bus_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-cfg.h b/drivers/net/wireless/iwlwifi/iwl-cfg.h
index 957bc00cdaf0..1ad14bbccc99 100644
--- a/drivers/net/wireless/iwlwifi/iwl-cfg.h
+++ b/drivers/net/wireless/iwlwifi/iwl-cfg.h
@@ -80,6 +80,8 @@ extern struct iwl_cfg iwl6005_2abg_cfg;
extern struct iwl_cfg iwl6005_2bg_cfg;
extern struct iwl_cfg iwl6005_2agn_sff_cfg;
extern struct iwl_cfg iwl6005_2agn_d_cfg;
+extern struct iwl_cfg iwl6005_2agn_mow1_cfg;
+extern struct iwl_cfg iwl6005_2agn_mow2_cfg;
extern struct iwl_cfg iwl1030_bgn_cfg;
extern struct iwl_cfg iwl1030_bg_cfg;
extern struct iwl_cfg iwl6030_2agn_cfg;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 0677b3dfbfb2..275e08966059 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -38,10 +38,10 @@
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-power.h"
-#include "iwl-agn.h"
#include "iwl-shared.h"
#include "iwl-agn.h"
#include "iwl-trans.h"
+#include "iwl-wifi.h"
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -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,
@@ -831,11 +830,16 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv,
}
#endif
-void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
+static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
{
unsigned int reload_msec;
unsigned long reload_jiffies;
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS)
+ iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
+#endif
+
/* Set the FW error flag -- cleared on iwl_down */
set_bit(STATUS_FW_ERROR, &priv->shrd->status);
@@ -875,7 +879,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");
@@ -1456,8 +1460,17 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
return cpu_to_le32(res);
}
-void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state)
+void iwl_nic_error(struct iwl_op_mode *op_mode)
{
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+ iwlagn_fw_error(priv, false);
+}
+
+void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
+{
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
}
@@ -1466,8 +1479,9 @@ void iwl_nic_config(struct iwl_priv *priv)
cfg(priv)->lib->nic_config(priv);
}
-void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb)
+void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
{
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
struct ieee80211_tx_info *info;
info = IEEE80211_SKB_CB(skb);
@@ -1475,12 +1489,16 @@ void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb)
dev_kfree_skb_any(skb);
}
-void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac)
+void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
{
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
ieee80211_stop_queue(priv->hw, ac);
}
-void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac)
+void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
{
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
ieee80211_wake_queue(priv->hw, ac);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 8d60dcf6f2eb..42630f5e8de7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/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,
@@ -197,6 +197,8 @@ const char *get_ctrl_string(int cmd);
void iwl_clear_traffic_stats(struct iwl_priv *priv);
void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc,
u16 len);
+void iwl_reset_traffic_log(struct iwl_priv *priv);
+
#else
static inline int iwl_alloc_traffic_mem(struct iwl_priv *priv)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c
new file mode 100644
index 000000000000..4bc2e70051d6
--- /dev/null
+++ b/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
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 351b41d7f4fd..01b23303d736 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -29,16 +29,34 @@
#ifndef __iwl_debug_h__
#define __iwl_debug_h__
-#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 +64,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 */
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 136de6fb3fa4..ad74138e1c70 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/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)
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index aa99457c3a52..6e5bf0a14609 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -47,9 +47,9 @@
#include "iwl-power.h"
#include "iwl-agn-rs.h"
#include "iwl-agn-tt.h"
-#include "iwl-bus.h"
#include "iwl-trans.h"
#include "iwl-shared.h"
+#include "iwl-op-mode.h"
struct iwl_tx_queue;
@@ -442,9 +442,6 @@ struct iwl_chain_noise_data {
u8 state;
};
-#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */
-#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
-
enum {
MEASUREMENT_READY = (1 << 0),
MEASUREMENT_ACTIVE = (1 << 1),
@@ -696,11 +693,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
@@ -710,6 +707,13 @@ struct iwl_wipan_noa_data {
u8 data[];
};
+#define IWL_OP_MODE_GET_DVM(_iwl_op_mode) \
+ ((struct iwl_priv *) ((_iwl_op_mode)->op_mode_specific))
+
+#define IWL_MAC80211_GET_DVM(_hw) \
+ ((struct iwl_priv *) ((struct iwl_op_mode *) \
+ (_hw)->priv)->op_mode_specific)
+
struct iwl_priv {
/*data shared among all the driver's layers */
@@ -721,6 +725,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 +791,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 +800,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 +867,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 +957,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
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h
index 4d892211ce4c..96e62338cec0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h
+++ b/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)
@@ -164,6 +169,66 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
);
#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
TRACE_EVENT(iwlwifi_dev_hcmd,
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
new file mode 100644
index 000000000000..8ff52568cf6e
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -0,0 +1,103 @@
+/******************************************************************************
+ *
+ * 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 - 2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#include <linux/completion.h>
+
+#include "iwl-drv.h"
+#include "iwl-trans.h"
+#include "iwl-wifi.h"
+#include "iwl-op-mode.h"
+
+int iwl_drv_start(struct iwl_shared *shrd,
+ struct iwl_trans *trans, struct iwl_cfg *cfg)
+{
+ int ret;
+
+ shrd->cfg = cfg;
+
+ shrd->nic = kzalloc(sizeof(*shrd->nic), GFP_KERNEL);
+ if (!shrd->nic) {
+ dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_nic");
+ return -ENOMEM;
+ }
+ shrd->nic->shrd = shrd;
+
+ init_completion(&shrd->nic->request_firmware_complete);
+
+ ret = iwl_request_firmware(shrd->nic, true);
+
+ if (ret) {
+ dev_printk(KERN_ERR, trans->dev, "Couldn't request the fw");
+ kfree(shrd->nic);
+ }
+
+ return ret;
+}
+
+void iwl_drv_stop(struct iwl_shared *shrd)
+{
+ /* op_mode can be NULL if its start failed */
+ if (shrd->nic->op_mode)
+ iwl_op_mode_stop(shrd->nic->op_mode);
+
+ kfree(shrd->nic);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.h b/drivers/net/wireless/iwlwifi/iwl-drv.h
new file mode 100644
index 000000000000..90534a23ddc8
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.h
@@ -0,0 +1,123 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef __iwl_drv_h__
+#define __iwl_drv_h__
+
+#include "iwl-shared.h"
+
+/**
+ * DOC: Driver system flows - drv component
+ *
+ * This component implements the system flows such as bus enumeration, bus
+ * removal. Bus dependent parts of system flows (such as iwl_pci_probe) are in
+ * bus specific files (transport files). This is the code that is common among
+ * different buses.
+ *
+ * This component is also in charge of managing the several implementations of
+ * the wifi flows: it will allow to have several fw API implementation. These
+ * different implementations will differ in the way they implement mac80211's
+ * handlers too.
+
+ * The init flow wrt to the drv component looks like this:
+ * 1) The bus specific component is called from module_init
+ * 2) The bus specific component registers the bus driver
+ * 3) The bus driver calls the probe function
+ * 4) The bus specific component configures the bus
+ * 5) The bus specific component calls to the drv bus agnostic part
+ * (iwl_drv_start)
+ * 6) iwl_drv_start fetches the fw ASYNC, iwl_ucode_callback
+ * 7) iwl_ucode_callback parses the fw file
+ * 8) iwl_ucode_callback starts the wifi implementation to matches the fw
+ */
+
+/**
+ * iwl_drv_start - start the drv
+ *
+ * @shrd: the shrd area
+ * @trans_ops: the ops of the transport
+ * @cfg: device specific constants / virtual functions
+ *
+ * TODO: review the parameters given to this function
+ *
+ * starts the driver: fetches the firmware. This should be called by bus
+ * specific system flows implementations. For example, the bus specific probe
+ * function should do bus related operations only, and then call to this
+ * function.
+ */
+int iwl_drv_start(struct iwl_shared *shrd,
+ struct iwl_trans *trans, struct iwl_cfg *cfg);
+
+/**
+ * iwl_drv_stop - stop the drv
+ *
+ * @shrd: the shrd area
+ *
+ * TODO: review the parameters given to this function
+ *
+ * Stop the driver. This should be called by bus specific system flows
+ * implementations. For example, the bus specific remove function should first
+ * call this function and then do the bus related operations only.
+ */
+void iwl_drv_stop(struct iwl_shared *shrd);
+
+#endif /* __iwl_drv_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index d1fd1cdb29c2..07e93787bce8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -149,23 +149,27 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
* EEPROM chip, not a single event, so even reads could conflict if they
* weren't arbitrated by the semaphore.
*/
-static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus)
+
+#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */
+#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
+
+static int iwl_eeprom_acquire_semaphore(struct iwl_trans *trans)
{
u16 count;
int ret;
for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
/* Request semaphore */
- iwl_set_bit(trans(bus), CSR_HW_IF_CONFIG_REG,
+ iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
/* See if we got it */
- ret = iwl_poll_bit(trans(bus), CSR_HW_IF_CONFIG_REG,
+ ret = iwl_poll_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
EEPROM_SEM_TIMEOUT);
if (ret >= 0) {
- IWL_DEBUG_EEPROM(trans(bus),
+ IWL_DEBUG_EEPROM(trans,
"Acquired semaphore after %d tries.\n",
count+1);
return ret;
@@ -175,9 +179,9 @@ static int iwl_eeprom_acquire_semaphore(struct iwl_bus *bus)
return ret;
}
-static void iwl_eeprom_release_semaphore(struct iwl_bus *bus)
+static void iwl_eeprom_release_semaphore(struct iwl_trans *trans)
{
- iwl_clear_bit(trans(bus), CSR_HW_IF_CONFIG_REG,
+ iwl_clear_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
}
@@ -304,19 +308,20 @@ void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac)
*
******************************************************************************/
-static void iwl_set_otp_access(struct iwl_bus *bus, enum iwl_access_mode mode)
+static void iwl_set_otp_access(struct iwl_trans *trans,
+ enum iwl_access_mode mode)
{
- iwl_read32(trans(bus), CSR_OTP_GP_REG);
+ iwl_read32(trans, CSR_OTP_GP_REG);
if (mode == IWL_OTP_ACCESS_ABSOLUTE)
- iwl_clear_bit(trans(bus), CSR_OTP_GP_REG,
+ iwl_clear_bit(trans, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_OTP_ACCESS_MODE);
else
- iwl_set_bit(trans(bus), CSR_OTP_GP_REG,
+ iwl_set_bit(trans, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_OTP_ACCESS_MODE);
}
-static int iwl_get_nvm_type(struct iwl_bus *bus, u32 hw_rev)
+static int iwl_get_nvm_type(struct iwl_trans *trans, u32 hw_rev)
{
u32 otpgp;
int nvm_type;
@@ -324,7 +329,7 @@ static int iwl_get_nvm_type(struct iwl_bus *bus, u32 hw_rev)
/* OTP only valid for CP/PP and after */
switch (hw_rev & CSR_HW_REV_TYPE_MSK) {
case CSR_HW_REV_TYPE_NONE:
- IWL_ERR(bus, "Unknown hardware type\n");
+ IWL_ERR(trans, "Unknown hardware type\n");
return -ENOENT;
case CSR_HW_REV_TYPE_5300:
case CSR_HW_REV_TYPE_5350:
@@ -333,7 +338,7 @@ static int iwl_get_nvm_type(struct iwl_bus *bus, u32 hw_rev)
nvm_type = NVM_DEVICE_TYPE_EEPROM;
break;
default:
- otpgp = iwl_read32(trans(bus), CSR_OTP_GP_REG);
+ otpgp = iwl_read32(trans, CSR_OTP_GP_REG);
if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT)
nvm_type = NVM_DEVICE_TYPE_OTP;
else
@@ -343,73 +348,74 @@ static int iwl_get_nvm_type(struct iwl_bus *bus, u32 hw_rev)
return nvm_type;
}
-static int iwl_init_otp_access(struct iwl_bus *bus)
+static int iwl_init_otp_access(struct iwl_trans *trans)
{
int ret;
/* Enable 40MHz radio clock */
- iwl_write32(trans(bus), CSR_GP_CNTRL,
- iwl_read32(trans(bus), CSR_GP_CNTRL) |
+ iwl_write32(trans, CSR_GP_CNTRL,
+ iwl_read32(trans, CSR_GP_CNTRL) |
CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* wait for clock to be ready */
- ret = iwl_poll_bit(trans(bus), CSR_GP_CNTRL,
+ ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
25000);
if (ret < 0)
- IWL_ERR(bus, "Time out access OTP\n");
+ IWL_ERR(trans, "Time out access OTP\n");
else {
- iwl_set_bits_prph(trans(bus), APMG_PS_CTRL_REG,
+ iwl_set_bits_prph(trans, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
udelay(5);
- iwl_clear_bits_prph(trans(bus), APMG_PS_CTRL_REG,
+ iwl_clear_bits_prph(trans, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
/*
* CSR auto clock gate disable bit -
* this is only applicable for HW with OTP shadow RAM
*/
- if (cfg(bus)->base_params->shadow_ram_support)
- iwl_set_bit(trans(bus), CSR_DBG_LINK_PWR_MGMT_REG,
+ if (cfg(trans)->base_params->shadow_ram_support)
+ iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
CSR_RESET_LINK_PWR_MGMT_DISABLED);
}
return ret;
}
-static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data)
+static int iwl_read_otp_word(struct iwl_trans *trans, u16 addr,
+ __le16 *eeprom_data)
{
int ret = 0;
u32 r;
u32 otpgp;
- iwl_write32(trans(bus), CSR_EEPROM_REG,
+ iwl_write32(trans, CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
- ret = iwl_poll_bit(trans(bus), CSR_EEPROM_REG,
+ ret = iwl_poll_bit(trans, CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK,
CSR_EEPROM_REG_READ_VALID_MSK,
IWL_EEPROM_ACCESS_TIMEOUT);
if (ret < 0) {
- IWL_ERR(bus, "Time out reading OTP[%d]\n", addr);
+ IWL_ERR(trans, "Time out reading OTP[%d]\n", addr);
return ret;
}
- r = iwl_read32(trans(bus), CSR_EEPROM_REG);
+ r = iwl_read32(trans, CSR_EEPROM_REG);
/* check for ECC errors: */
- otpgp = iwl_read32(trans(bus), CSR_OTP_GP_REG);
+ otpgp = iwl_read32(trans, CSR_OTP_GP_REG);
if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
/* stop in this case */
/* set the uncorrectable OTP ECC bit for acknowledgement */
- iwl_set_bit(trans(bus), CSR_OTP_GP_REG,
+ iwl_set_bit(trans, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
- IWL_ERR(bus, "Uncorrectable OTP ECC error, abort OTP read\n");
+ IWL_ERR(trans, "Uncorrectable OTP ECC error, abort OTP read\n");
return -EINVAL;
}
if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
/* continue in this case */
/* set the correctable OTP ECC bit for acknowledgement */
- iwl_set_bit(trans(bus), CSR_OTP_GP_REG,
+ iwl_set_bit(trans, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
- IWL_ERR(bus, "Correctable OTP ECC error, continue read\n");
+ IWL_ERR(trans, "Correctable OTP ECC error, continue read\n");
}
*eeprom_data = cpu_to_le16(r >> 16);
return 0;
@@ -418,20 +424,20 @@ static int iwl_read_otp_word(struct iwl_bus *bus, u16 addr, __le16 *eeprom_data)
/*
* iwl_is_otp_empty: check for empty OTP
*/
-static bool iwl_is_otp_empty(struct iwl_bus *bus)
+static bool iwl_is_otp_empty(struct iwl_trans *trans)
{
u16 next_link_addr = 0;
__le16 link_value;
bool is_empty = false;
/* locate the beginning of OTP link list */
- if (!iwl_read_otp_word(bus, next_link_addr, &link_value)) {
+ if (!iwl_read_otp_word(trans, next_link_addr, &link_value)) {
if (!link_value) {
- IWL_ERR(bus, "OTP is empty\n");
+ IWL_ERR(trans, "OTP is empty\n");
is_empty = true;
}
} else {
- IWL_ERR(bus, "Unable to read first block of OTP list.\n");
+ IWL_ERR(trans, "Unable to read first block of OTP list.\n");
is_empty = true;
}
@@ -448,7 +454,7 @@ static bool iwl_is_otp_empty(struct iwl_bus *bus)
* we should read and used to configure the device.
* only perform this operation if shadow RAM is disabled
*/
-static int iwl_find_otp_image(struct iwl_bus *bus,
+static int iwl_find_otp_image(struct iwl_trans *trans,
u16 *validblockaddr)
{
u16 next_link_addr = 0, valid_addr;
@@ -456,10 +462,10 @@ static int iwl_find_otp_image(struct iwl_bus *bus,
int usedblocks = 0;
/* set addressing mode to absolute to traverse the link list */
- iwl_set_otp_access(bus, IWL_OTP_ACCESS_ABSOLUTE);
+ iwl_set_otp_access(trans, IWL_OTP_ACCESS_ABSOLUTE);
/* checking for empty OTP or error */
- if (iwl_is_otp_empty(bus))
+ if (iwl_is_otp_empty(trans))
return -EINVAL;
/*
@@ -473,9 +479,9 @@ static int iwl_find_otp_image(struct iwl_bus *bus,
*/
valid_addr = next_link_addr;
next_link_addr = le16_to_cpu(link_value) * sizeof(u16);
- IWL_DEBUG_EEPROM(bus, "OTP blocks %d addr 0x%x\n",
+ IWL_DEBUG_EEPROM(trans, "OTP blocks %d addr 0x%x\n",
usedblocks, next_link_addr);
- if (iwl_read_otp_word(bus, next_link_addr, &link_value))
+ if (iwl_read_otp_word(trans, next_link_addr, &link_value))
return -EINVAL;
if (!link_value) {
/*
@@ -490,10 +496,10 @@ static int iwl_find_otp_image(struct iwl_bus *bus,
}
/* more in the link list, continue */
usedblocks++;
- } while (usedblocks <= cfg(bus)->base_params->max_ll_items);
+ } while (usedblocks <= cfg(trans)->base_params->max_ll_items);
/* OTP has no valid blocks */
- IWL_DEBUG_EEPROM(bus, "OTP has no valid blocks\n");
+ IWL_DEBUG_EEPROM(trans, "OTP has no valid blocks\n");
return -EINVAL;
}
@@ -653,63 +659,62 @@ void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
*
* NOTE: This routine uses the non-debug IO access functions.
*/
-int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
+int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev)
{
- struct iwl_shared *shrd = priv->shrd;
__le16 *e;
- u32 gp = iwl_read32(trans(priv), CSR_EEPROM_GP);
+ u32 gp = iwl_read32(trans, CSR_EEPROM_GP);
int sz;
int ret;
u16 addr;
u16 validblockaddr = 0;
u16 cache_addr = 0;
- trans(priv)->nvm_device_type = iwl_get_nvm_type(bus(priv), hw_rev);
- if (trans(priv)->nvm_device_type == -ENOENT)
+ trans->nvm_device_type = iwl_get_nvm_type(trans, hw_rev);
+ if (trans->nvm_device_type == -ENOENT)
return -ENOENT;
/* allocate eeprom */
- sz = cfg(priv)->base_params->eeprom_size;
- IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
- shrd->eeprom = kzalloc(sz, GFP_KERNEL);
- if (!shrd->eeprom) {
+ sz = cfg(trans)->base_params->eeprom_size;
+ IWL_DEBUG_EEPROM(trans, "NVM size = %d\n", sz);
+ trans->shrd->eeprom = kzalloc(sz, GFP_KERNEL);
+ if (!trans->shrd->eeprom) {
ret = -ENOMEM;
goto alloc_err;
}
- e = (__le16 *)shrd->eeprom;
+ e = (__le16 *)trans->shrd->eeprom;
- ret = iwl_eeprom_verify_signature(trans(priv));
+ ret = iwl_eeprom_verify_signature(trans);
if (ret < 0) {
- IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
+ IWL_ERR(trans, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
ret = -ENOENT;
goto err;
}
/* Make sure driver (instead of uCode) is allowed to read EEPROM */
- ret = iwl_eeprom_acquire_semaphore(bus(priv));
+ ret = iwl_eeprom_acquire_semaphore(trans);
if (ret < 0) {
- IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n");
+ IWL_ERR(trans, "Failed to acquire EEPROM semaphore.\n");
ret = -ENOENT;
goto err;
}
- if (trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
+ if (trans->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
- ret = iwl_init_otp_access(bus(priv));
+ ret = iwl_init_otp_access(trans);
if (ret) {
- IWL_ERR(priv, "Failed to initialize OTP access.\n");
+ IWL_ERR(trans, "Failed to initialize OTP access.\n");
ret = -ENOENT;
goto done;
}
- iwl_write32(trans(priv), CSR_EEPROM_GP,
- iwl_read32(trans(priv), CSR_EEPROM_GP) &
+ iwl_write32(trans, CSR_EEPROM_GP,
+ iwl_read32(trans, CSR_EEPROM_GP) &
~CSR_EEPROM_GP_IF_OWNER_MSK);
- iwl_set_bit(trans(priv), CSR_OTP_GP_REG,
+ iwl_set_bit(trans, CSR_OTP_GP_REG,
CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
/* traversing the linked list if no shadow ram supported */
- if (!cfg(priv)->base_params->shadow_ram_support) {
- if (iwl_find_otp_image(bus(priv), &validblockaddr)) {
+ if (!cfg(trans)->base_params->shadow_ram_support) {
+ if (iwl_find_otp_image(trans, &validblockaddr)) {
ret = -ENOENT;
goto done;
}
@@ -718,7 +723,7 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
addr += sizeof(u16)) {
__le16 eeprom_data;
- ret = iwl_read_otp_word(bus(priv), addr, &eeprom_data);
+ ret = iwl_read_otp_word(trans, addr, &eeprom_data);
if (ret)
goto done;
e[cache_addr / 2] = eeprom_data;
@@ -729,34 +734,35 @@ int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev)
for (addr = 0; addr < sz; addr += sizeof(u16)) {
u32 r;
- iwl_write32(trans(priv), CSR_EEPROM_REG,
+ iwl_write32(trans, CSR_EEPROM_REG,
CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
- ret = iwl_poll_bit(trans(priv), CSR_EEPROM_REG,
+ ret = iwl_poll_bit(trans, CSR_EEPROM_REG,
CSR_EEPROM_REG_READ_VALID_MSK,
CSR_EEPROM_REG_READ_VALID_MSK,
IWL_EEPROM_ACCESS_TIMEOUT);
if (ret < 0) {
- IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr);
+ IWL_ERR(trans,
+ "Time out reading EEPROM[%d]\n", addr);
goto done;
}
- r = iwl_read32(trans(priv), CSR_EEPROM_REG);
+ r = iwl_read32(trans, CSR_EEPROM_REG);
e[addr / 2] = cpu_to_le16(r >> 16);
}
}
- IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n",
- (trans(priv)->nvm_device_type == NVM_DEVICE_TYPE_OTP)
+ IWL_DEBUG_EEPROM(trans, "NVM Type: %s, version: 0x%x\n",
+ (trans->nvm_device_type == NVM_DEVICE_TYPE_OTP)
? "OTP" : "EEPROM",
- iwl_eeprom_query16(shrd, EEPROM_VERSION));
+ iwl_eeprom_query16(trans->shrd, EEPROM_VERSION));
ret = 0;
done:
- iwl_eeprom_release_semaphore(bus(priv));
+ iwl_eeprom_release_semaphore(trans);
err:
if (ret)
- iwl_eeprom_free(priv->shrd);
+ iwl_eeprom_free(trans->shrd);
alloc_err:
return ret;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 13f2d3928ef8..cbb86116917b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -67,6 +67,7 @@
struct iwl_priv;
struct iwl_shared;
+struct iwl_trans;
/*
* EEPROM access time values:
@@ -305,7 +306,7 @@ struct iwl_eeprom_ops {
};
-int iwl_eeprom_init(struct iwl_priv *priv, u32 hw_rev);
+int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev);
void iwl_eeprom_free(struct iwl_shared *shrd);
int iwl_eeprom_check_version(struct iwl_priv *priv);
int iwl_eeprom_check_sku(struct iwl_priv *priv);
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
index d8025fee7e0d..03f770543d8e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c
+++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
@@ -51,8 +51,8 @@
#include "iwl-agn-calib.h"
#include "iwl-agn.h"
#include "iwl-shared.h"
-#include "iwl-bus.h"
#include "iwl-trans.h"
+#include "iwl-op-mode.h"
/*****************************************************************************
*
@@ -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");
@@ -305,7 +305,7 @@ static int __iwl_up(struct iwl_priv *priv)
static int iwlagn_mac_start(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int ret;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -332,7 +332,7 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw)
static void iwlagn_mac_stop(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
IWL_DEBUG_MAC80211(priv, "enter\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
@@ -358,7 +362,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_gtk_rekey_data *data)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
if (iwlagn_mod_params.sw_crypto)
return;
@@ -385,7 +389,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
int ret;
@@ -427,7 +431,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
static int iwlagn_mac_resume(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct ieee80211_vif *vif;
unsigned long flags;
@@ -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
}
@@ -493,7 +497,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
@@ -508,7 +512,7 @@ static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
u32 iv32, u16 *phase1key)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
iwl_update_tkip_key(priv, vif, keyconf, sta, iv32, phase1key);
}
@@ -518,7 +522,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *ctx = vif_priv->ctx;
int ret;
@@ -622,7 +626,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
u8 buf_size)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int ret = -EINVAL;
struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
@@ -688,7 +692,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
@@ -731,7 +735,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_channel_switch *ch_switch)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
const struct iwl_channel_info *ch_info;
struct ieee80211_conf *conf = &hw->conf;
struct ieee80211_channel *channel = ch_switch->channel;
@@ -818,7 +822,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
unsigned int *total_flags,
u64 multicast)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
__le32 filter_or = 0, filter_nand = 0;
struct iwl_rxon_context *ctx;
@@ -865,7 +869,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
mutex_lock(&priv->shrd->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -902,7 +906,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
enum nl80211_channel_type channel_type,
int duration)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
int err = 0;
@@ -992,7 +996,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
return -EOPNOTSUPP;
@@ -1012,7 +1016,7 @@ static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw,
const u8 *bssid,
enum ieee80211_tx_sync_type type)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *ctx = vif_priv->ctx;
int ret;
@@ -1066,7 +1070,7 @@ static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw,
const u8 *bssid,
enum ieee80211_tx_sync_type type)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *ctx = vif_priv->ctx;
@@ -1090,7 +1094,7 @@ static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw,
static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
enum ieee80211_rssi_event rssi_event)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->shrd->mutex);
@@ -1115,9 +1119,9 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
static int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, bool set)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
- queue_work(priv->shrd->workqueue, &priv->beacon_update);
+ queue_work(priv->workqueue, &priv->beacon_update);
return 0;
}
@@ -1126,7 +1130,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *ctx = vif_priv->ctx;
unsigned long flags;
@@ -1169,7 +1173,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
static int iwlagn_mac_tx_last_beacon(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
return priv->ibss_manager == IWL_IBSS_MANAGER;
}
@@ -1223,7 +1227,7 @@ static int iwl_setup_interface(struct iwl_priv *priv,
static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *tmp, *ctx = NULL;
int err;
@@ -1320,7 +1324,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv,
static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -1348,7 +1352,7 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype newtype, bool newp2p)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl_rxon_context *tmp;
@@ -1434,7 +1438,7 @@ static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int ret;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -1480,7 +1484,7 @@ static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
int ret;
@@ -1519,7 +1523,7 @@ static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
enum sta_notify_cmd cmd,
struct ieee80211_sta *sta)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
int sta_id;
@@ -1587,15 +1591,18 @@ struct ieee80211_ops iwlagn_hw_ops = {
struct ieee80211_hw *iwl_alloc_all(void)
{
struct iwl_priv *priv;
+ struct iwl_op_mode *op_mode;
/* mac80211 allocates memory for this device instance, including
* space for this driver's private structure */
struct ieee80211_hw *hw;
- hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwlagn_hw_ops);
+ hw = ieee80211_alloc_hw(sizeof(struct iwl_priv) +
+ sizeof(struct iwl_op_mode), &iwlagn_hw_ops);
if (!hw)
goto out;
- priv = hw->priv;
+ op_mode = hw->priv;
+ priv = IWL_OP_MODE_GET_DVM(op_mode);
priv->hw = hw;
out:
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
new file mode 100644
index 000000000000..d4fc9be2d2f3
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -0,0 +1,198 @@
+/******************************************************************************
+ *
+ * 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 - 2012 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_op_mode_h__
+#define __iwl_op_mode_h__
+
+struct iwl_op_mode;
+struct iwl_trans;
+struct sk_buff;
+struct iwl_device_cmd;
+struct iwl_rx_mem_buffer;
+
+/**
+ * DOC: Operational mode - what is it ?
+ *
+ * The operational mode (a.k.a. op_mode) is the layer that implements
+ * mac80211's handlers. It knows two APIs: mac80211's and the fw's. It uses
+ * the transport API to access the HW. The op_mode doesn't need to know how the
+ * underlying HW works, since the transport layer takes care of that.
+ *
+ * There can be several op_mode: i.e. different fw APIs will require two
+ * different op_modes. This is why the op_mode is virtualized.
+ */
+
+/**
+ * DOC: Life cycle of the Operational mode
+ *
+ * The operational mode has a very simple life cycle.
+ *
+ * 1) The driver layer (iwl-drv.c) chooses the op_mode based on the
+ * capabilities advertized by the fw file (in TLV format).
+ * 2) The driver layer starts the op_mode (ops->start)
+ * 3) The op_mode registers registers mac80211
+ * 4) The op_mode is governed by mac80211
+ * 5) The driver layer stops the op_mode
+ */
+
+/**
+ * struct iwl_op_mode_ops - op_mode specific operations
+ *
+ * The op_mode exports its ops so that external components can start it and
+ * interact with it. The driver layer typically calls the start and stop
+ * handlers, the transport layer calls the others.
+ *
+ * All the handlers MUST be implemented
+ *
+ * @start: start the op_mode. The transport layer is already allocated.
+ * May sleep
+ * @stop: stop the op_mode. Must free all the memory allocated.
+ * May sleep
+ * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the
+ * HCMD the this Rx responds to.
+ * Must be atomic.
+ * @queue_full: notifies that a HW queue is full. Ac is the ac of the queue
+ * Must be atomic
+ * @queue_not_full: notifies that a HW queue is not full any more.
+ * Ac is the ac of the queue. Must be atomic
+ * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that
+ * the radio is killed. Must be atomic.
+ * @free_skb: allows the transport layer to free skbs that haven't been
+ * reclaimed by the op_mode. This can happen when the driver is freed and
+ * there are Tx packets pending in the transport layer.
+ * Must be atomic
+ * @nic_error: error notification. Must be atomic
+ */
+struct iwl_op_mode_ops {
+ struct iwl_op_mode *(*start)(struct iwl_trans *trans);
+ void (*stop)(struct iwl_op_mode *op_mode);
+ int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd);
+ void (*queue_full)(struct iwl_op_mode *op_mode, u8 ac);
+ void (*queue_not_full)(struct iwl_op_mode *op_mode, u8 ac);
+ void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
+ void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
+ void (*nic_error)(struct iwl_op_mode *op_mode);
+};
+
+/**
+ * struct iwl_op_mode - operational mode
+ *
+ * This holds an implementation of the mac80211 / fw API.
+ *
+ * @ops - pointer to its own ops
+ */
+struct iwl_op_mode {
+ const struct iwl_op_mode_ops *ops;
+ const struct iwl_trans *trans;
+
+ char op_mode_specific[0] __aligned(sizeof(void *));
+};
+
+static inline void iwl_op_mode_stop(struct iwl_op_mode *op_mode)
+{
+ might_sleep();
+
+ op_mode->ops->stop(op_mode);
+}
+
+static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode,
+ struct iwl_rx_mem_buffer *rxb,
+ struct iwl_device_cmd *cmd)
+{
+ return op_mode->ops->rx(op_mode, rxb, cmd);
+}
+
+static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode, u8 ac)
+{
+ op_mode->ops->queue_full(op_mode, ac);
+}
+
+static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode,
+ u8 ac)
+{
+ op_mode->ops->queue_not_full(op_mode, ac);
+}
+
+static inline void iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode,
+ bool state)
+{
+ op_mode->ops->hw_rf_kill(op_mode, state);
+}
+
+static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode,
+ struct sk_buff *skb)
+{
+ op_mode->ops->free_skb(op_mode, skb);
+}
+
+static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode)
+{
+ op_mode->ops->nic_error(op_mode);
+}
+
+/*****************************************************
+* Op mode layers implementations
+******************************************************/
+extern const struct iwl_op_mode_ops iwl_dvm_ops;
+
+#endif /* __iwl_op_mode_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c
index 3e2fce4ce00c..06e004157dcc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-pci.c
+++ b/drivers/net/wireless/iwlwifi/iwl-pci.c
@@ -64,12 +64,13 @@
#include <linux/pci.h>
#include <linux/pci-aspm.h>
-#include "iwl-bus.h"
#include "iwl-io.h"
#include "iwl-shared.h"
#include "iwl-trans.h"
#include "iwl-csr.h"
#include "iwl-cfg.h"
+#include "iwl-drv.h"
+#include "iwl-trans.h"
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
@@ -157,9 +158,9 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
{IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)},
{IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1341, iwl6005_2agn_d_cfg)},
- {IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_2agn_cfg)},/* low 5GHz active */
- {IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_2agn_cfg)},/* high 5GHz active */
+ {IWL_PCI_DEVICE(0x0082, 0x4820, iwl6005_2agn_d_cfg)},
+ {IWL_PCI_DEVICE(0x0082, 0x1304, iwl6005_2agn_mow1_cfg)},/* low 5GHz active */
+ {IWL_PCI_DEVICE(0x0082, 0x1305, iwl6005_2agn_mow2_cfg)},/* high 5GHz active */
/* 6x30 Series */
{IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
@@ -240,6 +241,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
+ {IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)},
/* 105 Series */
{IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
@@ -262,44 +264,40 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
- struct iwl_bus *bus;
+ struct iwl_shared *shrd;
+ struct iwl_trans *iwl_trans;
int err;
- bus = kzalloc(sizeof(*bus), GFP_KERNEL);
- if (!bus) {
- dev_printk(KERN_ERR, &pdev->dev,
- "Couldn't allocate iwl_pci_bus");
- return -ENOMEM;
- }
-
- bus->shrd = kzalloc(sizeof(*bus->shrd), GFP_KERNEL);
- if (!bus->shrd) {
+ shrd = kzalloc(sizeof(*iwl_trans->shrd), GFP_KERNEL);
+ if (!shrd) {
dev_printk(KERN_ERR, &pdev->dev,
"Couldn't allocate iwl_shared");
err = -ENOMEM;
goto out_free_bus;
}
- bus->shrd->bus = bus;
-
- pci_set_drvdata(pdev, bus);
-
#ifdef CONFIG_IWLWIFI_IDI
- trans(bus) = iwl_trans_idi_alloc(bus->shrd, pdev, ent);
- if (trans(bus) == NULL) {
+ iwl_trans = iwl_trans_idi_alloc(shrd, pdev, ent);
+ if (iwl_trans == NULL) {
err = -ENOMEM;
goto out_free_bus;
}
- err = iwl_probe(bus, &trans_ops_idi, cfg);
+ shrd->trans = iwl_trans;
+ pci_set_drvdata(pdev, iwl_trans);
+
+ err = iwl_drv_start(shrd, iwl_trans, cfg);
#else
- trans(bus) = iwl_trans_pcie_alloc(bus->shrd, pdev, ent);
- if (trans(bus) == NULL) {
+ iwl_trans = iwl_trans_pcie_alloc(shrd, pdev, ent);
+ if (iwl_trans == NULL) {
err = -ENOMEM;
goto out_free_bus;
}
- err = iwl_probe(bus, &trans_ops_pcie, cfg);
+ shrd->trans = iwl_trans;
+ pci_set_drvdata(pdev, iwl_trans);
+
+ err = iwl_drv_start(shrd, iwl_trans, cfg);
#endif
if (err)
goto out_free_trans;
@@ -307,26 +305,24 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return 0;
out_free_trans:
- iwl_trans_free(trans(bus));
+ iwl_trans_free(iwl_trans);
pci_set_drvdata(pdev, NULL);
out_free_bus:
- kfree(bus->shrd);
- kfree(bus);
+ kfree(shrd);
return err;
}
static void __devexit iwl_pci_remove(struct pci_dev *pdev)
{
- struct iwl_bus *bus = pci_get_drvdata(pdev);
- struct iwl_shared *shrd = bus->shrd;
+ struct iwl_trans *iwl_trans = pci_get_drvdata(pdev);
+ struct iwl_shared *shrd = iwl_trans->shrd;
- iwl_remove(shrd->priv);
+ iwl_drv_stop(shrd);
iwl_trans_free(shrd->trans);
pci_set_drvdata(pdev, NULL);
- kfree(bus->shrd);
- kfree(bus);
+ kfree(shrd);
}
#ifdef CONFIG_PM_SLEEP
@@ -334,22 +330,20 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
static int iwl_pci_suspend(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
- struct iwl_bus *bus = pci_get_drvdata(pdev);
- struct iwl_shared *shrd = bus->shrd;
+ struct iwl_trans *iwl_trans = pci_get_drvdata(pdev);
/* Before you put code here, think about WoWLAN. You cannot check here
* whether WoWLAN is enabled or not, and your code will run even if
* WoWLAN is enabled - don't kill the NIC, someone may need it in Sx.
*/
- return iwl_trans_suspend(shrd->trans);
+ return iwl_trans_suspend(iwl_trans);
}
static int iwl_pci_resume(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
- struct iwl_bus *bus = pci_get_drvdata(pdev);
- struct iwl_shared *shrd = bus->shrd;
+ struct iwl_trans *iwl_trans = pci_get_drvdata(pdev);
/* Before you put code here, think about WoWLAN. You cannot check here
* whether WoWLAN is enabled or not, and your code will run even if
@@ -362,7 +356,7 @@ static int iwl_pci_resume(struct device *device)
*/
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
- return iwl_trans_resume(shrd->trans);
+ return iwl_trans_resume(iwl_trans);
}
static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume);
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 7f2e3a1c80ef..42ee1c410efd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/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)
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h
index 63d4a4fc5b9e..a6441623e6b1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-shared.h
+++ b/drivers/net/wireless/iwlwifi/iwl-shared.h
@@ -94,7 +94,6 @@
* This implementation is iwl-pci.c
*/
-struct iwl_bus;
struct iwl_priv;
struct iwl_trans;
struct iwl_sensitivity_ranges;
@@ -173,8 +172,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 +189,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 +278,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 +317,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 +357,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.
@@ -385,13 +384,12 @@ struct iwl_shared {
bool wowlan;
u8 valid_contexts;
- struct iwl_bus *bus;
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;
@@ -416,10 +414,10 @@ struct iwl_shared {
};
-/*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */
+/*Whatever _m is (iwl_trans, iwl_priv, these macros will work */
#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)
@@ -531,24 +529,11 @@ enum iwl_rxon_context_id {
NUM_IWL_RXON_CTX
};
-int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
- struct iwl_cfg *cfg);
-void __devexit iwl_remove(struct iwl_priv * priv);
-struct iwl_device_cmd;
-int __must_check iwl_rx_dispatch(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
- struct iwl_device_cmd *cmd);
-
int iwlagn_hw_valid_rtc_data_addr(u32 addr);
-void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state);
void iwl_nic_config(struct iwl_priv *priv);
-void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb);
-void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand);
const char *get_cmd_string(u8 cmd);
bool iwl_check_for_ct_kill(struct iwl_priv *priv);
-void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac);
-void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac);
/* notification wait support */
void iwl_abort_notification_waits(struct iwl_shared *shrd);
@@ -568,20 +553,6 @@ void __releases(wait_entry)
iwl_remove_notification(struct iwl_shared *shrd,
struct iwl_notification_wait *wait_entry);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-void iwl_reset_traffic_log(struct iwl_priv *priv);
-#endif /* CONFIG_IWLWIFI_DEBUGFS */
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-void iwl_print_rx_config_cmd(struct iwl_priv *priv,
- enum iwl_rxon_context_id ctxid);
-#else
-static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
- enum iwl_rxon_context_id ctxid)
-{
-}
-#endif
-
#define IWL_CMD(x) case x: return #x
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c
index df7ab332c833..23eea06a74ad 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c
@@ -78,9 +78,15 @@
#include "iwl-agn.h"
#include "iwl-testmode.h"
#include "iwl-trans.h"
-#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 +116,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 +178,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 +189,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 +232,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,35 +244,80 @@ 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
*/
static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
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;
}
@@ -288,14 +340,14 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
*/
static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
u32 ofs, val32, cmd;
u8 val8;
struct sk_buff *skb;
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 +361,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 +373,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 +393,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 +401,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 +424,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;
@@ -434,7 +457,7 @@ cfg_init_calib_error:
*/
static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_trans *trans = trans(priv);
struct sk_buff *skb;
unsigned char *rsp_data_ptr = NULL;
@@ -448,8 +471,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 +480,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 +497,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 +512,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 +527,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 +537,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 +573,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 +613,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;
@@ -626,7 +642,7 @@ nla_put_failure:
*/
static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct sk_buff *skb;
int status = 0;
struct device *dev = trans(priv)->dev;
@@ -664,8 +680,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 +689,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 +700,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;
@@ -704,7 +717,7 @@ static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
struct sk_buff *skb,
struct netlink_callback *cb)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int idx, length;
if (priv->testmode_trace.trace_enabled &&
@@ -748,11 +761,11 @@ static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
*/
static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
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 +773,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 +872,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;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
+ 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;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
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;
@@ -892,20 +960,19 @@ static int iwl_testmode_sram_dump(struct ieee80211_hw *hw, struct nlattr **tb,
int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
{
struct nlattr *tb[IWL_TM_ATTR_MAX];
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int result;
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 +986,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 +1015,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;
}
@@ -970,7 +1037,7 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
void *data, int len)
{
struct nlattr *tb[IWL_TM_ATTR_MAX];
- struct iwl_priv *priv = hw->priv;
+ struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
int result;
u32 cmd;
@@ -981,15 +1048,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 +1069,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;
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h
index f97d06169b45..69b2e80f4071 100644
--- a/drivers/net/wireless/iwlwifi/iwl-testmode.h
+++ b/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 */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
index 561865f29d56..5b26b71ae3d5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h
@@ -40,6 +40,7 @@
#include "iwl-trans.h"
#include "iwl-debug.h"
#include "iwl-io.h"
+#include "iwl-op-mode.h"
struct iwl_tx_queue;
struct iwl_queue;
@@ -230,6 +231,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;
@@ -373,7 +375,7 @@ static inline void iwl_wake_queue(struct iwl_trans *trans,
if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) {
if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) {
- iwl_wake_sw_queue(priv(trans), ac);
+ iwl_op_mode_queue_not_full(trans->op_mode, ac);
IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d. %s",
hwq, ac, msg);
} else {
@@ -396,7 +398,7 @@ static inline void iwl_stop_queue(struct iwl_trans *trans,
if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) {
if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) {
- iwl_stop_sw_queue(priv(trans), ac);
+ iwl_op_mode_queue_full(trans->op_mode, ac);
IWL_DEBUG_TX_QUEUES(trans, "Stop hwq %d ac %d"
" stop count %d. %s",
hwq, ac, atomic_read(&trans_pcie->
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
index 3826852ec5f0..2c910fddaaf6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
@@ -34,6 +34,8 @@
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-trans-pcie-int.h"
+#include "iwl-wifi.h"
+#include "iwl-op-mode.h"
#ifdef CONFIG_IWLWIFI_IDI
#include "iwl-amfh.h"
@@ -227,7 +229,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 +333,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 +354,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);
}
/**
@@ -464,7 +461,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
"reclaim is false, SEQ_RX_FRAME unset: %s\n",
get_cmd_string(pkt->hdr.cmd));
- err = iwl_rx_dispatch(priv(trans), rxb, cmd);
+ err = iwl_op_mode_rx(trans->op_mode, rxb, cmd);
/*
* XXX: After here, we should always check rxb->page
@@ -594,17 +591,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 +613,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 +623,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,
@@ -674,9 +671,8 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
*/
static void iwl_irq_handle_error(struct iwl_trans *trans)
{
- struct iwl_priv *priv = priv(trans);
/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
- if (cfg(priv)->internal_wimax_coex &&
+ if (cfg(trans)->internal_wimax_coex &&
(!(iwl_read_prph(trans, APMG_CLK_CTRL_REG) &
APMS_CLK_VAL_MRB_FUNC_MODE) ||
(iwl_read_prph(trans, APMG_PS_CTRL_REG) &
@@ -687,24 +683,20 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
*/
clear_bit(STATUS_READY, &trans->shrd->status);
clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
- wake_up(&priv->shrd->wait_command_queue);
+ wake_up(&trans->shrd->wait_command_queue);
IWL_ERR(trans, "RF is used by WiMAX\n");
return;
}
IWL_ERR(trans, "Loaded firmware version: %s\n",
- priv->hw->wiphy->fw_version);
+ nic(trans)->fw.fw_version);
iwl_dump_nic_error_log(trans);
iwl_dump_csr(trans);
iwl_dump_fh(trans, NULL, false);
iwl_dump_nic_event_log(trans, false, NULL, false);
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS)
- iwl_print_rx_config_cmd(priv(trans), IWL_RXON_CTX_BSS);
-#endif
- iwlagn_fw_error(priv, false);
+ iwl_op_mode_nic_error(trans->op_mode);
}
#define EVENT_START_OFFSET (4 * sizeof(u32))
@@ -723,7 +715,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 +723,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 +756,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 +770,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 +832,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 +941,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 +971,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) {
@@ -1039,7 +1031,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
else
clear_bit(STATUS_RF_KILL_HW,
&trans->shrd->status);
- iwl_set_hw_rfkill_state(priv(trans), hw_rf_kill);
+ iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rf_kill);
}
handled |= CSR_INT_BIT_RF_KILL;
@@ -1232,7 +1224,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 +1241,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 +1252,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 +1273,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 +1317,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 +1327,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 +1361,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 +1432,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 +1443,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;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
index a8dfecadea11..4e1e74e1b794 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
@@ -35,6 +35,7 @@
#include "iwl-prph.h"
#include "iwl-io.h"
#include "iwl-agn-hw.h"
+#include "iwl-op-mode.h"
#include "iwl-trans-pcie-int.h"
#define IWL_TX_CRC_SIZE 4
@@ -229,7 +230,7 @@ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
* freed and that the queue is not empty - free the skb
*/
if (skb) {
- iwl_free_skb(priv(trans), skb);
+ iwl_op_mode_free_skb(trans->op_mode, skb);
txq->skbs[index] = NULL;
}
}
@@ -492,7 +493,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 +533,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);
}
/*
@@ -688,7 +689,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
is_ct_kill = iwl_check_for_ct_kill(priv(trans));
if (!is_ct_kill) {
IWL_ERR(trans, "Restarting adapter queue is full\n");
- iwlagn_fw_error(priv(trans), false);
+ iwl_op_mode_nic_error(trans->op_mode);
}
return -ENOSPC;
}
@@ -821,7 +822,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
if (nfreed++ > 0) {
IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n", idx,
q->write_ptr, q->read_ptr);
- iwlagn_fw_error(priv(trans), false);
+ iwl_op_mode_nic_error(trans->op_mode);
}
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index f5cb5d3cd926..9f8b23909404 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -76,6 +76,7 @@
#include "iwl-eeprom.h"
#include "iwl-agn-hw.h"
#include "iwl-core.h"
+#include "iwl-ucode.h"
static int iwl_trans_rx_alloc(struct iwl_trans *trans)
{
@@ -219,10 +220,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 +586,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 +595,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 +804,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);
@@ -1044,7 +1046,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
if (iwl_is_rfkill(trans->shrd)) {
- iwl_set_hw_rfkill_state(priv(trans), true);
+ iwl_op_mode_hw_rf_kill(trans->op_mode, true);
iwl_enable_interrupts(trans);
return -ERFKILL;
}
@@ -1078,10 +1080,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 +1102,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 +1198,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 +1221,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 +1237,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 +1257,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 +1292,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);
}
@@ -1516,7 +1525,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
else
set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
- iwl_set_hw_rfkill_state(priv(trans),
+ iwl_op_mode_hw_rf_kill(trans->op_mode,
test_bit(STATUS_RF_KILL_HW,
&trans->shrd->status));
@@ -1661,7 +1670,7 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans)
else
clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
- iwl_set_hw_rfkill_state(priv(trans), hw_rfkill);
+ iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
return 0;
}
@@ -2259,6 +2268,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 */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index ae68c51e5327..4e7e6c0eede9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -63,23 +63,75 @@
#ifndef __iwl_trans_h__
#define __iwl_trans_h__
-#include <linux/debugfs.h>
-#include <linux/skbuff.h>
+#include <linux/ieee80211.h>
#include "iwl-shared.h"
-#include "iwl-commands.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.
+ */
struct iwl_priv;
struct iwl_shared;
+struct iwl_op_mode;
+struct fw_img;
+struct sk_buff;
+struct dentry;
+/**
+ * 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 +156,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 +192,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
@@ -227,27 +293,39 @@ struct iwl_calib_result {
};
/**
+ * 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
+ * @op_mode - pointer to the op_mode
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
* @hcmd_lock: protects HCMD
* @reg_lock - protect hw register access
* @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
*/
struct iwl_trans {
const struct iwl_trans_ops *ops;
+ struct iwl_op_mode *op_mode;
struct iwl_shared *shrd;
+ enum iwl_trans_state state;
spinlock_t hcmd_lock;
spinlock_t reg_lock;
@@ -257,36 +335,51 @@ 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 */
/*Ensure that this pointer will always be aligned to sizeof pointer */
- char trans_specific[0] __attribute__((__aligned__(sizeof(void *))));
+ char trans_specific[0] __aligned(sizeof(void *));
};
+static inline void iwl_trans_configure(struct iwl_trans *trans,
+ struct iwl_op_mode *op_mode)
+{
+ /*
+ * only set the op_mode for the moment. Later on, this function will do
+ * more
+ */
+ trans->op_mode = op_mode;
+}
+
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 +391,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 +412,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 +425,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 +435,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 +445,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 +470,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 +486,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 +543,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);
@@ -426,6 +557,8 @@ extern const struct iwl_trans_ops trans_ops_pcie;
struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
struct pci_dev *pdev,
const struct pci_device_id *ent);
+int __must_check iwl_pci_register_driver(void);
+void iwl_pci_unregister_driver(void);
extern const struct iwl_trans_ops trans_ops_idi;
struct iwl_trans *iwl_trans_idi_alloc(struct iwl_shared *shrd,
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c
index 11b659ab261d..b16efc00ba6e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c
@@ -44,6 +44,7 @@
#include "iwl-agn-calib.h"
#include "iwl-trans.h"
#include "iwl-fh.h"
+#include "iwl-op-mode.h"
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
@@ -82,29 +83,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 +113,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 +123,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 +398,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 +423,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 +444,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 +456,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 +586,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 +621,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 +650,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)
@@ -685,42 +688,42 @@ int iwl_run_init_ucode(struct iwl_trans *trans)
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 {
@@ -728,31 +731,30 @@ struct iwlagn_firmware_pieces {
size_t inst_size, data_size, init_size, init_data_size,
wowlan_inst_size, wowlan_data_size;
- u32 build;
-
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
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)
{
struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
- u32 api_ver, hdr_size;
+ u32 api_ver, hdr_size, build;
+ char buildstr[25];
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);
+ build = le32_to_cpu(ucode->u.v2.build);
pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size);
pieces->data_size = le32_to_cpu(ucode->u.v2.data_size);
pieces->init_size = le32_to_cpu(ucode->u.v2.init_size);
@@ -764,10 +766,10 @@ 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;
+ build = 0;
pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size);
pieces->data_size = le32_to_cpu(ucode->u.v1.data_size);
pieces->init_size = le32_to_cpu(ucode->u.v1.init_size);
@@ -776,12 +778,28 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
break;
}
+ if (build)
+ sprintf(buildstr, " build %u%s", build,
+ (nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
+ ? " (EXP)" : "");
+ else
+ buildstr[0] = '\0';
+
+ snprintf(nic->fw.fw_version,
+ sizeof(nic->fw.fw_version),
+ "%u.%u.%u.%u%s",
+ 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);
+
/* Verify size of file vs. image size info in file's header */
if (ucode_raw->size != hdr_size + pieces->inst_size +
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 +817,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;
@@ -814,14 +832,16 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
u32 tlv_len;
enum iwl_ucode_tlv_type tlv_type;
const u8 *tlv_data;
+ char buildstr[25];
+ u32 build;
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,12 +859,29 @@ 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);
- pieces->build = le32_to_cpu(ucode->build);
+ nic->fw.ucode_ver = le32_to_cpu(ucode->ver);
+ build = le32_to_cpu(ucode->build);
+
+ if (build)
+ sprintf(buildstr, " build %u%s", build,
+ (nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
+ ? " (EXP)" : "");
+ else
+ buildstr[0] = '\0';
+
+ snprintf(nic->fw.fw_version,
+ sizeof(nic->fw.fw_version),
+ "%u.%u.%u.%u%s",
+ 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);
+
data = ucode->data;
len -= sizeof(*ucode);
@@ -861,7 +898,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 +931,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 +999,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 +1016,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 +1044,20 @@ 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_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 +1065,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,16 +1085,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);
- build = pieces.build;
+ api_ver = IWL_UCODE_API(nic->fw.ucode_ver);
/*
* api_ver should match the api version forming part of the
@@ -1066,9 +1101,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,40 +1112,19 @@ 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)
- ? " (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),
- 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),
- buildstr);
+ IWL_INFO(nic, "loaded firmware version %s", nic->fw.fw_version);
/*
* For any of the failures below (before allocating pci memory)
@@ -1118,38 +1132,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 +1173,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 +1213,54 @@ 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;
-#ifndef CONFIG_IWLWIFI_P2P
- ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
-#endif
-
- priv->new_scan_threshold_behaviour =
- !!(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 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;
+ nic->inst_evtlog_size =
+ cfg->base_params->max_event_log_size;
+ nic->inst_errlog_ptr = pieces.inst_errlog_ptr;
- if (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;
- } else {
- priv->sta_key_max_num = STA_KEY_MAX_NUM;
- priv->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;
- priv->phy_calib_chain_noise_gain_cmd =
- ucode_capa.standard_phy_calibration_size + 1;
+ /* We have our copies now, allow OS release its copies */
+ release_firmware(ucode_raw);
+ complete(&nic->request_firmware_complete);
- /* initialize all valid contexts */
- iwl_init_context(priv, ucode_capa.flags);
+ nic->op_mode = iwl_dvm_ops.start(nic->shrd->trans);
- /**************************************************
- * 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);
- if (err)
+ if (!nic->op_mode)
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);
-
- /* We have our copies now, allow OS release its copies */
- release_firmware(ucode_raw);
- complete(&priv->firmware_loading_complete);
return;
try_again:
/* try next, if any */
- if (iwl_request_firmware(priv, false))
- goto out_unbind;
release_firmware(ucode_raw);
+ if (iwl_request_firmware(nic, false))
+ goto out_unbind;
return;
err_pci_alloc:
- IWL_ERR(priv, "failed to allocate pci memory\n");
- iwl_dealloc_ucode(trans(priv));
- out_unbind:
- complete(&priv->firmware_loading_complete);
- device_release_driver(trans(priv)->dev);
+ IWL_ERR(nic, "failed to allocate pci memory\n");
+ iwl_dealloc_ucode(nic);
release_firmware(ucode_raw);
+ out_unbind:
+ complete(&nic->request_firmware_complete);
+ device_release_driver(trans(nic)->dev);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.h b/drivers/net/wireless/iwlwifi/iwl-ucode.h
index eccf92519a84..8bebeb003bef 100644
--- a/drivers/net/wireless/iwlwifi/iwl-ucode.h
+++ b/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,48 @@ 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 */
+};
+
+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 {
+
+ u32 ucode_ver;
-int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first);
+ 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__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-wifi.h b/drivers/net/wireless/iwlwifi/iwl-wifi.h
index 7e6eb20823cf..d5cba07a24c8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-wifi.h
+++ b/drivers/net/wireless/iwlwifi/iwl-wifi.h
@@ -64,6 +64,43 @@
#define __iwl_wifi_h__
#include "iwl-shared.h"
+#include "iwl-ucode.h"
+
+#define UCODE_EXPERIMENTAL_INDEX 100
+
+/**
+ * struct iwl_nic - nic common data
+ * @fw: the iwl_fw structure
+ * @shrd: pointer to common shared structure
+ * @op_mode: the running op_mode
+ * @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;
+ struct iwl_op_mode *op_mode;
+
+ 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);