summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-devices.c74
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c30
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rx.c39
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c309
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-sta.c146
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c126
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h59
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c604
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h68
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-mac80211.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-shared.h1
15 files changed, 755 insertions, 763 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 565611eef0d4..db6c6e528022 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -113,20 +113,21 @@ config IWLWIFI_DEVICE_TESTMODE
generic netlink message via NL80211_TESTMODE channel.
config IWLWIFI_P2P
- bool "iwlwifi experimental P2P support"
- depends on IWLWIFI
- help
- This option enables experimental P2P support for some devices
- based on microcode support. Since P2P support is still under
- development, this option may even enable it for some devices
- now that turn out to not support it in the future due to
- microcode restrictions.
-
- To determine if your microcode supports the experimental P2P
- offered by this option, check if the driver advertises AP
- support when it is loaded.
-
- Say Y only if you want to experiment with P2P.
+ def_bool y
+ bool "iwlwifi experimental P2P support"
+ depends on IWLWIFI
+ help
+ This option enables experimental P2P support for some devices
+ based on microcode support. Since P2P support is still under
+ development, this option may even enable it for some devices
+ now that turn out to not support it in the future due to
+ microcode restrictions.
+
+ To determine if your microcode supports the experimental P2P
+ offered by this option, check if the driver advertises AP
+ support when it is loaded.
+
+ Say Y only if you want to experiment with P2P.
config IWLWIFI_EXPERIMENTAL_MFP
bool "support MFP (802.11w) even if uCode doesn't advertise"
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c b/drivers/net/wireless/iwlwifi/iwl-agn-devices.c
index bc9cb5c0ec6c..08718caf4aa9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-devices.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-devices.c
@@ -71,6 +71,80 @@ static void iwl1000_nic_config(struct iwl_priv *priv)
~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
}
+/**
+ * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
+ * @priv -- pointer to iwl_priv data structure
+ * @tsf_bits -- number of bits need to shift for masking)
+ */
+static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
+ u16 tsf_bits)
+{
+ return (1 << tsf_bits) - 1;
+}
+
+/**
+ * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
+ * @priv -- pointer to iwl_priv data structure
+ * @tsf_bits -- number of bits need to shift for masking)
+ */
+static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv,
+ u16 tsf_bits)
+{
+ return ((1 << (32 - tsf_bits)) - 1) << tsf_bits;
+}
+
+/*
+ * extended beacon time format
+ * time in usec will be changed into a 32-bit value in extended:internal format
+ * the extended part is the beacon counts
+ * the internal part is the time in usec within one beacon interval
+ */
+static u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec,
+ u32 beacon_interval)
+{
+ u32 quot;
+ u32 rem;
+ u32 interval = beacon_interval * TIME_UNIT;
+
+ if (!interval || !usec)
+ return 0;
+
+ quot = (usec / interval) &
+ (iwl_beacon_time_mask_high(priv, IWLAGN_EXT_BEACON_TIME_POS) >>
+ IWLAGN_EXT_BEACON_TIME_POS);
+ rem = (usec % interval) & iwl_beacon_time_mask_low(priv,
+ IWLAGN_EXT_BEACON_TIME_POS);
+
+ return (quot << IWLAGN_EXT_BEACON_TIME_POS) + rem;
+}
+
+/* base is usually what we get from ucode with each received frame,
+ * the same as HW timer counter counting down
+ */
+static __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
+ u32 addon, u32 beacon_interval)
+{
+ u32 base_low = base & iwl_beacon_time_mask_low(priv,
+ IWLAGN_EXT_BEACON_TIME_POS);
+ u32 addon_low = addon & iwl_beacon_time_mask_low(priv,
+ IWLAGN_EXT_BEACON_TIME_POS);
+ u32 interval = beacon_interval * TIME_UNIT;
+ u32 res = (base & iwl_beacon_time_mask_high(priv,
+ IWLAGN_EXT_BEACON_TIME_POS)) +
+ (addon & iwl_beacon_time_mask_high(priv,
+ IWLAGN_EXT_BEACON_TIME_POS));
+
+ if (base_low > addon_low)
+ res += base_low - addon_low;
+ else if (base_low < addon_low) {
+ res += interval + base_low - addon_low;
+ res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
+ } else
+ res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
+
+ return cpu_to_le32(res);
+}
+
static const struct iwl_sensitivity_ranges iwl1000_sensitivity = {
.min_nrg_cck = 95,
.auto_corr_min_ofdm = 90,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index b5ee99e236b1..da023fdbc7b2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -307,24 +307,30 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
.bt3_prio_sample_time = IWLAGN_BT3_PRIO_SAMPLE_DEFAULT,
.bt3_timer_t2_value = IWLAGN_BT3_T2_DEFAULT,
};
- struct iwl6000_bt_cmd bt_cmd_6000;
- struct iwl2000_bt_cmd bt_cmd_2000;
+ struct iwl_bt_cmd_v1 bt_cmd_v1;
+ struct iwl_bt_cmd_v2 bt_cmd_v2;
int ret;
BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) !=
sizeof(basic.bt3_lookup_table));
if (cfg(priv)->bt_params) {
+ /*
+ * newer generation of devices (2000 series and newer)
+ * use the version 2 of the bt command
+ * we need to make sure sending the host command
+ * with correct data structure to avoid uCode assert
+ */
if (cfg(priv)->bt_params->bt_session_2) {
- bt_cmd_2000.prio_boost = cpu_to_le32(
+ bt_cmd_v2.prio_boost = cpu_to_le32(
cfg(priv)->bt_params->bt_prio_boost);
- bt_cmd_2000.tx_prio_boost = 0;
- bt_cmd_2000.rx_prio_boost = 0;
+ bt_cmd_v2.tx_prio_boost = 0;
+ bt_cmd_v2.rx_prio_boost = 0;
} else {
- bt_cmd_6000.prio_boost =
+ bt_cmd_v1.prio_boost =
cfg(priv)->bt_params->bt_prio_boost;
- bt_cmd_6000.tx_prio_boost = 0;
- bt_cmd_6000.rx_prio_boost = 0;
+ bt_cmd_v1.tx_prio_boost = 0;
+ bt_cmd_v1.rx_prio_boost = 0;
}
} else {
IWL_ERR(priv, "failed to construct BT Coex Config\n");
@@ -371,15 +377,15 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
"full concurrency" : "3-wire");
if (cfg(priv)->bt_params->bt_session_2) {
- memcpy(&bt_cmd_2000.basic, &basic,
+ memcpy(&bt_cmd_v2.basic, &basic,
sizeof(basic));
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
+ CMD_SYNC, sizeof(bt_cmd_v2), &bt_cmd_v2);
} else {
- memcpy(&bt_cmd_6000.basic, &basic,
+ memcpy(&bt_cmd_v1.basic, &basic,
sizeof(basic));
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
+ CMD_SYNC, sizeof(bt_cmd_v1), &bt_cmd_v1);
}
if (ret)
IWL_ERR(priv, "failed to send BT Coex Config\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 08419e833c4d..8b13b6cf940a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -2826,6 +2826,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
struct iwl_station_priv *sta_priv;
struct iwl_lq_sta *lq_sta;
struct ieee80211_supported_band *sband;
+ unsigned long supp; /* must be unsigned long for for_each_set_bit */
sta_priv = (struct iwl_station_priv *) sta->drv_priv;
lq_sta = &sta_priv->lq_sta;
@@ -2855,8 +2856,15 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
lq_sta->max_rate_idx = -1;
lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
lq_sta->is_green = rs_use_green(sta);
- lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
- lq_sta->band = priv->band;
+ lq_sta->band = sband->band;
+ /*
+ * active legacy rates as per supported rates bitmap
+ */
+ supp = sta->supp_rates[sband->band];
+ lq_sta->active_legacy_rate = 0;
+ for_each_set_bit(i, &supp, BITS_PER_LONG)
+ lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value);
+
/*
* active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
* supp_rates[] does not; shift to convert format, force 9 MBits off.
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index aba1da231d70..93a687175fa6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -284,6 +284,45 @@ static bool iwlagn_good_plcp_health(struct iwl_priv *priv,
return true;
}
+int iwl_force_rf_reset(struct iwl_priv *priv, bool external)
+{
+ struct iwl_rf_reset *rf_reset;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return -EAGAIN;
+
+ if (!iwl_is_any_associated(priv)) {
+ IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
+ return -ENOLINK;
+ }
+
+ rf_reset = &priv->rf_reset;
+ rf_reset->reset_request_count++;
+ if (!external && rf_reset->last_reset_jiffies &&
+ time_after(rf_reset->last_reset_jiffies +
+ IWL_DELAY_NEXT_FORCE_RF_RESET, jiffies)) {
+ IWL_DEBUG_INFO(priv, "RF reset rejected\n");
+ rf_reset->reset_reject_count++;
+ return -EAGAIN;
+ }
+ rf_reset->reset_success_count++;
+ rf_reset->last_reset_jiffies = jiffies;
+
+ /*
+ * There is no easy and better way to force reset the radio,
+ * the only known method is switching channel which will force to
+ * reset and tune the radio.
+ * Use internal short scan (single channel) operation to should
+ * achieve this objective.
+ * Driver should reset the radio when number of consecutive missed
+ * beacon, or any other uCode error condition detected.
+ */
+ IWL_DEBUG_INFO(priv, "perform radio reset.\n");
+ iwl_internal_short_hw_scan(priv);
+ return 0;
+}
+
+
static void iwlagn_recover_from_statistics(struct iwl_priv *priv,
struct statistics_rx_phy *cur_ofdm,
struct statistics_rx_ht_phy *cur_ofdm_ht,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 369cd8b2ad0d..69279af5a41d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -32,6 +32,78 @@
#include "iwl-trans.h"
#include "iwl-shared.h"
+/*
+ * initialize rxon structure with default values from eeprom
+ */
+void iwl_connection_init_rx_config(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx)
+{
+ const struct iwl_channel_info *ch_info;
+
+ memset(&ctx->staging, 0, sizeof(ctx->staging));
+
+ if (!ctx->vif) {
+ ctx->staging.dev_type = ctx->unused_devtype;
+ } else
+ switch (ctx->vif->type) {
+ case NL80211_IFTYPE_AP:
+ ctx->staging.dev_type = ctx->ap_devtype;
+ break;
+
+ case NL80211_IFTYPE_STATION:
+ ctx->staging.dev_type = ctx->station_devtype;
+ ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
+ break;
+
+ case NL80211_IFTYPE_ADHOC:
+ ctx->staging.dev_type = ctx->ibss_devtype;
+ ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
+ ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
+ RXON_FILTER_ACCEPT_GRP_MSK;
+ break;
+
+ default:
+ IWL_ERR(priv, "Unsupported interface type %d\n",
+ ctx->vif->type);
+ break;
+ }
+
+#if 0
+ /* TODO: Figure out when short_preamble would be set and cache from
+ * that */
+ if (!hw_to_local(priv->hw)->short_preamble)
+ ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+ else
+ ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+#endif
+
+ ch_info = iwl_get_channel_info(priv, priv->band,
+ le16_to_cpu(ctx->active.channel));
+
+ if (!ch_info)
+ ch_info = &priv->channel_info[0];
+
+ ctx->staging.channel = cpu_to_le16(ch_info->channel);
+ priv->band = ch_info->band;
+
+ iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
+
+ ctx->staging.ofdm_basic_rates =
+ (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+ ctx->staging.cck_basic_rates =
+ (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
+
+ /* clear both MIX and PURE40 mode flag */
+ ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
+ RXON_FLG_CHANNEL_MODE_PURE_40);
+ if (ctx->vif)
+ memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
+
+ ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
+ ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
+ ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff;
+}
+
static int iwlagn_disable_bss(struct iwl_priv *priv,
struct iwl_rxon_context *ctx,
struct iwl_rxon_cmd *send)
@@ -335,6 +407,61 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv,
return 0;
}
+static int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
+{
+ int ret;
+ s8 prev_tx_power;
+ bool defer;
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+ lockdep_assert_held(&priv->mutex);
+
+ if (priv->tx_power_user_lmt == tx_power && !force)
+ return 0;
+
+ if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
+ IWL_WARN(priv,
+ "Requested user TXPOWER %d below lower limit %d.\n",
+ tx_power,
+ IWLAGN_TX_POWER_TARGET_POWER_MIN);
+ return -EINVAL;
+ }
+
+ if (tx_power > priv->tx_power_device_lmt) {
+ IWL_WARN(priv,
+ "Requested user TXPOWER %d above upper limit %d.\n",
+ tx_power, priv->tx_power_device_lmt);
+ return -EINVAL;
+ }
+
+ if (!iwl_is_ready_rf(priv))
+ return -EIO;
+
+ /* scan complete and commit_rxon use tx_power_next value,
+ * it always need to be updated for newest request */
+ priv->tx_power_next = tx_power;
+
+ /* do not set tx power when scanning or channel changing */
+ defer = test_bit(STATUS_SCANNING, &priv->status) ||
+ memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
+ if (defer && !force) {
+ IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
+ return 0;
+ }
+
+ prev_tx_power = priv->tx_power_user_lmt;
+ priv->tx_power_user_lmt = tx_power;
+
+ ret = iwlagn_send_tx_power(priv);
+
+ /* if fail to set tx_power, restore the orig. tx power */
+ if (ret) {
+ priv->tx_power_user_lmt = prev_tx_power;
+ priv->tx_power_next = prev_tx_power;
+ }
+ return ret;
+}
+
static int iwlagn_rxon_connect(struct iwl_priv *priv,
struct iwl_rxon_context *ctx)
{
@@ -501,6 +628,161 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
return ret;
}
+static void _iwl_set_rxon_ht(struct iwl_priv *priv,
+ struct iwl_ht_config *ht_conf,
+ struct iwl_rxon_context *ctx)
+{
+ struct iwl_rxon_cmd *rxon = &ctx->staging;
+
+ if (!ctx->ht.enabled) {
+ rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
+ RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
+ RXON_FLG_HT40_PROT_MSK |
+ RXON_FLG_HT_PROT_MSK);
+ return;
+ }
+
+ /* FIXME: if the definition of ht.protection changed, the "translation"
+ * will be needed for rxon->flags
+ */
+ rxon->flags |= cpu_to_le32(ctx->ht.protection <<
+ RXON_FLG_HT_OPERATING_MODE_POS);
+
+ /* Set up channel bandwidth:
+ * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
+ /* clear the HT channel mode before set the mode */
+ rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
+ RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
+ if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) {
+ /* pure ht40 */
+ if (ctx->ht.protection ==
+ IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
+ rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
+ /*
+ * Note: control channel is opposite of extension
+ * channel
+ */
+ switch (ctx->ht.extension_chan_offset) {
+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+ rxon->flags &=
+ ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+ rxon->flags |=
+ RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+ break;
+ }
+ } else {
+ /*
+ * Note: control channel is opposite of extension
+ * channel
+ */
+ switch (ctx->ht.extension_chan_offset) {
+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+ rxon->flags &=
+ ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
+ rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+ rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+ rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
+ break;
+ case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+ default:
+ /*
+ * channel location only valid if in Mixed
+ * mode
+ */
+ IWL_ERR(priv,
+ "invalid extension channel offset\n");
+ break;
+ }
+ }
+ } else {
+ rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
+ }
+
+ iwlagn_set_rxon_chain(priv, ctx);
+
+ IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
+ "extension channel offset 0x%x\n",
+ le32_to_cpu(rxon->flags), ctx->ht.protection,
+ ctx->ht.extension_chan_offset);
+}
+
+void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
+{
+ struct iwl_rxon_context *ctx;
+
+ for_each_context(priv, ctx)
+ _iwl_set_rxon_ht(priv, ht_conf, ctx);
+}
+
+/**
+ * iwl_set_rxon_channel - Set the band and channel values in staging RXON
+ * @ch: requested channel as a pointer to struct ieee80211_channel
+
+ * NOTE: Does not commit to the hardware; it sets appropriate bit fields
+ * in the staging RXON flag structure based on the ch->band
+ */
+void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
+ struct iwl_rxon_context *ctx)
+{
+ enum ieee80211_band band = ch->band;
+ u16 channel = ch->hw_value;
+
+ if ((le16_to_cpu(ctx->staging.channel) == channel) &&
+ (priv->band == band))
+ return;
+
+ ctx->staging.channel = cpu_to_le16(channel);
+ if (band == IEEE80211_BAND_5GHZ)
+ ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
+ else
+ ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
+
+ priv->band = band;
+
+ IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band);
+
+}
+
+void iwl_set_flags_for_band(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ enum ieee80211_band band,
+ struct ieee80211_vif *vif)
+{
+ if (band == IEEE80211_BAND_5GHZ) {
+ ctx->staging.flags &=
+ ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
+ | RXON_FLG_CCK_MSK);
+ ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ } else {
+ /* Copied from iwl_post_associate() */
+ if (vif && vif->bss_conf.use_short_slot)
+ ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+ else
+ ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+
+ ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
+ ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
+ ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
+ }
+}
+
+void iwl_set_rate(struct iwl_priv *priv)
+{
+ struct iwl_rxon_context *ctx;
+
+ for_each_context(priv, ctx) {
+ ctx->staging.cck_basic_rates =
+ (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
+
+ ctx->staging.ofdm_basic_rates =
+ (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+ }
+}
+
static void iwl_set_rxon_hwcrypto(struct iwl_priv *priv,
struct iwl_rxon_context *ctx, int hw_decrypt)
{
@@ -649,6 +931,33 @@ static int iwl_full_rxon_required(struct iwl_priv *priv,
return 0;
}
+#ifdef CONFIG_IWLWIFI_DEBUG
+void iwl_print_rx_config_cmd(struct iwl_priv *priv,
+ enum iwl_rxon_context_id ctxid)
+{
+ struct iwl_rxon_context *ctx = &priv->contexts[ctxid];
+ struct iwl_rxon_cmd *rxon = &ctx->staging;
+
+ IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
+ iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+ IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n",
+ le16_to_cpu(rxon->channel));
+ IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n",
+ le32_to_cpu(rxon->flags));
+ IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n",
+ le32_to_cpu(rxon->filter_flags));
+ IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type);
+ IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n",
+ rxon->ofdm_basic_rates);
+ IWL_DEBUG_RADIO(priv, "u8 cck_basic_rates: 0x%02x\n",
+ rxon->cck_basic_rates);
+ IWL_DEBUG_RADIO(priv, "u8[6] node_addr: %pM\n", rxon->node_addr);
+ IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
+ IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n",
+ le16_to_cpu(rxon->assoc_id));
+}
+#endif
+
/**
* iwlagn_commit_rxon - commit staging_rxon to hardware
*
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index b74bb6854b61..0119e7a7b78d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -34,6 +34,8 @@
#include "iwl-agn.h"
#include "iwl-trans.h"
+const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
{
lockdep_assert_held(&priv->sta_lock);
@@ -170,6 +172,50 @@ int iwl_send_add_sta(struct iwl_priv *priv,
return cmd.handler_status;
}
+static bool iwl_is_channel_extension(struct iwl_priv *priv,
+ enum ieee80211_band band,
+ u16 channel, u8 extension_chan_offset)
+{
+ const struct iwl_channel_info *ch_info;
+
+ ch_info = iwl_get_channel_info(priv, band, channel);
+ if (!is_channel_valid(ch_info))
+ return false;
+
+ if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
+ return !(ch_info->ht40_extension_channel &
+ IEEE80211_CHAN_NO_HT40PLUS);
+ else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
+ return !(ch_info->ht40_extension_channel &
+ IEEE80211_CHAN_NO_HT40MINUS);
+
+ return false;
+}
+
+bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_sta_ht_cap *ht_cap)
+{
+ if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
+ return false;
+
+ /*
+ * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
+ * the bit will not set if it is pure 40MHz case
+ */
+ if (ht_cap && !ht_cap->ht_supported)
+ return false;
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ if (priv->disable_ht40)
+ return false;
+#endif
+
+ return iwl_is_channel_extension(priv, priv->band,
+ le16_to_cpu(ctx->staging.channel),
+ ctx->ht.extension_chan_offset);
+}
+
static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
struct ieee80211_sta *sta,
struct iwl_rxon_context *ctx,
@@ -581,6 +627,56 @@ void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
spin_unlock_bh(&priv->sta_lock);
}
+static void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+ u8 sta_id, struct iwl_link_quality_cmd *link_cmd)
+{
+ int i, r;
+ u32 rate_flags = 0;
+ __le32 rate_n_flags;
+
+ lockdep_assert_held(&priv->mutex);
+
+ memset(link_cmd, 0, sizeof(*link_cmd));
+
+ /* Set up the rate scaling to start at selected rate, fall back
+ * all the way down to 1M in IEEE order, and then spin on 1M */
+ if (priv->band == IEEE80211_BAND_5GHZ)
+ r = IWL_RATE_6M_INDEX;
+ else if (ctx && ctx->vif && ctx->vif->p2p)
+ r = IWL_RATE_6M_INDEX;
+ else
+ r = IWL_RATE_1M_INDEX;
+
+ if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
+ rate_flags |= RATE_MCS_CCK_MSK;
+
+ rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
+ RATE_MCS_ANT_POS;
+ rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
+ for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+ link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
+
+ link_cmd->general_params.single_stream_ant_msk =
+ first_antenna(priv->hw_params.valid_tx_ant);
+
+ link_cmd->general_params.dual_stream_ant_msk =
+ priv->hw_params.valid_tx_ant &
+ ~first_antenna(priv->hw_params.valid_tx_ant);
+ if (!link_cmd->general_params.dual_stream_ant_msk) {
+ link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
+ } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
+ link_cmd->general_params.dual_stream_ant_msk =
+ priv->hw_params.valid_tx_ant;
+ }
+
+ link_cmd->agg_params.agg_dis_start_th =
+ LINK_QUAL_AGG_DISABLE_START_DEF;
+ link_cmd->agg_params.agg_time_limit =
+ cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
+
+ link_cmd->sta_id = sta_id;
+}
+
/**
* iwl_clear_ucode_stations - clear ucode station table bits
*
@@ -841,56 +937,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
}
-void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- u8 sta_id, struct iwl_link_quality_cmd *link_cmd)
-{
- int i, r;
- u32 rate_flags = 0;
- __le32 rate_n_flags;
-
- lockdep_assert_held(&priv->mutex);
-
- memset(link_cmd, 0, sizeof(*link_cmd));
-
- /* Set up the rate scaling to start at selected rate, fall back
- * all the way down to 1M in IEEE order, and then spin on 1M */
- if (priv->band == IEEE80211_BAND_5GHZ)
- r = IWL_RATE_6M_INDEX;
- else if (ctx && ctx->vif && ctx->vif->p2p)
- r = IWL_RATE_6M_INDEX;
- else
- r = IWL_RATE_1M_INDEX;
-
- if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
- rate_flags |= RATE_MCS_CCK_MSK;
-
- rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
- RATE_MCS_ANT_POS;
- rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
- for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
- link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
-
- link_cmd->general_params.single_stream_ant_msk =
- first_antenna(priv->hw_params.valid_tx_ant);
-
- link_cmd->general_params.dual_stream_ant_msk =
- priv->hw_params.valid_tx_ant &
- ~first_antenna(priv->hw_params.valid_tx_ant);
- if (!link_cmd->general_params.dual_stream_ant_msk) {
- link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
- } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
- link_cmd->general_params.dual_stream_ant_msk =
- priv->hw_params.valid_tx_ant;
- }
-
- link_cmd->agg_params.agg_dis_start_th =
- LINK_QUAL_AGG_DISABLE_START_DEF;
- link_cmd->agg_params.agg_time_limit =
- cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
-
- link_cmd->sta_id = sta_id;
-}
-
static struct iwl_link_quality_cmd *
iwl_sta_alloc_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
u8 sta_id)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index b507ee69b3bb..500eaa3cd642 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -289,6 +289,25 @@ out:
mutex_unlock(&priv->mutex);
}
+int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
+{
+ struct iwl_statistics_cmd statistics_cmd = {
+ .configuration_flags =
+ clear ? IWL_STATS_CONF_CLEAR_STATS : 0,
+ };
+
+ if (flags & CMD_ASYNC)
+ return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
+ CMD_ASYNC,
+ sizeof(struct iwl_statistics_cmd),
+ &statistics_cmd);
+ else
+ return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
+ CMD_SYNC,
+ sizeof(struct iwl_statistics_cmd),
+ &statistics_cmd);
+}
+
/**
* iwl_bg_statistics_periodic - Timer callback to queue statistics
*
@@ -726,6 +745,29 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
}
}
+static void iwl_send_bt_config(struct iwl_priv *priv)
+{
+ struct iwl_bt_cmd bt_cmd = {
+ .lead_time = BT_LEAD_TIME_DEF,
+ .max_kill = BT_MAX_KILL_DEF,
+ .kill_ack_mask = 0,
+ .kill_cts_mask = 0,
+ };
+
+ if (!iwlagn_mod_params.bt_coex_active)
+ bt_cmd.flags = BT_COEX_DISABLE;
+ else
+ bt_cmd.flags = BT_COEX_ENABLE;
+
+ priv->bt_enable_flag = bt_cmd.flags;
+ IWL_DEBUG_INFO(priv, "BT coex %s\n",
+ (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
+
+ if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+ CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
+ IWL_ERR(priv, "failed to send BT Coex Config\n");
+}
+
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
@@ -790,8 +832,6 @@ int iwl_alive_start(struct iwl_priv *priv)
ieee80211_wake_queues(priv->hw);
- priv->active_rate = IWL_RATES_MASK;
-
/* Configure Tx antenna selection based on H/W config */
iwlagn_send_tx_ant_config(priv, priv->hw_params.valid_tx_ant);
@@ -1524,7 +1564,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
ucode_flags = fw->ucode_capa.flags;
#ifndef CONFIG_IWLWIFI_P2P
- ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+ ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
#endif
if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
@@ -2121,6 +2161,65 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
return pos;
}
+static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
+{
+ unsigned int reload_msec;
+ unsigned long reload_jiffies;
+
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (iwl_have_debug_level(IWL_DL_FW_ERRORS))
+ iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
+#endif
+
+ /* uCode is no longer loaded. */
+ priv->ucode_loaded = false;
+
+ /* Set the FW error flag -- cleared on iwl_down */
+ set_bit(STATUS_FW_ERROR, &priv->status);
+
+ /* Cancel currently queued command. */
+ clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status);
+
+ iwl_abort_notification_waits(&priv->notif_wait);
+
+ /* Keep the restart process from trying to send host
+ * commands by clearing the ready bit */
+ clear_bit(STATUS_READY, &priv->status);
+
+ wake_up(&trans(priv)->wait_command_queue);
+
+ if (!ondemand) {
+ /*
+ * If firmware keep reloading, then it indicate something
+ * serious wrong and firmware having problem to recover
+ * from it. Instead of keep trying which will fill the syslog
+ * and hang the system, let's just stop it
+ */
+ reload_jiffies = jiffies;
+ reload_msec = jiffies_to_msecs((long) reload_jiffies -
+ (long) priv->reload_jiffies);
+ priv->reload_jiffies = reload_jiffies;
+ if (reload_msec <= IWL_MIN_RELOAD_DURATION) {
+ priv->reload_count++;
+ if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) {
+ IWL_ERR(priv, "BUG_ON, Stop restarting\n");
+ return;
+ }
+ } else
+ priv->reload_count = 0;
+ }
+
+ if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+ if (iwlagn_mod_params.restart_fw) {
+ IWL_DEBUG_FW_ERRORS(priv,
+ "Restarting adapter due to uCode error.\n");
+ queue_work(priv->workqueue, &priv->restart);
+ } else
+ IWL_DEBUG_FW_ERRORS(priv,
+ "Detected FW error, but not restarting\n");
+ }
+}
+
static void iwl_nic_error(struct iwl_op_mode *op_mode)
{
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
@@ -2210,6 +2309,27 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
priv->passive_no_rx = false;
}
+static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info;
+
+ info = IEEE80211_SKB_CB(skb);
+ kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
+ dev_kfree_skb_any(skb);
+}
+
+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);
+
+ if (state)
+ set_bit(STATUS_RF_KILL_HW, &priv->status);
+ else
+ clear_bit(STATUS_RF_KILL_HW, &priv->status);
+
+ wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
+}
+
const struct iwl_op_mode_ops iwl_dvm_ops = {
.start = iwl_op_mode_dvm_start,
.stop = iwl_op_mode_dvm_stop,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 6ebb3f75dad1..caef7a996d36 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -97,11 +97,9 @@ static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
void iwl_down(struct iwl_priv *priv);
void iwl_cancel_deferred_work(struct iwl_priv *priv);
void iwlagn_prepare_restart(struct iwl_priv *priv);
-void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb);
int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
-void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state);
bool iwl_check_for_ct_kill(struct iwl_priv *priv);
@@ -119,6 +117,8 @@ int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id,
u32 flags, u16 len, const void *data);
/* RXON */
+void iwl_connection_init_rx_config(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx);
int iwlagn_set_pan_params(struct iwl_priv *priv);
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
@@ -129,6 +129,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
u32 changes);
void iwlagn_config_ht40(struct ieee80211_conf *conf,
struct iwl_rxon_context *ctx);
+void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
+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,
+ enum ieee80211_band band,
+ struct ieee80211_vif *vif);
+void iwl_set_rate(struct iwl_priv *priv);
/* uCode */
int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
@@ -141,9 +149,9 @@ int iwl_send_calib_results(struct iwl_priv *priv);
int iwl_calib_set(struct iwl_priv *priv,
const struct iwl_calib_hdr *cmd, int len);
void iwl_calib_free_results(struct iwl_priv *priv);
-void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand);
int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
char **buf, bool display);
+int iwlagn_hw_valid_rtc_data_addr(u32 addr);
/* lib */
int iwlagn_send_tx_power(struct iwl_priv *priv);
@@ -151,6 +159,15 @@ void iwlagn_temperature(struct iwl_priv *priv);
int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
+int iwl_send_statistics_request(struct iwl_priv *priv,
+ u8 flags, bool clear);
+
+static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
+ struct iwl_priv *priv, enum ieee80211_band band)
+{
+ return priv->hw->wiphy->bands[band];
+}
+
#ifdef CONFIG_PM_SLEEP
int iwlagn_send_patterns(struct iwl_priv *priv,
struct cfg80211_wowlan *wowlan);
@@ -160,6 +177,7 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan);
/* rx */
int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
void iwl_setup_rx_handlers(struct iwl_priv *priv);
+void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
/* tx */
@@ -205,6 +223,30 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
void iwlagn_post_scan(struct iwl_priv *priv);
void iwlagn_disable_roc(struct iwl_priv *priv);
int iwl_force_rf_reset(struct iwl_priv *priv, bool external);
+void iwl_init_scan_params(struct iwl_priv *priv);
+int iwl_scan_cancel(struct iwl_priv *priv);
+void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
+void iwl_force_scan_end(struct iwl_priv *priv);
+void iwl_internal_short_hw_scan(struct iwl_priv *priv);
+void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
+void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
+void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
+int __must_check iwl_scan_initiate(struct iwl_priv *priv,
+ struct ieee80211_vif *vif,
+ enum iwl_scan_type scan_type,
+ enum ieee80211_band band);
+
+/* For faster active scanning, scan will move to the next channel if fewer than
+ * PLCP_QUIET_THRESH packets are heard on this channel within
+ * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell
+ * time if it's a quiet channel (nothing responded to our probe, and there's
+ * no other traffic).
+ * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
+#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)
+
/* bt coex */
void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
@@ -217,6 +259,12 @@ void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv);
void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv);
void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena);
+static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
+{
+ return cfg(priv)->bt_params &&
+ cfg(priv)->bt_params->advanced_bt_coexist;
+}
+
#ifdef CONFIG_IWLWIFI_DEBUG
const char *iwl_get_tx_fail_reason(u32 status);
const char *iwl_get_agg_tx_fail_reason(u16 status);
@@ -255,8 +303,6 @@ void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
-void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
- u8 sta_id, struct iwl_link_quality_cmd *link_cmd);
int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct iwl_link_quality_cmd *lq, u8 flags, bool init);
int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
@@ -264,6 +310,9 @@ int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct ieee80211_sta *sta);
+bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
+ struct iwl_rxon_context *ctx,
+ struct ieee80211_sta_ht_cap *ht_cap);
static inline int iwl_sta_id(struct ieee80211_sta *sta)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 9ed73e5154be..296347a8290f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1918,7 +1918,7 @@ struct iwl_basic_bt_cmd {
__le16 valid;
};
-struct iwl6000_bt_cmd {
+struct iwl_bt_cmd_v1 {
struct iwl_basic_bt_cmd basic;
u8 prio_boost;
/*
@@ -1929,7 +1929,7 @@ struct iwl6000_bt_cmd {
__le16 rx_prio_boost; /* SW boost of WiFi rx priority */
};
-struct iwl2000_bt_cmd {
+struct iwl_bt_cmd_v2 {
struct iwl_basic_bt_cmd basic;
__le32 prio_boost;
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 6a02ade07a24..94a4ebcb447b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -41,477 +41,6 @@
#include "iwl-agn.h"
#include "iwl-trans.h"
-const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-
-static bool iwl_is_channel_extension(struct iwl_priv *priv,
- enum ieee80211_band band,
- u16 channel, u8 extension_chan_offset)
-{
- const struct iwl_channel_info *ch_info;
-
- ch_info = iwl_get_channel_info(priv, band, channel);
- if (!is_channel_valid(ch_info))
- return false;
-
- if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
- return !(ch_info->ht40_extension_channel &
- IEEE80211_CHAN_NO_HT40PLUS);
- else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
- return !(ch_info->ht40_extension_channel &
- IEEE80211_CHAN_NO_HT40MINUS);
-
- return false;
-}
-
-bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx,
- struct ieee80211_sta_ht_cap *ht_cap)
-{
- if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
- return false;
-
- /*
- * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
- * the bit will not set if it is pure 40MHz case
- */
- if (ht_cap && !ht_cap->ht_supported)
- return false;
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
- if (priv->disable_ht40)
- return false;
-#endif
-
- return iwl_is_channel_extension(priv, priv->band,
- le16_to_cpu(ctx->staging.channel),
- ctx->ht.extension_chan_offset);
-}
-
-static void _iwl_set_rxon_ht(struct iwl_priv *priv,
- struct iwl_ht_config *ht_conf,
- struct iwl_rxon_context *ctx)
-{
- struct iwl_rxon_cmd *rxon = &ctx->staging;
-
- if (!ctx->ht.enabled) {
- rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
- RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
- RXON_FLG_HT40_PROT_MSK |
- RXON_FLG_HT_PROT_MSK);
- return;
- }
-
- /* FIXME: if the definition of ht.protection changed, the "translation"
- * will be needed for rxon->flags
- */
- rxon->flags |= cpu_to_le32(ctx->ht.protection << RXON_FLG_HT_OPERATING_MODE_POS);
-
- /* Set up channel bandwidth:
- * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
- /* clear the HT channel mode before set the mode */
- rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
- RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
- if (iwl_is_ht40_tx_allowed(priv, ctx, NULL)) {
- /* pure ht40 */
- if (ctx->ht.protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
- rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
- /* Note: control channel is opposite of extension channel */
- switch (ctx->ht.extension_chan_offset) {
- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
- rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
- break;
- case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
- rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
- break;
- }
- } else {
- /* Note: control channel is opposite of extension channel */
- switch (ctx->ht.extension_chan_offset) {
- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
- rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
- rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
- break;
- case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
- rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
- rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
- break;
- case IEEE80211_HT_PARAM_CHA_SEC_NONE:
- default:
- /* channel location only valid if in Mixed mode */
- IWL_ERR(priv, "invalid extension channel offset\n");
- break;
- }
- }
- } else {
- rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
- }
-
- iwlagn_set_rxon_chain(priv, ctx);
-
- IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
- "extension channel offset 0x%x\n",
- le32_to_cpu(rxon->flags), ctx->ht.protection,
- ctx->ht.extension_chan_offset);
-}
-
-void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
-{
- struct iwl_rxon_context *ctx;
-
- for_each_context(priv, ctx)
- _iwl_set_rxon_ht(priv, ht_conf, ctx);
-}
-
-/**
- * iwl_set_rxon_channel - Set the band and channel values in staging RXON
- * @ch: requested channel as a pointer to struct ieee80211_channel
-
- * NOTE: Does not commit to the hardware; it sets appropriate bit fields
- * in the staging RXON flag structure based on the ch->band
- */
-void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
- struct iwl_rxon_context *ctx)
-{
- enum ieee80211_band band = ch->band;
- u16 channel = ch->hw_value;
-
- if ((le16_to_cpu(ctx->staging.channel) == channel) &&
- (priv->band == band))
- return;
-
- ctx->staging.channel = cpu_to_le16(channel);
- if (band == IEEE80211_BAND_5GHZ)
- ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
- else
- ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
-
- priv->band = band;
-
- IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band);
-
-}
-
-void iwl_set_flags_for_band(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx,
- enum ieee80211_band band,
- struct ieee80211_vif *vif)
-{
- if (band == IEEE80211_BAND_5GHZ) {
- ctx->staging.flags &=
- ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
- | RXON_FLG_CCK_MSK);
- ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
- } else {
- /* Copied from iwl_post_associate() */
- if (vif && vif->bss_conf.use_short_slot)
- ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
- else
- ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-
- ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
- ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
- ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
- }
-}
-
-/*
- * initialize rxon structure with default values from eeprom
- */
-void iwl_connection_init_rx_config(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx)
-{
- const struct iwl_channel_info *ch_info;
-
- memset(&ctx->staging, 0, sizeof(ctx->staging));
-
- if (!ctx->vif) {
- ctx->staging.dev_type = ctx->unused_devtype;
- } else switch (ctx->vif->type) {
- case NL80211_IFTYPE_AP:
- ctx->staging.dev_type = ctx->ap_devtype;
- break;
-
- case NL80211_IFTYPE_STATION:
- ctx->staging.dev_type = ctx->station_devtype;
- ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
- break;
-
- case NL80211_IFTYPE_ADHOC:
- ctx->staging.dev_type = ctx->ibss_devtype;
- ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
- ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
- RXON_FILTER_ACCEPT_GRP_MSK;
- break;
-
- default:
- IWL_ERR(priv, "Unsupported interface type %d\n",
- ctx->vif->type);
- break;
- }
-
-#if 0
- /* TODO: Figure out when short_preamble would be set and cache from
- * that */
- if (!hw_to_local(priv->hw)->short_preamble)
- ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
- else
- ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-#endif
-
- ch_info = iwl_get_channel_info(priv, priv->band,
- le16_to_cpu(ctx->active.channel));
-
- if (!ch_info)
- ch_info = &priv->channel_info[0];
-
- ctx->staging.channel = cpu_to_le16(ch_info->channel);
- priv->band = ch_info->band;
-
- iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
-
- ctx->staging.ofdm_basic_rates =
- (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
- ctx->staging.cck_basic_rates =
- (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
-
- /* clear both MIX and PURE40 mode flag */
- ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
- RXON_FLG_CHANNEL_MODE_PURE_40);
- if (ctx->vif)
- memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
-
- ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
- ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
- ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff;
-}
-
-void iwl_set_rate(struct iwl_priv *priv)
-{
- const struct ieee80211_supported_band *hw = NULL;
- struct ieee80211_rate *rate;
- struct iwl_rxon_context *ctx;
- int i;
-
- hw = iwl_get_hw_mode(priv, priv->band);
- if (!hw) {
- IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n");
- return;
- }
-
- priv->active_rate = 0;
-
- for (i = 0; i < hw->n_bitrates; i++) {
- rate = &(hw->bitrates[i]);
- if (rate->hw_value < IWL_RATE_COUNT_LEGACY)
- priv->active_rate |= (1 << rate->hw_value);
- }
-
- IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate);
-
- for_each_context(priv, ctx) {
- ctx->staging.cck_basic_rates =
- (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
-
- ctx->staging.ofdm_basic_rates =
- (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
- }
-}
-
-void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
-{
- /*
- * MULTI-FIXME
- * See iwlagn_mac_channel_switch.
- */
- struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
- if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
- ieee80211_chswitch_done(ctx->vif, is_success);
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-void iwl_print_rx_config_cmd(struct iwl_priv *priv,
- enum iwl_rxon_context_id ctxid)
-{
- struct iwl_rxon_context *ctx = &priv->contexts[ctxid];
- struct iwl_rxon_cmd *rxon = &ctx->staging;
-
- IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
- iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
- IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
- IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
- IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n",
- le32_to_cpu(rxon->filter_flags));
- IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type);
- IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n",
- rxon->ofdm_basic_rates);
- IWL_DEBUG_RADIO(priv, "u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
- IWL_DEBUG_RADIO(priv, "u8[6] node_addr: %pM\n", rxon->node_addr);
- IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
- IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
-}
-#endif
-
-void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
-{
- unsigned int reload_msec;
- unsigned long reload_jiffies;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_have_debug_level(IWL_DL_FW_ERRORS))
- iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
-#endif
-
- /* uCode is no longer loaded. */
- priv->ucode_loaded = false;
-
- /* Set the FW error flag -- cleared on iwl_down */
- set_bit(STATUS_FW_ERROR, &priv->status);
-
- /* Cancel currently queued command. */
- clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status);
-
- iwl_abort_notification_waits(&priv->notif_wait);
-
- /* Keep the restart process from trying to send host
- * commands by clearing the ready bit */
- clear_bit(STATUS_READY, &priv->status);
-
- wake_up(&trans(priv)->wait_command_queue);
-
- if (!ondemand) {
- /*
- * If firmware keep reloading, then it indicate something
- * serious wrong and firmware having problem to recover
- * from it. Instead of keep trying which will fill the syslog
- * and hang the system, let's just stop it
- */
- reload_jiffies = jiffies;
- reload_msec = jiffies_to_msecs((long) reload_jiffies -
- (long) priv->reload_jiffies);
- priv->reload_jiffies = reload_jiffies;
- if (reload_msec <= IWL_MIN_RELOAD_DURATION) {
- priv->reload_count++;
- if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) {
- IWL_ERR(priv, "BUG_ON, Stop restarting\n");
- return;
- }
- } else
- priv->reload_count = 0;
- }
-
- if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
- if (iwlagn_mod_params.restart_fw) {
- IWL_DEBUG_FW_ERRORS(priv,
- "Restarting adapter due to uCode error.\n");
- queue_work(priv->workqueue, &priv->restart);
- } else
- IWL_DEBUG_FW_ERRORS(priv,
- "Detected FW error, but not restarting\n");
- }
-}
-
-int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
-{
- int ret;
- s8 prev_tx_power;
- bool defer;
- struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
- lockdep_assert_held(&priv->mutex);
-
- if (priv->tx_power_user_lmt == tx_power && !force)
- return 0;
-
- if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
- IWL_WARN(priv,
- "Requested user TXPOWER %d below lower limit %d.\n",
- tx_power,
- IWLAGN_TX_POWER_TARGET_POWER_MIN);
- return -EINVAL;
- }
-
- if (tx_power > priv->tx_power_device_lmt) {
- IWL_WARN(priv,
- "Requested user TXPOWER %d above upper limit %d.\n",
- tx_power, priv->tx_power_device_lmt);
- return -EINVAL;
- }
-
- if (!iwl_is_ready_rf(priv))
- return -EIO;
-
- /* scan complete and commit_rxon use tx_power_next value,
- * it always need to be updated for newest request */
- priv->tx_power_next = tx_power;
-
- /* do not set tx power when scanning or channel changing */
- defer = test_bit(STATUS_SCANNING, &priv->status) ||
- memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
- if (defer && !force) {
- IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
- return 0;
- }
-
- prev_tx_power = priv->tx_power_user_lmt;
- priv->tx_power_user_lmt = tx_power;
-
- ret = iwlagn_send_tx_power(priv);
-
- /* if fail to set tx_power, restore the orig. tx power */
- if (ret) {
- priv->tx_power_user_lmt = prev_tx_power;
- priv->tx_power_next = prev_tx_power;
- }
- return ret;
-}
-
-void iwl_send_bt_config(struct iwl_priv *priv)
-{
- struct iwl_bt_cmd bt_cmd = {
- .lead_time = BT_LEAD_TIME_DEF,
- .max_kill = BT_MAX_KILL_DEF,
- .kill_ack_mask = 0,
- .kill_cts_mask = 0,
- };
-
- if (!iwlagn_mod_params.bt_coex_active)
- bt_cmd.flags = BT_COEX_DISABLE;
- else
- bt_cmd.flags = BT_COEX_ENABLE;
-
- priv->bt_enable_flag = bt_cmd.flags;
- IWL_DEBUG_INFO(priv, "BT coex %s\n",
- (bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
-
- if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
- IWL_ERR(priv, "failed to send BT Coex Config\n");
-}
-
-int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
-{
- struct iwl_statistics_cmd statistics_cmd = {
- .configuration_flags =
- clear ? IWL_STATS_CONF_CLEAR_STATS : 0,
- };
-
- if (flags & CMD_ASYNC)
- return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
- CMD_ASYNC,
- sizeof(struct iwl_statistics_cmd),
- &statistics_cmd);
- else
- return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
- CMD_SYNC,
- sizeof(struct iwl_statistics_cmd),
- &statistics_cmd);
-}
-
-
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -746,45 +275,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
}
#endif
-int iwl_force_rf_reset(struct iwl_priv *priv, bool external)
-{
- struct iwl_rf_reset *rf_reset;
-
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return -EAGAIN;
-
- if (!iwl_is_any_associated(priv)) {
- IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
- return -ENOLINK;
- }
-
- rf_reset = &priv->rf_reset;
- rf_reset->reset_request_count++;
- if (!external && rf_reset->last_reset_jiffies &&
- time_after(rf_reset->last_reset_jiffies +
- IWL_DELAY_NEXT_FORCE_RF_RESET, jiffies)) {
- IWL_DEBUG_INFO(priv, "RF reset rejected\n");
- rf_reset->reset_reject_count++;
- return -EAGAIN;
- }
- rf_reset->reset_success_count++;
- rf_reset->last_reset_jiffies = jiffies;
-
- /*
- * There is no easy and better way to force reset the radio,
- * the only known method is switching channel which will force to
- * reset and tune the radio.
- * Use internal short scan (single channel) operation to should
- * achieve this objective.
- * Driver should reset the radio when number of consecutive missed
- * beacon, or any other uCode error condition detected.
- */
- IWL_DEBUG_INFO(priv, "perform radio reset.\n");
- iwl_internal_short_hw_scan(priv);
- return 0;
-}
-
-
int iwl_cmd_echo_test(struct iwl_priv *priv)
{
int ret;
@@ -801,97 +291,3 @@ int iwl_cmd_echo_test(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "echo testing pass\n");
return ret;
}
-
-/**
- * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time
- * @priv -- pointer to iwl_priv data structure
- * @tsf_bits -- number of bits need to shift for masking)
- */
-static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv,
- u16 tsf_bits)
-{
- return (1 << tsf_bits) - 1;
-}
-
-/**
- * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time
- * @priv -- pointer to iwl_priv data structure
- * @tsf_bits -- number of bits need to shift for masking)
- */
-static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv,
- u16 tsf_bits)
-{
- return ((1 << (32 - tsf_bits)) - 1) << tsf_bits;
-}
-
-/*
- * extended beacon time format
- * time in usec will be changed into a 32-bit value in extended:internal format
- * the extended part is the beacon counts
- * the internal part is the time in usec within one beacon interval
- */
-u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval)
-{
- u32 quot;
- u32 rem;
- u32 interval = beacon_interval * TIME_UNIT;
-
- if (!interval || !usec)
- return 0;
-
- quot = (usec / interval) &
- (iwl_beacon_time_mask_high(priv, IWLAGN_EXT_BEACON_TIME_POS) >>
- IWLAGN_EXT_BEACON_TIME_POS);
- rem = (usec % interval) & iwl_beacon_time_mask_low(priv,
- IWLAGN_EXT_BEACON_TIME_POS);
-
- return (quot << IWLAGN_EXT_BEACON_TIME_POS) + rem;
-}
-
-/* base is usually what we get from ucode with each received frame,
- * the same as HW timer counter counting down
- */
-__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
- u32 addon, u32 beacon_interval)
-{
- u32 base_low = base & iwl_beacon_time_mask_low(priv,
- IWLAGN_EXT_BEACON_TIME_POS);
- u32 addon_low = addon & iwl_beacon_time_mask_low(priv,
- IWLAGN_EXT_BEACON_TIME_POS);
- u32 interval = beacon_interval * TIME_UNIT;
- u32 res = (base & iwl_beacon_time_mask_high(priv,
- IWLAGN_EXT_BEACON_TIME_POS)) +
- (addon & iwl_beacon_time_mask_high(priv,
- IWLAGN_EXT_BEACON_TIME_POS));
-
- if (base_low > addon_low)
- res += base_low - addon_low;
- else if (base_low < addon_low) {
- res += interval + base_low - addon_low;
- res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
- } else
- res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
-
- return cpu_to_le32(res);
-}
-
-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);
-
- if (state)
- set_bit(STATUS_RF_KILL_HW, &priv->status);
- else
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
-
- wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
-}
-
-void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
-{
- struct ieee80211_tx_info *info;
-
- info = IEEE80211_SKB_CB(skb);
- kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
- dev_kfree_skb_any(skb);
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 96a2f8dee40b..199a0c03774c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -78,19 +78,6 @@ struct iwl_cmd;
* L i b *
***************************/
-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,
- enum ieee80211_band band,
- struct ieee80211_vif *vif);
-void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
-bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx,
- struct ieee80211_sta_ht_cap *ht_cap);
-void iwl_connection_init_rx_config(struct iwl_priv *priv,
- struct iwl_rxon_context *ctx);
-void iwl_set_rate(struct iwl_priv *priv);
int iwl_cmd_echo_test(struct iwl_priv *priv);
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_alloc_traffic_mem(struct iwl_priv *priv);
@@ -131,43 +118,9 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
}
#endif
-/*****************************************************
-* RX
-******************************************************/
-void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
-
-/*****************************************************
- * TX power
- ****************************************************/
-int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
-
/*******************************************************************************
* Scanning
******************************************************************************/
-void iwl_init_scan_params(struct iwl_priv *priv);
-int iwl_scan_cancel(struct iwl_priv *priv);
-void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
-void iwl_force_scan_end(struct iwl_priv *priv);
-void iwl_internal_short_hw_scan(struct iwl_priv *priv);
-void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
-void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
-void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
-int __must_check iwl_scan_initiate(struct iwl_priv *priv,
- struct ieee80211_vif *vif,
- enum iwl_scan_type scan_type,
- enum ieee80211_band band);
-
-/* For faster active scanning, scan will move to the next channel if fewer than
- * PLCP_QUIET_THRESH packets are heard on this channel within
- * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell
- * time if it's a quiet channel (nothing responded to our probe, and there's
- * no other traffic).
- * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
-#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)
-
/* traffic log definitions */
#define IWL_TRAFFIC_ENTRIES (256)
#define IWL_TRAFFIC_ENTRY_SIZE (64)
@@ -175,27 +128,6 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
/*****************************************************
* S e n d i n g H o s t C o m m a n d s *
*****************************************************/
-
-u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
-__le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
- u32 addon, u32 beacon_interval);
-
-extern void iwl_send_bt_config(struct iwl_priv *priv);
-extern int iwl_send_statistics_request(struct iwl_priv *priv,
- u8 flags, bool clear);
-
-static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
- struct iwl_priv *priv, enum ieee80211_band band)
-{
- return priv->hw->wiphy->bands[band];
-}
-
-static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
-{
- return cfg(priv)->bt_params &&
- cfg(priv)->bt_params->advanced_bt_coexist;
-}
-
extern bool bt_siso_mode;
#endif /* __iwl_core_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 2c41423a5e43..d8dd9ac79629 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -861,8 +861,6 @@ struct iwl_priv {
__le16 switch_channel;
- u16 active_rate;
-
u8 start_calib;
struct iwl_sensitivity_data sensitivity_data;
struct iwl_chain_noise_data chain_noise_data;
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
index a3aa5a4fe327..d98249369784 100644
--- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c
+++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
@@ -914,6 +914,21 @@ out:
IWL_DEBUG_MAC80211(priv, "leave\n");
}
+void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
+{
+ /*
+ * MULTI-FIXME
+ * See iwlagn_mac_channel_switch.
+ */
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+ if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+ ieee80211_chswitch_done(ctx->vif, is_success);
+}
+
static void iwlagn_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h
index 68f452dc2272..4b764d7967ca 100644
--- a/drivers/net/wireless/iwlwifi/iwl-shared.h
+++ b/drivers/net/wireless/iwlwifi/iwl-shared.h
@@ -190,7 +190,6 @@ enum iwl_rxon_context_id {
NUM_IWL_RXON_CTX
};
-int iwlagn_hw_valid_rtc_data_addr(u32 addr);
const char *get_cmd_string(u8 cmd);
#define IWL_CMD(x) case x: return #x