From 02f5ba5bac8b374bc2126920c7204c63019f28ce Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Jul 2010 13:30:46 +0200 Subject: iwlwifi: fix possible recursive locking deadlock commit f84b29ec0a1ab767679d3f2428877b65f94bc3ff Author: Johannes Berg Date: Tue May 18 02:29:13 2010 -0700 iwlwifi: queue user-initiated scan when doing internal scan introduced a potential deadlock because it calls ieee80211_scan_completed() with the priv->mutex held, but mac80211 may call back into iwlwifi which would lead to recursive locking. Move this out from under the mutex. Cc: stable@kernel.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/iwlwifi') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8024d44ce4bb..8ccb6d205b6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2000,6 +2000,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; + bool scan_completed = false; IWL_DEBUG_MAC80211(priv, "enter\n"); @@ -2013,7 +2014,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, if (priv->vif == vif) { priv->vif = NULL; if (priv->scan_vif == vif) { - ieee80211_scan_completed(priv->hw, true); + scan_completed = true; priv->scan_vif = NULL; priv->scan_request = NULL; } @@ -2021,6 +2022,9 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, } mutex_unlock(&priv->mutex); + if (scan_completed) + ieee80211_scan_completed(priv->hw, true); + IWL_DEBUG_MAC80211(priv, "leave\n"); } -- cgit v1.2.3 From 5fc97f7789e6ff3d1698a544f863b55dba9d9cd9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 31 Jul 2010 08:34:09 -0700 Subject: iwlwifi: fix compile warning When iwlwifi is compiled w/o debug, we get this warning: iwl-agn.c: In function ‘iwlagn_load_firmware’: iwl-agn.c:2014: warning: passing argument 3 of ‘iwl_print_hex_dump’ discards qualifiers from pointer target type iwl-debug.h:73: note: expected ‘void *’ but argument is of type ‘const u8 *’ because the const qualifier is missing in the inline stub. Fix this. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/iwlwifi') diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 5c2bcef5df0c..0b961a353ff6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -71,7 +71,7 @@ do { \ #define IWL_DEBUG(__priv, level, fmt, args...) #define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, - void *p, u32 len) + const void *p, u32 len) {} #endif /* CONFIG_IWLWIFI_DEBUG */ -- cgit v1.2.3 From 735df29a0641d9d8d65117c48ee460284ffcfc05 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 31 Jul 2010 08:34:11 -0700 Subject: iwlwifi: BA scd_flow not match condition detected It is a uCode bug which cause the tx queue id not match scd_flow in compressed block ack frame, and it need to be addressed in uCode. Currently, driver will log the information when it happen. Since it is possible happen very often and we do not want to fill the syslog, so don't enable the logging by default. Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/iwlwifi') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 55a1b31fd09a..ecb953f28068 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1331,7 +1331,14 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, tid = ba_resp->tid; agg = &priv->stations[sta_id].tid[tid].agg; if (unlikely(agg->txq_id != scd_flow)) { - IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n", + /* + * FIXME: this is a uCode bug which need to be addressed, + * log the information and return for now! + * since it is possible happen very often and in order + * not to fill the syslog, don't enable the logging by default + */ + IWL_DEBUG_TX_REPLY(priv, + "BA scd_flow %d does not match txq_id %d\n", scd_flow, agg->txq_id); return; } -- cgit v1.2.3 From 74dee2c3e1a3dc5cd6100f110f7935dece7a3505 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Sat, 31 Jul 2010 08:34:12 -0700 Subject: iwlagn: fix typo in ucode_bt_stats_read debugfs small typo fix in ucode_bt_stats_read debugfs file Signed-off-by: Wey-Yi Guy Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/iwlwifi') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index f052c6d09b37..d706b8afbe5a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -980,7 +980,7 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file, le32_to_cpu(bt->lo_priority_tx_req_cnt), accum_bt->lo_priority_tx_req_cnt); pos += scnprintf(buf + pos, bufsz - pos, - "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n", + "lo_priority_tx_denied_cnt:\t%u\t\t\t%u\n", le32_to_cpu(bt->lo_priority_tx_denied_cnt), accum_bt->lo_priority_tx_denied_cnt); pos += scnprintf(buf + pos, bufsz - pos, -- cgit v1.2.3 From 2411054ae9eb7e7ef488a39912abfc4ebadbe3ad Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sun, 25 Jul 2010 13:14:29 -0400 Subject: iwlagn: Improve aggregation failure error messages 82ca9341763107615a15da6e59b9535d49eb91c3 added scary looking but harmless error messages. Make them clearer and make the actual failure message show up with the same severity as the harmless one. Signed-off-by: Andy Lutomirski Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/iwlwifi') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 35c86d22b14b..23e5c42e7d7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -300,8 +300,9 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, struct ieee80211_sta *sta) { int ret = -EAGAIN; + u32 load = rs_tl_get_load(lq_data, tid); - if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { + if (load > IWL_AGG_LOAD_THRESHOLD) { IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", sta->addr, tid); ret = ieee80211_start_tx_ba_session(sta, tid); @@ -311,12 +312,14 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, * this might be cause by reloading firmware * stop the tx ba session here */ - IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", + IWL_ERR(priv, "Fail start Tx agg on tid: %d\n", tid); ieee80211_stop_tx_ba_session(sta, tid); } - } else - IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid); + } else { + IWL_ERR(priv, "Aggregation not enabled for tid %d " + "because load = %u\n", tid, load); + } return ret; } -- cgit v1.2.3 From e95b743536937a72e1560c85696b425c5d1a1c18 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 6 Aug 2010 16:00:48 +0200 Subject: iwlwifi: fix TX tracer The TX tracing code copies with the wrong length, which will typically copy too little data. Fix this by using the correct length variable. Cc: stable@kernel.org [2.6.32+] Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-devtrace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/iwlwifi') diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index ae7319bb3a99..4cf864c664ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -193,7 +193,7 @@ TRACE_EVENT(iwlwifi_dev_tx, __entry->framelen = buf0_len + buf1_len; memcpy(__get_dynamic_array(tfd), tfd, tfdlen); memcpy(__get_dynamic_array(buf0), buf0, buf0_len); - memcpy(__get_dynamic_array(buf1), buf1, buf0_len); + memcpy(__get_dynamic_array(buf1), buf1, buf1_len); ), TP_printk("[%p] TX %.2x (%zu bytes)", __entry->priv, -- cgit v1.2.3 From a24d52f390a77ce90dc8cf0cd75d27ec0a6ea3f8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 6 Aug 2010 16:17:53 +0200 Subject: iwlwifi: fix locking assertions spin_is_locked() can return zero on some (UP?) configurations because locks don't exist, and that causes an endless amount of warnings. Use lockdep_assert_held() instead, which has two advantages: 1) it verifies the current task is holding the lock or mutex 2) it compiles away completely when lockdep is not enabled Cc: stable@kernel.org [2.6.34+, maybe only parts of patch] Reported-by: Thomas Meyer Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/iwlwifi') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index a1b6d202d57c..9dd9e64c2b0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1429,7 +1429,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed) { - WARN_ON(!spin_is_locked(&priv->sta_lock)); + lockdep_assert_held(&priv->sta_lock); if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index ecb953f28068..d04502d54df3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1117,7 +1117,7 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv, u8 *addr = priv->stations[sta_id].sta.sta.addr; struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; - WARN_ON(!spin_is_locked(&priv->sta_lock)); + lockdep_assert_held(&priv->sta_lock); switch (priv->stations[sta_id].tid[tid].agg.state) { case IWL_EMPTYING_HW_QUEUE_DELBA: diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index b0c6b0473901..a4b3663a262f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -298,7 +298,7 @@ EXPORT_SYMBOL(iwl_init_scan_params); static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif) { - WARN_ON(!mutex_is_locked(&priv->mutex)); + lockdep_assert_held(&priv->mutex); IWL_DEBUG_INFO(priv, "Starting scan...\n"); set_bit(STATUS_SCANNING, &priv->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 9511f03f07e0..7e0829be5e78 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -773,7 +773,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) int iwl_restore_default_wep_keys(struct iwl_priv *priv) { - WARN_ON(!mutex_is_locked(&priv->mutex)); + lockdep_assert_held(&priv->mutex); return iwl_send_static_wepkey_cmd(priv, 0); } @@ -784,7 +784,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, { int ret; - WARN_ON(!mutex_is_locked(&priv->mutex)); + lockdep_assert_held(&priv->mutex); IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", keyconf->keyidx); @@ -808,7 +808,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, { int ret; - WARN_ON(!mutex_is_locked(&priv->mutex)); + lockdep_assert_held(&priv->mutex); if (keyconf->keylen != WEP_KEY_LEN_128 && keyconf->keylen != WEP_KEY_LEN_64) { -- cgit v1.2.3