From 678b385d07835c6c21371c12eaaa3fba4de05168 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 26 Mar 2010 12:54:37 -0700 Subject: iwlwifi: default max event log size Size of event log is determined by uCode which is different per NICs. Set the maximum event log size per device to better match uCode configuration. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-3945.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-5000.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-6000.c | 7 +++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 15 ++++++--------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl3945-base.c | 15 ++++++--------- 8 files changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index b941b3e95697..9a0191a5ea35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -253,6 +253,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 128, }; struct iwl_cfg iwl1000_bg_cfg = { @@ -282,6 +283,7 @@ struct iwl_cfg iwl1000_bg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 128, }; MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index f88f75dfd96e..7424586a5edb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2770,6 +2770,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; static struct iwl_cfg iwl3945_abg_cfg = { @@ -2789,6 +2790,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { .broken_powersave = true, .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 6edae9b83bb7..0164c3f2109d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2250,6 +2250,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .monitor_recover_period = IWL_MONITORING_PERIOD, .temperature_kelvin = true, .off_channel_workaround = true, + .max_event_log_size = 512, }; /* Module firmware */ diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index ecc302e4c205..e967cfcac224 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -423,6 +423,7 @@ struct iwl_cfg iwl5300_agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5100_bgn_cfg = { @@ -450,6 +451,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5100_abg_cfg = { @@ -475,6 +477,7 @@ struct iwl_cfg iwl5100_abg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5100_agn_cfg = { @@ -502,6 +505,7 @@ struct iwl_cfg iwl5100_agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5350_agn_cfg = { @@ -529,6 +533,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5150_agn_cfg = { @@ -556,6 +561,7 @@ struct iwl_cfg iwl5150_agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; struct iwl_cfg iwl5150_abg_cfg = { @@ -581,6 +587,7 @@ struct iwl_cfg iwl5150_abg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 512, }; MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 7473518e7e0a..dd03384432f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -394,6 +394,7 @@ struct iwl_cfg iwl6000i_g2_2agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6000i_2agn_cfg = { @@ -427,6 +428,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6000i_2abg_cfg = { @@ -459,6 +461,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6000i_2bg_cfg = { @@ -491,6 +494,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6050_2agn_cfg = { @@ -524,6 +528,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6050_2abg_cfg = { @@ -556,6 +561,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1500, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; struct iwl_cfg iwl6000_3agn_cfg = { @@ -589,6 +595,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, .chain_noise_scale = 1000, .monitor_recover_period = IWL_MONITORING_PERIOD, + .max_event_log_size = 1024, }; MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4f0cb803f732..978604f8ae92 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1990,9 +1990,6 @@ static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, return pos; } -/* For sanity check only. Actual size is determined by uCode, typ. 512 */ -#define MAX_EVENT_LOG_SIZE (512) - #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, @@ -2025,16 +2022,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); - if (capacity > MAX_EVENT_LOG_SIZE) { + if (capacity > priv->cfg->max_event_log_size) { IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", - capacity, MAX_EVENT_LOG_SIZE); - capacity = MAX_EVENT_LOG_SIZE; + capacity, priv->cfg->max_event_log_size); + capacity = priv->cfg->max_event_log_size; } - if (next_entry > MAX_EVENT_LOG_SIZE) { + if (next_entry > priv->cfg->max_event_log_size) { IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", - next_entry, MAX_EVENT_LOG_SIZE); - next_entry = MAX_EVENT_LOG_SIZE; + next_entry, priv->cfg->max_event_log_size); + next_entry = priv->cfg->max_event_log_size; } size = num_wraps ? capacity : next_entry; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 10f95724536f..d89755f5031a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -307,6 +307,7 @@ struct iwl_cfg { u32 monitor_recover_period; bool temperature_kelvin; bool off_channel_workaround; + u32 max_event_log_size; }; /*************************** diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c9188b9c5651..24e969440b31 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1603,9 +1603,6 @@ static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, return pos; } -/* For sanity check only. Actual size is determined by uCode, typ. 512 */ -#define IWL3945_MAX_EVENT_LOG_SIZE (512) - #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, @@ -1632,16 +1629,16 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); - if (capacity > IWL3945_MAX_EVENT_LOG_SIZE) { + if (capacity > priv->cfg->max_event_log_size) { IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", - capacity, IWL3945_MAX_EVENT_LOG_SIZE); - capacity = IWL3945_MAX_EVENT_LOG_SIZE; + capacity, priv->cfg->max_event_log_size); + capacity = priv->cfg->max_event_log_size; } - if (next_entry > IWL3945_MAX_EVENT_LOG_SIZE) { + if (next_entry > priv->cfg->max_event_log_size) { IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", - next_entry, IWL3945_MAX_EVENT_LOG_SIZE); - next_entry = IWL3945_MAX_EVENT_LOG_SIZE; + next_entry, priv->cfg->max_event_log_size); + next_entry = priv->cfg->max_event_log_size; } size = num_wraps ? capacity : next_entry; -- cgit v1.2.3 From 335348b1702cf78c9e79987a3d66e85a05c98b5c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2010 10:11:46 -0700 Subject: iwlwifi: make WEP key restoring explicit The firmware clears default WEP keys on transitions to !associated, so we need to restore them just like stations. This is rather implicit as part of sending a station right now, which is odd. Make it explicit instead and only for agn since 3945 doesn't use hw crypto for WEP. Due to that, iwl_send_static_wepkey_cmd is now only used in iwl-sta.c and can be static. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 25 ++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 1 - drivers/net/wireless/iwlwifi/iwl-sta.c | 14 +++++++++----- drivers/net/wireless/iwlwifi/iwl-sta.h | 2 +- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 978604f8ae92..8a3b0edf83b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -158,6 +158,11 @@ int iwl_commit_rxon(struct iwl_priv *priv) } iwl_clear_ucode_stations(priv, false); iwl_restore_stations(priv); + ret = iwl_restore_default_wep_keys(priv); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } } IWL_DEBUG_INFO(priv, "Sending RXON\n" @@ -185,6 +190,11 @@ int iwl_commit_rxon(struct iwl_priv *priv) memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); iwl_clear_ucode_stations(priv, false); iwl_restore_stations(priv); + ret = iwl_restore_default_wep_keys(priv); + if (ret) { + IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); + return ret; + } } priv->start_calib = 0; @@ -3030,19 +3040,6 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, } } -/** - * iwl_restore_wepkeys - Restore WEP keys to device - */ -static void iwl_restore_wepkeys(struct iwl_priv *priv) -{ - mutex_lock(&priv->mutex); - if (priv->iw_mode == NL80211_IFTYPE_STATION && - priv->default_wep_key && - iwl_send_static_wepkey_cmd(priv, 0)) - IWL_ERR(priv, "Could not send WEP static key\n"); - mutex_unlock(&priv->mutex); -} - static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) @@ -3069,8 +3066,6 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, return ret; } - iwl_restore_wepkeys(priv); - /* Initialize rate scaling */ IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4319bda487d9..95c2bc3c79ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1167,7 +1167,6 @@ struct iwl_priv { int num_stations; struct iwl_station_entry stations[IWL_STATION_COUNT]; struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */ - u8 default_wep_key; u8 key_mapping_key; unsigned long ucode_key_table; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index e34ac0355c75..be3d222d8f2b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -759,7 +759,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_get_free_ucode_key_index); -int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) +static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) { int i, not_empty = 0; u8 buff[sizeof(struct iwl_wep_cmd) + @@ -803,7 +803,14 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) else return 0; } -EXPORT_SYMBOL(iwl_send_static_wepkey_cmd); + +int iwl_restore_default_wep_keys(struct iwl_priv *priv) +{ + WARN_ON(!mutex_is_locked(&priv->mutex)); + + return iwl_send_static_wepkey_cmd(priv, 0); +} +EXPORT_SYMBOL(iwl_restore_default_wep_keys); int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf) @@ -819,7 +826,6 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, IWL_ERR(priv, "index %d not used in uCode key table.\n", keyconf->keyidx); - priv->default_wep_key--; memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); if (iwl_is_rfkill(priv)) { IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); @@ -851,8 +857,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->hw_key_idx = HW_KEY_DEFAULT; priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; - priv->default_wep_key++; - if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) IWL_ERR(priv, "index %d already used in uCode key table.\n", keyconf->keyidx); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 87a34997a758..42cd2f4a01cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -44,11 +44,11 @@ */ u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); -int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); int iwl_set_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); +int iwl_restore_default_wep_keys(struct iwl_priv *priv); int iwl_set_dynamic_key(struct iwl_priv *priv, struct ieee80211_key_conf *key, u8 sta_id); int iwl_remove_dynamic_key(struct iwl_priv *priv, -- cgit v1.2.3 From 43a61261d7f571f760611711cd4e6b64ef661ad1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2010 02:43:05 -0700 Subject: iwlwifi: remove wrong key use check Default WEP keys and regular keys are not allocated from the same space in the firmware, so we shouldn't use the same bits to indicate in use. For default WEP keys, however, mac80211 won't allow using the same key index twice, so the check is not necessary at all -- add/remove are perfectly nested due to those checks. Other keys are allocated in the device in a global array that only has a certain number of slots, so for that we need to keep the allocation bitmap; but the 802.11 key index isn't relevant there. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index be3d222d8f2b..a43493f2abcf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -822,10 +822,6 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", keyconf->keyidx); - if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) - IWL_ERR(priv, "index %d not used in uCode key table.\n", - keyconf->keyidx); - memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); if (iwl_is_rfkill(priv)) { IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); @@ -857,10 +853,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, keyconf->hw_key_idx = HW_KEY_DEFAULT; priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; - if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) - IWL_ERR(priv, "index %d already used in uCode key table.\n", - keyconf->keyidx); - priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, keyconf->keylen); -- cgit v1.2.3 From a90178fa1dce52816ae9fa4a3ba031886b79c5ae Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2010 02:44:16 -0700 Subject: iwlagn: simplify WEP key check Simplify the WEP group key check by checking the sta pointer instead of the sta_id we calculate with it; also clean up the comment formatting. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8a3b0edf83b0..3526d5ee4755 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2901,12 +2901,13 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mutex_lock(&priv->mutex); iwl_scan_cancel_timeout(priv, 100); - /* If we are getting WEP group key and we didn't receive any key mapping + /* + * If we are getting WEP group key and we didn't receive any key mapping * so far, we are in legacy wep mode (group key only), otherwise we are * in 1X mode. - * In legacy wep mode, we use another host command to the uCode */ - if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id && - priv->iw_mode != NL80211_IFTYPE_AP) { + * In legacy wep mode, we use another host command to the uCode. + */ + if (key->alg == ALG_WEP && !sta && vif->type != NL80211_IFTYPE_AP) { if (cmd == SET_KEY) is_default_wep_key = !priv->key_mapping_key; else -- cgit v1.2.3 From 76c3c698bf47927fb31044fa2f4321c99ed7411d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Mar 2010 02:46:29 -0700 Subject: iwlwifi: remove pointless sta_id invalid check lq->sta_id cannot be invalid here since this function will only be called after the station has been added properly. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index a43493f2abcf..6876f7c59368 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -1187,13 +1187,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, .data = lq, }; - if ((lq->sta_id == 0xFF) && - (priv->iw_mode == NL80211_IFTYPE_ADHOC)) + if (WARN_ON(lq->sta_id == IWL_INVALID_STATION)) return -EINVAL; - if (lq->sta_id == 0xFF) - lq->sta_id = IWL_AP_ID; - iwl_dump_lq_cmd(priv, lq); BUG_ON(init && (cmd.flags & CMD_ASYNC)); -- cgit v1.2.3 From 05d5752027d02ca9204d1ece5074d41000fee23d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 31 Mar 2010 08:59:17 -0700 Subject: iwlwifi: clean up last_phy_res The last_phy_res[100] variable is used in an odd way. The first byte of it is used as a flag, and the rest as the data. Thus, the array need only be 61 bytes, since it is just the flag and a struct iwl_rx_phy_res (which is 60 bytes). Clean this up by splitting the variable into two: last_phy_res and last_phy_res_valid, using correct types for both (struct and bool). While doing all this also move the variables to the _agn part of the hw-specific union since they only apply to A-MPDUs. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 49e20f1acb7c..7f27a945c187 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1001,11 +1001,11 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, phy_res->cfg_phy_cnt + len); ampdu_status = le32_to_cpu(rx_pkt_status); } else { - if (!priv->last_phy_res[0]) { + if (!priv->_agn.last_phy_res_valid) { IWL_ERR(priv, "MPDU frame without cached PHY data\n"); return; } - phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; + phy_res = &priv->_agn.last_phy_res; amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); len = le16_to_cpu(amsdu->byte_count); @@ -1094,10 +1094,10 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) + struct iwl_rx_mem_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - priv->last_phy_res[0] = 1; - memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), + priv->_agn.last_phy_res_valid = true; + memcpy(&priv->_agn.last_phy_res, pkt->u.raw, sizeof(struct iwl_rx_phy_res)); } diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 95c2bc3c79ed..9466e909f553 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1120,7 +1120,6 @@ struct iwl_priv { __le16 sensitivity_tbl[HD_TABLE_SIZE]; struct iwl_ht_config current_ht_config; - u8 last_phy_res[100]; /* Rate scaling data */ u8 retry_rate; @@ -1237,6 +1236,9 @@ struct iwl_priv { * no AGGREGATION */ u8 agg_tids_count; + + struct iwl_rx_phy_res last_phy_res; + bool last_phy_res_valid; } _agn; #endif }; -- cgit v1.2.3 From 461ef382fd68f02b7bac8f94f7f2b85162bad896 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 30 Mar 2010 17:57:53 -0700 Subject: iwlwifi: add more debug info in error event dump When sys assert happen, driver will dump the error table information provided by uCode. There are more information available but is not being display by the driver; adding program counter and last host command the to log to help uCode debugging. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 ++++++---- drivers/net/wireless/iwlwifi/iwl-commands.h | 27 ++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 3526d5ee4755..8a002c6f3a61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1843,6 +1843,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) u32 data2, line; u32 desc, time, count, base, data1; u32 blink1, blink2, ilink1, ilink2; + u32 pc, hcmd; if (priv->ucode_type == UCODE_INIT) base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); @@ -1865,6 +1866,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) } desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); + pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); @@ -1873,6 +1875,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); + hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32)); trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, blink1, blink2, ilink1, ilink2); @@ -1881,10 +1884,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) "data1 data2 line\n"); IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", desc_lookup(desc), desc, time, data1, data2, line); - IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n"); - IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, - ilink1, ilink2); - + IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); + IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", + pc, blink1, blink2, ilink1, ilink2, hcmd); } #define EVENT_START_OFFSET (4 * sizeof(u32)) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6383d9f8c9b3..74d6887c7500 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -512,8 +512,9 @@ struct iwl_init_alive_resp { * * Entries without timestamps contain only event_id and data. * + * * 2) error_event_table_ptr indicates base of the error log. This contains - * information about any uCode error that occurs. For 4965, the format + * information about any uCode error that occurs. For agn, the format * of the error log is: * * __le32 valid; (nonzero) valid, (0) log is empty @@ -529,6 +530,30 @@ struct iwl_init_alive_resp { * __le32 bcon_time; beacon timer * __le32 tsf_low; network timestamp function timer * __le32 tsf_hi; network timestamp function timer + * __le32 gp1; GP1 timer register + * __le32 gp2; GP2 timer register + * __le32 gp3; GP3 timer register + * __le32 ucode_ver; uCode version + * __le32 hw_ver; HW Silicon version + * __le32 brd_ver; HW board version + * __le32 log_pc; log program counter + * __le32 frame_ptr; frame pointer + * __le32 stack_ptr; stack pointer + * __le32 hcmd; last host command + * __le32 isr0; isr status register LMPM_NIC_ISR0: rxtx_flag + * __le32 isr1; isr status register LMPM_NIC_ISR1: host_flag + * __le32 isr2; isr status register LMPM_NIC_ISR2: enc_flag + * __le32 isr3; isr status register LMPM_NIC_ISR3: time_flag + * __le32 isr4; isr status register LMPM_NIC_ISR4: wico interrupt + * __le32 isr_pref; isr status register LMPM_NIC_PREF_STAT + * __le32 wait_event; wait event() caller address + * __le32 l2p_control; L2pControlField + * __le32 l2p_duration; L2pDurationField + * __le32 l2p_mhvalid; L2pMhValidBits + * __le32 l2p_addr_match; L2pAddrMatchStat + * __le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL) + * __le32 u_timestamp; indicate when the date and time of the compilation + * __le32 reserved; * * The Linux driver can print both logs to the system log when a uCode error * occurs. -- cgit v1.2.3 From 04569cbe7653fe0057acc46afc07f2c2fd2508b3 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 31 Mar 2010 17:57:28 -0700 Subject: iwlwifi: update tx command response status Update to include additional tx command response status for "_agn" devices. The following status indicate the transmission was postponed: TX_STATUS_POSTPONE_DELAY TX_STATUS_POSTPONE_FEW_BYTES TX_STATUS_POSTPONE_BT_PRIO TX_STATUS_POSTPONE_QUIET_PERIOD TX_STATUS_POSTPONE_CALC_TTAK Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 3 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 11 +++- drivers/net/wireless/iwlwifi/iwl-agn.h | 24 +++++++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 79 ++++++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-tx.c | 41 ++++++++------- 6 files changed, 108 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7424586a5edb..ae5efc376b91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -191,12 +191,12 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) } #ifdef CONFIG_IWLWIFI_DEBUG -#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x +#define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x static const char *iwl3945_get_tx_fail_reason(u32 status) { switch (status & TX_STATUS_MSK) { - case TX_STATUS_SUCCESS: + case TX_3945_STATUS_SUCCESS: return "SUCCESS"; TX_STATUS_ENTRY(SHORT_LIMIT); TX_STATUS_ENTRY(LONG_LIMIT); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 0164c3f2109d..c710b26a1c86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2049,8 +2049,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); + iwl_check_abort_status(priv, tx_resp->frame_count, status); } static int iwl4965_calc_rssi(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 7f27a945c187..384b45c519f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -161,6 +161,14 @@ static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, return 0; } +void iwl_check_abort_status(struct iwl_priv *priv, + u8 frame_count, u32 status) +{ + if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { + IWL_ERR(priv, "TODO: Implement Tx flush command!!!\n"); + } +} + static void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { @@ -246,8 +254,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv, iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); + iwl_check_abort_status(priv, tx_resp->frame_count, status); } void iwlagn_rx_handler_setup(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 5ad14055eda3..608060abe80c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -105,6 +105,8 @@ void iwlagn_init_alive_start(struct iwl_priv *priv); int iwlagn_alive_notify(struct iwl_priv *priv); /* lib */ +void iwl_check_abort_status(struct iwl_priv *priv, + u8 frame_count, u32 status); void iwlagn_rx_handler_setup(struct iwl_priv *priv); void iwlagn_setup_deferred_work(struct iwl_priv *priv); int iwlagn_hw_valid_rtc_data_addr(u32 addr); @@ -146,4 +148,26 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); int iwlagn_txq_ctx_reset(struct iwl_priv *priv); void iwlagn_txq_ctx_stop(struct iwl_priv *priv); +static inline u32 iwl_tx_status_to_mac80211(u32 status) +{ + status &= TX_STATUS_MSK; + + switch (status) { + case TX_STATUS_SUCCESS: + case TX_STATUS_DIRECT_DONE: + return IEEE80211_TX_STAT_ACK; + case TX_STATUS_FAIL_DEST_PS: + return IEEE80211_TX_STAT_TX_FILTERED; + default: + return 0; + } +} + +static inline bool iwl_is_tx_success(u32 status) +{ + status &= TX_STATUS_MSK; + return (status == TX_STATUS_SUCCESS) || + (status == TX_STATUS_DIRECT_DONE); +} + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 74d6887c7500..82a9378f72e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -1662,7 +1662,7 @@ struct iwl_tx_cmd { struct ieee80211_hdr hdr[0]; } __attribute__ ((packed)); -/* TX command response is sent after *all* transmission attempts. +/* TX command response is sent after *3945* transmission attempts. * * NOTES: * @@ -1689,25 +1689,66 @@ struct iwl_tx_cmd { * command FIFO has been cleared. The host must then deactivate the TX Abort * control line. Receiving is still allowed in this case. */ +enum { + TX_3945_STATUS_SUCCESS = 0x01, + TX_3945_STATUS_DIRECT_DONE = 0x02, + TX_3945_STATUS_FAIL_SHORT_LIMIT = 0x82, + TX_3945_STATUS_FAIL_LONG_LIMIT = 0x83, + TX_3945_STATUS_FAIL_FIFO_UNDERRUN = 0x84, + TX_3945_STATUS_FAIL_MGMNT_ABORT = 0x85, + TX_3945_STATUS_FAIL_NEXT_FRAG = 0x86, + TX_3945_STATUS_FAIL_LIFE_EXPIRE = 0x87, + TX_3945_STATUS_FAIL_DEST_PS = 0x88, + TX_3945_STATUS_FAIL_ABORTED = 0x89, + TX_3945_STATUS_FAIL_BT_RETRY = 0x8a, + TX_3945_STATUS_FAIL_STA_INVALID = 0x8b, + TX_3945_STATUS_FAIL_FRAG_DROPPED = 0x8c, + TX_3945_STATUS_FAIL_TID_DISABLE = 0x8d, + TX_3945_STATUS_FAIL_FRAME_FLUSHED = 0x8e, + TX_3945_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, + TX_3945_STATUS_FAIL_TX_LOCKED = 0x90, + TX_3945_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, +}; + +/* + * TX command response is sent after *agn* transmission attempts. + * + * both postpone and abort status are expected behavior from uCode. there is + * no special operation required from driver; except for RFKILL_FLUSH, + * which required tx flush host command to flush all the tx frames in queues + */ enum { TX_STATUS_SUCCESS = 0x01, TX_STATUS_DIRECT_DONE = 0x02, + /* postpone TX */ + TX_STATUS_POSTPONE_DELAY = 0x40, + TX_STATUS_POSTPONE_FEW_BYTES = 0x41, + TX_STATUS_POSTPONE_BT_PRIO = 0x42, + TX_STATUS_POSTPONE_QUIET_PERIOD = 0x43, + TX_STATUS_POSTPONE_CALC_TTAK = 0x44, + /* abort TX */ + TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY = 0x81, TX_STATUS_FAIL_SHORT_LIMIT = 0x82, TX_STATUS_FAIL_LONG_LIMIT = 0x83, TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84, - TX_STATUS_FAIL_MGMNT_ABORT = 0x85, - TX_STATUS_FAIL_NEXT_FRAG = 0x86, + TX_STATUS_FAIL_DRAIN_FLOW = 0x85, + TX_STATUS_FAIL_RFKILL_FLUSH = 0x86, TX_STATUS_FAIL_LIFE_EXPIRE = 0x87, TX_STATUS_FAIL_DEST_PS = 0x88, - TX_STATUS_FAIL_ABORTED = 0x89, + TX_STATUS_FAIL_HOST_ABORTED = 0x89, TX_STATUS_FAIL_BT_RETRY = 0x8a, TX_STATUS_FAIL_STA_INVALID = 0x8b, TX_STATUS_FAIL_FRAG_DROPPED = 0x8c, TX_STATUS_FAIL_TID_DISABLE = 0x8d, - TX_STATUS_FAIL_FRAME_FLUSHED = 0x8e, + TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e, TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, - TX_STATUS_FAIL_TX_LOCKED = 0x90, - TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, + /* uCode drop due to FW drop request */ + TX_STATUS_FAIL_FW_DROP = 0x90, + /* + * uCode drop due to station color mismatch + * between tx command and station table + */ + TX_STATUS_FAIL_STA_COLOR_MISMATCH_DROP = 0x91, }; #define TX_PACKET_MODE_REGULAR 0x0000 @@ -1729,30 +1770,6 @@ enum { TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ }; -static inline u32 iwl_tx_status_to_mac80211(u32 status) -{ - status &= TX_STATUS_MSK; - - switch (status) { - case TX_STATUS_SUCCESS: - case TX_STATUS_DIRECT_DONE: - return IEEE80211_TX_STAT_ACK; - case TX_STATUS_FAIL_DEST_PS: - return IEEE80211_TX_STAT_TX_FILTERED; - default: - return 0; - } -} - -static inline bool iwl_is_tx_success(u32 status) -{ - status &= TX_STATUS_MSK; - return (status == TX_STATUS_SUCCESS) || - (status == TX_STATUS_DIRECT_DONE); -} - - - /* ******************************* * TX aggregation status ******************************* */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index a631afef5e33..aea6a2eee9c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -629,29 +629,36 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) EXPORT_SYMBOL(iwl_tx_cmd_complete); #ifdef CONFIG_IWLWIFI_DEBUG -#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x +#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x +#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x const char *iwl_get_tx_fail_reason(u32 status) { switch (status & TX_STATUS_MSK) { case TX_STATUS_SUCCESS: return "SUCCESS"; - TX_STATUS_ENTRY(SHORT_LIMIT); - TX_STATUS_ENTRY(LONG_LIMIT); - TX_STATUS_ENTRY(FIFO_UNDERRUN); - TX_STATUS_ENTRY(MGMNT_ABORT); - TX_STATUS_ENTRY(NEXT_FRAG); - TX_STATUS_ENTRY(LIFE_EXPIRE); - TX_STATUS_ENTRY(DEST_PS); - TX_STATUS_ENTRY(ABORTED); - TX_STATUS_ENTRY(BT_RETRY); - TX_STATUS_ENTRY(STA_INVALID); - TX_STATUS_ENTRY(FRAG_DROPPED); - TX_STATUS_ENTRY(TID_DISABLE); - TX_STATUS_ENTRY(FRAME_FLUSHED); - TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); - TX_STATUS_ENTRY(TX_LOCKED); - TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); + TX_STATUS_POSTPONE(DELAY); + TX_STATUS_POSTPONE(FEW_BYTES); + TX_STATUS_POSTPONE(BT_PRIO); + TX_STATUS_POSTPONE(QUIET_PERIOD); + TX_STATUS_POSTPONE(CALC_TTAK); + TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); + TX_STATUS_FAIL(SHORT_LIMIT); + TX_STATUS_FAIL(LONG_LIMIT); + TX_STATUS_FAIL(FIFO_UNDERRUN); + TX_STATUS_FAIL(DRAIN_FLOW); + TX_STATUS_FAIL(RFKILL_FLUSH); + TX_STATUS_FAIL(LIFE_EXPIRE); + TX_STATUS_FAIL(DEST_PS); + TX_STATUS_FAIL(HOST_ABORTED); + TX_STATUS_FAIL(BT_RETRY); + TX_STATUS_FAIL(STA_INVALID); + TX_STATUS_FAIL(FRAG_DROPPED); + TX_STATUS_FAIL(TID_DISABLE); + TX_STATUS_FAIL(FIFO_FLUSHED); + TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); + TX_STATUS_FAIL(FW_DROP); + TX_STATUS_FAIL(STA_COLOR_MISMATCH_DROP); } return "UNKNOWN"; -- cgit v1.2.3 From 4c8d1913ac1baab64080c1030cb94e24cbd9a0f8 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 31 Mar 2010 18:16:52 -0700 Subject: iwlwifi: small changes in comments REPLY_TX_LINK_QUALITY_CMD was used by 4965, 5000 series and up Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 82a9378f72e2..d830086ca195 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -106,7 +106,7 @@ enum { REPLY_TX = 0x1c, REPLY_RATE_SCALE = 0x47, /* 3945 only */ REPLY_LEDS_CMD = 0x48, - REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ + REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */ /* WiMAX coexistence */ COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */ -- cgit v1.2.3 From f875f5183b8f511161eddcbb4e9a1aada33d4aaf Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 5 Apr 2010 10:43:10 -0700 Subject: iwlwifi: fix compile warnings when compiling without debug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: CC [M] drivers/net/wireless/iwlwifi/iwl-agn-rs.o drivers/net/wireless/iwlwifi/iwl-agn-rs.c: In function ‘rs_get_rate’: drivers/net/wireless/iwlwifi/iwl-agn-rs.c:2419: warning: unused variable ‘priv’ CC [M] drivers/net/wireless/iwlwifi/iwl-sta.o drivers/net/wireless/iwlwifi/iwl-sta.c: In function ‘iwl_send_add_sta’: drivers/net/wireless/iwlwifi/iwl-sta.c:197: warning: unused variable ‘sta_id’ drivers/net/wireless/iwlwifi/iwl-3945.c: In function ‘iwl3945_rx_reply_rx’: drivers/net/wireless/iwlwifi/iwl-3945.c:601: warning: unused variable ‘rx_stats_noise_diff’ drivers/net/wireless/iwlwifi/iwl-3945.c:600: warning: unused variable ‘rx_stats_sig_avg’ drivers/net/wireless/iwlwifi/iwl-3945-rs.c: In function ‘rs_get_rate’: drivers/net/wireless/iwlwifi/iwl-3945-rs.c:650: warning: unused variable ‘priv’ Reported-by: Luis R. Rodriguez Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 9e411dc0e5e1..80e9bbc7884a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -647,7 +647,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, unsigned long flags; u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; s8 max_rate_idx = -1; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE(priv, "enter\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index ae5efc376b91..15de649888d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -597,8 +597,8 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); - u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); - u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); + u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg); + u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff); u8 network_packet; rx_status.flag = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 0c3c76803c5e..3c1cd417bbc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2409,7 +2409,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb = txrc->skb; struct ieee80211_supported_band *sband = txrc->sband; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; + struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct iwl_lq_sta *lq_sta = priv_sta; int rate_idx; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 6876f7c59368..9b4d527bd3f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -194,7 +194,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, .flags = flags, .data = data, }; - u8 sta_id = sta->sta.sta_id; + u8 sta_id __maybe_unused = sta->sta.sta_id; IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); -- cgit v1.2.3 From 57e40d36e59f828f43d60b2662041991dcd78044 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 9 Mar 2010 15:36:10 -0800 Subject: iwlwifi: fix compiler warning Check return code on iwl_send_cmd_pdu() to get rid of compiler warning. Signed-off-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-sta.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 9b4d527bd3f8..d86ecd2f9ec2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -425,6 +425,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) .reserved1 = 0, }; u32 rate_flags; + int ret = 0; /* 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 */ @@ -458,8 +459,10 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) /* Update the rate scaling for control frame Tx to AP */ link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; - iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, + ret = iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd), &link_cmd); + if (ret) + IWL_ERR(priv, "REPLY_TX_LINK_QUALITY_CMD failed (%d)\n", ret); } /* -- cgit v1.2.3 From 470058e0ad82fcfaaffd57307d8bf8c094e8e9d7 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Fri, 2 Apr 2010 13:38:54 -0700 Subject: iwlwifi: avoid Tx queue memory allocation in interface down We used to free all the Tx queues memory when interface is brought down and reallocate them again in interface up. This requires order-4 allocation for txq->cmd[]. In situations like s2ram, this usually leads to allocation failure in the memory subsystem. The patch fixed this problem by allocating the Tx queues memory only at the first time. Later iwl_down/iwl_up only initialize but don't free and reallocate them. The memory is freed at the device removal time. BTW, we have already done this for the Rx queue. This fixed bug https://bugzilla.kernel.org/show_bug.cgi?id=15551 Signed-off-by: Zhu Yi Acked-by: Wey-Yi Guy Signed-off-by: Reinette Chatre --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 11 ++++++--- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 39 ++++++++++++++++++++++-------- drivers/net/wireless/iwlwifi/iwl-agn.h | 3 ++- drivers/net/wireless/iwlwifi/iwl-tx.c | 20 +++++++++++++++ 4 files changed, 58 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 384b45c519f1..c465c8590833 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -512,10 +512,13 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); - /* Allocate and init all Tx and Command queues */ - ret = iwlagn_txq_ctx_reset(priv); - if (ret) - return ret; + /* Allocate or reset and init all Tx and Command queues */ + if (!priv->txq) { + ret = iwlagn_txq_ctx_alloc(priv); + if (ret) + return ret; + } else + iwlagn_txq_ctx_reset(priv); set_bit(STATUS_INIT, &priv->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index a76e14351b5a..3077eac58880 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -809,8 +809,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) /* Tx queues */ if (priv->txq) { - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; - txq_id++) + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) if (txq_id == IWL_CMD_QUEUE_NUM) iwl_cmd_queue_free(priv); else @@ -825,15 +824,15 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) } /** - * iwlagn_txq_ctx_reset - Reset TX queue context - * Destroys all DMA structures and initialize them again + * iwlagn_txq_ctx_alloc - allocate TX queue context + * Allocate all Tx DMA structures and initialize them * * @param priv * @return error code */ -int iwlagn_txq_ctx_reset(struct iwl_priv *priv) +int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) { - int ret = 0; + int ret; int txq_id, slots_num; unsigned long flags; @@ -891,8 +890,31 @@ int iwlagn_txq_ctx_reset(struct iwl_priv *priv) return ret; } +void iwlagn_txq_ctx_reset(struct iwl_priv *priv) +{ + int txq_id, slots_num; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + /* Turn off all Tx DMA fifos */ + priv->cfg->ops->lib->txq_set_sched(priv, 0); + + /* Tell NIC where to find the "keep warm" buffer */ + iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Alloc and init all Tx queues, including the command queue (#4) */ + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { + slots_num = txq_id == IWL_CMD_QUEUE_NUM ? + TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); + } +} + /** - * iwlagn_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory + * iwlagn_txq_ctx_stop - Stop all Tx DMA channels */ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) { @@ -912,9 +934,6 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) 1000); } spin_unlock_irqrestore(&priv->lock, flags); - - /* Deallocate memory for all Tx queues */ - iwlagn_hw_txq_ctx_free(priv); } /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 608060abe80c..5d3142287e14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -145,7 +145,8 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); -int iwlagn_txq_ctx_reset(struct iwl_priv *priv); +int iwlagn_txq_ctx_alloc(struct iwl_priv *priv); +void iwlagn_txq_ctx_reset(struct iwl_priv *priv); void iwlagn_txq_ctx_stop(struct iwl_priv *priv); static inline u32 iwl_tx_status_to_mac80211(u32 status) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index aea6a2eee9c3..c3c6505a8c69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -394,6 +394,26 @@ out_free_arrays: } EXPORT_SYMBOL(iwl_tx_queue_init); +void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, + int slots_num, u32 txq_id) +{ + int actual_slots = slots_num; + + if (txq_id == IWL_CMD_QUEUE_NUM) + actual_slots++; + + memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); + + txq->need_update = 0; + + /* Initialize queue's high/low-water marks, and head/tail indexes */ + iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); + + /* Tell device where to find queue */ + priv->cfg->ops->lib->txq_init(priv, txq); +} +EXPORT_SYMBOL(iwl_tx_queue_reset); + /*************** HOST COMMAND QUEUE FUNCTIONS *****/ /** -- cgit v1.2.3