summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/dvm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/dvm')
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/agn.h2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/devices.c13
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/lib.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c55
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c29
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/scan.c47
7 files changed, 78 insertions, 72 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h
index 6d10241..9bb16bd 100644
--- a/drivers/net/wireless/iwlwifi/dvm/agn.h
+++ b/drivers/net/wireless/iwlwifi/dvm/agn.h
@@ -269,7 +269,7 @@ void iwl_scan_offchannel_skb_status(struct iwl_priv *priv);
#define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */
#define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */
-#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7)
+#define IWL_SCAN_CHECK_WATCHDOG (HZ * 15)
/* bt coex */
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h
index 4620b65..54cf085 100644
--- a/drivers/net/wireless/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/iwlwifi/dvm/dev.h
@@ -568,7 +568,6 @@ enum iwl_scan_type {
*
* @tx_chains_num: Number of TX chains
* @rx_chains_num: Number of RX chains
- * @sku: sku read from EEPROM
* @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
@@ -579,7 +578,6 @@ struct iwl_hw_params {
u8 tx_chains_num;
u8 rx_chains_num;
bool use_rts_for_aggregation;
- u16 sku;
u32 ct_kill_threshold;
u32 ct_kill_exit_threshold;
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c
index 0521a6b..349c205 100644
--- a/drivers/net/wireless/iwlwifi/dvm/devices.c
+++ b/drivers/net/wireless/iwlwifi/dvm/devices.c
@@ -250,17 +250,6 @@ struct iwl_lib_ops iwl2030_lib = {
*/
/* NIC configuration for 5000 series */
-static void iwl5000_nic_config(struct iwl_priv *priv)
-{
- /* 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);
-}
-
static const struct iwl_sensitivity_ranges iwl5000_sensitivity = {
.min_nrg_cck = 100,
.auto_corr_min_ofdm = 90,
@@ -433,14 +422,12 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
struct iwl_lib_ops iwl5000_lib = {
.set_hw_params = iwl5000_hw_set_hw_params,
.set_channel_switch = iwl5000_hw_channel_switch,
- .nic_config = iwl5000_nic_config,
.temperature = iwlagn_temperature,
};
struct iwl_lib_ops iwl5150_lib = {
.set_hw_params = iwl5150_hw_set_hw_params,
.set_channel_switch = iwl5000_hw_channel_switch,
- .nic_config = iwl5000_nic_config,
.temperature = iwl5150_temperature,
};
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index 76f2592..207ae91 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -160,7 +160,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
IWL_PAN_SCD_MULTICAST_MSK;
- if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
+ if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE)
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index 2f10346..a5f7bce 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -164,7 +164,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
*/
- if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE)
+ if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE)
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
@@ -649,7 +649,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
sta->addr, tid);
- if (!(priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE))
+ if (!(priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE))
return -EACCES;
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -1048,8 +1048,18 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
- err = -EBUSY;
- goto out;
+ /* mac80211 should not scan while ROC or ROC while scanning */
+ if (WARN_ON_ONCE(priv->scan_type != IWL_SCAN_RADIO_RESET)) {
+ err = -EBUSY;
+ goto out;
+ }
+
+ iwl_scan_cancel_timeout(priv, 100);
+
+ if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+ err = -EBUSY;
+ goto out;
+ }
}
priv->hw_roc_channel = channel;
@@ -1413,13 +1423,11 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
}
static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- enum nl80211_iftype newtype, bool newp2p)
+ struct ieee80211_vif *vif,
+ enum nl80211_iftype newtype, bool newp2p)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
- struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
- struct iwl_rxon_context *bss_ctx = &priv->contexts[IWL_RXON_CTX_BSS];
- struct iwl_rxon_context *tmp;
+ struct iwl_rxon_context *ctx, *tmp;
enum nl80211_iftype newviftype = newtype;
u32 interface_modes;
int err;
@@ -1430,6 +1438,18 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
+ ctx = iwl_rxon_ctx_from_vif(vif);
+
+ /*
+ * To simplify this code, only support changes on the
+ * BSS context. The PAN context is usually reassigned
+ * by creating/removing P2P interfaces anyway.
+ */
+ if (ctx->ctxid != IWL_RXON_CTX_BSS) {
+ err = -EBUSY;
+ goto out;
+ }
+
if (!ctx->vif || !iwl_is_ready_rf(priv)) {
/*
* Huh? But wait ... this can maybe happen when
@@ -1439,32 +1459,19 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
goto out;
}
+ /* Check if the switch is supported in the same context */
interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
-
if (!(interface_modes & BIT(newtype))) {
err = -EBUSY;
goto out;
}
- /*
- * Refuse a change that should be done by moving from the PAN
- * context to the BSS context instead, if the BSS context is
- * available and can support the new interface type.
- */
- if (ctx->ctxid == IWL_RXON_CTX_PAN && !bss_ctx->vif &&
- (bss_ctx->interface_modes & BIT(newtype) ||
- bss_ctx->exclusive_interface_modes & BIT(newtype))) {
- BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
- err = -EBUSY;
- goto out;
- }
-
if (ctx->exclusive_interface_modes & BIT(newtype)) {
for_each_context(priv, tmp) {
if (ctx == tmp)
continue;
- if (!tmp->vif)
+ if (!tmp->is_active)
continue;
/*
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index e620af3..abfd791 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -51,11 +51,13 @@
#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"
+
/******************************************************************************
*
* module boiler plate
@@ -1185,9 +1187,6 @@ static void iwl_set_hw_params(struct iwl_priv *priv)
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);
}
@@ -1232,20 +1231,20 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
{
u16 radio_cfg;
- priv->hw_params.sku = priv->eeprom_data->sku;
+ priv->eeprom_data->sku = priv->eeprom_data->sku;
- if (priv->hw_params.sku & EEPROM_SKU_CAP_11N_ENABLE &&
+ 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->hw_params.sku) {
+ if (!priv->eeprom_data->sku) {
IWL_ERR(priv, "Invalid device sku\n");
return -EINVAL;
}
- IWL_INFO(priv, "Device SKU: 0x%X\n", priv->hw_params.sku);
+ IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku);
radio_cfg = priv->eeprom_data->radio_cfg;
@@ -1352,6 +1351,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
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
@@ -1448,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;
/*
@@ -2073,7 +2075,16 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode)
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
- priv->lib->nic_config(priv);
+ /* 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)
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c
index 2f271c9..6633074 100644
--- a/drivers/net/wireless/iwlwifi/dvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/dvm/scan.c
@@ -51,6 +51,9 @@
#define IWL_CHANNEL_TUNE_TIME 5
#define MAX_SCAN_CHANNEL 50
+/* For reset radio, need minimal dwell time only */
+#define IWL_RADIO_RESET_DWELL_TIME 5
+
static int iwl_send_scan_abort(struct iwl_priv *priv)
{
int ret;
@@ -469,45 +472,39 @@ static u8 iwl_get_single_channel_number(struct iwl_priv *priv,
return 0;
}
-static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- enum ieee80211_band band,
- struct iwl_scan_channel *scan_ch)
+static int iwl_get_channel_for_reset_scan(struct iwl_priv *priv,
+ struct ieee80211_vif *vif,
+ enum ieee80211_band band,
+ struct iwl_scan_channel *scan_ch)
{
const struct ieee80211_supported_band *sband;
- u16 passive_dwell = 0;
- u16 active_dwell = 0;
- int added = 0;
- u16 channel = 0;
+ u16 channel;
sband = iwl_get_hw_mode(priv, band);
if (!sband) {
IWL_ERR(priv, "invalid band\n");
- return added;
+ return 0;
}
- active_dwell = iwl_get_active_dwell_time(priv, band, 0);
- passive_dwell = iwl_get_passive_dwell_time(priv, band);
-
- if (passive_dwell <= active_dwell)
- passive_dwell = active_dwell + 1;
-
channel = iwl_get_single_channel_number(priv, band);
if (channel) {
scan_ch->channel = cpu_to_le16(channel);
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
- scan_ch->active_dwell = cpu_to_le16(active_dwell);
- scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+ scan_ch->active_dwell =
+ cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME);
+ scan_ch->passive_dwell =
+ cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME);
/* Set txpower levels to defaults */
scan_ch->dsp_atten = 110;
if (band == IEEE80211_BAND_5GHZ)
scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
else
scan_ch->tx_gain = ((1 << 5) | (5 << 3));
- added++;
- } else
- IWL_ERR(priv, "no valid channel found\n");
- return added;
+ return 1;
+ }
+
+ IWL_ERR(priv, "no valid channel found\n");
+ return 0;
}
static int iwl_get_channels_for_scan(struct iwl_priv *priv,
@@ -723,6 +720,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
switch (priv->scan_type) {
case IWL_SCAN_RADIO_RESET:
IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
+ /*
+ * Override quiet time as firmware checks that active
+ * dwell is >= quiet; since we use passive scan it'll
+ * not actually be used.
+ */
+ scan->quiet_time = cpu_to_le16(IWL_RADIO_RESET_DWELL_TIME);
break;
case IWL_SCAN_NORMAL:
if (priv->scan_request->n_ssids) {
@@ -896,7 +899,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
switch (priv->scan_type) {
case IWL_SCAN_RADIO_RESET:
scan->channel_count =
- iwl_get_single_channel_for_scan(priv, vif, band,
+ iwl_get_channel_for_reset_scan(priv, vif, band,
(void *)&scan->data[cmd_len]);
break;
case IWL_SCAN_NORMAL:
OpenPOWER on IntegriCloud