From b955fba29b2082bba8cb94a959a8ec0a375aec8f Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Mon, 31 Jan 2011 13:25:29 +0530 Subject: ath9k: Fix memory leak due to failed PAPRD frames free the skb's when the Tx of PAPRD frames fails and also add a debug message indicating that. Signed-off-by: Mohammed Shafi Shajakhan Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 568f7be2ec75..9040c2ff1909 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -325,6 +325,8 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int { struct ieee80211_hw *hw = sc->hw; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); struct ath_tx_control txctl; int time_left; @@ -342,8 +344,12 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int init_completion(&sc->paprd_complete); sc->paprd_pending = true; txctl.paprd = BIT(chain); - if (ath_tx_start(hw, skb, &txctl) != 0) + + if (ath_tx_start(hw, skb, &txctl) != 0) { + ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n"); + dev_kfree_skb_any(skb); return false; + } time_left = wait_for_completion_timeout(&sc->paprd_complete, msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); -- cgit v1.2.3-59-g8ed1b From 10480b056662dc9595850598f0bbc5a16a4884f4 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 14 Jan 2011 17:48:06 -0800 Subject: iwlwifi: check ucode loading error and restart Driver check alive message from ucode, if it is not ok, then need to restart the loading process. instead of checking multiple places for failure, only need to check in once place when receive alive message from uCode. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-4965.c | 8 -------- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 8 -------- drivers/net/wireless/iwlwifi/iwl-agn.c | 15 ++++++--------- 3 files changed, 6 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 7c14eb31d954..ace0b98d91ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -251,14 +251,6 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) */ static void iwl4965_init_alive_start(struct iwl_priv *priv) { - /* Check alive response for "valid" sign from uCode */ - if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { - /* We had an error bringing up the hardware, so take it - * all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); - goto restart; - } - /* Bootstrap uCode has loaded initialize uCode ... verify inst image. * This is a paranoid check, because we would not have gotten the * "initialize" alive if code weren't properly loaded. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 24dabcd2a36c..d807e5e2b718 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -308,14 +308,6 @@ void iwlagn_init_alive_start(struct iwl_priv *priv) { int ret = 0; - /* Check alive response for "valid" sign from uCode */ - if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { - /* We had an error bringing up the hardware, so take it - * all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); - goto restart; - } - /* initialize uCode was loaded... verify inst image. * This is a paranoid check, because we would not have gotten the * "initialize" alive if code weren't properly loaded. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 646ccb2430b4..3e586d3c7d0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -462,8 +462,12 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv, if (palive->is_valid == UCODE_VALID_OK) queue_delayed_work(priv->workqueue, pwork, msecs_to_jiffies(5)); - else - IWL_WARN(priv, "uCode did not respond OK.\n"); + else { + IWL_WARN(priv, "%s uCode did not respond OK.\n", + (palive->ver_subtype == INITIALIZE_SUBTYPE) ? + "init" : "runtime"); + queue_work(priv->workqueue, &priv->restart); + } } static void iwl_bg_beacon_update(struct work_struct *work) @@ -2648,13 +2652,6 @@ static void iwl_alive_start(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); - if (priv->card_alive.is_valid != UCODE_VALID_OK) { - /* We had an error bringing up the hardware, so take it - * all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Alive failed.\n"); - goto restart; - } - /* Initialize uCode has loaded Runtime uCode ... verify inst image. * This is a paranoid check, because we would not have gotten the * "runtime" alive if code weren't properly loaded. */ -- cgit v1.2.3-59-g8ed1b From 7fc11e9bbe3436e8110febf0da5c58bcb4342ede Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 15 Jan 2011 09:16:59 -0800 Subject: iwlagn: adjust rate table Minor adjustment for rate scale table Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 75fcd30a7c13..20d01a312a07 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -179,31 +179,31 @@ static s32 expected_tpt_legacy[IWL_RATE_COUNT] = { }; static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = { - {0, 0, 0, 0, 42, 0, 76, 102, 124, 158, 183, 193, 202}, /* Norm */ - {0, 0, 0, 0, 46, 0, 82, 110, 132, 167, 192, 202, 210}, /* SGI */ - {0, 0, 0, 0, 48, 0, 93, 135, 176, 251, 319, 351, 381}, /* AGG */ - {0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */ + {0, 0, 0, 0, 42, 0, 76, 102, 124, 159, 183, 193, 202}, /* Norm */ + {0, 0, 0, 0, 46, 0, 82, 110, 132, 168, 192, 202, 210}, /* SGI */ + {0, 0, 0, 0, 47, 0, 91, 133, 171, 242, 305, 334, 362}, /* AGG */ + {0, 0, 0, 0, 52, 0, 101, 145, 187, 264, 330, 361, 390}, /* AGG+SGI */ }; static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = { {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */ {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */ - {0, 0, 0, 0, 96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */ - {0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */ + {0, 0, 0, 0, 94, 0, 177, 249, 313, 423, 512, 550, 586}, /* AGG */ + {0, 0, 0, 0, 104, 0, 193, 270, 338, 454, 545, 584, 620}, /* AGG+SGI */ }; static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { - {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */ - {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */ - {0, 0, 0, 0, 92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */ - {0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/ + {0, 0, 0, 0, 74, 0, 123, 155, 179, 214, 236, 244, 251}, /* Norm */ + {0, 0, 0, 0, 81, 0, 131, 164, 188, 223, 243, 251, 257}, /* SGI */ + {0, 0, 0, 0, 89, 0, 167, 235, 296, 402, 488, 526, 560}, /* AGG */ + {0, 0, 0, 0, 97, 0, 182, 255, 320, 431, 520, 558, 593}, /* AGG+SGI*/ }; static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */ {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */ - {0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */ - {0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */ + {0, 0, 0, 0, 171, 0, 305, 410, 496, 634, 731, 771, 805}, /* AGG */ + {0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */ }; static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = { -- cgit v1.2.3-59-g8ed1b From 52e6b85fe07ed1d2b5c76fd42ce1d77f1a190c72 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 18 Jan 2011 08:58:48 -0800 Subject: iwlagn: add IQ inversion support for 2000 series devices The I/Q swapping is extremely important and should be dealt with extra care. It will affects OFDM and CCK differently. For 6000/6005/6030 series devices, the I/Q were swapped, and for 2000 series devices, it is in non-swapped status (but its swapped with respected to 6000/6005/6030). so the CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER register need to be set to support the correct behavior. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-2000.c | 10 ++++++++-- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-csr.h | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 3c9e1b5724c7..ac5996f40e78 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -97,6 +97,10 @@ static void iwl2000_nic_config(struct iwl_priv *priv) CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); + if (priv->cfg->iq_invert) + iwl_set_bit(priv, CSR_GP_DRIVER_REG, + CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); + } static struct iwl_sensitivity_ranges iwl2000_sensitivity = { @@ -428,7 +432,8 @@ static struct iwl_bt_params iwl2030_bt_params = { .base_params = &iwl2000_base_params, \ .need_dc_calib = true, \ .need_temp_offset_calib = true, \ - .led_mode = IWL_LED_RF_STATE \ + .led_mode = IWL_LED_RF_STATE, \ + .iq_invert = true \ struct iwl_cfg iwl2000_2bgn_cfg = { .name = "2000 Series 2x2 BGN", @@ -454,7 +459,8 @@ struct iwl_cfg iwl2000_2bg_cfg = { .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .led_mode = IWL_LED_RF_STATE, \ - .adv_pm = true \ + .adv_pm = true, \ + .iq_invert = true \ struct iwl_cfg iwl2030_2bgn_cfg = { .name = "2000 Series 2x2 BGN/BT", diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index c83fcc60ccc5..b57e739e5bbb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -364,6 +364,7 @@ struct iwl_ht_params { * @adv_pm: advance power management * @rx_with_siso_diversity: 1x1 device with rx antenna diversity * @internal_wimax_coex: internal wifi/wimax combo device + * @iq_invert: I/Q inversion * * We enable the driver to be backward compatible wrt API version. The * driver specifies which APIs it supports (with @ucode_api_max being the @@ -413,6 +414,7 @@ struct iwl_cfg { const bool adv_pm; const bool rx_with_siso_diversity; const bool internal_wimax_coex; + const bool iq_invert; }; /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 6c2b2df7ee7e..f52bc040bcbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -382,6 +382,8 @@ #define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004) #define CSR_GP_DRIVER_REG_BIT_6050_1x2 (0x00000008) +#define CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER (0x00000080) + /* GIO Chicken Bits (PCI Express bus link power management) */ #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) -- cgit v1.2.3-59-g8ed1b From 9dc2153315650eae220898668b6aa56a25c130be Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 17 Jan 2011 11:05:52 -0800 Subject: iwlwifi: always support idle mode for agn devices For agn devices, always support idle mode which help power consumption in idle unassociated state. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-2000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-6000.c | 3 --- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl-power.c | 3 +-- 5 files changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 127723e6319f..ba78bc8a259f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -270,7 +270,6 @@ static struct iwl_base_params iwl1000_base_params = { .ucode_tracing = true, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, - .supports_idle = true, }; static struct iwl_ht_params iwl1000_ht_params = { .ht_greenfield_support = true, diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index ac5996f40e78..8d637e778c65 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -368,7 +368,6 @@ static struct iwl_base_params iwl2000_base_params = { .shadow_ram_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, - .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, @@ -393,7 +392,6 @@ static struct iwl_base_params iwl2030_base_params = { .shadow_ram_support = true, .led_compensation = 57, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, - .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c195674454f4..aa32b1e05dff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -479,7 +479,6 @@ static struct iwl_base_params iwl6000_base_params = { .shadow_ram_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, - .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, @@ -503,7 +502,6 @@ static struct iwl_base_params iwl6050_base_params = { .shadow_ram_support = true, .led_compensation = 51, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, - .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, @@ -526,7 +524,6 @@ static struct iwl_base_params iwl6000_g2_base_params = { .shadow_ram_support = true, .led_compensation = 57, .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, - .supports_idle = true, .adv_thermal_throttle = true, .support_ct_kill_exit = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index b57e739e5bbb..e0ec17079dc0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -305,7 +305,6 @@ struct iwl_base_params { u16 led_compensation; const bool broken_powersave; int chain_noise_num_beacons; - const bool supports_idle; bool adv_thermal_throttle; bool support_ct_kill_exit; const bool support_wimax_coexist; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 25f7d474f346..1d1bf3234d8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -356,8 +356,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, if (priv->cfg->base_params->broken_powersave) iwl_power_sleep_cam_cmd(priv, cmd); - else if (priv->cfg->base_params->supports_idle && - priv->hw->conf.flags & IEEE80211_CONF_IDLE) + else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && priv->cfg->ops->lib->tt_ops.tt_power_mode && -- cgit v1.2.3-59-g8ed1b From 274102a8a2a4a0b67c401b75a96694db76cfc701 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 18 Jan 2011 04:44:03 -0800 Subject: iwlwifi: support RSN IBSS In order to support RSN IBSS, we need to (ok actually maybe it's just easiest to) disable group key programming so that any group-addressed frames will be decrypted in software which handles the per-station keys for this easily. We could keep the encryption in the device, but that takes more work and seems unnecessary. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 11 ++++++++++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3e586d3c7d0f..de84d1f802ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3207,7 +3207,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, hw->wiphy->max_remain_on_channel_duration = 1000; hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | - WIPHY_FLAG_DISABLE_BEACON_HINTS; + WIPHY_FLAG_DISABLE_BEACON_HINTS | + WIPHY_FLAG_IBSS_RSN; /* * For now, disable PS by default because it affects @@ -3359,6 +3360,14 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } + /* + * To support IBSS RSN, don't program group keys in IBSS, the + * hardware will then not attempt to decrypt the frames. + */ + if (vif->type == NL80211_IFTYPE_ADHOC && + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta); if (sta_id == IWL_INVALID_STATION) return -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 2945acd955f0..76fae81ddc4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -3286,6 +3286,14 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } + /* + * To support IBSS RSN, don't program group keys in IBSS, the + * hardware will then not attempt to decrypt the frames. + */ + if (vif->type == NL80211_IFTYPE_ADHOC && + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) + return -EOPNOTSUPP; + static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS); if (!static_key) { @@ -3915,7 +3923,8 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) priv->contexts[IWL_RXON_CTX_BSS].interface_modes; hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | - WIPHY_FLAG_DISABLE_BEACON_HINTS; + WIPHY_FLAG_DISABLE_BEACON_HINTS | + WIPHY_FLAG_IBSS_RSN; hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; /* we create the 802.11 header and a zero-length SSID element */ -- cgit v1.2.3-59-g8ed1b From 9b7688328422b88a7a15dc0dc123ad9ab1a6e22d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Jan 2011 02:54:18 -0800 Subject: iwlwifi: advertise max aggregate size Allow peers to size their reorder buffer more accurately by advertising that we'll never send aggregates longer than the default (31). Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index de84d1f802ec..dcc4b2d55988 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3188,6 +3188,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS; + hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; + if (!priv->cfg->base_params->broken_powersave) hw->flags |= IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; -- cgit v1.2.3-59-g8ed1b From 7b09068721b1a1bbba9372d0293c21d2425b14de Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Jan 2011 02:53:54 -0800 Subject: iwlwifi: use maximum aggregation size Use the values from the peer to set up the ucode for the right maximum number of subframes in an aggregate. Since the ucode only tracks this per station, use the minimum across all aggregation sessions with this peer. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 5 ++++- drivers/net/wireless/iwlwifi/iwl-agn.c | 32 ++++++++++++++++++++++++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 20d01a312a07..d03b4734c892 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2890,6 +2890,8 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, u8 ant_toggle_cnt = 0; u8 use_ht_possible = 1; u8 valid_tx_ant = 0; + struct iwl_station_priv *sta_priv = + container_of(lq_sta, struct iwl_station_priv, lq_sta); struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq; /* Override starting rate (index 0) if needed for debug purposes */ @@ -3008,7 +3010,8 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, repeat_rate--; } - lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; + lq_cmd->agg_params.agg_frame_cnt_limit = + sta_priv->max_agg_bufsize ?: LINK_QUAL_AGG_FRAME_LIMIT_DEF; lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; lq_cmd->agg_params.agg_time_limit = diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index dcc4b2d55988..cf285f53ad1d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3429,6 +3429,7 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; int ret = -EINVAL; + struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", sta->addr, tid); @@ -3483,11 +3484,28 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, } break; case IEEE80211_AMPDU_TX_OPERATIONAL: + /* + * If the limit is 0, then it wasn't initialised yet, + * use the default. We can do that since we take the + * minimum below, and we don't want to go above our + * default due to hardware restrictions. + */ + if (sta_priv->max_agg_bufsize == 0) + sta_priv->max_agg_bufsize = + LINK_QUAL_AGG_FRAME_LIMIT_DEF; + + /* + * Even though in theory the peer could have different + * aggregation reorder buffer sizes for different sessions, + * our ucode doesn't allow for that and has a global limit + * for each station. Therefore, use the minimum of all the + * aggregation sessions and our default value. + */ + sta_priv->max_agg_bufsize = + min(sta_priv->max_agg_bufsize, buf_size); + if (priv->cfg->ht_params && priv->cfg->ht_params->use_rts_for_aggregation) { - struct iwl_station_priv *sta_priv = - (void *) sta->drv_priv; - /* * switch to RTS/CTS if it is the prefer protection * method for HT traffic @@ -3495,9 +3513,13 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, sta_priv->lq_sta.lq.general_params.flags |= LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; - iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), - &sta_priv->lq_sta.lq, CMD_ASYNC, false); } + + sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit = + sta_priv->max_agg_bufsize; + + iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), + &sta_priv->lq_sta.lq, CMD_ASYNC, false); ret = 0; break; } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b5f21e041953..c56b797e1a1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -509,6 +509,7 @@ struct iwl_station_priv { atomic_t pending_frames; bool client; bool asleep; + u8 max_agg_bufsize; }; /** -- cgit v1.2.3-59-g8ed1b From 241887a2d3b725fd0f87113bb7c4a51b5c6a2d06 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Jan 2011 11:11:22 -0800 Subject: iwlwifi: fix beacon notification parsing The beacon notification changed between 4965 and agn because the embedded TX response changed, but iwlwifi was never updated to know about this. Update it now so the IBSS manager status will be tracked correctly. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-4965.c | 24 ++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 16 ++++++++-------- drivers/net/wireless/iwlwifi/iwl-commands.h | 7 +++++++ 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index ace0b98d91ae..8998ed134d1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2266,6 +2266,29 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, spin_unlock_irqrestore(&priv->sta_lock, flags); } +static void iwl4965_rx_beacon_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl4965_beacon_notif *beacon = (void *)pkt->u.raw; +#ifdef CONFIG_IWLWIFI_DEBUG + u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); + + IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d " + "tsf:0x%.8x%.8x rate:%d\n", + le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK, + beacon->beacon_notify_hdr.failure_frame, + le32_to_cpu(beacon->ibss_mgr_status), + le32_to_cpu(beacon->high_tsf), + le32_to_cpu(beacon->low_tsf), rate); +#endif + + priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); + + if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) + queue_work(priv->workqueue, &priv->beacon_update); +} + static int iwl4965_calc_rssi(struct iwl_priv *priv, struct iwl_rx_phy_res *rx_resp) { @@ -2308,6 +2331,7 @@ static void iwl4965_rx_handler_setup(struct iwl_priv *priv) priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx; /* Tx response */ priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; + priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif; /* set up notification wait support */ spin_lock_init(&priv->_agn.notif_wait_lock); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index cf285f53ad1d..d62e59249667 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -704,18 +704,18 @@ static void iwl_bg_ucode_trace(unsigned long data) } } -static void iwl_rx_beacon_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) +static void iwlagn_rx_beacon_notif(struct iwl_priv *priv, + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl4965_beacon_notif *beacon = - (struct iwl4965_beacon_notif *)pkt->u.raw; + struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; #ifdef CONFIG_IWLWIFI_DEBUG + u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status); u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); - IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " - "tsf %d %d rate %d\n", - le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK, + IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d " + "tsf:0x%.8x%.8x rate:%d\n", + status & TX_STATUS_MSK, beacon->beacon_notify_hdr.failure_frame, le32_to_cpu(beacon->ibss_mgr_status), le32_to_cpu(beacon->high_tsf), @@ -818,7 +818,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif; - priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif; + priv->rx_handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif; /* * The same handler is used for both the REPLY to a discrete diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 935b19e2c260..c3ab6ba5b45a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3083,6 +3083,13 @@ struct iwl4965_beacon_notif { __le32 ibss_mgr_status; } __packed; +struct iwlagn_beacon_notif { + struct iwlagn_tx_resp beacon_notify_hdr; + __le32 low_tsf; + __le32 high_tsf; + __le32 ibss_mgr_status; +} __packed; + /* * REPLY_TX_BEACON = 0x91 (command, has simple generic response) */ -- cgit v1.2.3-59-g8ed1b From 96234cc84e0cce55421e981a865a4817db24ba4a Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 24 Jan 2011 11:44:42 -0800 Subject: iwlagn: use 2030 macro for 2030 devices For 2030 series of devices, 2030 macro need to be used. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-2000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 8d637e778c65..3c5dd36ff417 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -462,13 +462,13 @@ struct iwl_cfg iwl2000_2bg_cfg = { struct iwl_cfg iwl2030_2bgn_cfg = { .name = "2000 Series 2x2 BGN/BT", - IWL_DEVICE_2000, + IWL_DEVICE_2030, .ht_params = &iwl2000_ht_params, }; struct iwl_cfg iwl2030_2bg_cfg = { .name = "2000 Series 2x2 BG/BT", - IWL_DEVICE_2000, + IWL_DEVICE_2030, }; #define IWL_DEVICE_6035 \ -- cgit v1.2.3-59-g8ed1b From 187bc4f6b2f81e1c8f6b1e9d5dee3e8e9018ebbf Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 27 Jan 2011 13:01:33 -0800 Subject: iwlagn: remove unsupported BT SCO command During the period of BT coex changes, REPLY_BT_COEX_SCO host command is no longer needed to support SCO/eSCO type of traffic. delete it. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 24 ------------------------ drivers/net/wireless/iwlwifi/iwl-agn.c | 5 +---- drivers/net/wireless/iwlwifi/iwl-commands.h | 1 - drivers/net/wireless/iwlwifi/iwl-debugfs.c | 7 +++---- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - 5 files changed, 4 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index c7d03874b380..600f41745b99 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1863,21 +1863,6 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd)) IWL_ERR(priv, "failed to send BT Coex Config\n"); - /* - * When we are doing a restart, need to also reconfigure BT - * SCO to the device. If not doing a restart, bt_sco_active - * will always be false, so there's no need to have an extra - * variable to check for it. - */ - if (priv->bt_sco_active) { - struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 }; - - if (priv->bt_sco_active) - sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE; - if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_SCO, - sizeof(sco_cmd), &sco_cmd)) - IWL_ERR(priv, "failed to send BT SCO command\n"); - } } static void iwlagn_bt_traffic_change_work(struct work_struct *work) @@ -2069,15 +2054,6 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, queue_work(priv->workqueue, &priv->bt_traffic_change_work); } - if (priv->bt_sco_active != - (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) { - priv->bt_sco_active = uart_msg->frame3 & - BT_UART_MSG_FRAME3SCOESCO_MSK; - if (priv->bt_sco_active) - sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE; - iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO, - sizeof(sco_cmd), &sco_cmd, NULL); - } } iwlagn_set_kill_msk(priv, uart_msg); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index d62e59249667..a5daf6447178 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2780,7 +2780,6 @@ static void __iwl_down(struct iwl_priv *priv) priv->cfg->bt_params->bt_init_traffic_load; else priv->bt_traffic_load = 0; - priv->bt_sco_active = false; priv->bt_full_concurrent = false; priv->bt_ci_compliance = 0; @@ -3099,7 +3098,7 @@ static void iwl_bg_restart(struct work_struct *data) if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { struct iwl_rxon_context *ctx; - bool bt_sco, bt_full_concurrent; + bool bt_full_concurrent; u8 bt_ci_compliance; u8 bt_load; u8 bt_status; @@ -3118,7 +3117,6 @@ static void iwl_bg_restart(struct work_struct *data) * re-configure the hw when we reconfigure the BT * command. */ - bt_sco = priv->bt_sco_active; bt_full_concurrent = priv->bt_full_concurrent; bt_ci_compliance = priv->bt_ci_compliance; bt_load = priv->bt_traffic_load; @@ -3126,7 +3124,6 @@ static void iwl_bg_restart(struct work_struct *data) __iwl_down(priv); - priv->bt_sco_active = bt_sco; priv->bt_full_concurrent = bt_full_concurrent; priv->bt_ci_compliance = bt_ci_compliance; priv->bt_traffic_load = bt_load; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index c3ab6ba5b45a..0a1d4aeb36aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -178,7 +178,6 @@ enum { REPLY_BT_COEX_PRIO_TABLE = 0xcc, REPLY_BT_COEX_PROT_ENV = 0xcd, REPLY_BT_COEX_PROFILE_NOTIF = 0xce, - REPLY_BT_COEX_SCO = 0xcf, /* PAN commands */ REPLY_WIPAN_PARAMS = 0xb2, diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index bdcb74279f1e..bc7a965c18f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1587,10 +1587,9 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, "last traffic notif: %d\n", priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load); pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, " - "sco_active: %d, kill_ack_mask: %x, " - "kill_cts_mask: %x\n", - priv->bt_ch_announce, priv->bt_sco_active, - priv->kill_ack_mask, priv->kill_cts_mask); + "kill_ack_mask: %x, kill_cts_mask: %x\n", + priv->bt_ch_announce, priv->kill_ack_mask, + priv->kill_cts_mask); pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: "); switch (priv->bt_traffic_load) { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c56b797e1a1a..ecfbef402781 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1504,7 +1504,6 @@ struct iwl_priv { u8 bt_status; u8 bt_traffic_load, last_bt_traffic_load; bool bt_ch_announce; - bool bt_sco_active; bool bt_full_concurrent; bool bt_ant_couple_ok; __le32 kill_ack_mask; -- cgit v1.2.3-59-g8ed1b From c52bf9b73ad1086fbf7f8b5fdd0acdc66637e80b Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 29 Jan 2011 08:13:27 -0800 Subject: iiwlagn: remove unused parameter sco_cmd is not being used, remove it Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 600f41745b99..d4ba3357b628 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2023,7 +2023,6 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, unsigned long flags; struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; - struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 }; struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); -- cgit v1.2.3-59-g8ed1b