|
@@ -44,15 +44,19 @@
|
|
|
|
|
|
#include <asm/div64.h>
|
|
|
|
|
|
-#include "iwl-eeprom.h"
|
|
|
-#include "iwl-dev.h"
|
|
|
+#include "iwl-eeprom-read.h"
|
|
|
+#include "iwl-eeprom-parse.h"
|
|
|
#include "iwl-io.h"
|
|
|
-#include "iwl-agn-calib.h"
|
|
|
-#include "iwl-agn.h"
|
|
|
#include "iwl-trans.h"
|
|
|
#include "iwl-op-mode.h"
|
|
|
#include "iwl-drv.h"
|
|
|
#include "iwl-modparams.h"
|
|
|
+#include "iwl-prph.h"
|
|
|
+
|
|
|
+#include "dev.h"
|
|
|
+#include "calib.h"
|
|
|
+#include "agn.h"
|
|
|
+
|
|
|
|
|
|
/******************************************************************************
|
|
|
*
|
|
@@ -79,6 +83,8 @@ MODULE_VERSION(DRV_VERSION);
|
|
|
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
|
|
+static const struct iwl_op_mode_ops iwl_dvm_ops;
|
|
|
+
|
|
|
void iwl_update_chain_flags(struct iwl_priv *priv)
|
|
|
{
|
|
|
struct iwl_rxon_context *ctx;
|
|
@@ -179,7 +185,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
|
|
|
rate = info->control.rates[0].idx;
|
|
|
|
|
|
priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant,
|
|
|
- priv->hw_params.valid_tx_ant);
|
|
|
+ priv->eeprom_data->valid_tx_ant);
|
|
|
rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
|
|
|
|
|
|
/* In mac80211, rates for 5 GHz start at 0 */
|
|
@@ -402,7 +408,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
|
|
|
|
|
|
base = priv->device_pointers.log_event_table;
|
|
|
if (iwlagn_hw_valid_rtc_data_addr(base)) {
|
|
|
- iwl_read_targ_mem_words(priv->trans, base, &read, sizeof(read));
|
|
|
+ iwl_read_targ_mem_bytes(priv->trans, base, &read, sizeof(read));
|
|
|
capacity = read.capacity;
|
|
|
mode = read.mode;
|
|
|
num_wraps = read.wrap_counter;
|
|
@@ -577,7 +583,7 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
|
|
|
7, 6, 5, 4,
|
|
|
};
|
|
|
|
|
|
-void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
|
|
|
+static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
|
|
|
{
|
|
|
int i;
|
|
|
|
|
@@ -644,7 +650,7 @@ void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
|
|
|
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
|
|
|
}
|
|
|
|
|
|
-void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
|
|
+static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
|
|
{
|
|
|
struct iwl_ct_kill_config cmd;
|
|
|
struct iwl_ct_kill_throttling_config adv_cmd;
|
|
@@ -725,7 +731,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void iwl_send_bt_config(struct iwl_priv *priv)
|
|
|
+static void iwl_send_bt_config(struct iwl_priv *priv)
|
|
|
{
|
|
|
struct iwl_bt_cmd bt_cmd = {
|
|
|
.lead_time = BT_LEAD_TIME_DEF,
|
|
@@ -813,7 +819,7 @@ int iwl_alive_start(struct iwl_priv *priv)
|
|
|
ieee80211_wake_queues(priv->hw);
|
|
|
|
|
|
/* Configure Tx antenna selection based on H/W config */
|
|
|
- iwlagn_send_tx_ant_config(priv, priv->hw_params.valid_tx_ant);
|
|
|
+ iwlagn_send_tx_ant_config(priv, priv->eeprom_data->valid_tx_ant);
|
|
|
|
|
|
if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
|
|
|
struct iwl_rxon_cmd *active_rxon =
|
|
@@ -931,11 +937,12 @@ void iwl_down(struct iwl_priv *priv)
|
|
|
priv->ucode_loaded = false;
|
|
|
iwl_trans_stop_device(priv->trans);
|
|
|
|
|
|
+ /* Set num_aux_in_flight must be done after the transport is stopped */
|
|
|
+ atomic_set(&priv->num_aux_in_flight, 0);
|
|
|
+
|
|
|
/* Clear out all status bits but a few that are stable across reset */
|
|
|
priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
|
|
|
STATUS_RF_KILL_HW |
|
|
|
- test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
|
|
|
- STATUS_GEO_CONFIGURED |
|
|
|
test_bit(STATUS_FW_ERROR, &priv->status) <<
|
|
|
STATUS_FW_ERROR |
|
|
|
test_bit(STATUS_EXIT_PENDING, &priv->status) <<
|
|
@@ -1077,7 +1084,7 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
|
|
|
*
|
|
|
*****************************************************************************/
|
|
|
|
|
|
-void iwl_setup_deferred_work(struct iwl_priv *priv)
|
|
|
+static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
|
|
{
|
|
|
priv->workqueue = create_singlethread_workqueue(DRV_NAME);
|
|
|
|
|
@@ -1122,224 +1129,14 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
|
|
del_timer_sync(&priv->ucode_trace);
|
|
|
}
|
|
|
|
|
|
-static void iwl_init_hw_rates(struct ieee80211_rate *rates)
|
|
|
-{
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
|
|
|
- rates[i].bitrate = iwl_rates[i].ieee * 5;
|
|
|
- rates[i].hw_value = i; /* Rate scaling will work on indexes */
|
|
|
- rates[i].hw_value_short = i;
|
|
|
- rates[i].flags = 0;
|
|
|
- if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) {
|
|
|
- /*
|
|
|
- * If CCK != 1M then set short preamble rate flag.
|
|
|
- */
|
|
|
- rates[i].flags |=
|
|
|
- (iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ?
|
|
|
- 0 : IEEE80211_RATE_SHORT_PREAMBLE;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
|
|
|
-#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
|
|
|
-static void iwl_init_ht_hw_capab(const struct iwl_priv *priv,
|
|
|
- struct ieee80211_sta_ht_cap *ht_info,
|
|
|
- enum ieee80211_band band)
|
|
|
+static int iwl_init_drv(struct iwl_priv *priv)
|
|
|
{
|
|
|
- u16 max_bit_rate = 0;
|
|
|
- u8 rx_chains_num = priv->hw_params.rx_chains_num;
|
|
|
- u8 tx_chains_num = priv->hw_params.tx_chains_num;
|
|
|
-
|
|
|
- ht_info->cap = 0;
|
|
|
- memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
|
|
|
-
|
|
|
- ht_info->ht_supported = true;
|
|
|
-
|
|
|
- if (priv->cfg->ht_params &&
|
|
|
- priv->cfg->ht_params->ht_greenfield_support)
|
|
|
- ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
|
|
|
- ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
|
|
|
- max_bit_rate = MAX_BIT_RATE_20_MHZ;
|
|
|
- if (priv->hw_params.ht40_channel & BIT(band)) {
|
|
|
- ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
|
|
- ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
|
|
|
- ht_info->mcs.rx_mask[4] = 0x01;
|
|
|
- max_bit_rate = MAX_BIT_RATE_40_MHZ;
|
|
|
- }
|
|
|
-
|
|
|
- if (iwlwifi_mod_params.amsdu_size_8K)
|
|
|
- ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
|
|
|
-
|
|
|
- ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
|
|
|
- ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
|
|
|
-
|
|
|
- ht_info->mcs.rx_mask[0] = 0xFF;
|
|
|
- if (rx_chains_num >= 2)
|
|
|
- ht_info->mcs.rx_mask[1] = 0xFF;
|
|
|
- if (rx_chains_num >= 3)
|
|
|
- ht_info->mcs.rx_mask[2] = 0xFF;
|
|
|
-
|
|
|
- /* Highest supported Rx data rate */
|
|
|
- max_bit_rate *= rx_chains_num;
|
|
|
- WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
|
|
|
- ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
|
|
|
-
|
|
|
- /* Tx MCS capabilities */
|
|
|
- ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
|
|
|
- if (tx_chains_num != rx_chains_num) {
|
|
|
- ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
|
|
|
- ht_info->mcs.tx_params |= ((tx_chains_num - 1) <<
|
|
|
- IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom
|
|
|
- */
|
|
|
-static int iwl_init_geos(struct iwl_priv *priv)
|
|
|
-{
|
|
|
- struct iwl_channel_info *ch;
|
|
|
- struct ieee80211_supported_band *sband;
|
|
|
- struct ieee80211_channel *channels;
|
|
|
- struct ieee80211_channel *geo_ch;
|
|
|
- struct ieee80211_rate *rates;
|
|
|
- int i = 0;
|
|
|
- s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN;
|
|
|
-
|
|
|
- if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
|
|
|
- priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
|
|
|
- IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
|
|
|
- set_bit(STATUS_GEO_CONFIGURED, &priv->status);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- channels = kcalloc(priv->channel_count,
|
|
|
- sizeof(struct ieee80211_channel), GFP_KERNEL);
|
|
|
- if (!channels)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate),
|
|
|
- GFP_KERNEL);
|
|
|
- if (!rates) {
|
|
|
- kfree(channels);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
-
|
|
|
- /* 5.2GHz channels start after the 2.4GHz channels */
|
|
|
- sband = &priv->bands[IEEE80211_BAND_5GHZ];
|
|
|
- sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
|
|
|
- /* just OFDM */
|
|
|
- sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
|
|
|
- sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
|
|
|
-
|
|
|
- if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
|
|
|
- iwl_init_ht_hw_capab(priv, &sband->ht_cap,
|
|
|
- IEEE80211_BAND_5GHZ);
|
|
|
-
|
|
|
- sband = &priv->bands[IEEE80211_BAND_2GHZ];
|
|
|
- sband->channels = channels;
|
|
|
- /* OFDM & CCK */
|
|
|
- sband->bitrates = rates;
|
|
|
- sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
|
|
|
-
|
|
|
- if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
|
|
|
- iwl_init_ht_hw_capab(priv, &sband->ht_cap,
|
|
|
- IEEE80211_BAND_2GHZ);
|
|
|
-
|
|
|
- priv->ieee_channels = channels;
|
|
|
- priv->ieee_rates = rates;
|
|
|
-
|
|
|
- for (i = 0; i < priv->channel_count; i++) {
|
|
|
- ch = &priv->channel_info[i];
|
|
|
-
|
|
|
- /* FIXME: might be removed if scan is OK */
|
|
|
- if (!is_channel_valid(ch))
|
|
|
- continue;
|
|
|
-
|
|
|
- sband = &priv->bands[ch->band];
|
|
|
-
|
|
|
- geo_ch = &sband->channels[sband->n_channels++];
|
|
|
-
|
|
|
- geo_ch->center_freq =
|
|
|
- ieee80211_channel_to_frequency(ch->channel, ch->band);
|
|
|
- geo_ch->max_power = ch->max_power_avg;
|
|
|
- geo_ch->max_antenna_gain = 0xff;
|
|
|
- geo_ch->hw_value = ch->channel;
|
|
|
-
|
|
|
- if (is_channel_valid(ch)) {
|
|
|
- if (!(ch->flags & EEPROM_CHANNEL_IBSS))
|
|
|
- geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
|
|
|
-
|
|
|
- if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
|
|
|
- geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
|
|
|
-
|
|
|
- if (ch->flags & EEPROM_CHANNEL_RADAR)
|
|
|
- geo_ch->flags |= IEEE80211_CHAN_RADAR;
|
|
|
-
|
|
|
- geo_ch->flags |= ch->ht40_extension_channel;
|
|
|
-
|
|
|
- if (ch->max_power_avg > max_tx_power)
|
|
|
- max_tx_power = ch->max_power_avg;
|
|
|
- } else {
|
|
|
- geo_ch->flags |= IEEE80211_CHAN_DISABLED;
|
|
|
- }
|
|
|
-
|
|
|
- IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
|
|
|
- ch->channel, geo_ch->center_freq,
|
|
|
- is_channel_a_band(ch) ? "5.2" : "2.4",
|
|
|
- geo_ch->flags & IEEE80211_CHAN_DISABLED ?
|
|
|
- "restricted" : "valid",
|
|
|
- geo_ch->flags);
|
|
|
- }
|
|
|
-
|
|
|
- priv->tx_power_device_lmt = max_tx_power;
|
|
|
- priv->tx_power_user_lmt = max_tx_power;
|
|
|
- priv->tx_power_next = max_tx_power;
|
|
|
-
|
|
|
- if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
|
|
|
- priv->hw_params.sku & EEPROM_SKU_CAP_BAND_52GHZ) {
|
|
|
- IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
|
|
|
- "Please send your %s to maintainer.\n",
|
|
|
- priv->trans->hw_id_str);
|
|
|
- priv->hw_params.sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
|
|
|
- }
|
|
|
-
|
|
|
- if (iwlwifi_mod_params.disable_5ghz)
|
|
|
- priv->bands[IEEE80211_BAND_5GHZ].n_channels = 0;
|
|
|
-
|
|
|
- IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
|
|
|
- priv->bands[IEEE80211_BAND_2GHZ].n_channels,
|
|
|
- priv->bands[IEEE80211_BAND_5GHZ].n_channels);
|
|
|
-
|
|
|
- set_bit(STATUS_GEO_CONFIGURED, &priv->status);
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * iwl_free_geos - undo allocations in iwl_init_geos
|
|
|
- */
|
|
|
-static void iwl_free_geos(struct iwl_priv *priv)
|
|
|
-{
|
|
|
- kfree(priv->ieee_channels);
|
|
|
- kfree(priv->ieee_rates);
|
|
|
- clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
|
|
|
-}
|
|
|
-
|
|
|
-int iwl_init_drv(struct iwl_priv *priv)
|
|
|
-{
|
|
|
- int ret;
|
|
|
-
|
|
|
spin_lock_init(&priv->sta_lock);
|
|
|
|
|
|
mutex_init(&priv->mutex);
|
|
|
|
|
|
INIT_LIST_HEAD(&priv->calib_results);
|
|
|
|
|
|
- priv->ieee_channels = NULL;
|
|
|
- priv->ieee_rates = NULL;
|
|
|
priv->band = IEEE80211_BAND_2GHZ;
|
|
|
|
|
|
priv->plcp_delta_threshold =
|
|
@@ -1370,31 +1167,11 @@ int iwl_init_drv(struct iwl_priv *priv)
|
|
|
priv->dynamic_frag_thresh = BT_FRAG_THRESHOLD_DEF;
|
|
|
}
|
|
|
|
|
|
- ret = iwl_init_channel_map(priv);
|
|
|
- if (ret) {
|
|
|
- IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- ret = iwl_init_geos(priv);
|
|
|
- if (ret) {
|
|
|
- IWL_ERR(priv, "initializing geos failed: %d\n", ret);
|
|
|
- goto err_free_channel_map;
|
|
|
- }
|
|
|
- iwl_init_hw_rates(priv->ieee_rates);
|
|
|
-
|
|
|
return 0;
|
|
|
-
|
|
|
-err_free_channel_map:
|
|
|
- iwl_free_channel_map(priv);
|
|
|
-err:
|
|
|
- return ret;
|
|
|
}
|
|
|
|
|
|
-void iwl_uninit_drv(struct iwl_priv *priv)
|
|
|
+static void iwl_uninit_drv(struct iwl_priv *priv)
|
|
|
{
|
|
|
- iwl_free_geos(priv);
|
|
|
- iwl_free_channel_map(priv);
|
|
|
kfree(priv->scan_cmd);
|
|
|
kfree(priv->beacon_cmd);
|
|
|
kfree(rcu_dereference_raw(priv->noa_data));
|
|
@@ -1404,15 +1181,12 @@ void iwl_uninit_drv(struct iwl_priv *priv)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-void iwl_set_hw_params(struct iwl_priv *priv)
|
|
|
+static void iwl_set_hw_params(struct iwl_priv *priv)
|
|
|
{
|
|
|
if (priv->cfg->ht_params)
|
|
|
priv->hw_params.use_rts_for_aggregation =
|
|
|
priv->cfg->ht_params->use_rts_for_aggregation;
|
|
|
|
|
|
- if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
|
|
|
- priv->hw_params.sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
|
|
|
-
|
|
|
/* Device-specific setup */
|
|
|
priv->lib->set_hw_params(priv);
|
|
|
}
|
|
@@ -1420,7 +1194,7 @@ void iwl_set_hw_params(struct iwl_priv *priv)
|
|
|
|
|
|
|
|
|
/* show what optional capabilities we have */
|
|
|
-void iwl_option_config(struct iwl_priv *priv)
|
|
|
+static void iwl_option_config(struct iwl_priv *priv)
|
|
|
{
|
|
|
#ifdef CONFIG_IWLWIFI_DEBUG
|
|
|
IWL_INFO(priv, "CONFIG_IWLWIFI_DEBUG enabled\n");
|
|
@@ -1453,6 +1227,42 @@ void iwl_option_config(struct iwl_priv *priv)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
|
|
|
+{
|
|
|
+ u16 radio_cfg;
|
|
|
+
|
|
|
+ priv->eeprom_data->sku = priv->eeprom_data->sku;
|
|
|
+
|
|
|
+ if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE &&
|
|
|
+ !priv->cfg->ht_params) {
|
|
|
+ IWL_ERR(priv, "Invalid 11n configuration\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!priv->eeprom_data->sku) {
|
|
|
+ IWL_ERR(priv, "Invalid device sku\n");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku);
|
|
|
+
|
|
|
+ radio_cfg = priv->eeprom_data->radio_cfg;
|
|
|
+
|
|
|
+ priv->hw_params.tx_chains_num =
|
|
|
+ num_of_ant(priv->eeprom_data->valid_tx_ant);
|
|
|
+ if (priv->cfg->rx_with_siso_diversity)
|
|
|
+ priv->hw_params.rx_chains_num = 1;
|
|
|
+ else
|
|
|
+ priv->hw_params.rx_chains_num =
|
|
|
+ num_of_ant(priv->eeprom_data->valid_rx_ant);
|
|
|
+
|
|
|
+ IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
|
|
|
+ priv->eeprom_data->valid_tx_ant,
|
|
|
+ priv->eeprom_data->valid_rx_ant);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|
|
const struct iwl_cfg *cfg,
|
|
|
const struct iwl_fw *fw)
|
|
@@ -1538,9 +1348,12 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|
|
trans_cfg.queue_watchdog_timeout =
|
|
|
priv->cfg->base_params->wd_timeout;
|
|
|
else
|
|
|
- trans_cfg.queue_watchdog_timeout = IWL_WATCHHDOG_DISABLED;
|
|
|
+ trans_cfg.queue_watchdog_timeout = IWL_WATCHDOG_DISABLED;
|
|
|
trans_cfg.command_names = iwl_dvm_cmd_strings;
|
|
|
|
|
|
+ WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE <
|
|
|
+ priv->cfg->base_params->num_of_queues);
|
|
|
+
|
|
|
ucode_flags = fw->ucode_capa.flags;
|
|
|
|
|
|
#ifndef CONFIG_IWLWIFI_P2P
|
|
@@ -1598,25 +1411,33 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|
|
goto out_free_hw;
|
|
|
|
|
|
/* Read the EEPROM */
|
|
|
- if (iwl_eeprom_init(priv, priv->trans->hw_rev)) {
|
|
|
+ if (iwl_read_eeprom(priv->trans, &priv->eeprom_blob,
|
|
|
+ &priv->eeprom_blob_size)) {
|
|
|
IWL_ERR(priv, "Unable to init EEPROM\n");
|
|
|
goto out_free_hw;
|
|
|
}
|
|
|
+
|
|
|
/* Reset chip to save power until we load uCode during "up". */
|
|
|
iwl_trans_stop_hw(priv->trans, false);
|
|
|
|
|
|
- if (iwl_eeprom_check_version(priv))
|
|
|
+ priv->eeprom_data = iwl_parse_eeprom_data(priv->trans->dev, priv->cfg,
|
|
|
+ priv->eeprom_blob,
|
|
|
+ priv->eeprom_blob_size);
|
|
|
+ if (!priv->eeprom_data)
|
|
|
+ goto out_free_eeprom_blob;
|
|
|
+
|
|
|
+ if (iwl_eeprom_check_version(priv->eeprom_data, priv->trans))
|
|
|
goto out_free_eeprom;
|
|
|
|
|
|
if (iwl_eeprom_init_hw_params(priv))
|
|
|
goto out_free_eeprom;
|
|
|
|
|
|
/* extract MAC Address */
|
|
|
- iwl_eeprom_get_mac(priv, priv->addresses[0].addr);
|
|
|
+ memcpy(priv->addresses[0].addr, priv->eeprom_data->hw_addr, ETH_ALEN);
|
|
|
IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
|
|
|
priv->hw->wiphy->addresses = priv->addresses;
|
|
|
priv->hw->wiphy->n_addresses = 1;
|
|
|
- num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS);
|
|
|
+ num_mac = priv->eeprom_data->n_hw_addrs;
|
|
|
if (num_mac > 1) {
|
|
|
memcpy(priv->addresses[1].addr, priv->addresses[0].addr,
|
|
|
ETH_ALEN);
|
|
@@ -1629,7 +1450,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
|
|
************************/
|
|
|
iwl_set_hw_params(priv);
|
|
|
|
|
|
- if (!(priv->hw_params.sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
|
|
|
+ if (!(priv->eeprom_data->sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
|
|
|
IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN");
|
|
|
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
|
|
/*
|
|
@@ -1710,8 +1531,10 @@ out_destroy_workqueue:
|
|
|
destroy_workqueue(priv->workqueue);
|
|
|
priv->workqueue = NULL;
|
|
|
iwl_uninit_drv(priv);
|
|
|
+out_free_eeprom_blob:
|
|
|
+ kfree(priv->eeprom_blob);
|
|
|
out_free_eeprom:
|
|
|
- iwl_eeprom_free(priv);
|
|
|
+ iwl_free_eeprom_data(priv->eeprom_data);
|
|
|
out_free_hw:
|
|
|
ieee80211_free_hw(priv->hw);
|
|
|
out:
|
|
@@ -1719,7 +1542,7 @@ out:
|
|
|
return op_mode;
|
|
|
}
|
|
|
|
|
|
-void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
|
|
+static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
|
|
{
|
|
|
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
|
|
|
|
@@ -1727,7 +1550,7 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
|
|
|
|
|
iwl_dbgfs_unregister(priv);
|
|
|
|
|
|
- iwl_testmode_cleanup(priv);
|
|
|
+ iwl_testmode_free(priv);
|
|
|
iwlagn_mac_unregister(priv);
|
|
|
|
|
|
iwl_tt_exit(priv);
|
|
@@ -1736,7 +1559,8 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
|
|
priv->ucode_loaded = false;
|
|
|
iwl_trans_stop_device(priv->trans);
|
|
|
|
|
|
- iwl_eeprom_free(priv);
|
|
|
+ kfree(priv->eeprom_blob);
|
|
|
+ iwl_free_eeprom_data(priv->eeprom_data);
|
|
|
|
|
|
/*netif_stop_queue(dev); */
|
|
|
flush_workqueue(priv->workqueue);
|
|
@@ -1849,7 +1673,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
|
|
|
}
|
|
|
|
|
|
/*TODO: Update dbgfs with ISR error stats obtained below */
|
|
|
- iwl_read_targ_mem_words(trans, base, &table, sizeof(table));
|
|
|
+ iwl_read_targ_mem_bytes(trans, base, &table, sizeof(table));
|
|
|
|
|
|
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
|
|
|
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
|
|
@@ -2184,7 +2008,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void iwl_nic_error(struct iwl_op_mode *op_mode)
|
|
|
+static void iwl_nic_error(struct iwl_op_mode *op_mode)
|
|
|
{
|
|
|
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
|
|
|
|
@@ -2197,7 +2021,7 @@ void iwl_nic_error(struct iwl_op_mode *op_mode)
|
|
|
iwlagn_fw_error(priv, false);
|
|
|
}
|
|
|
|
|
|
-void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
|
|
|
+static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
|
|
|
{
|
|
|
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
|
|
|
|
@@ -2207,11 +2031,60 @@ void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void iwl_nic_config(struct iwl_op_mode *op_mode)
|
|
|
+#define EEPROM_RF_CONFIG_TYPE_MAX 0x3
|
|
|
+
|
|
|
+static void iwl_nic_config(struct iwl_op_mode *op_mode)
|
|
|
{
|
|
|
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
|
|
+ u16 radio_cfg = priv->eeprom_data->radio_cfg;
|
|
|
+
|
|
|
+ /* SKU Control */
|
|
|
+ iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
|
|
+ CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH |
|
|
|
+ CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP,
|
|
|
+ (CSR_HW_REV_STEP(priv->trans->hw_rev) <<
|
|
|
+ CSR_HW_IF_CONFIG_REG_POS_MAC_STEP) |
|
|
|
+ (CSR_HW_REV_DASH(priv->trans->hw_rev) <<
|
|
|
+ CSR_HW_IF_CONFIG_REG_POS_MAC_DASH));
|
|
|
+
|
|
|
+ /* write radio config values to register */
|
|
|
+ if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) {
|
|
|
+ u32 reg_val =
|
|
|
+ EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <<
|
|
|
+ CSR_HW_IF_CONFIG_REG_POS_PHY_TYPE |
|
|
|
+ EEPROM_RF_CFG_STEP_MSK(radio_cfg) <<
|
|
|
+ CSR_HW_IF_CONFIG_REG_POS_PHY_STEP |
|
|
|
+ EEPROM_RF_CFG_DASH_MSK(radio_cfg) <<
|
|
|
+ CSR_HW_IF_CONFIG_REG_POS_PHY_DASH;
|
|
|
+
|
|
|
+ iwl_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG,
|
|
|
+ CSR_HW_IF_CONFIG_REG_MSK_PHY_TYPE |
|
|
|
+ CSR_HW_IF_CONFIG_REG_MSK_PHY_STEP |
|
|
|
+ CSR_HW_IF_CONFIG_REG_MSK_PHY_DASH, reg_val);
|
|
|
+
|
|
|
+ IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
|
|
|
+ EEPROM_RF_CFG_TYPE_MSK(radio_cfg),
|
|
|
+ EEPROM_RF_CFG_STEP_MSK(radio_cfg),
|
|
|
+ EEPROM_RF_CFG_DASH_MSK(radio_cfg));
|
|
|
+ } else {
|
|
|
+ WARN_ON(1);
|
|
|
+ }
|
|
|
|
|
|
- priv->lib->nic_config(priv);
|
|
|
+ /* set CSR_HW_CONFIG_REG for uCode use */
|
|
|
+ iwl_set_bit(priv->trans, CSR_HW_IF_CONFIG_REG,
|
|
|
+ CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
|
|
|
+ CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
|
|
|
+
|
|
|
+ /* W/A : NIC is stuck in a reset state after Early PCIe power off
|
|
|
+ * (PCIe power is lost before PERST# is asserted),
|
|
|
+ * causing ME FW to lose ownership and not being able to obtain it back.
|
|
|
+ */
|
|
|
+ iwl_set_bits_mask_prph(priv->trans, APMG_PS_CTRL_REG,
|
|
|
+ APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
|
|
|
+ ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
|
|
|
+
|
|
|
+ if (priv->lib->nic_config)
|
|
|
+ priv->lib->nic_config(priv);
|
|
|
}
|
|
|
|
|
|
static void iwl_wimax_active(struct iwl_op_mode *op_mode)
|
|
@@ -2222,7 +2095,7 @@ static void iwl_wimax_active(struct iwl_op_mode *op_mode)
|
|
|
IWL_ERR(priv, "RF is used by WiMAX\n");
|
|
|
}
|
|
|
|
|
|
-void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
|
|
+static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
|
|
{
|
|
|
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
|
|
int mq = priv->queue_to_mac80211[queue];
|
|
@@ -2241,7 +2114,7 @@ void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
|
|
ieee80211_stop_queue(priv->hw, mq);
|
|
|
}
|
|
|
|
|
|
-void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
|
|
+static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue)
|
|
|
{
|
|
|
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
|
|
int mq = priv->queue_to_mac80211[queue];
|
|
@@ -2281,16 +2154,17 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
|
|
|
priv->passive_no_rx = false;
|
|
|
}
|
|
|
|
|
|
-void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
|
|
+static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
|
|
{
|
|
|
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
|
|
struct ieee80211_tx_info *info;
|
|
|
|
|
|
info = IEEE80211_SKB_CB(skb);
|
|
|
- kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
|
|
|
+ iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
|
|
|
dev_kfree_skb_any(skb);
|
|
|
}
|
|
|
|
|
|
-void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
|
|
+static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
|
|
{
|
|
|
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
|
|
|
|
@@ -2302,7 +2176,7 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
|
|
wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
|
|
|
}
|
|
|
|
|
|
-const struct iwl_op_mode_ops iwl_dvm_ops = {
|
|
|
+static const struct iwl_op_mode_ops iwl_dvm_ops = {
|
|
|
.start = iwl_op_mode_dvm_start,
|
|
|
.stop = iwl_op_mode_dvm_stop,
|
|
|
.rx = iwl_rx_dispatch,
|
|
@@ -2321,9 +2195,6 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
|
|
|
* driver and module entry point
|
|
|
*
|
|
|
*****************************************************************************/
|
|
|
-
|
|
|
-struct kmem_cache *iwl_tx_cmd_pool;
|
|
|
-
|
|
|
static int __init iwl_init(void)
|
|
|
{
|
|
|
|
|
@@ -2331,29 +2202,18 @@ static int __init iwl_init(void)
|
|
|
pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
|
|
|
pr_info(DRV_COPYRIGHT "\n");
|
|
|
|
|
|
- iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd",
|
|
|
- sizeof(struct iwl_device_cmd),
|
|
|
- sizeof(void *), 0, NULL);
|
|
|
- if (!iwl_tx_cmd_pool)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
ret = iwlagn_rate_control_register();
|
|
|
if (ret) {
|
|
|
pr_err("Unable to register rate control algorithm: %d\n", ret);
|
|
|
- goto error_rc_register;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
ret = iwl_opmode_register("iwldvm", &iwl_dvm_ops);
|
|
|
if (ret) {
|
|
|
pr_err("Unable to register op_mode: %d\n", ret);
|
|
|
- goto error_opmode_register;
|
|
|
+ iwlagn_rate_control_unregister();
|
|
|
}
|
|
|
- return ret;
|
|
|
|
|
|
-error_opmode_register:
|
|
|
- iwlagn_rate_control_unregister();
|
|
|
-error_rc_register:
|
|
|
- kmem_cache_destroy(iwl_tx_cmd_pool);
|
|
|
return ret;
|
|
|
}
|
|
|
module_init(iwl_init);
|
|
@@ -2362,6 +2222,5 @@ static void __exit iwl_exit(void)
|
|
|
{
|
|
|
iwl_opmode_deregister("iwldvm");
|
|
|
iwlagn_rate_control_unregister();
|
|
|
- kmem_cache_destroy(iwl_tx_cmd_pool);
|
|
|
}
|
|
|
module_exit(iwl_exit);
|