Skip to content

Commit

Permalink
Merge branch 'wireless-next' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/iwlwifi/iwlwifi
  • Loading branch information
linvjw committed Apr 16, 2012
2 parents 94a2ca3 + ef213d6 commit 0d92098
Show file tree
Hide file tree
Showing 15 changed files with 755 additions and 763 deletions.
29 changes: 15 additions & 14 deletions drivers/net/wireless/iwlwifi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
74 changes: 74 additions & 0 deletions drivers/net/wireless/iwlwifi/iwl-agn-devices.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
30 changes: 18 additions & 12 deletions drivers/net/wireless/iwlwifi/iwl-agn-lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down
12 changes: 10 additions & 2 deletions drivers/net/wireless/iwlwifi/iwl-agn-rs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
39 changes: 39 additions & 0 deletions drivers/net/wireless/iwlwifi/iwl-agn-rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading

0 comments on commit 0d92098

Please sign in to comment.