mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-17 01:36:12 +07:00
Merge branch 'wireless-next' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi
This commit is contained in:
commit
d896d463ee
@ -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
|
||||
|
||||
|
@ -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, \
|
||||
|
@ -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, \
|
||||
|
@ -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, \
|
||||
|
@ -137,7 +137,7 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
|
||||
.nrg_th_cca = 62,
|
||||
};
|
||||
|
||||
static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
static void iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||
@ -145,8 +145,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
iwlagn_mod_params.num_of_queues;
|
||||
|
||||
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||
hw_params(priv).max_data_size = IWL60_RTC_DATA_SIZE;
|
||||
hw_params(priv).max_inst_size = IWL60_RTC_INST_SIZE;
|
||||
|
||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
BIT(IEEE80211_BAND_5GHZ);
|
||||
@ -165,7 +163,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
/* Set initial sensitivity parameters */
|
||||
hw_params(priv).sens = &iwl6000_sensitivity;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
||||
@ -349,6 +346,8 @@ static struct iwl_bt_params iwl6000_bt_params = {
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
|
||||
.ucode_api_ok = IWL6000G2_UCODE_API_OK, \
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
|
||||
.max_inst_size = IWL60_RTC_INST_SIZE, \
|
||||
.max_data_size = IWL60_RTC_DATA_SIZE, \
|
||||
.eeprom_ver = EEPROM_6005_EEPROM_VERSION, \
|
||||
.eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \
|
||||
.lib = &iwl6000_lib, \
|
||||
@ -389,6 +388,8 @@ struct iwl_cfg iwl6005_2agn_d_cfg = {
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
|
||||
.ucode_api_ok = IWL6000G2_UCODE_API_OK, \
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
|
||||
.max_inst_size = IWL60_RTC_INST_SIZE, \
|
||||
.max_data_size = IWL60_RTC_DATA_SIZE, \
|
||||
.eeprom_ver = EEPROM_6030_EEPROM_VERSION, \
|
||||
.eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
|
||||
.lib = &iwl6030_lib, \
|
||||
@ -458,6 +459,8 @@ struct iwl_cfg iwl130_bg_cfg = {
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX, \
|
||||
.ucode_api_ok = IWL6000_UCODE_API_OK, \
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN, \
|
||||
.max_inst_size = IWL60_RTC_INST_SIZE, \
|
||||
.max_data_size = IWL60_RTC_DATA_SIZE, \
|
||||
.valid_tx_ant = ANT_BC, /* .cfg overwrite */ \
|
||||
.valid_rx_ant = ANT_BC, /* .cfg overwrite */ \
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION, \
|
||||
@ -487,6 +490,8 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
|
||||
.fw_name_pre = IWL6050_FW_PRE, \
|
||||
.ucode_api_max = IWL6050_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL6050_UCODE_API_MIN, \
|
||||
.max_inst_size = IWL60_RTC_INST_SIZE, \
|
||||
.max_data_size = IWL60_RTC_DATA_SIZE, \
|
||||
.valid_tx_ant = ANT_AB, /* .cfg overwrite */ \
|
||||
.valid_rx_ant = ANT_AB, /* .cfg overwrite */ \
|
||||
.lib = &iwl6000_lib, \
|
||||
@ -512,6 +517,8 @@ struct iwl_cfg iwl6050_2abg_cfg = {
|
||||
.fw_name_pre = IWL6050_FW_PRE, \
|
||||
.ucode_api_max = IWL6050_UCODE_API_MAX, \
|
||||
.ucode_api_min = IWL6050_UCODE_API_MIN, \
|
||||
.max_inst_size = IWL60_RTC_INST_SIZE, \
|
||||
.max_data_size = IWL60_RTC_DATA_SIZE, \
|
||||
.lib = &iwl6000_lib, \
|
||||
.additional_nic_config = iwl6150_additional_nic_config, \
|
||||
.eeprom_ver = EEPROM_6150_EEPROM_VERSION, \
|
||||
@ -537,6 +544,8 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
.ucode_api_ok = IWL6000_UCODE_API_OK,
|
||||
.ucode_api_min = IWL6000_UCODE_API_MIN,
|
||||
.max_inst_size = IWL60_RTC_INST_SIZE,
|
||||
.max_data_size = IWL60_RTC_DATA_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
|
||||
.lib = &iwl6000_lib,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -892,7 +892,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
|
||||
iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
|
||||
|
||||
queue_work(priv->shrd->workqueue, &priv->bt_full_concurrency);
|
||||
queue_work(priv->workqueue, &priv->bt_full_concurrency);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -983,7 +983,7 @@ static void iwl_check_abort_status(struct iwl_priv *priv,
|
||||
if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
|
||||
IWL_ERR(priv, "Tx flush command to flush out all frames\n");
|
||||
if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
queue_work(priv->shrd->workqueue, &priv->tx_flush);
|
||||
queue_work(priv->workqueue, &priv->tx_flush);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -618,7 +618,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
|
||||
.valid = cpu_to_le32(valid_tx_ant),
|
||||
};
|
||||
|
||||
if (IWL_UCODE_API(priv->ucode_ver) > 1) {
|
||||
if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) > 1) {
|
||||
IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
|
||||
return iwl_trans_send_cmd_pdu(trans(priv),
|
||||
TX_ANT_CONFIGURATION_CMD,
|
||||
@ -738,14 +738,14 @@ int iwl_alive_start(struct iwl_priv *priv)
|
||||
return iwl_power_update_mode(priv, true);
|
||||
}
|
||||
|
||||
static void iwl_cancel_deferred_work(struct iwl_priv *priv);
|
||||
|
||||
void __iwl_down(struct iwl_priv *priv)
|
||||
void iwl_down(struct iwl_priv *priv)
|
||||
{
|
||||
int exit_pending;
|
||||
|
||||
IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
|
||||
/*
|
||||
@ -803,15 +803,6 @@ void __iwl_down(struct iwl_priv *priv)
|
||||
priv->beacon_skb = NULL;
|
||||
}
|
||||
|
||||
void iwl_down(struct iwl_priv *priv)
|
||||
{
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
__iwl_down(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
|
||||
iwl_cancel_deferred_work(priv);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Workqueue callbacks
|
||||
@ -869,7 +860,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
|
||||
bt_status = priv->bt_status;
|
||||
bt_is_sco = priv->bt_is_sco;
|
||||
|
||||
__iwl_down(priv);
|
||||
iwl_down(priv);
|
||||
|
||||
priv->bt_full_concurrent = bt_full_concurrent;
|
||||
priv->bt_ci_compliance = bt_ci_compliance;
|
||||
@ -939,7 +930,7 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
|
||||
|
||||
static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
||||
{
|
||||
priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME);
|
||||
priv->workqueue = create_singlethread_workqueue(DRV_NAME);
|
||||
|
||||
init_waitqueue_head(&priv->shrd->wait_command_queue);
|
||||
|
||||
@ -970,7 +961,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
||||
priv->watchdog.function = iwl_bg_watchdog;
|
||||
}
|
||||
|
||||
static void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
||||
void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
||||
{
|
||||
if (cfg(priv)->lib->cancel_deferred_work)
|
||||
cfg(priv)->lib->cancel_deferred_work(priv);
|
||||
@ -1091,7 +1082,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
|
||||
#define IWL_RX_BUF_SIZE_4K (4 * 1024)
|
||||
#define IWL_RX_BUF_SIZE_8K (8 * 1024)
|
||||
|
||||
static int iwl_set_hw_params(struct iwl_priv *priv)
|
||||
static void iwl_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (iwlagn_mod_params.amsdu_size_8K)
|
||||
hw_params(priv).rx_page_order =
|
||||
@ -1111,7 +1102,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
|
||||
hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
|
||||
|
||||
/* Device-specific setup */
|
||||
return cfg(priv)->lib->set_hw_params(priv);
|
||||
cfg(priv)->lib->set_hw_params(priv);
|
||||
}
|
||||
|
||||
|
||||
@ -1248,11 +1239,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
|
||||
/************************
|
||||
* 5. Setup HW constants
|
||||
************************/
|
||||
if (iwl_set_hw_params(priv)) {
|
||||
err = -ENOENT;
|
||||
IWL_ERR(priv, "failed to set hw parameters\n");
|
||||
goto out_free_eeprom;
|
||||
}
|
||||
iwl_set_hw_params(priv);
|
||||
|
||||
/*******************
|
||||
* 6. Setup priv
|
||||
@ -1273,17 +1260,17 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
|
||||
iwl_power_initialize(priv);
|
||||
iwl_tt_initialize(priv);
|
||||
|
||||
init_completion(&priv->firmware_loading_complete);
|
||||
init_completion(&nic(priv)->request_firmware_complete);
|
||||
|
||||
err = iwl_request_firmware(priv, true);
|
||||
err = iwl_request_firmware(nic(priv), true);
|
||||
if (err)
|
||||
goto out_destroy_workqueue;
|
||||
|
||||
return 0;
|
||||
|
||||
out_destroy_workqueue:
|
||||
destroy_workqueue(priv->shrd->workqueue);
|
||||
priv->shrd->workqueue = NULL;
|
||||
destroy_workqueue(priv->workqueue);
|
||||
priv->workqueue = NULL;
|
||||
iwl_uninit_drv(priv);
|
||||
out_free_eeprom:
|
||||
iwl_eeprom_free(priv->shrd);
|
||||
@ -1296,7 +1283,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
|
||||
|
||||
void __devexit iwl_remove(struct iwl_priv * priv)
|
||||
{
|
||||
wait_for_completion(&priv->firmware_loading_complete);
|
||||
wait_for_completion(&nic(priv)->request_firmware_complete);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
|
||||
|
||||
@ -1316,18 +1303,18 @@ void __devexit iwl_remove(struct iwl_priv * priv)
|
||||
/*This will stop the queues, move the device to low power state */
|
||||
iwl_trans_stop_device(trans(priv));
|
||||
|
||||
iwl_dealloc_ucode(trans(priv));
|
||||
iwl_dealloc_ucode(nic(priv));
|
||||
|
||||
iwl_eeprom_free(priv->shrd);
|
||||
|
||||
/*netif_stop_queue(dev); */
|
||||
flush_workqueue(priv->shrd->workqueue);
|
||||
flush_workqueue(priv->workqueue);
|
||||
|
||||
/* ieee80211_unregister_hw calls iwlagn_mac_stop, which flushes
|
||||
* priv->shrd->workqueue... so we can't take down the workqueue
|
||||
* priv->workqueue... so we can't take down the workqueue
|
||||
* until now... */
|
||||
destroy_workqueue(priv->shrd->workqueue);
|
||||
priv->shrd->workqueue = NULL;
|
||||
destroy_workqueue(priv->workqueue);
|
||||
priv->workqueue = NULL;
|
||||
iwl_free_traffic_mem(priv);
|
||||
|
||||
iwl_uninit_drv(priv);
|
||||
|
@ -65,11 +65,7 @@
|
||||
|
||||
#include "iwl-dev.h"
|
||||
|
||||
struct iwlagn_ucode_capabilities {
|
||||
u32 max_probe_length;
|
||||
u32 standard_phy_calibration_size;
|
||||
u32 flags;
|
||||
};
|
||||
struct iwl_ucode_capabilities;
|
||||
|
||||
extern struct ieee80211_ops iwlagn_hw_ops;
|
||||
|
||||
@ -81,14 +77,14 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
|
||||
hdr->data_valid = 1;
|
||||
}
|
||||
|
||||
void __iwl_down(struct iwl_priv *priv);
|
||||
void iwl_down(struct iwl_priv *priv);
|
||||
void iwl_cancel_deferred_work(struct iwl_priv *priv);
|
||||
void iwlagn_prepare_restart(struct iwl_priv *priv);
|
||||
|
||||
/* MAC80211 */
|
||||
struct ieee80211_hw *iwl_alloc_all(void);
|
||||
int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
struct iwlagn_ucode_capabilities *capa);
|
||||
struct iwl_ucode_capabilities *capa);
|
||||
void iwlagn_mac_unregister(struct iwl_priv *priv);
|
||||
|
||||
/* RXON */
|
||||
|
@ -643,7 +643,7 @@ u8 iwl_get_single_channel_number(struct iwl_priv *priv,
|
||||
* NOTE: Does not commit to the hardware; it sets appropriate bit fields
|
||||
* in the staging RXON flag structure based on the ch->band
|
||||
*/
|
||||
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
|
||||
void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
enum ieee80211_band band = ch->band;
|
||||
@ -651,7 +651,7 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
|
||||
|
||||
if ((le16_to_cpu(ctx->staging.channel) == channel) &&
|
||||
(priv->band == band))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
ctx->staging.channel = cpu_to_le16(channel);
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
@ -663,7 +663,6 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||
@ -875,7 +874,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
||||
if (iwlagn_mod_params.restart_fw) {
|
||||
IWL_DEBUG_FW_ERRORS(priv,
|
||||
"Restarting adapter due to uCode error.\n");
|
||||
queue_work(priv->shrd->workqueue, &priv->restart);
|
||||
queue_work(priv->workqueue, &priv->restart);
|
||||
} else
|
||||
IWL_DEBUG_FW_ERRORS(priv,
|
||||
"Detected FW error, but not restarting\n");
|
||||
|
@ -76,7 +76,7 @@ struct iwl_cmd;
|
||||
|
||||
struct iwl_lib_ops {
|
||||
/* set hw dependent parameters */
|
||||
int (*set_hw_params)(struct iwl_priv *priv);
|
||||
void (*set_hw_params)(struct iwl_priv *priv);
|
||||
/* setup BT Rx handler */
|
||||
void (*bt_rx_handler_setup)(struct iwl_priv *priv);
|
||||
/* setup BT related deferred work */
|
||||
@ -169,7 +169,7 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
int hw_decrypt);
|
||||
int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
|
||||
void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
|
||||
struct iwl_rxon_context *ctx);
|
||||
void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
|
127
drivers/net/wireless/iwlwifi/iwl-debug.c
Normal file
127
drivers/net/wireless/iwlwifi/iwl-debug.c
Normal file
@ -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
|
@ -31,14 +31,33 @@
|
||||
|
||||
#include "iwl-bus.h"
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-devtrace.h"
|
||||
|
||||
struct iwl_priv;
|
||||
|
||||
/*No matter what is m (priv, bus, trans), this will work */
|
||||
#define IWL_ERR(m, f, a...) dev_err(trans(m)->dev, f, ## a)
|
||||
#define IWL_WARN(m, f, a...) dev_warn(trans(m)->dev, f, ## a)
|
||||
#define IWL_INFO(m, f, a...) dev_info(trans(m)->dev, f, ## a)
|
||||
#define IWL_CRIT(m, f, a...) dev_crit(trans(m)->dev, f, ## a)
|
||||
void __iwl_err(struct device *dev, bool rfkill_prefix, bool only_trace,
|
||||
const char *fmt, ...);
|
||||
void __iwl_warn(struct device *dev, const char *fmt, ...);
|
||||
void __iwl_info(struct device *dev, const char *fmt, ...);
|
||||
void __iwl_crit(struct device *dev, const char *fmt, ...);
|
||||
|
||||
/* No matter what is m (priv, bus, trans), this will work */
|
||||
#define IWL_ERR(m, f, a...) __iwl_err(trans(m)->dev, false, false, f, ## a)
|
||||
#define IWL_WARN(m, f, a...) __iwl_warn(trans(m)->dev, f, ## a)
|
||||
#define IWL_INFO(m, f, a...) __iwl_info(trans(m)->dev, f, ## a)
|
||||
#define IWL_CRIT(m, f, a...) __iwl_crit(trans(m)->dev, f, ## a)
|
||||
|
||||
#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
|
||||
void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
|
||||
u32 level, bool limit, const char *function,
|
||||
const char *fmt, ...);
|
||||
#else
|
||||
static inline void
|
||||
__iwl_dbg(struct iwl_shared *shared, struct device *dev,
|
||||
u32 level, bool limit, const char *function,
|
||||
const char *fmt, ...)
|
||||
{}
|
||||
#endif
|
||||
|
||||
#define iwl_print_hex_error(m, p, len) \
|
||||
do { \
|
||||
@ -46,53 +65,35 @@ do { \
|
||||
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
|
||||
} while (0)
|
||||
|
||||
#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_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_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 */
|
||||
|
||||
|
@ -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)
|
||||
|
@ -696,11 +696,11 @@ struct iwl_testmode_trace {
|
||||
dma_addr_t dma_addr;
|
||||
bool trace_enabled;
|
||||
};
|
||||
struct iwl_testmode_sram {
|
||||
struct iwl_testmode_mem {
|
||||
u32 buff_size;
|
||||
u32 num_chunks;
|
||||
u8 *buff_addr;
|
||||
bool sram_readed;
|
||||
bool read_in_progress;
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -721,6 +721,8 @@ struct iwl_priv {
|
||||
struct ieee80211_rate *ieee_rates;
|
||||
struct kmem_cache *tx_cmd_pool;
|
||||
|
||||
struct workqueue_struct *workqueue;
|
||||
|
||||
enum ieee80211_band band;
|
||||
|
||||
void (*pre_rx_handler)(struct iwl_priv *priv,
|
||||
@ -785,13 +787,6 @@ struct iwl_priv {
|
||||
/* EEPROM MAC addresses */
|
||||
struct mac_address addresses[2];
|
||||
|
||||
/* uCode images, save to reload in case of failure */
|
||||
int fw_index; /* firmware we're trying to load */
|
||||
u32 ucode_ver; /* version of ucode, copy of
|
||||
iwl_ucode.ver */
|
||||
|
||||
char firmware_name[25];
|
||||
|
||||
struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
|
||||
|
||||
__le16 switch_channel;
|
||||
@ -801,7 +796,6 @@ struct iwl_priv {
|
||||
u8 start_calib;
|
||||
struct iwl_sensitivity_data sensitivity_data;
|
||||
struct iwl_chain_noise_data chain_noise_data;
|
||||
bool enhance_sensitivity_table;
|
||||
__le16 sensitivity_tbl[HD_TABLE_SIZE];
|
||||
__le16 enhance_sensitivity_tbl[ENHANCE_HD_TABLE_ENTRIES];
|
||||
|
||||
@ -869,11 +863,6 @@ struct iwl_priv {
|
||||
struct iwl_rx_phy_res last_phy_res;
|
||||
bool last_phy_res_valid;
|
||||
|
||||
struct completion firmware_loading_complete;
|
||||
|
||||
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
|
||||
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
|
||||
|
||||
/*
|
||||
* chain noise reset and gain commands are the
|
||||
* two extra calibration commands follows the standard
|
||||
@ -964,7 +953,7 @@ struct iwl_priv {
|
||||
bool led_registered;
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE
|
||||
struct iwl_testmode_trace testmode_trace;
|
||||
struct iwl_testmode_sram testmode_sram;
|
||||
struct iwl_testmode_mem testmode_mem;
|
||||
u32 tm_fixed_rate;
|
||||
#endif
|
||||
|
||||
|
@ -34,6 +34,11 @@
|
||||
#undef TRACE_EVENT
|
||||
#define TRACE_EVENT(name, proto, ...) \
|
||||
static inline void trace_ ## name(proto) {}
|
||||
#undef DECLARE_EVENT_CLASS
|
||||
#define DECLARE_EVENT_CLASS(...)
|
||||
#undef DEFINE_EVENT
|
||||
#define DEFINE_EVENT(evt_class, name, proto, ...) \
|
||||
static inline void trace_ ## name(proto) {}
|
||||
#endif
|
||||
|
||||
#define PRIV_ENTRY __field(void *, priv)
|
||||
@ -163,6 +168,66 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
|
||||
__entry->p_entry)
|
||||
);
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM iwlwifi_msg
|
||||
|
||||
#define MAX_MSG_LEN 100
|
||||
|
||||
DECLARE_EVENT_CLASS(iwlwifi_msg_event,
|
||||
TP_PROTO(struct va_format *vaf),
|
||||
TP_ARGS(vaf),
|
||||
TP_STRUCT__entry(
|
||||
__dynamic_array(char, msg, MAX_MSG_LEN)
|
||||
),
|
||||
TP_fast_assign(
|
||||
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
|
||||
MAX_MSG_LEN, vaf->fmt,
|
||||
*vaf->va) >= MAX_MSG_LEN);
|
||||
),
|
||||
TP_printk("%s", (char *)__get_dynamic_array(msg))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_err,
|
||||
TP_PROTO(struct va_format *vaf),
|
||||
TP_ARGS(vaf)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_warn,
|
||||
TP_PROTO(struct va_format *vaf),
|
||||
TP_ARGS(vaf)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_info,
|
||||
TP_PROTO(struct va_format *vaf),
|
||||
TP_ARGS(vaf)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(iwlwifi_msg_event, iwlwifi_crit,
|
||||
TP_PROTO(struct va_format *vaf),
|
||||
TP_ARGS(vaf)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dbg,
|
||||
TP_PROTO(u32 level, bool in_interrupt, const char *function,
|
||||
struct va_format *vaf),
|
||||
TP_ARGS(level, in_interrupt, function, vaf),
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, level)
|
||||
__field(u8, in_interrupt)
|
||||
__string(function, function)
|
||||
__dynamic_array(char, msg, MAX_MSG_LEN)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->level = level;
|
||||
__entry->in_interrupt = in_interrupt;
|
||||
__assign_str(function, function);
|
||||
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
|
||||
MAX_MSG_LEN, vaf->fmt,
|
||||
*vaf->va) >= MAX_MSG_LEN);
|
||||
),
|
||||
TP_printk("%s", (char *)__get_dynamic_array(msg))
|
||||
);
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM iwlwifi
|
||||
|
||||
|
@ -136,7 +136,7 @@ iwlagn_iface_combinations_p2p[] = {
|
||||
* other mac80211 functions grouped here.
|
||||
*/
|
||||
int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
struct iwlagn_ucode_capabilities *capa)
|
||||
struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
int ret;
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
@ -195,7 +195,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
||||
WIPHY_FLAG_IBSS_RSN;
|
||||
|
||||
if (trans(priv)->ucode_wowlan.code.len &&
|
||||
if (nic(priv)->fw.ucode_wowlan.code.len &&
|
||||
device_can_wakeup(trans(priv)->dev)) {
|
||||
hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
|
||||
WIPHY_WOWLAN_DISCONNECT |
|
||||
@ -296,7 +296,7 @@ static int __iwl_up(struct iwl_priv *priv)
|
||||
|
||||
error:
|
||||
set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
|
||||
__iwl_down(priv);
|
||||
iwl_down(priv);
|
||||
clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
|
||||
|
||||
IWL_ERR(priv, "Unable to initialize device.\n");
|
||||
@ -341,9 +341,13 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
|
||||
|
||||
priv->is_open = 0;
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
iwl_down(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
|
||||
flush_workqueue(priv->shrd->workqueue);
|
||||
iwl_cancel_deferred_work(priv);
|
||||
|
||||
flush_workqueue(priv->workqueue);
|
||||
|
||||
/* User space software may expect getting rfkill changes
|
||||
* even if interface is down, trans->down will leave the RF
|
||||
@ -453,17 +457,17 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (ret == 0) {
|
||||
struct iwl_trans *trans = trans(priv);
|
||||
struct iwl_nic *nic = nic(priv);
|
||||
if (!priv->wowlan_sram)
|
||||
priv->wowlan_sram =
|
||||
kzalloc(trans->ucode_wowlan.data.len,
|
||||
kzalloc(nic->fw.ucode_wowlan.data.len,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (priv->wowlan_sram)
|
||||
_iwl_read_targ_mem_words(
|
||||
trans(priv), 0x800000,
|
||||
priv->wowlan_sram,
|
||||
trans->ucode_wowlan.data.len / 4);
|
||||
nic->fw.ucode_wowlan.data.len / 4);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -1117,7 +1121,7 @@ static int iwlagn_mac_set_tim(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
|
||||
queue_work(priv->shrd->workqueue, &priv->beacon_update);
|
||||
queue_work(priv->workqueue, &priv->beacon_update);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -70,6 +70,7 @@
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-cfg.h"
|
||||
#include "iwl-wifi.h"
|
||||
|
||||
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
|
||||
.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
|
||||
@ -282,13 +283,23 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
bus->shrd->bus = bus;
|
||||
|
||||
/* temporarily create this here */
|
||||
bus->shrd->nic = kzalloc(sizeof(*bus->shrd->nic), GFP_KERNEL);
|
||||
if (!bus->shrd->nic) {
|
||||
dev_printk(KERN_ERR, &pdev->dev,
|
||||
"Couldn't allocate iwl_nic");
|
||||
err = -ENOMEM;
|
||||
goto out_free_bus;
|
||||
}
|
||||
/* and initialize it as well, temporarily */
|
||||
bus->shrd->nic->shrd = bus->shrd;
|
||||
pci_set_drvdata(pdev, bus);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_IDI
|
||||
trans(bus) = iwl_trans_idi_alloc(bus->shrd, pdev, ent);
|
||||
if (trans(bus) == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto out_free_bus;
|
||||
goto out_free_nic;
|
||||
}
|
||||
|
||||
err = iwl_probe(bus, &trans_ops_idi, cfg);
|
||||
@ -296,7 +307,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
trans(bus) = iwl_trans_pcie_alloc(bus->shrd, pdev, ent);
|
||||
if (trans(bus) == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto out_free_bus;
|
||||
goto out_free_nic;
|
||||
}
|
||||
|
||||
err = iwl_probe(bus, &trans_ops_pcie, cfg);
|
||||
@ -309,6 +320,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
out_free_trans:
|
||||
iwl_trans_free(trans(bus));
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
out_free_nic:
|
||||
kfree(bus->shrd->nic);
|
||||
out_free_bus:
|
||||
kfree(bus->shrd);
|
||||
kfree(bus);
|
||||
@ -325,6 +338,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
|
||||
kfree(bus->shrd->nic);
|
||||
kfree(bus->shrd);
|
||||
kfree(bus);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -173,8 +173,6 @@ struct iwl_mod_params {
|
||||
* @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX)
|
||||
* @sku: sku read from EEPROM
|
||||
* @rx_page_order: Rx buffer page order
|
||||
* @max_inst_size: for ucode use
|
||||
* @max_data_size: for ucode use
|
||||
* @ct_kill_threshold: temperature threshold - in hw dependent unit
|
||||
* @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit
|
||||
* relevant for 1000, 6000 and up
|
||||
@ -192,8 +190,6 @@ struct iwl_hw_params {
|
||||
bool shadow_reg_enable;
|
||||
u16 sku;
|
||||
u32 rx_page_order;
|
||||
u32 max_inst_size;
|
||||
u32 max_data_size;
|
||||
u32 ct_kill_threshold;
|
||||
u32 ct_kill_exit_threshold;
|
||||
unsigned int wd_timeout;
|
||||
@ -283,6 +279,8 @@ enum iwl_led_mode {
|
||||
* @ucode_api_ok: oldest version of the uCode API that is OK to load
|
||||
* without a warning, for use in transitions
|
||||
* @ucode_api_min: Lowest version of uCode API supported by driver.
|
||||
* @max_inst_size: The maximal length of the fw inst section
|
||||
* @max_data_size: The maximal length of the fw data section
|
||||
* @valid_tx_ant: valid transmit antenna
|
||||
* @valid_rx_ant: valid receive antenna
|
||||
* @sku: sku information from EEPROM
|
||||
@ -320,6 +318,8 @@ struct iwl_cfg {
|
||||
const unsigned int ucode_api_max;
|
||||
const unsigned int ucode_api_ok;
|
||||
const unsigned int ucode_api_min;
|
||||
const u32 max_data_size;
|
||||
const u32 max_inst_size;
|
||||
u8 valid_tx_ant;
|
||||
u8 valid_rx_ant;
|
||||
u16 sku;
|
||||
@ -358,8 +358,8 @@ struct iwl_cfg {
|
||||
* @cfg: see struct iwl_cfg
|
||||
* @priv: pointer to the upper layer data
|
||||
* @trans: pointer to the transport layer data
|
||||
* @nic: pointer to the nic data
|
||||
* @hw_params: see struct iwl_hw_params
|
||||
* @workqueue: the workqueue used by all the layers of the driver
|
||||
* @lock: protect general shared data
|
||||
* @sta_lock: protects the station table.
|
||||
* If lock and sta_lock are needed, lock must be acquired first.
|
||||
@ -389,9 +389,9 @@ struct iwl_shared {
|
||||
struct iwl_cfg *cfg;
|
||||
struct iwl_priv *priv;
|
||||
struct iwl_trans *trans;
|
||||
struct iwl_nic *nic;
|
||||
struct iwl_hw_params hw_params;
|
||||
|
||||
struct workqueue_struct *workqueue;
|
||||
spinlock_t lock;
|
||||
spinlock_t sta_lock;
|
||||
struct mutex mutex;
|
||||
@ -420,6 +420,7 @@ struct iwl_shared {
|
||||
#define priv(_m) ((_m)->shrd->priv)
|
||||
#define cfg(_m) ((_m)->shrd->cfg)
|
||||
#define bus(_m) ((_m)->shrd->bus)
|
||||
#define nic(_m) ((_m)->shrd->nic)
|
||||
#define trans(_m) ((_m)->shrd->trans)
|
||||
#define hw_params(_m) ((_m)->shrd->hw_params)
|
||||
|
||||
|
@ -81,6 +81,13 @@
|
||||
#include "iwl-bus.h"
|
||||
#include "iwl-fh.h"
|
||||
|
||||
|
||||
/* Periphery registers absolute lower bound. This is used in order to
|
||||
* differentiate registery access through HBUS_TARG_PRPH_* and
|
||||
* HBUS_TARG_MEM_* accesses.
|
||||
*/
|
||||
#define IWL_TM_ABS_PRPH_START (0xA00000)
|
||||
|
||||
/* The TLVs used in the gnl message policy between the kernel module and
|
||||
* user space application. iwl_testmode_gnl_msg_policy is to be carried
|
||||
* through the NL80211_CMD_TESTMODE channel regulated by nl80211.
|
||||
@ -110,9 +117,9 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
|
||||
|
||||
[IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, },
|
||||
|
||||
[IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, },
|
||||
[IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, },
|
||||
[IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, },
|
||||
[IWL_TM_ATTR_MEM_ADDR] = { .type = NLA_U32, },
|
||||
[IWL_TM_ATTR_BUFFER_SIZE] = { .type = NLA_U32, },
|
||||
[IWL_TM_ATTR_BUFFER_DUMP] = { .type = NLA_UNSPEC, },
|
||||
|
||||
[IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, },
|
||||
[IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, },
|
||||
@ -172,7 +179,7 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
|
||||
skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length,
|
||||
GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
IWL_ERR(priv,
|
||||
"Run out of memory for messages to user space ?\n");
|
||||
return;
|
||||
}
|
||||
@ -183,24 +190,24 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
|
||||
|
||||
nla_put_failure:
|
||||
kfree_skb(skb);
|
||||
IWL_DEBUG_INFO(priv, "Ouch, overran buffer, check allocation!\n");
|
||||
IWL_ERR(priv, "Ouch, overran buffer, check allocation!\n");
|
||||
}
|
||||
|
||||
void iwl_testmode_init(struct iwl_priv *priv)
|
||||
{
|
||||
priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
|
||||
priv->testmode_trace.trace_enabled = false;
|
||||
priv->testmode_sram.sram_readed = false;
|
||||
priv->testmode_mem.read_in_progress = false;
|
||||
}
|
||||
|
||||
static void iwl_sram_cleanup(struct iwl_priv *priv)
|
||||
static void iwl_mem_cleanup(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->testmode_sram.sram_readed) {
|
||||
kfree(priv->testmode_sram.buff_addr);
|
||||
priv->testmode_sram.buff_addr = NULL;
|
||||
priv->testmode_sram.buff_size = 0;
|
||||
priv->testmode_sram.num_chunks = 0;
|
||||
priv->testmode_sram.sram_readed = false;
|
||||
if (priv->testmode_mem.read_in_progress) {
|
||||
kfree(priv->testmode_mem.buff_addr);
|
||||
priv->testmode_mem.buff_addr = NULL;
|
||||
priv->testmode_mem.buff_size = 0;
|
||||
priv->testmode_mem.num_chunks = 0;
|
||||
priv->testmode_mem.read_in_progress = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,9 +233,10 @@ static void iwl_trace_cleanup(struct iwl_priv *priv)
|
||||
void iwl_testmode_cleanup(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_trace_cleanup(priv);
|
||||
iwl_sram_cleanup(priv);
|
||||
iwl_mem_cleanup(priv);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function handles the user application commands to the ucode.
|
||||
*
|
||||
@ -237,8 +245,10 @@ void iwl_testmode_cleanup(struct iwl_priv *priv)
|
||||
* host command to the ucode.
|
||||
*
|
||||
* If any mandatory field is missing, -ENOMSG is replied to the user space
|
||||
* application; otherwise, the actual execution result of the host command to
|
||||
* ucode is replied.
|
||||
* application; otherwise, waits for the host command to be sent and checks
|
||||
* the return code. In case or error, it is returned, otherwise a reply is
|
||||
* allocated and the reply RX packet
|
||||
* is returned.
|
||||
*
|
||||
* @hw: ieee80211_hw object that represents the device
|
||||
* @tb: gnl message fields from the user space
|
||||
@ -247,25 +257,68 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_host_cmd cmd;
|
||||
struct iwl_rx_packet *pkt;
|
||||
struct sk_buff *skb;
|
||||
void *reply_buf;
|
||||
u32 reply_len;
|
||||
int ret;
|
||||
bool cmd_want_skb;
|
||||
|
||||
memset(&cmd, 0, sizeof(struct iwl_host_cmd));
|
||||
|
||||
if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] ||
|
||||
!tb[IWL_TM_ATTR_UCODE_CMD_DATA]) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error finding ucode command mandatory fields\n");
|
||||
IWL_ERR(priv, "Missing ucode command mandatory fields\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
cmd.flags = CMD_ON_DEMAND;
|
||||
cmd.flags = CMD_ON_DEMAND | CMD_SYNC;
|
||||
cmd_want_skb = nla_get_flag(tb[IWL_TM_ATTR_UCODE_CMD_SKB]);
|
||||
if (cmd_want_skb)
|
||||
cmd.flags |= CMD_WANT_SKB;
|
||||
|
||||
cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]);
|
||||
cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
|
||||
cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]);
|
||||
cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
|
||||
IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
|
||||
IWL_DEBUG_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
|
||||
" len %d\n", cmd.id, cmd.flags, cmd.len[0]);
|
||||
/* ok, let's submit the command to ucode */
|
||||
return iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
|
||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to send hcmd\n");
|
||||
return ret;
|
||||
}
|
||||
if (!cmd_want_skb)
|
||||
return ret;
|
||||
|
||||
/* Handling return of SKB to the user */
|
||||
pkt = (struct iwl_rx_packet *)cmd.reply_page;
|
||||
if (!pkt) {
|
||||
IWL_ERR(priv, "HCMD received a null response packet\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
reply_len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, reply_len + 20);
|
||||
reply_buf = kmalloc(reply_len, GFP_KERNEL);
|
||||
if (!skb || !reply_buf) {
|
||||
kfree_skb(skb);
|
||||
kfree(reply_buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* The reply is in a page, that we cannot send to user space. */
|
||||
memcpy(reply_buf, &(pkt->hdr), reply_len);
|
||||
iwl_free_pages(priv->shrd, cmd.reply_page);
|
||||
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
|
||||
NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf);
|
||||
return cfg80211_testmode_reply(skb);
|
||||
|
||||
nla_put_failure:
|
||||
IWL_DEBUG_INFO(priv, "Failed creating NL attributes\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
|
||||
@ -295,7 +348,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
int status = 0;
|
||||
|
||||
if (!tb[IWL_TM_ATTR_REG_OFFSET]) {
|
||||
IWL_DEBUG_INFO(priv, "Error finding register offset\n");
|
||||
IWL_ERR(priv, "Missing register offset\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]);
|
||||
@ -309,7 +362,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 ||
|
||||
cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8) &&
|
||||
(ofs >= FH_MEM_UPPER_BOUND)) {
|
||||
IWL_DEBUG_INFO(priv, "offset out of segment (0x0 - 0x%x)\n",
|
||||
IWL_ERR(priv, "offset out of segment (0x0 - 0x%x)\n",
|
||||
FH_MEM_UPPER_BOUND);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -321,19 +374,17 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
|
||||
if (!skb) {
|
||||
IWL_DEBUG_INFO(priv, "Error allocating memory\n");
|
||||
IWL_ERR(priv, "Memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32);
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error sending msg : %d\n", status);
|
||||
IWL_ERR(priv, "Error sending msg : %d\n", status);
|
||||
break;
|
||||
case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
|
||||
if (!tb[IWL_TM_ATTR_REG_VALUE32]) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error finding value to write\n");
|
||||
IWL_ERR(priv, "Missing value to write\n");
|
||||
return -ENOMSG;
|
||||
} else {
|
||||
val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
|
||||
@ -343,7 +394,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
break;
|
||||
case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
|
||||
if (!tb[IWL_TM_ATTR_REG_VALUE8]) {
|
||||
IWL_DEBUG_INFO(priv, "Error finding value to write\n");
|
||||
IWL_ERR(priv, "Missing value to write\n");
|
||||
return -ENOMSG;
|
||||
} else {
|
||||
val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]);
|
||||
@ -351,34 +402,8 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
iwl_write8(trans(priv), ofs, val8);
|
||||
}
|
||||
break;
|
||||
case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32:
|
||||
val32 = iwl_read_prph(trans(priv), ofs);
|
||||
IWL_INFO(priv, "32bit value to read 0x%x\n", val32);
|
||||
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
|
||||
if (!skb) {
|
||||
IWL_DEBUG_INFO(priv, "Error allocating memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32);
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error sending msg : %d\n", status);
|
||||
break;
|
||||
case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32:
|
||||
if (!tb[IWL_TM_ATTR_REG_VALUE32]) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error finding value to write\n");
|
||||
return -ENOMSG;
|
||||
} else {
|
||||
val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]);
|
||||
IWL_INFO(priv, "32bit value to write 0x%x\n", val32);
|
||||
iwl_write_prph(trans(priv), ofs, val32);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n");
|
||||
IWL_ERR(priv, "Unknown testmode register command ID\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
@ -400,14 +425,13 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
|
||||
NULL, NULL);
|
||||
ret = iwl_init_alive_start(trans(priv));
|
||||
if (ret) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error configuring init calibration: %d\n", ret);
|
||||
IWL_ERR(priv, "Fail init calibration: %d\n", ret);
|
||||
goto cfg_init_calib_error;
|
||||
}
|
||||
|
||||
ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ);
|
||||
if (ret)
|
||||
IWL_DEBUG_INFO(priv, "Error detecting"
|
||||
IWL_ERR(priv, "Error detecting"
|
||||
" CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
|
||||
return ret;
|
||||
|
||||
@ -448,8 +472,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
|
||||
rsp_data_len + 20);
|
||||
if (!skb) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error allocating memory\n");
|
||||
IWL_ERR(priv, "Memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
|
||||
@ -458,15 +481,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
rsp_data_len, rsp_data_ptr);
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_DEBUG_INFO(priv, "Error sending msg : %d\n",
|
||||
status);
|
||||
IWL_ERR(priv, "Error sending msg : %d\n", status);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
|
||||
status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
|
||||
if (status)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error loading init ucode: %d\n", status);
|
||||
IWL_ERR(priv, "Error loading init ucode: %d\n", status);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB:
|
||||
@ -477,13 +498,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
|
||||
status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR);
|
||||
if (status) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
IWL_ERR(priv,
|
||||
"Error loading runtime ucode: %d\n", status);
|
||||
break;
|
||||
}
|
||||
status = iwl_alive_start(priv);
|
||||
if (status)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
IWL_ERR(priv,
|
||||
"Error starting the device: %d\n", status);
|
||||
break;
|
||||
|
||||
@ -492,13 +513,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
iwl_trans_stop_device(trans);
|
||||
status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN);
|
||||
if (status) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
IWL_ERR(priv,
|
||||
"Error loading WOWLAN ucode: %d\n", status);
|
||||
break;
|
||||
}
|
||||
status = iwl_alive_start(priv);
|
||||
if (status)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
IWL_ERR(priv,
|
||||
"Error starting the device: %d\n", status);
|
||||
break;
|
||||
|
||||
@ -507,8 +528,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
|
||||
cfg(priv)->base_params->eeprom_size + 20);
|
||||
if (!skb) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error allocating memory\n");
|
||||
IWL_ERR(priv, "Memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND,
|
||||
@ -518,35 +538,34 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
priv->shrd->eeprom);
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error sending msg : %d\n",
|
||||
status);
|
||||
IWL_ERR(priv, "Error sending msg : %d\n",
|
||||
status);
|
||||
} else
|
||||
return -EFAULT;
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_FIXRATE_REQ:
|
||||
if (!tb[IWL_TM_ATTR_FIXRATE]) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error finding fixrate setting\n");
|
||||
IWL_ERR(priv, "Missing fixrate setting\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
|
||||
IWL_INFO(priv, "uCode version raw: 0x%x\n", priv->ucode_ver);
|
||||
IWL_INFO(priv, "uCode version raw: 0x%x\n",
|
||||
nic(priv)->fw.ucode_ver);
|
||||
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
|
||||
if (!skb) {
|
||||
IWL_DEBUG_INFO(priv, "Error allocating memory\n");
|
||||
IWL_ERR(priv, "Memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION, priv->ucode_ver);
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION,
|
||||
nic(priv)->fw.ucode_ver);
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error sending msg : %d\n", status);
|
||||
IWL_ERR(priv, "Error sending msg : %d\n", status);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID:
|
||||
@ -555,40 +574,39 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
|
||||
if (!skb) {
|
||||
IWL_DEBUG_INFO(priv, "Error allocating memory\n");
|
||||
IWL_ERR(priv, "Memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_DEVICE_ID, devid);
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error sending msg : %d\n", status);
|
||||
IWL_ERR(priv, "Error sending msg : %d\n", status);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_GET_FW_INFO:
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8);
|
||||
if (!skb) {
|
||||
IWL_DEBUG_INFO(priv, "Error allocating memory\n");
|
||||
IWL_ERR(priv, "Memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
switch (priv->shrd->ucode_type) {
|
||||
case IWL_UCODE_REGULAR:
|
||||
inst_size = trans(priv)->ucode_rt.code.len;
|
||||
data_size = trans(priv)->ucode_rt.data.len;
|
||||
inst_size = nic(priv)->fw.ucode_rt.code.len;
|
||||
data_size = nic(priv)->fw.ucode_rt.data.len;
|
||||
break;
|
||||
case IWL_UCODE_INIT:
|
||||
inst_size = trans(priv)->ucode_init.code.len;
|
||||
data_size = trans(priv)->ucode_init.data.len;
|
||||
inst_size = nic(priv)->fw.ucode_init.code.len;
|
||||
data_size = nic(priv)->fw.ucode_init.data.len;
|
||||
break;
|
||||
case IWL_UCODE_WOWLAN:
|
||||
inst_size = trans(priv)->ucode_wowlan.code.len;
|
||||
data_size = trans(priv)->ucode_wowlan.data.len;
|
||||
inst_size = nic(priv)->fw.ucode_wowlan.code.len;
|
||||
data_size = nic(priv)->fw.ucode_wowlan.data.len;
|
||||
break;
|
||||
case IWL_UCODE_NONE:
|
||||
IWL_DEBUG_INFO(priv, "The uCode has not been loaded\n");
|
||||
IWL_ERR(priv, "No uCode has not been loaded\n");
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_INFO(priv, "Unsupported uCode type\n");
|
||||
IWL_ERR(priv, "Unsupported uCode type\n");
|
||||
break;
|
||||
}
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type);
|
||||
@ -596,12 +614,11 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size);
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error sending msg : %d\n", status);
|
||||
IWL_ERR(priv, "Error sending msg : %d\n", status);
|
||||
break;
|
||||
|
||||
default:
|
||||
IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n");
|
||||
IWL_ERR(priv, "Unknown testmode driver command ID\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
return status;
|
||||
@ -664,8 +681,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
|
||||
sizeof(priv->testmode_trace.dma_addr) + 20);
|
||||
if (!skb) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error allocating memory\n");
|
||||
IWL_ERR(priv, "Memory allocation fail\n");
|
||||
iwl_trace_cleanup(priv);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -674,9 +690,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
(u64 *)&priv->testmode_trace.dma_addr);
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error sending msg : %d\n",
|
||||
status);
|
||||
IWL_ERR(priv, "Error sending msg : %d\n", status);
|
||||
}
|
||||
priv->testmode_trace.num_chunks =
|
||||
DIV_ROUND_UP(priv->testmode_trace.buff_size,
|
||||
@ -687,7 +701,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
iwl_trace_cleanup(priv);
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
|
||||
IWL_ERR(priv, "Unknown testmode mem command ID\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
return status;
|
||||
@ -752,7 +766,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
u8 owner;
|
||||
|
||||
if (!tb[IWL_TM_ATTR_UCODE_OWNER]) {
|
||||
IWL_DEBUG_INFO(priv, "Error finding ucode owner\n");
|
||||
IWL_ERR(priv, "Missing ucode owner\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
|
||||
@ -760,12 +774,89 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
|
||||
priv->shrd->ucode_owner = owner;
|
||||
else {
|
||||
IWL_DEBUG_INFO(priv, "Invalid owner\n");
|
||||
IWL_ERR(priv, "Invalid owner\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_testmode_indirect_read(struct iwl_priv *priv, u32 addr, u32 size)
|
||||
{
|
||||
struct iwl_trans *trans = trans(priv);
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if (size & 0x3)
|
||||
return -EINVAL;
|
||||
priv->testmode_mem.buff_size = size;
|
||||
priv->testmode_mem.buff_addr =
|
||||
kmalloc(priv->testmode_mem.buff_size, GFP_KERNEL);
|
||||
if (priv->testmode_mem.buff_addr == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Hard-coded periphery absolute address */
|
||||
if (IWL_TM_ABS_PRPH_START <= addr &&
|
||||
addr < IWL_TM_ABS_PRPH_START + PRPH_END) {
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_RADDR,
|
||||
addr | (3 << 24));
|
||||
for (i = 0; i < size; i += 4)
|
||||
*(u32 *)(priv->testmode_mem.buff_addr + i) =
|
||||
iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
|
||||
iwl_release_nic_access(trans);
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
} else { /* target memory (SRAM) */
|
||||
_iwl_read_targ_mem_words(trans, addr,
|
||||
priv->testmode_mem.buff_addr,
|
||||
priv->testmode_mem.buff_size / 4);
|
||||
}
|
||||
|
||||
priv->testmode_mem.num_chunks =
|
||||
DIV_ROUND_UP(priv->testmode_mem.buff_size, DUMP_CHUNK_SIZE);
|
||||
priv->testmode_mem.read_in_progress = true;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int iwl_testmode_indirect_write(struct iwl_priv *priv, u32 addr,
|
||||
u32 size, unsigned char *buf)
|
||||
{
|
||||
struct iwl_trans *trans = trans(priv);
|
||||
u32 val, i;
|
||||
unsigned long flags;
|
||||
|
||||
if (IWL_TM_ABS_PRPH_START <= addr &&
|
||||
addr < IWL_TM_ABS_PRPH_START + PRPH_END) {
|
||||
/* Periphery writes can be 1-3 bytes long, or DWORDs */
|
||||
if (size < 4) {
|
||||
memcpy(&val, buf, size);
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
|
||||
(addr & 0x0000FFFF) |
|
||||
((size - 1) << 24));
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
|
||||
iwl_release_nic_access(trans);
|
||||
/* needed after consecutive writes w/o read */
|
||||
mmiowb();
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
} else {
|
||||
if (size % 4)
|
||||
return -EINVAL;
|
||||
for (i = 0; i < size; i += 4)
|
||||
iwl_write_prph(trans, addr+i,
|
||||
*(u32 *)(buf+i));
|
||||
}
|
||||
} else if (iwlagn_hw_valid_rtc_data_addr(addr) ||
|
||||
(IWLAGN_RTC_INST_LOWER_BOUND <= addr &&
|
||||
addr < IWLAGN_RTC_INST_UPPER_BOUND)) {
|
||||
_iwl_write_targ_mem_words(trans, addr, buf, size/4);
|
||||
} else
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the user application commands for SRAM data dump
|
||||
*
|
||||
@ -782,82 +873,60 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
* @hw: ieee80211_hw object that represents the device
|
||||
* @tb: gnl message fields from the user space
|
||||
*/
|
||||
static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
static int iwl_testmode_indirect_mem(struct ieee80211_hw *hw,
|
||||
struct nlattr **tb)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
u32 ofs, size, maxsize;
|
||||
u32 addr, size, cmd;
|
||||
unsigned char *buf;
|
||||
|
||||
if (priv->testmode_sram.sram_readed)
|
||||
/* Both read and write should be blocked, for atomicity */
|
||||
if (priv->testmode_mem.read_in_progress)
|
||||
return -EBUSY;
|
||||
|
||||
if (!tb[IWL_TM_ATTR_SRAM_ADDR]) {
|
||||
IWL_DEBUG_INFO(priv, "Error finding SRAM offset address\n");
|
||||
cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
|
||||
if (!tb[IWL_TM_ATTR_MEM_ADDR]) {
|
||||
IWL_ERR(priv, "Error finding memory offset address\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
ofs = nla_get_u32(tb[IWL_TM_ATTR_SRAM_ADDR]);
|
||||
if (!tb[IWL_TM_ATTR_SRAM_SIZE]) {
|
||||
IWL_DEBUG_INFO(priv, "Error finding size for SRAM reading\n");
|
||||
addr = nla_get_u32(tb[IWL_TM_ATTR_MEM_ADDR]);
|
||||
if (!tb[IWL_TM_ATTR_BUFFER_SIZE]) {
|
||||
IWL_ERR(priv, "Error finding size for memory reading\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]);
|
||||
switch (priv->shrd->ucode_type) {
|
||||
case IWL_UCODE_REGULAR:
|
||||
maxsize = trans(priv)->ucode_rt.data.len;
|
||||
break;
|
||||
case IWL_UCODE_INIT:
|
||||
maxsize = trans(priv)->ucode_init.data.len;
|
||||
break;
|
||||
case IWL_UCODE_WOWLAN:
|
||||
maxsize = trans(priv)->ucode_wowlan.data.len;
|
||||
break;
|
||||
case IWL_UCODE_NONE:
|
||||
IWL_ERR(priv, "Error, uCode does not been loaded\n");
|
||||
return -ENOSYS;
|
||||
default:
|
||||
IWL_ERR(priv, "Error, unsupported uCode type\n");
|
||||
return -ENOSYS;
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
_iwl_read_targ_mem_words(trans(priv), ofs,
|
||||
priv->testmode_sram.buff_addr,
|
||||
priv->testmode_sram.buff_size / 4);
|
||||
priv->testmode_sram.num_chunks =
|
||||
DIV_ROUND_UP(priv->testmode_sram.buff_size, DUMP_CHUNK_SIZE);
|
||||
priv->testmode_sram.sram_readed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_testmode_sram_dump(struct ieee80211_hw *hw, struct nlattr **tb,
|
||||
static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb,
|
||||
struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
int idx, length;
|
||||
|
||||
if (priv->testmode_sram.sram_readed) {
|
||||
if (priv->testmode_mem.read_in_progress) {
|
||||
idx = cb->args[4];
|
||||
if (idx >= priv->testmode_sram.num_chunks) {
|
||||
iwl_sram_cleanup(priv);
|
||||
if (idx >= priv->testmode_mem.num_chunks) {
|
||||
iwl_mem_cleanup(priv);
|
||||
return -ENOENT;
|
||||
}
|
||||
length = DUMP_CHUNK_SIZE;
|
||||
if (((idx + 1) == priv->testmode_sram.num_chunks) &&
|
||||
(priv->testmode_sram.buff_size % DUMP_CHUNK_SIZE))
|
||||
length = priv->testmode_sram.buff_size %
|
||||
if (((idx + 1) == priv->testmode_mem.num_chunks) &&
|
||||
(priv->testmode_mem.buff_size % DUMP_CHUNK_SIZE))
|
||||
length = priv->testmode_mem.buff_size %
|
||||
DUMP_CHUNK_SIZE;
|
||||
|
||||
NLA_PUT(skb, IWL_TM_ATTR_SRAM_DUMP, length,
|
||||
priv->testmode_sram.buff_addr +
|
||||
NLA_PUT(skb, IWL_TM_ATTR_BUFFER_DUMP, length,
|
||||
priv->testmode_mem.buff_addr +
|
||||
(DUMP_CHUNK_SIZE * idx));
|
||||
idx++;
|
||||
cb->args[4] = idx;
|
||||
@ -898,14 +967,13 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
|
||||
result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
|
||||
iwl_testmode_gnl_msg_policy);
|
||||
if (result != 0) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error parsing the gnl message : %d\n", result);
|
||||
IWL_ERR(priv, "Error parsing the gnl message : %d\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* IWL_TM_ATTR_COMMAND is absolutely mandatory */
|
||||
if (!tb[IWL_TM_ATTR_COMMAND]) {
|
||||
IWL_DEBUG_INFO(priv, "Error finding testmode command type\n");
|
||||
IWL_ERR(priv, "Missing testmode command type\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
/* in case multiple accesses to the device happens */
|
||||
@ -919,8 +987,6 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
|
||||
case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32:
|
||||
case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32:
|
||||
case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8:
|
||||
case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32:
|
||||
case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32:
|
||||
IWL_DEBUG_INFO(priv, "testmode cmd to register\n");
|
||||
result = iwl_testmode_reg(hw, tb);
|
||||
break;
|
||||
@ -950,13 +1016,15 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
|
||||
result = iwl_testmode_ownership(hw, tb);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_READ_SRAM:
|
||||
IWL_DEBUG_INFO(priv, "testmode sram read cmd to driver\n");
|
||||
result = iwl_testmode_sram(hw, tb);
|
||||
case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ:
|
||||
case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE:
|
||||
IWL_DEBUG_INFO(priv, "testmode indirect memory cmd "
|
||||
"to driver\n");
|
||||
result = iwl_testmode_indirect_mem(hw, tb);
|
||||
break;
|
||||
|
||||
default:
|
||||
IWL_DEBUG_INFO(priv, "Unknown testmode command\n");
|
||||
IWL_ERR(priv, "Unknown testmode command\n");
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
@ -981,15 +1049,14 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
|
||||
iwl_testmode_gnl_msg_policy);
|
||||
if (result) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error parsing the gnl message : %d\n", result);
|
||||
IWL_ERR(priv,
|
||||
"Error parsing the gnl message : %d\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* IWL_TM_ATTR_COMMAND is absolutely mandatory */
|
||||
if (!tb[IWL_TM_ATTR_COMMAND]) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Error finding testmode command type\n");
|
||||
IWL_ERR(priv, "Missing testmode command type\n");
|
||||
return -ENOMSG;
|
||||
}
|
||||
cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
|
||||
@ -1003,9 +1070,9 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
|
||||
result = iwl_testmode_trace_dump(hw, tb, skb, cb);
|
||||
break;
|
||||
case IWL_TM_CMD_APP2DEV_DUMP_SRAM:
|
||||
case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP:
|
||||
IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n");
|
||||
result = iwl_testmode_sram_dump(hw, tb, skb, cb);
|
||||
result = iwl_testmode_buffer_dump(hw, tb, skb, cb);
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
|
@ -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 */
|
||||
|
@ -230,6 +230,7 @@ struct iwl_trans_pcie {
|
||||
struct tasklet_struct irq_tasklet;
|
||||
struct isr_statistics isr_stats;
|
||||
|
||||
spinlock_t irq_lock;
|
||||
u32 inta_mask;
|
||||
u32 scd_base_addr;
|
||||
struct iwl_dma_ptr scd_bc_tbls;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans-pcie-int.h"
|
||||
#include "iwl-wifi.h"
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_IDI
|
||||
#include "iwl-amfh.h"
|
||||
@ -227,7 +228,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans)
|
||||
/* If the pre-allocated buffer pool is dropping low, schedule to
|
||||
* refill it */
|
||||
if (rxq->free_count <= RX_LOW_WATERMARK)
|
||||
queue_work(trans->shrd->workqueue, &trans_pcie->rx_replenish);
|
||||
schedule_work(&trans_pcie->rx_replenish);
|
||||
|
||||
|
||||
/* If we've added more space for the firmware to place data, tell it.
|
||||
@ -331,13 +332,14 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority)
|
||||
|
||||
void iwlagn_rx_replenish(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
unsigned long flags;
|
||||
|
||||
iwlagn_rx_allocate(trans, GFP_KERNEL);
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
iwlagn_rx_queue_restock(trans);
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
}
|
||||
|
||||
static void iwlagn_rx_replenish_now(struct iwl_trans *trans)
|
||||
@ -351,14 +353,8 @@ void iwl_bg_rx_replenish(struct work_struct *data)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
container_of(data, struct iwl_trans_pcie, rx_replenish);
|
||||
struct iwl_trans *trans = trans_pcie->trans;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
|
||||
return;
|
||||
|
||||
mutex_lock(&trans->shrd->mutex);
|
||||
iwlagn_rx_replenish(trans);
|
||||
mutex_unlock(&trans->shrd->mutex);
|
||||
iwlagn_rx_replenish(trans_pcie->trans);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -594,17 +590,17 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
|
||||
{
|
||||
u32 base;
|
||||
struct iwl_error_event_table table;
|
||||
struct iwl_priv *priv = priv(trans);
|
||||
struct iwl_nic *nic = nic(trans);
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
base = trans->shrd->device_pointers.error_event_table;
|
||||
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
|
||||
if (!base)
|
||||
base = priv->init_errlog_ptr;
|
||||
base = nic->init_errlog_ptr;
|
||||
} else {
|
||||
if (!base)
|
||||
base = priv->inst_errlog_ptr;
|
||||
base = nic->inst_errlog_ptr;
|
||||
}
|
||||
|
||||
if (!iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
@ -616,7 +612,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_read_targ_mem_words(trans(priv), base, &table, sizeof(table));
|
||||
iwl_read_targ_mem_words(trans, base, &table, sizeof(table));
|
||||
|
||||
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
|
||||
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
|
||||
@ -626,7 +622,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
|
||||
|
||||
trans_pcie->isr_stats.err_code = table.error_id;
|
||||
|
||||
trace_iwlwifi_dev_ucode_error(priv, table.error_id, table.tsf_low,
|
||||
trace_iwlwifi_dev_ucode_error(priv(nic), table.error_id, table.tsf_low,
|
||||
table.data1, table.data2, table.line,
|
||||
table.blink1, table.blink2, table.ilink1,
|
||||
table.ilink2, table.bcon_time, table.gp1,
|
||||
@ -723,7 +719,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
|
||||
u32 ptr; /* SRAM byte address of log data */
|
||||
u32 ev, time, data; /* event log data */
|
||||
unsigned long reg_flags;
|
||||
struct iwl_priv *priv = priv(trans);
|
||||
struct iwl_nic *nic = nic(trans);
|
||||
|
||||
if (num_events == 0)
|
||||
return pos;
|
||||
@ -731,10 +727,10 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
|
||||
base = trans->shrd->device_pointers.log_event_table;
|
||||
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
|
||||
if (!base)
|
||||
base = priv->init_evtlog_ptr;
|
||||
base = nic->init_evtlog_ptr;
|
||||
} else {
|
||||
if (!base)
|
||||
base = priv->inst_evtlog_ptr;
|
||||
base = nic->inst_evtlog_ptr;
|
||||
}
|
||||
|
||||
if (mode == 0)
|
||||
@ -764,7 +760,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
|
||||
"EVT_LOG:0x%08x:%04u\n",
|
||||
time, ev);
|
||||
} else {
|
||||
trace_iwlwifi_dev_ucode_event(priv, 0,
|
||||
trace_iwlwifi_dev_ucode_event(priv(trans), 0,
|
||||
time, ev);
|
||||
IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n",
|
||||
time, ev);
|
||||
@ -778,7 +774,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
|
||||
} else {
|
||||
IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n",
|
||||
time, data, ev);
|
||||
trace_iwlwifi_dev_ucode_event(priv, time,
|
||||
trace_iwlwifi_dev_ucode_event(priv(trans), time,
|
||||
data, ev);
|
||||
}
|
||||
}
|
||||
@ -840,17 +836,17 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
|
||||
u32 logsize;
|
||||
int pos = 0;
|
||||
size_t bufsz = 0;
|
||||
struct iwl_priv *priv = priv(trans);
|
||||
struct iwl_nic *nic = nic(trans);
|
||||
|
||||
base = trans->shrd->device_pointers.log_event_table;
|
||||
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
|
||||
logsize = priv->init_evtlog_size;
|
||||
logsize = nic->init_evtlog_size;
|
||||
if (!base)
|
||||
base = priv->init_evtlog_ptr;
|
||||
base = nic->init_evtlog_ptr;
|
||||
} else {
|
||||
logsize = priv->inst_evtlog_size;
|
||||
logsize = nic->inst_evtlog_size;
|
||||
if (!base)
|
||||
base = priv->inst_evtlog_ptr;
|
||||
base = nic->inst_evtlog_ptr;
|
||||
}
|
||||
|
||||
if (!iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
@ -949,7 +945,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
||||
struct isr_statistics *isr_stats = &trans_pcie->isr_stats;
|
||||
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* Ack/clear/reset pending uCode interrupts.
|
||||
* Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
|
||||
@ -979,7 +975,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
||||
/* saved interrupt in inta variable now we can reset trans_pcie->inta */
|
||||
trans_pcie->inta = 0;
|
||||
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* Now service all interrupt bits discovered above. */
|
||||
if (inta & CSR_INT_BIT_HW_ERR) {
|
||||
@ -1232,7 +1228,7 @@ void iwl_reset_ict(struct iwl_trans *trans)
|
||||
if (!trans_pcie->ict_tbl)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
iwl_disable_interrupts(trans);
|
||||
|
||||
memset(trans_pcie->ict_tbl, 0, ICT_SIZE);
|
||||
@ -1249,7 +1245,7 @@ void iwl_reset_ict(struct iwl_trans *trans)
|
||||
trans_pcie->ict_index = 0;
|
||||
iwl_write32(trans, CSR_INT, trans_pcie->inta_mask);
|
||||
iwl_enable_interrupts(trans);
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
}
|
||||
|
||||
/* Device is going down disable ict interrupt usage */
|
||||
@ -1260,9 +1256,9 @@ void iwl_disable_ict(struct iwl_trans *trans)
|
||||
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
trans_pcie->use_ict = false;
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
}
|
||||
|
||||
static irqreturn_t iwl_isr(int irq, void *data)
|
||||
@ -1281,7 +1277,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
|
||||
|
||||
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* Disable (but don't clear!) interrupts here to avoid
|
||||
* back-to-back ISRs and sporadic interrupts from our NIC.
|
||||
@ -1325,7 +1321,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
unplugged:
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
none:
|
||||
@ -1335,7 +1331,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
|
||||
!trans_pcie->inta)
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
@ -1369,7 +1365,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
|
||||
|
||||
trace_iwlwifi_dev_irq(priv(trans));
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* Disable (but don't clear!) interrupts here to avoid
|
||||
* back-to-back ISRs and sporadic interrupts from our NIC.
|
||||
@ -1440,7 +1436,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
|
||||
iwl_enable_interrupts(trans);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
none:
|
||||
@ -1451,6 +1447,6 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
|
||||
!trans_pcie->inta)
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
@ -492,7 +492,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
|
||||
|
||||
ra_tid = BUILD_RAxTID(sta_id, tid);
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* Stop this Tx queue before configuring it */
|
||||
iwlagn_tx_queue_stop_scheduler(trans, txq_id);
|
||||
@ -532,7 +532,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
|
||||
trans_pcie->txq[txq_id].sta_id = sta_id;
|
||||
trans_pcie->txq[txq_id].tid = tid;
|
||||
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -219,10 +219,10 @@ static int iwl_rx_init(struct iwl_trans *trans)
|
||||
|
||||
iwl_trans_rx_hw_init(trans, rxq);
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
rxq->need_update = 1;
|
||||
iwl_rx_queue_update_write_ptr(trans, rxq);
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -585,7 +585,7 @@ static int iwl_tx_init(struct iwl_trans *trans)
|
||||
alloc = true;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* Turn off all Tx DMA fifos */
|
||||
iwl_write_prph(trans, SCD_TXFACT, 0);
|
||||
@ -594,7 +594,7 @@ static int iwl_tx_init(struct iwl_trans *trans)
|
||||
iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
|
||||
trans_pcie->kw.dma >> 4);
|
||||
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* Alloc and init all Tx queues, including the command queue (#4/#9) */
|
||||
for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
|
||||
@ -803,17 +803,18 @@ static void iwl_apm_stop(struct iwl_trans *trans)
|
||||
|
||||
static int iwl_nic_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
unsigned long flags;
|
||||
|
||||
/* nic_init */
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
iwl_apm_init(trans);
|
||||
|
||||
/* Set interrupt coalescing calibration timer to default (512 usecs) */
|
||||
iwl_write8(trans, CSR_INT_COALESCING,
|
||||
IWL_HOST_INT_CALIB_TIMEOUT_DEF);
|
||||
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
iwl_set_pwr_vmain(trans);
|
||||
|
||||
@ -1078,10 +1079,15 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
|
||||
|
||||
/*
|
||||
* Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
|
||||
* must be called under priv->shrd->lock and mac access
|
||||
* must be called under the irq lock and with MAC access
|
||||
*/
|
||||
static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask)
|
||||
{
|
||||
struct iwl_trans_pcie __maybe_unused *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
lockdep_assert_held(&trans_pcie->irq_lock);
|
||||
|
||||
iwl_write_prph(trans, SCD_TXFACT, mask);
|
||||
}
|
||||
|
||||
@ -1095,7 +1101,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
|
||||
int i, chan;
|
||||
u32 reg_val;
|
||||
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
|
||||
trans_pcie->scd_base_addr =
|
||||
iwl_read_prph(trans, SCD_SRAM_BASE_ADDR);
|
||||
@ -1191,7 +1197,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
|
||||
fifo, 0);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* Enable L1-Active */
|
||||
iwl_clear_bits_prph(trans, APMG_PCIDEV_STT_REG,
|
||||
@ -1214,7 +1220,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
/* Turn off all Tx DMA fifos */
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
|
||||
iwl_trans_txq_set_sched(trans, 0);
|
||||
|
||||
@ -1230,7 +1236,7 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
|
||||
iwl_read_direct32(trans,
|
||||
FH_TSSR_TX_STATUS_REG));
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
if (!trans_pcie->txq) {
|
||||
IWL_WARN(trans, "Stopping tx queues that aren't allocated...");
|
||||
@ -1250,9 +1256,9 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
/* tell the device to stop sending interrupts */
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
iwl_disable_interrupts(trans);
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* device going down, Stop using ICT table */
|
||||
iwl_disable_ict(trans);
|
||||
@ -1285,14 +1291,16 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
||||
/* Upon stop, the APM issues an interrupt if HW RF kill is set.
|
||||
* Clean again the interrupt here
|
||||
*/
|
||||
spin_lock_irqsave(&trans->shrd->lock, flags);
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
iwl_disable_interrupts(trans);
|
||||
spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* wait to make sure we flush pending tasklet*/
|
||||
synchronize_irq(trans->irq);
|
||||
tasklet_kill(&trans_pcie->irq_tasklet);
|
||||
|
||||
cancel_work_sync(&trans_pcie->rx_replenish);
|
||||
|
||||
/* stop and reset the on-board processor */
|
||||
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
|
||||
}
|
||||
@ -2259,6 +2267,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
|
||||
trans->shrd = shrd;
|
||||
trans_pcie->trans = trans;
|
||||
spin_lock_init(&trans->hcmd_lock);
|
||||
spin_lock_init(&trans_pcie->irq_lock);
|
||||
|
||||
/* W/A - seems to solve weird behavior. We need to remove this if we
|
||||
* don't want to stay in L1 all the time. This wastes a lot of power */
|
||||
|
@ -68,18 +68,75 @@
|
||||
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-commands.h"
|
||||
#include "iwl-ucode.h"
|
||||
#include "iwl-debug.h"
|
||||
|
||||
/*This file includes the declaration that are exported from the transport
|
||||
* layer */
|
||||
/**
|
||||
* DOC: Transport layer - what is it ?
|
||||
*
|
||||
* The tranport layer is the layer that deals with the HW directly. It provides
|
||||
* an abstraction of the underlying HW to the upper layer. The transport layer
|
||||
* doesn't provide any policy, algorithm or anything of this kind, but only
|
||||
* mechanisms to make the HW do something.It is not completely stateless but
|
||||
* close to it.
|
||||
* We will have an implementation for each different supported bus.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: Life cycle of the transport layer
|
||||
*
|
||||
* The transport layer has a very precise life cycle.
|
||||
*
|
||||
* 1) A helper function is called during the module initialization and
|
||||
* registers the bus driver's ops with the transport's alloc function.
|
||||
* 2) Bus's probe calls to the transport layer's allocation functions.
|
||||
* Of course this function is bus specific.
|
||||
* 3) This allocation functions will spawn the upper layer which will
|
||||
* register mac80211.
|
||||
*
|
||||
* 4) At some point (i.e. mac80211's start call), the op_mode will call
|
||||
* the following sequence:
|
||||
* start_hw
|
||||
* start_fw
|
||||
*
|
||||
* 5) Then when finished (or reset):
|
||||
* stop_fw (a.k.a. stop device for the moment)
|
||||
* stop_hw
|
||||
*
|
||||
* 6) Eventually, the free function will be called.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: API needed by the transport layer from the op_mode
|
||||
*
|
||||
* TODO
|
||||
*/
|
||||
|
||||
struct iwl_priv;
|
||||
struct iwl_shared;
|
||||
|
||||
/**
|
||||
* DOC: Host command section
|
||||
*
|
||||
* A host command is a commaned issued by the upper layer to the fw. There are
|
||||
* several versions of fw that have several APIs. The transport layer is
|
||||
* completely agnostic to these differences.
|
||||
* The transport does provide helper functionnality (i.e. SYNC / ASYNC mode),
|
||||
*/
|
||||
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
|
||||
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
|
||||
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
|
||||
|
||||
enum {
|
||||
/**
|
||||
* enum CMD_MODE - how to send the host commands ?
|
||||
*
|
||||
* @CMD_SYNC: The caller will be stalled until the fw responds to the command
|
||||
* @CMD_ASYNC: Return right away and don't want for the response
|
||||
* @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
|
||||
* response.
|
||||
* @CMD_ON_DEMAND: This command is sent by the test mode pipe.
|
||||
*/
|
||||
enum CMD_MODE {
|
||||
CMD_SYNC = 0,
|
||||
CMD_ASYNC = BIT(0),
|
||||
CMD_WANT_SKB = BIT(1),
|
||||
@ -104,20 +161,29 @@ struct iwl_device_cmd {
|
||||
|
||||
#define IWL_MAX_CMD_TFDS 2
|
||||
|
||||
/**
|
||||
* struct iwl_hcmd_dataflag - flag for each one of the chunks of the command
|
||||
*
|
||||
* IWL_HCMD_DFL_NOCOPY: By default, the command is copied to the host command's
|
||||
* ring. The transport layer doesn't map the command's buffer to DMA, but
|
||||
* rather copies it to an previously allocated DMA buffer. This flag tells
|
||||
* the transport layer not to copy the command, but to map the existing
|
||||
* buffer. This can save memcpy and is worth with very big comamnds.
|
||||
*/
|
||||
enum iwl_hcmd_dataflag {
|
||||
IWL_HCMD_DFL_NOCOPY = BIT(0),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_host_cmd - Host command to the uCode
|
||||
*
|
||||
* @data: array of chunks that composes the data of the host command
|
||||
* @reply_page: pointer to the page that holds the response to the host command
|
||||
* @handler_status: return value of the handler of the command
|
||||
* (put in setup_rx_handlers) - valid for SYNC mode only
|
||||
* @callback:
|
||||
* @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
|
||||
* @flags: can be CMD_*
|
||||
* @len: array of the lenths of the chunks in data
|
||||
* @dataflags:
|
||||
* @dataflags: IWL_HCMD_DFL_*
|
||||
* @id: id of the host command
|
||||
*/
|
||||
struct iwl_host_cmd {
|
||||
@ -131,40 +197,45 @@ struct iwl_host_cmd {
|
||||
u8 id;
|
||||
};
|
||||
|
||||
/* one for each uCode image (inst/data, boot/init/runtime) */
|
||||
struct fw_desc {
|
||||
dma_addr_t p_addr; /* hardware address */
|
||||
void *v_addr; /* software address */
|
||||
u32 len; /* size in bytes */
|
||||
};
|
||||
|
||||
struct fw_img {
|
||||
struct fw_desc code; /* firmware code image */
|
||||
struct fw_desc data; /* firmware data image */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans_ops - transport specific operations
|
||||
*
|
||||
* All the handlers MUST be implemented
|
||||
*
|
||||
* @start_hw: starts the HW- from that point on, the HW can send interrupts
|
||||
* May sleep
|
||||
* @stop_hw: stops the HW- from that point on, the HW will be in low power but
|
||||
* will still issue interrupt if the HW RF kill is triggered.
|
||||
* May sleep
|
||||
* @start_fw: allocates and inits all the resources for the transport
|
||||
* layer. Also kick a fw image. This handler may sleep.
|
||||
* layer. Also kick a fw image.
|
||||
* May sleep
|
||||
* @fw_alive: called when the fw sends alive notification
|
||||
* May sleep
|
||||
* @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
|
||||
* @stop_device:stops the whole device (embedded CPU put to reset)
|
||||
* May sleep
|
||||
* @send_cmd:send a host command
|
||||
* May sleep only if CMD_SYNC is set
|
||||
* @tx: send an skb
|
||||
* Must be atomic
|
||||
* @reclaim: free packet until ssn. Returns a list of freed packets.
|
||||
* Must be atomic
|
||||
* @tx_agg_alloc: allocate resources for a TX BA session
|
||||
* May sleep
|
||||
* @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
|
||||
* ready and a successful ADDBA response has been received.
|
||||
* ready and a successful ADDBA response has been received.
|
||||
* May sleep
|
||||
* @tx_agg_disable: de-configure a Tx queue to send AMPDUs
|
||||
* May sleep
|
||||
* @free: release all the ressource for the transport layer itself such as
|
||||
* irq, tasklet etc...
|
||||
* irq, tasklet etc... From this point on, the device may not issue
|
||||
* any interrupt (incl. RFKILL).
|
||||
* May sleep
|
||||
* @stop_queue: stop a specific queue
|
||||
* @check_stuck_queue: check if a specific queue is stuck
|
||||
* @wait_tx_queue_empty: wait until all tx queues are empty
|
||||
* May sleep
|
||||
* @dbgfs_register: add the dbgfs files under this directory. Files will be
|
||||
* automatically deleted.
|
||||
* @suspend: stop the device unless WoWLAN is configured
|
||||
@ -226,8 +297,20 @@ struct iwl_calib_result {
|
||||
/* data follows */
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_trans_state - state of the transport layer
|
||||
*
|
||||
* @IWL_TRANS_NO_FW: no fw has sent an alive response
|
||||
* @IWL_TRANS_FW_ALIVE: a fw has sent an alive response
|
||||
*/
|
||||
enum iwl_trans_state {
|
||||
IWL_TRANS_NO_FW = 0,
|
||||
IWL_TRANS_FW_ALIVE = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans - transport common data
|
||||
*
|
||||
* @ops - pointer to iwl_trans_ops
|
||||
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
|
||||
* @hcmd_lock: protects HCMD
|
||||
@ -235,12 +318,9 @@ struct iwl_calib_result {
|
||||
* @dev - pointer to struct device * that represents the device
|
||||
* @irq - the irq number for the device
|
||||
* @hw_id: a u32 with the ID of the device / subdevice.
|
||||
* Set during transport alloaction.
|
||||
* Set during transport allocation.
|
||||
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
|
||||
* @ucode_write_complete: indicates that the ucode has been copied.
|
||||
* @ucode_rt: run time ucode image
|
||||
* @ucode_init: init ucode image
|
||||
* @ucode_wowlan: wake on wireless ucode image (optional)
|
||||
* @nvm_device_type: indicates OTP or eeprom
|
||||
* @pm_support: set to true in start_hw if link pm is supported
|
||||
* @calib_results: list head for init calibration results
|
||||
@ -248,6 +328,7 @@ struct iwl_calib_result {
|
||||
struct iwl_trans {
|
||||
const struct iwl_trans_ops *ops;
|
||||
struct iwl_shared *shrd;
|
||||
enum iwl_trans_state state;
|
||||
spinlock_t hcmd_lock;
|
||||
spinlock_t reg_lock;
|
||||
|
||||
@ -257,16 +338,11 @@ struct iwl_trans {
|
||||
u32 hw_id;
|
||||
char hw_id_str[52];
|
||||
|
||||
u8 ucode_write_complete; /* the image write is complete */
|
||||
struct fw_img ucode_rt;
|
||||
struct fw_img ucode_init;
|
||||
struct fw_img ucode_wowlan;
|
||||
u8 ucode_write_complete;
|
||||
|
||||
/* eeprom related variables */
|
||||
int nvm_device_type;
|
||||
bool pm_support;
|
||||
|
||||
/* init calibration results */
|
||||
struct list_head calib_results;
|
||||
|
||||
/* pointer to trans specific struct */
|
||||
@ -276,17 +352,27 @@ struct iwl_trans {
|
||||
|
||||
static inline int iwl_trans_start_hw(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
return trans->ops->start_hw(trans);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_stop_hw(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
trans->ops->stop_hw(trans);
|
||||
|
||||
trans->state = IWL_TRANS_NO_FW;
|
||||
}
|
||||
|
||||
static inline void iwl_trans_fw_alive(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
trans->ops->fw_alive(trans);
|
||||
|
||||
trans->state = IWL_TRANS_FW_ALIVE;
|
||||
}
|
||||
|
||||
static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw)
|
||||
@ -298,13 +384,20 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw)
|
||||
|
||||
static inline void iwl_trans_stop_device(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
trans->ops->stop_device(trans);
|
||||
|
||||
trans->state = IWL_TRANS_NO_FW;
|
||||
}
|
||||
|
||||
static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
|
||||
enum iwl_rxon_context_id ctx,
|
||||
const char *msg)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
trans->ops->wake_any_queue(trans, ctx, msg);
|
||||
}
|
||||
|
||||
@ -312,6 +405,9 @@ static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
|
||||
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
|
||||
struct iwl_host_cmd *cmd)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
return trans->ops->send_cmd(trans, cmd);
|
||||
}
|
||||
|
||||
@ -322,6 +418,9 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
||||
u8 sta_id, u8 tid)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id, tid);
|
||||
}
|
||||
|
||||
@ -329,6 +428,9 @@ static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
|
||||
int tid, int txq_id, int ssn, u32 status,
|
||||
struct sk_buff_head *skbs)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn,
|
||||
status, skbs);
|
||||
}
|
||||
@ -336,12 +438,22 @@ static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
|
||||
static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
|
||||
int sta_id, int tid)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
return trans->ops->tx_agg_disable(trans, sta_id, tid);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans,
|
||||
int sta_id, int tid)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
return trans->ops->tx_agg_alloc(trans, sta_id, tid);
|
||||
}
|
||||
|
||||
@ -351,6 +463,11 @@ static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans,
|
||||
int sta_id, int tid,
|
||||
int frame_limit, u16 ssn)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn);
|
||||
}
|
||||
|
||||
@ -362,16 +479,25 @@ static inline void iwl_trans_free(struct iwl_trans *trans)
|
||||
static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q,
|
||||
const char *msg)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
trans->ops->stop_queue(trans, q, msg);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
return trans->ops->wait_tx_queue_empty(trans);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_check_stuck_queue(struct iwl_trans *trans, int q)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
return trans->ops->check_stuck_queue(trans, q);
|
||||
}
|
||||
static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
|
||||
@ -410,8 +536,6 @@ static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs)
|
||||
/*****************************************************
|
||||
* Utils functions
|
||||
******************************************************/
|
||||
void iwl_dealloc_ucode(struct iwl_trans *trans);
|
||||
|
||||
int iwl_send_calib_results(struct iwl_trans *trans);
|
||||
int iwl_calib_set(struct iwl_trans *trans,
|
||||
const struct iwl_calib_hdr *cmd, int len);
|
||||
|
@ -82,29 +82,29 @@ static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void iwl_free_fw_desc(struct iwl_trans *trans, struct fw_desc *desc)
|
||||
static void iwl_free_fw_desc(struct iwl_nic *nic, struct fw_desc *desc)
|
||||
{
|
||||
if (desc->v_addr)
|
||||
dma_free_coherent(trans->dev, desc->len,
|
||||
dma_free_coherent(trans(nic)->dev, desc->len,
|
||||
desc->v_addr, desc->p_addr);
|
||||
desc->v_addr = NULL;
|
||||
desc->len = 0;
|
||||
}
|
||||
|
||||
static void iwl_free_fw_img(struct iwl_trans *trans, struct fw_img *img)
|
||||
static void iwl_free_fw_img(struct iwl_nic *nic, struct fw_img *img)
|
||||
{
|
||||
iwl_free_fw_desc(trans, &img->code);
|
||||
iwl_free_fw_desc(trans, &img->data);
|
||||
iwl_free_fw_desc(nic, &img->code);
|
||||
iwl_free_fw_desc(nic, &img->data);
|
||||
}
|
||||
|
||||
void iwl_dealloc_ucode(struct iwl_trans *trans)
|
||||
void iwl_dealloc_ucode(struct iwl_nic *nic)
|
||||
{
|
||||
iwl_free_fw_img(trans, &trans->ucode_rt);
|
||||
iwl_free_fw_img(trans, &trans->ucode_init);
|
||||
iwl_free_fw_img(trans, &trans->ucode_wowlan);
|
||||
iwl_free_fw_img(nic, &nic->fw.ucode_rt);
|
||||
iwl_free_fw_img(nic, &nic->fw.ucode_init);
|
||||
iwl_free_fw_img(nic, &nic->fw.ucode_wowlan);
|
||||
}
|
||||
|
||||
static int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc,
|
||||
static int iwl_alloc_fw_desc(struct iwl_nic *nic, struct fw_desc *desc,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
if (!len) {
|
||||
@ -112,7 +112,7 @@ static int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
desc->v_addr = dma_alloc_coherent(trans->dev, len,
|
||||
desc->v_addr = dma_alloc_coherent(trans(nic)->dev, len,
|
||||
&desc->p_addr, GFP_KERNEL);
|
||||
if (!desc->v_addr)
|
||||
return -ENOMEM;
|
||||
@ -122,16 +122,16 @@ static int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
|
||||
static inline struct fw_img *iwl_get_ucode_image(struct iwl_nic *nic,
|
||||
enum iwl_ucode_type ucode_type)
|
||||
{
|
||||
switch (ucode_type) {
|
||||
case IWL_UCODE_INIT:
|
||||
return &trans->ucode_init;
|
||||
return &nic->fw.ucode_init;
|
||||
case IWL_UCODE_WOWLAN:
|
||||
return &trans->ucode_wowlan;
|
||||
return &nic->fw.ucode_wowlan;
|
||||
case IWL_UCODE_REGULAR:
|
||||
return &trans->ucode_rt;
|
||||
return &nic->fw.ucode_rt;
|
||||
case IWL_UCODE_NONE:
|
||||
break;
|
||||
}
|
||||
@ -397,15 +397,16 @@ static int iwl_alive_notify(struct iwl_trans *trans)
|
||||
* using sample data 100 bytes apart. If these sample points are good,
|
||||
* it's a pretty good bet that everything between them is good, too.
|
||||
*/
|
||||
static int iwl_verify_inst_sparse(struct iwl_trans *trans,
|
||||
static int iwl_verify_inst_sparse(struct iwl_nic *nic,
|
||||
struct fw_desc *fw_desc)
|
||||
{
|
||||
struct iwl_trans *trans = trans(nic);
|
||||
__le32 *image = (__le32 *)fw_desc->v_addr;
|
||||
u32 len = fw_desc->len;
|
||||
u32 val;
|
||||
u32 i;
|
||||
|
||||
IWL_DEBUG_FW(trans, "ucode inst image size is %u\n", len);
|
||||
IWL_DEBUG_FW(nic, "ucode inst image size is %u\n", len);
|
||||
|
||||
for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
|
||||
/* read data comes through single port, auto-incr addr */
|
||||
@ -421,16 +422,17 @@ static int iwl_verify_inst_sparse(struct iwl_trans *trans,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_print_mismatch_inst(struct iwl_trans *trans,
|
||||
static void iwl_print_mismatch_inst(struct iwl_nic *nic,
|
||||
struct fw_desc *fw_desc)
|
||||
{
|
||||
struct iwl_trans *trans = trans(nic);
|
||||
__le32 *image = (__le32 *)fw_desc->v_addr;
|
||||
u32 len = fw_desc->len;
|
||||
u32 val;
|
||||
u32 offs;
|
||||
int errors = 0;
|
||||
|
||||
IWL_DEBUG_FW(trans, "ucode inst image size is %u\n", len);
|
||||
IWL_DEBUG_FW(nic, "ucode inst image size is %u\n", len);
|
||||
|
||||
iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR,
|
||||
IWLAGN_RTC_INST_LOWER_BOUND);
|
||||
@ -441,7 +443,7 @@ static void iwl_print_mismatch_inst(struct iwl_trans *trans,
|
||||
/* read data comes through single port, auto-incr addr */
|
||||
val = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
if (val != le32_to_cpu(*image)) {
|
||||
IWL_ERR(trans, "uCode INST section at "
|
||||
IWL_ERR(nic, "uCode INST section at "
|
||||
"offset 0x%x, is 0x%x, s/b 0x%x\n",
|
||||
offs, val, le32_to_cpu(*image));
|
||||
errors++;
|
||||
@ -453,24 +455,24 @@ static void iwl_print_mismatch_inst(struct iwl_trans *trans,
|
||||
* iwl_verify_ucode - determine which instruction image is in SRAM,
|
||||
* and verify its contents
|
||||
*/
|
||||
static int iwl_verify_ucode(struct iwl_trans *trans,
|
||||
static int iwl_verify_ucode(struct iwl_nic *nic,
|
||||
enum iwl_ucode_type ucode_type)
|
||||
{
|
||||
struct fw_img *img = iwl_get_ucode_image(trans, ucode_type);
|
||||
struct fw_img *img = iwl_get_ucode_image(nic, ucode_type);
|
||||
|
||||
if (!img) {
|
||||
IWL_ERR(trans, "Invalid ucode requested (%d)\n", ucode_type);
|
||||
IWL_ERR(nic, "Invalid ucode requested (%d)\n", ucode_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!iwl_verify_inst_sparse(trans, &img->code)) {
|
||||
IWL_DEBUG_FW(trans, "uCode is good in inst SRAM\n");
|
||||
if (!iwl_verify_inst_sparse(nic, &img->code)) {
|
||||
IWL_DEBUG_FW(nic, "uCode is good in inst SRAM\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
IWL_ERR(trans, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
|
||||
IWL_ERR(nic, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
|
||||
|
||||
iwl_print_mismatch_inst(trans, &img->code);
|
||||
iwl_print_mismatch_inst(nic, &img->code);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@ -583,7 +585,7 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
|
||||
|
||||
old_type = trans->shrd->ucode_type;
|
||||
trans->shrd->ucode_type = ucode_type;
|
||||
fw = iwl_get_ucode_image(trans, ucode_type);
|
||||
fw = iwl_get_ucode_image(nic(trans), ucode_type);
|
||||
|
||||
if (!fw)
|
||||
return -EINVAL;
|
||||
@ -618,7 +620,7 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
|
||||
* skip it for WoWLAN.
|
||||
*/
|
||||
if (ucode_type != IWL_UCODE_WOWLAN) {
|
||||
ret = iwl_verify_ucode(trans, ucode_type);
|
||||
ret = iwl_verify_ucode(nic(trans), ucode_type);
|
||||
if (ret) {
|
||||
trans->shrd->ucode_type = old_type;
|
||||
return ret;
|
||||
@ -647,7 +649,7 @@ int iwl_run_init_ucode(struct iwl_trans *trans)
|
||||
lockdep_assert_held(&trans->shrd->mutex);
|
||||
|
||||
/* No init ucode required? Curious, but maybe ok */
|
||||
if (!trans->ucode_init.code.len)
|
||||
if (!nic(trans)->fw.ucode_init.code.len)
|
||||
return 0;
|
||||
|
||||
if (trans->shrd->ucode_type != IWL_UCODE_NONE)
|
||||
@ -688,39 +690,40 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
|
||||
#define UCODE_EXPERIMENTAL_INDEX 100
|
||||
#define UCODE_EXPERIMENTAL_TAG "exp"
|
||||
|
||||
int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
|
||||
int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first)
|
||||
{
|
||||
const char *name_pre = cfg(priv)->fw_name_pre;
|
||||
struct iwl_cfg *cfg = cfg(nic);
|
||||
const char *name_pre = cfg->fw_name_pre;
|
||||
char tag[8];
|
||||
|
||||
if (first) {
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
|
||||
priv->fw_index = UCODE_EXPERIMENTAL_INDEX;
|
||||
nic->fw_index = UCODE_EXPERIMENTAL_INDEX;
|
||||
strcpy(tag, UCODE_EXPERIMENTAL_TAG);
|
||||
} else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
|
||||
} else if (nic->fw_index == UCODE_EXPERIMENTAL_INDEX) {
|
||||
#endif
|
||||
priv->fw_index = cfg(priv)->ucode_api_max;
|
||||
sprintf(tag, "%d", priv->fw_index);
|
||||
nic->fw_index = cfg->ucode_api_max;
|
||||
sprintf(tag, "%d", nic->fw_index);
|
||||
} else {
|
||||
priv->fw_index--;
|
||||
sprintf(tag, "%d", priv->fw_index);
|
||||
nic->fw_index--;
|
||||
sprintf(tag, "%d", nic->fw_index);
|
||||
}
|
||||
|
||||
if (priv->fw_index < cfg(priv)->ucode_api_min) {
|
||||
IWL_ERR(priv, "no suitable firmware found!\n");
|
||||
if (nic->fw_index < cfg->ucode_api_min) {
|
||||
IWL_ERR(nic, "no suitable firmware found!\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
|
||||
sprintf(nic->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
|
||||
|
||||
IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n",
|
||||
(priv->fw_index == UCODE_EXPERIMENTAL_INDEX)
|
||||
IWL_DEBUG_INFO(nic, "attempting to load firmware %s'%s'\n",
|
||||
(nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
|
||||
? "EXPERIMENTAL " : "",
|
||||
priv->firmware_name);
|
||||
nic->firmware_name);
|
||||
|
||||
return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
|
||||
trans(priv)->dev,
|
||||
GFP_KERNEL, priv, iwl_ucode_callback);
|
||||
return request_firmware_nowait(THIS_MODULE, 1, nic->firmware_name,
|
||||
trans(nic)->dev,
|
||||
GFP_KERNEL, nic, iwl_ucode_callback);
|
||||
}
|
||||
|
||||
struct iwlagn_firmware_pieces {
|
||||
@ -734,7 +737,7 @@ struct iwlagn_firmware_pieces {
|
||||
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
|
||||
};
|
||||
|
||||
static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
|
||||
static int iwl_parse_v1_v2_firmware(struct iwl_nic *nic,
|
||||
const struct firmware *ucode_raw,
|
||||
struct iwlagn_firmware_pieces *pieces)
|
||||
{
|
||||
@ -742,14 +745,14 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
|
||||
u32 api_ver, hdr_size;
|
||||
const u8 *src;
|
||||
|
||||
priv->ucode_ver = le32_to_cpu(ucode->ver);
|
||||
api_ver = IWL_UCODE_API(priv->ucode_ver);
|
||||
nic->fw.ucode_ver = le32_to_cpu(ucode->ver);
|
||||
api_ver = IWL_UCODE_API(nic->fw.ucode_ver);
|
||||
|
||||
switch (api_ver) {
|
||||
default:
|
||||
hdr_size = 28;
|
||||
if (ucode_raw->size < hdr_size) {
|
||||
IWL_ERR(priv, "File size too small!\n");
|
||||
IWL_ERR(nic, "File size too small!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
pieces->build = le32_to_cpu(ucode->u.v2.build);
|
||||
@ -764,7 +767,7 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
|
||||
case 2:
|
||||
hdr_size = 24;
|
||||
if (ucode_raw->size < hdr_size) {
|
||||
IWL_ERR(priv, "File size too small!\n");
|
||||
IWL_ERR(nic, "File size too small!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
pieces->build = 0;
|
||||
@ -781,7 +784,7 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
|
||||
pieces->data_size + pieces->init_size +
|
||||
pieces->init_data_size) {
|
||||
|
||||
IWL_ERR(priv,
|
||||
IWL_ERR(nic,
|
||||
"uCode file size %d does not match expected size\n",
|
||||
(int)ucode_raw->size);
|
||||
return -EINVAL;
|
||||
@ -799,10 +802,10 @@ static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwlagn_load_firmware(struct iwl_priv *priv,
|
||||
static int iwl_parse_tlv_firmware(struct iwl_nic *nic,
|
||||
const struct firmware *ucode_raw,
|
||||
struct iwlagn_firmware_pieces *pieces,
|
||||
struct iwlagn_ucode_capabilities *capa)
|
||||
struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
|
||||
struct iwl_ucode_tlv *tlv;
|
||||
@ -816,12 +819,12 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
|
||||
const u8 *tlv_data;
|
||||
|
||||
if (len < sizeof(*ucode)) {
|
||||
IWL_ERR(priv, "uCode has invalid length: %zd\n", len);
|
||||
IWL_ERR(nic, "uCode has invalid length: %zd\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) {
|
||||
IWL_ERR(priv, "invalid uCode magic: 0X%x\n",
|
||||
IWL_ERR(nic, "invalid uCode magic: 0X%x\n",
|
||||
le32_to_cpu(ucode->magic));
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -839,11 +842,11 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
|
||||
while (wanted_alternative && !(alternatives & BIT(wanted_alternative)))
|
||||
wanted_alternative--;
|
||||
if (wanted_alternative && wanted_alternative != tmp)
|
||||
IWL_WARN(priv,
|
||||
IWL_WARN(nic,
|
||||
"uCode alternative %d not available, choosing %d\n",
|
||||
tmp, wanted_alternative);
|
||||
|
||||
priv->ucode_ver = le32_to_cpu(ucode->ver);
|
||||
nic->fw.ucode_ver = le32_to_cpu(ucode->ver);
|
||||
pieces->build = le32_to_cpu(ucode->build);
|
||||
data = ucode->data;
|
||||
|
||||
@ -861,7 +864,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
|
||||
tlv_data = tlv->data;
|
||||
|
||||
if (len < tlv_len) {
|
||||
IWL_ERR(priv, "invalid TLV len: %zd/%u\n",
|
||||
IWL_ERR(nic, "invalid TLV len: %zd/%u\n",
|
||||
len, tlv_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -894,7 +897,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
|
||||
pieces->init_data_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_BOOT:
|
||||
IWL_ERR(priv, "Found unexpected BOOT ucode\n");
|
||||
IWL_ERR(nic, "Found unexpected BOOT ucode\n");
|
||||
break;
|
||||
case IWL_UCODE_TLV_PROBE_MAX_LEN:
|
||||
if (tlv_len != sizeof(u32))
|
||||
@ -962,7 +965,7 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
|
||||
case IWL_UCODE_TLV_ENHANCE_SENS_TBL:
|
||||
if (tlv_len)
|
||||
goto invalid_tlv_len;
|
||||
priv->enhance_sensitivity_table = true;
|
||||
nic->fw.enhance_sensitivity_table = true;
|
||||
break;
|
||||
case IWL_UCODE_TLV_WOWLAN_INST:
|
||||
pieces->wowlan_inst = tlv_data;
|
||||
@ -979,22 +982,22 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_INFO(priv, "unknown TLV: %d\n", tlv_type);
|
||||
IWL_DEBUG_INFO(nic, "unknown TLV: %d\n", tlv_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len) {
|
||||
IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len);
|
||||
iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len);
|
||||
IWL_ERR(nic, "invalid TLV after parsing: %zd\n", len);
|
||||
iwl_print_hex_dump(nic, IWL_DL_FW, (u8 *)data, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
invalid_tlv_len:
|
||||
IWL_ERR(priv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
|
||||
iwl_print_hex_dump(priv, IWL_DL_FW, tlv_data, tlv_len);
|
||||
IWL_ERR(nic, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
|
||||
iwl_print_hex_dump(nic, IWL_DL_FW, tlv_data, tlv_len);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1007,21 +1010,23 @@ static int iwlagn_load_firmware(struct iwl_priv *priv,
|
||||
*/
|
||||
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
{
|
||||
struct iwl_priv *priv = context;
|
||||
struct iwl_nic *nic = context;
|
||||
struct iwl_cfg *cfg = cfg(nic);
|
||||
struct iwl_fw *fw = &nic->fw;
|
||||
struct iwl_priv *priv = priv(nic); /* temporary */
|
||||
struct iwl_ucode_header *ucode;
|
||||
int err;
|
||||
struct iwlagn_firmware_pieces pieces;
|
||||
const unsigned int api_max = cfg(priv)->ucode_api_max;
|
||||
unsigned int api_ok = cfg(priv)->ucode_api_ok;
|
||||
const unsigned int api_min = cfg(priv)->ucode_api_min;
|
||||
const unsigned int api_max = cfg->ucode_api_max;
|
||||
unsigned int api_ok = cfg->ucode_api_ok;
|
||||
const unsigned int api_min = cfg->ucode_api_min;
|
||||
u32 api_ver;
|
||||
char buildstr[25];
|
||||
u32 build;
|
||||
struct iwlagn_ucode_capabilities ucode_capa = {
|
||||
.max_probe_length = 200,
|
||||
.standard_phy_calibration_size =
|
||||
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE,
|
||||
};
|
||||
|
||||
fw->ucode_capa.max_probe_length = 200;
|
||||
fw->ucode_capa.standard_phy_calibration_size =
|
||||
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
|
||||
|
||||
if (!api_ok)
|
||||
api_ok = api_max;
|
||||
@ -1029,19 +1034,19 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
memset(&pieces, 0, sizeof(pieces));
|
||||
|
||||
if (!ucode_raw) {
|
||||
if (priv->fw_index <= api_ok)
|
||||
IWL_ERR(priv,
|
||||
if (nic->fw_index <= api_ok)
|
||||
IWL_ERR(nic,
|
||||
"request for firmware file '%s' failed.\n",
|
||||
priv->firmware_name);
|
||||
nic->firmware_name);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n",
|
||||
priv->firmware_name, ucode_raw->size);
|
||||
IWL_DEBUG_INFO(nic, "Loaded firmware file '%s' (%zd bytes).\n",
|
||||
nic->firmware_name, ucode_raw->size);
|
||||
|
||||
/* Make sure that we got at least the API version number */
|
||||
if (ucode_raw->size < 4) {
|
||||
IWL_ERR(priv, "File size way too small!\n");
|
||||
IWL_ERR(nic, "File size way too small!\n");
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
@ -1049,15 +1054,15 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
ucode = (struct iwl_ucode_header *)ucode_raw->data;
|
||||
|
||||
if (ucode->ver)
|
||||
err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces);
|
||||
err = iwl_parse_v1_v2_firmware(nic, ucode_raw, &pieces);
|
||||
else
|
||||
err = iwlagn_load_firmware(priv, ucode_raw, &pieces,
|
||||
&ucode_capa);
|
||||
err = iwl_parse_tlv_firmware(nic, ucode_raw, &pieces,
|
||||
&fw->ucode_capa);
|
||||
|
||||
if (err)
|
||||
goto try_again;
|
||||
|
||||
api_ver = IWL_UCODE_API(priv->ucode_ver);
|
||||
api_ver = IWL_UCODE_API(nic->fw.ucode_ver);
|
||||
build = pieces.build;
|
||||
|
||||
/*
|
||||
@ -1066,9 +1071,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
* on the API version read from firmware header from here on forward
|
||||
*/
|
||||
/* no api version check required for experimental uCode */
|
||||
if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) {
|
||||
if (nic->fw_index != UCODE_EXPERIMENTAL_INDEX) {
|
||||
if (api_ver < api_min || api_ver > api_max) {
|
||||
IWL_ERR(priv,
|
||||
IWL_ERR(nic,
|
||||
"Driver unable to support your firmware API. "
|
||||
"Driver supports v%u, firmware is v%u.\n",
|
||||
api_max, api_ver);
|
||||
@ -1077,39 +1082,39 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
|
||||
if (api_ver < api_ok) {
|
||||
if (api_ok != api_max)
|
||||
IWL_ERR(priv, "Firmware has old API version, "
|
||||
IWL_ERR(nic, "Firmware has old API version, "
|
||||
"expected v%u through v%u, got v%u.\n",
|
||||
api_ok, api_max, api_ver);
|
||||
else
|
||||
IWL_ERR(priv, "Firmware has old API version, "
|
||||
IWL_ERR(nic, "Firmware has old API version, "
|
||||
"expected v%u, got v%u.\n",
|
||||
api_max, api_ver);
|
||||
IWL_ERR(priv, "New firmware can be obtained from "
|
||||
IWL_ERR(nic, "New firmware can be obtained from "
|
||||
"http://www.intellinuxwireless.org/.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (build)
|
||||
sprintf(buildstr, " build %u%s", build,
|
||||
(priv->fw_index == UCODE_EXPERIMENTAL_INDEX)
|
||||
(nic->fw_index == UCODE_EXPERIMENTAL_INDEX)
|
||||
? " (EXP)" : "");
|
||||
else
|
||||
buildstr[0] = '\0';
|
||||
|
||||
IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n",
|
||||
IWL_UCODE_MAJOR(priv->ucode_ver),
|
||||
IWL_UCODE_MINOR(priv->ucode_ver),
|
||||
IWL_UCODE_API(priv->ucode_ver),
|
||||
IWL_UCODE_SERIAL(priv->ucode_ver),
|
||||
IWL_INFO(nic, "loaded firmware version %u.%u.%u.%u%s\n",
|
||||
IWL_UCODE_MAJOR(nic->fw.ucode_ver),
|
||||
IWL_UCODE_MINOR(nic->fw.ucode_ver),
|
||||
IWL_UCODE_API(nic->fw.ucode_ver),
|
||||
IWL_UCODE_SERIAL(nic->fw.ucode_ver),
|
||||
buildstr);
|
||||
|
||||
snprintf(priv->hw->wiphy->fw_version,
|
||||
sizeof(priv->hw->wiphy->fw_version),
|
||||
"%u.%u.%u.%u%s",
|
||||
IWL_UCODE_MAJOR(priv->ucode_ver),
|
||||
IWL_UCODE_MINOR(priv->ucode_ver),
|
||||
IWL_UCODE_API(priv->ucode_ver),
|
||||
IWL_UCODE_SERIAL(priv->ucode_ver),
|
||||
IWL_UCODE_MAJOR(nic->fw.ucode_ver),
|
||||
IWL_UCODE_MINOR(nic->fw.ucode_ver),
|
||||
IWL_UCODE_API(nic->fw.ucode_ver),
|
||||
IWL_UCODE_SERIAL(nic->fw.ucode_ver),
|
||||
buildstr);
|
||||
|
||||
/*
|
||||
@ -1118,38 +1123,38 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
* user just got a corrupted version of the latest API.
|
||||
*/
|
||||
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
|
||||
priv->ucode_ver);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n",
|
||||
IWL_DEBUG_INFO(nic, "f/w package hdr ucode version raw = 0x%x\n",
|
||||
nic->fw.ucode_ver);
|
||||
IWL_DEBUG_INFO(nic, "f/w package hdr runtime inst size = %Zd\n",
|
||||
pieces.inst_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n",
|
||||
IWL_DEBUG_INFO(nic, "f/w package hdr runtime data size = %Zd\n",
|
||||
pieces.data_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n",
|
||||
IWL_DEBUG_INFO(nic, "f/w package hdr init inst size = %Zd\n",
|
||||
pieces.init_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n",
|
||||
IWL_DEBUG_INFO(nic, "f/w package hdr init data size = %Zd\n",
|
||||
pieces.init_data_size);
|
||||
|
||||
/* Verify that uCode images will fit in card's SRAM */
|
||||
if (pieces.inst_size > hw_params(priv).max_inst_size) {
|
||||
IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n",
|
||||
if (pieces.inst_size > cfg->max_inst_size) {
|
||||
IWL_ERR(nic, "uCode instr len %Zd too large to fit in\n",
|
||||
pieces.inst_size);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (pieces.data_size > hw_params(priv).max_data_size) {
|
||||
IWL_ERR(priv, "uCode data len %Zd too large to fit in\n",
|
||||
if (pieces.data_size > cfg->max_data_size) {
|
||||
IWL_ERR(nic, "uCode data len %Zd too large to fit in\n",
|
||||
pieces.data_size);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (pieces.init_size > hw_params(priv).max_inst_size) {
|
||||
IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n",
|
||||
if (pieces.init_size > cfg->max_inst_size) {
|
||||
IWL_ERR(nic, "uCode init instr len %Zd too large to fit in\n",
|
||||
pieces.init_size);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (pieces.init_data_size > hw_params(priv).max_data_size) {
|
||||
IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n",
|
||||
if (pieces.init_data_size > cfg->max_data_size) {
|
||||
IWL_ERR(nic, "uCode init data len %Zd too large to fit in\n",
|
||||
pieces.init_data_size);
|
||||
goto try_again;
|
||||
}
|
||||
@ -1159,34 +1164,34 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
/* Runtime instructions and 2 copies of data:
|
||||
* 1) unmodified from disk
|
||||
* 2) backup cache for save/restore during power-downs */
|
||||
if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.code,
|
||||
if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.code,
|
||||
pieces.inst, pieces.inst_size))
|
||||
goto err_pci_alloc;
|
||||
if (iwl_alloc_fw_desc(trans(priv), &trans(priv)->ucode_rt.data,
|
||||
if (iwl_alloc_fw_desc(nic, &nic->fw.ucode_rt.data,
|
||||
pieces.data, pieces.data_size))
|
||||
goto err_pci_alloc;
|
||||
|
||||
/* Initialization instructions and data */
|
||||
if (pieces.init_size && pieces.init_data_size) {
|
||||
if (iwl_alloc_fw_desc(trans(priv),
|
||||
&trans(priv)->ucode_init.code,
|
||||
if (iwl_alloc_fw_desc(nic,
|
||||
&nic->fw.ucode_init.code,
|
||||
pieces.init, pieces.init_size))
|
||||
goto err_pci_alloc;
|
||||
if (iwl_alloc_fw_desc(trans(priv),
|
||||
&trans(priv)->ucode_init.data,
|
||||
if (iwl_alloc_fw_desc(nic,
|
||||
&nic->fw.ucode_init.data,
|
||||
pieces.init_data, pieces.init_data_size))
|
||||
goto err_pci_alloc;
|
||||
}
|
||||
|
||||
/* WoWLAN instructions and data */
|
||||
if (pieces.wowlan_inst_size && pieces.wowlan_data_size) {
|
||||
if (iwl_alloc_fw_desc(trans(priv),
|
||||
&trans(priv)->ucode_wowlan.code,
|
||||
if (iwl_alloc_fw_desc(nic,
|
||||
&nic->fw.ucode_wowlan.code,
|
||||
pieces.wowlan_inst,
|
||||
pieces.wowlan_inst_size))
|
||||
goto err_pci_alloc;
|
||||
if (iwl_alloc_fw_desc(trans(priv),
|
||||
&trans(priv)->ucode_wowlan.data,
|
||||
if (iwl_alloc_fw_desc(nic,
|
||||
&nic->fw.ucode_wowlan.data,
|
||||
pieces.wowlan_data,
|
||||
pieces.wowlan_data_size))
|
||||
goto err_pci_alloc;
|
||||
@ -1199,92 +1204,94 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
* for each event, which is of mode 1 (including timestamp) for all
|
||||
* new microcodes that include this information.
|
||||
*/
|
||||
priv->init_evtlog_ptr = pieces.init_evtlog_ptr;
|
||||
nic->init_evtlog_ptr = pieces.init_evtlog_ptr;
|
||||
if (pieces.init_evtlog_size)
|
||||
priv->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
|
||||
nic->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
|
||||
else
|
||||
priv->init_evtlog_size =
|
||||
cfg(priv)->base_params->max_event_log_size;
|
||||
priv->init_errlog_ptr = pieces.init_errlog_ptr;
|
||||
priv->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
|
||||
nic->init_evtlog_size =
|
||||
cfg->base_params->max_event_log_size;
|
||||
nic->init_errlog_ptr = pieces.init_errlog_ptr;
|
||||
nic->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
|
||||
if (pieces.inst_evtlog_size)
|
||||
priv->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
|
||||
nic->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
|
||||
else
|
||||
priv->inst_evtlog_size =
|
||||
cfg(priv)->base_params->max_event_log_size;
|
||||
priv->inst_errlog_ptr = pieces.inst_errlog_ptr;
|
||||
nic->inst_evtlog_size =
|
||||
cfg->base_params->max_event_log_size;
|
||||
nic->inst_errlog_ptr = pieces.inst_errlog_ptr;
|
||||
#ifndef CONFIG_IWLWIFI_P2P
|
||||
ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
||||
fw->ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
||||
#endif
|
||||
|
||||
priv->new_scan_threshold_behaviour =
|
||||
!!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
|
||||
!!(fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
|
||||
|
||||
if (!(cfg(priv)->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
|
||||
ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
||||
if (!(cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
|
||||
fw->ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
||||
|
||||
/*
|
||||
* if not PAN, then don't support P2P -- might be a uCode
|
||||
* packaging bug or due to the eeprom check above
|
||||
*/
|
||||
if (!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN))
|
||||
ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
|
||||
if (!(fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN))
|
||||
fw->ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
|
||||
|
||||
if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
|
||||
if (fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
|
||||
priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
|
||||
nic->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
|
||||
} else {
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM;
|
||||
priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
|
||||
nic->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
|
||||
}
|
||||
/*
|
||||
* figure out the offset of chain noise reset and gain commands
|
||||
* base on the size of standard phy calibration commands table size
|
||||
*/
|
||||
if (ucode_capa.standard_phy_calibration_size >
|
||||
if (fw->ucode_capa.standard_phy_calibration_size >
|
||||
IWL_MAX_PHY_CALIBRATE_TBL_SIZE)
|
||||
ucode_capa.standard_phy_calibration_size =
|
||||
fw->ucode_capa.standard_phy_calibration_size =
|
||||
IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
|
||||
|
||||
priv->phy_calib_chain_noise_reset_cmd =
|
||||
ucode_capa.standard_phy_calibration_size;
|
||||
fw->ucode_capa.standard_phy_calibration_size;
|
||||
priv->phy_calib_chain_noise_gain_cmd =
|
||||
ucode_capa.standard_phy_calibration_size + 1;
|
||||
fw->ucode_capa.standard_phy_calibration_size + 1;
|
||||
|
||||
/* initialize all valid contexts */
|
||||
iwl_init_context(priv, ucode_capa.flags);
|
||||
iwl_init_context(priv, fw->ucode_capa.flags);
|
||||
|
||||
/**************************************************
|
||||
* This is still part of probe() in a sense...
|
||||
*
|
||||
* 9. Setup and register with mac80211 and debugfs
|
||||
**************************************************/
|
||||
err = iwlagn_mac_setup_register(priv, &ucode_capa);
|
||||
err = iwlagn_mac_setup_register(priv, &fw->ucode_capa);
|
||||
if (err)
|
||||
goto out_unbind;
|
||||
|
||||
err = iwl_dbgfs_register(priv, DRV_NAME);
|
||||
if (err)
|
||||
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
|
||||
IWL_ERR(nic,
|
||||
"failed to create debugfs files. Ignoring error: %d\n",
|
||||
err);
|
||||
|
||||
/* We have our copies now, allow OS release its copies */
|
||||
release_firmware(ucode_raw);
|
||||
complete(&priv->firmware_loading_complete);
|
||||
complete(&nic->request_firmware_complete);
|
||||
return;
|
||||
|
||||
try_again:
|
||||
/* try next, if any */
|
||||
if (iwl_request_firmware(priv, false))
|
||||
if (iwl_request_firmware(nic, false))
|
||||
goto out_unbind;
|
||||
release_firmware(ucode_raw);
|
||||
return;
|
||||
|
||||
err_pci_alloc:
|
||||
IWL_ERR(priv, "failed to allocate pci memory\n");
|
||||
iwl_dealloc_ucode(trans(priv));
|
||||
IWL_ERR(nic, "failed to allocate pci memory\n");
|
||||
iwl_dealloc_ucode(nic);
|
||||
out_unbind:
|
||||
complete(&priv->firmware_loading_complete);
|
||||
device_release_driver(trans(priv)->dev);
|
||||
complete(&nic->request_firmware_complete);
|
||||
device_release_driver(trans(nic)->dev);
|
||||
release_firmware(ucode_raw);
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,8 @@
|
||||
#ifndef __iwl_ucode_h__
|
||||
#define __iwl_ucode_h__
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
/* v1/v2 uCode file layout */
|
||||
struct iwl_ucode_header {
|
||||
__le32 ver; /* major/minor/API/serial */
|
||||
@ -171,8 +173,49 @@ struct iwl_tlv_ucode_header {
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
struct iwl_priv;
|
||||
struct iwl_ucode_capabilities {
|
||||
u32 max_probe_length;
|
||||
u32 standard_phy_calibration_size;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first);
|
||||
/* 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 {
|
||||
|
||||
/* ucode image and variables */
|
||||
u32 ucode_ver; /* version of ucode, copy of
|
||||
iwl_ucode.ver */
|
||||
char fw_version[ETHTOOL_BUSINFO_LEN];
|
||||
|
||||
/* ucode images */
|
||||
struct fw_img ucode_rt;
|
||||
struct fw_img ucode_init;
|
||||
struct fw_img ucode_wowlan;
|
||||
|
||||
struct iwl_ucode_capabilities ucode_capa;
|
||||
bool enhance_sensitivity_table;
|
||||
};
|
||||
|
||||
#endif /* __iwl_ucode_h__ */
|
||||
|
@ -64,6 +64,39 @@
|
||||
#define __iwl_wifi_h__
|
||||
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-ucode.h"
|
||||
|
||||
/**
|
||||
* struct iwl_nic - nic common data
|
||||
* @fw: the iwl_fw structure
|
||||
* @shrd: pointer to common shared structure
|
||||
* @fw_index: firmware revision to try loading
|
||||
* @firmware_name: composite filename of ucode file to load
|
||||
* @init_evtlog_ptr: event log offset for init ucode.
|
||||
* @init_evtlog_size: event log size for init ucode.
|
||||
* @init_errlog_ptr: error log offfset for init ucode.
|
||||
* @inst_evtlog_ptr: event log offset for runtime ucode.
|
||||
* @inst_evtlog_size: event log size for runtime ucode.
|
||||
* @inst_errlog_ptr: error log offfset for runtime ucode.
|
||||
* @request_firmware_complete: the firmware has been obtained from user space
|
||||
*/
|
||||
struct iwl_nic {
|
||||
struct iwl_fw fw;
|
||||
|
||||
struct iwl_shared *shrd;
|
||||
|
||||
int fw_index; /* firmware we're trying to load */
|
||||
char firmware_name[25]; /* name of firmware file to load */
|
||||
|
||||
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
|
||||
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
|
||||
|
||||
struct completion request_firmware_complete;
|
||||
};
|
||||
|
||||
|
||||
int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first);
|
||||
void iwl_dealloc_ucode(struct iwl_nic *nic);
|
||||
|
||||
int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type);
|
||||
void iwl_send_prio_tbl(struct iwl_trans *trans);
|
||||
|
Loading…
Reference in New Issue
Block a user