diff options
author | Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> | 2011-11-01 07:08:50 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2011-11-11 05:59:00 -0500 |
commit | 11f6e40d9f21767a9090e4e559d3c63edf25e6c0 (patch) | |
tree | c3fd39804436cc897756271f3fd1e6ba0d2a53db /drivers/net/wireless/ath | |
parent | b4b2a0b116d79510640622a5f28f219065e61b03 (diff) |
ath6kl: Fix lockdep warning
The following is the lockdep warning which detects possible
deadlock condition with the way ar->lock and ar->list_lock
are being used.
(&(&ar->lock)->rlock){+.-...}, at: [<ffffffffa0492d13>] ath6kl_indicate_tx_activity+0x83/0x110 [ath6kl]
but this lock took another, SOFTIRQ-unsafe lock in the past:
(&(&ar->list_lock)->rlock){+.+...}
and interrupts could create inverse lock ordering between them.
other info that might help us debug this:
Possible interrupt unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&(&ar->list_lock)->rlock);
local_irq_disable();
lock(&(&ar->lock)->rlock);
lock(&(&ar->list_lock)->rlock);
<Interrupt>
lock(&(&ar->lock)->rlock);
*** DEADLOCK ***
softirqs have to be disabled when acquiring ar->list_lock to avoid
the above deadlock condition. When the above warning printed the
interface is still up and running without issue.
Reported-by: Kalle Valo <kvalo@qca.qualcomm.com>
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/init.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/main.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/txrx.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.c | 4 |
5 files changed, 20 insertions, 20 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 5dab4f20146a..4a880b4dda5b 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -1320,9 +1320,9 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy, | |||
1320 | struct ath6kl *ar = wiphy_priv(wiphy); | 1320 | struct ath6kl *ar = wiphy_priv(wiphy); |
1321 | struct ath6kl_vif *vif = netdev_priv(ndev); | 1321 | struct ath6kl_vif *vif = netdev_priv(ndev); |
1322 | 1322 | ||
1323 | spin_lock(&ar->list_lock); | 1323 | spin_lock_bh(&ar->list_lock); |
1324 | list_del(&vif->list); | 1324 | list_del(&vif->list); |
1325 | spin_unlock(&ar->list_lock); | 1325 | spin_unlock_bh(&ar->list_lock); |
1326 | 1326 | ||
1327 | ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); | 1327 | ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); |
1328 | 1328 | ||
@@ -2437,9 +2437,9 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | |||
2437 | if (type == NL80211_IFTYPE_ADHOC) | 2437 | if (type == NL80211_IFTYPE_ADHOC) |
2438 | ar->ibss_if_active = true; | 2438 | ar->ibss_if_active = true; |
2439 | 2439 | ||
2440 | spin_lock(&ar->list_lock); | 2440 | spin_lock_bh(&ar->list_lock); |
2441 | list_add_tail(&vif->list, &ar->vif_list); | 2441 | list_add_tail(&vif->list, &ar->vif_list); |
2442 | spin_unlock(&ar->list_lock); | 2442 | spin_unlock_bh(&ar->list_lock); |
2443 | 2443 | ||
2444 | return ndev; | 2444 | return ndev; |
2445 | 2445 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 83b4f165eebf..bb2254d3b439 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -1685,17 +1685,17 @@ void ath6kl_stop_txrx(struct ath6kl *ar) | |||
1685 | return; | 1685 | return; |
1686 | } | 1686 | } |
1687 | 1687 | ||
1688 | spin_lock(&ar->list_lock); | 1688 | spin_lock_bh(&ar->list_lock); |
1689 | list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) { | 1689 | list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) { |
1690 | list_del(&vif->list); | 1690 | list_del(&vif->list); |
1691 | spin_unlock(&ar->list_lock); | 1691 | spin_unlock_bh(&ar->list_lock); |
1692 | ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); | 1692 | ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); |
1693 | rtnl_lock(); | 1693 | rtnl_lock(); |
1694 | ath6kl_deinit_if_data(vif); | 1694 | ath6kl_deinit_if_data(vif); |
1695 | rtnl_unlock(); | 1695 | rtnl_unlock(); |
1696 | spin_lock(&ar->list_lock); | 1696 | spin_lock_bh(&ar->list_lock); |
1697 | } | 1697 | } |
1698 | spin_unlock(&ar->list_lock); | 1698 | spin_unlock_bh(&ar->list_lock); |
1699 | 1699 | ||
1700 | clear_bit(WMI_READY, &ar->flag); | 1700 | clear_bit(WMI_READY, &ar->flag); |
1701 | 1701 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 23da82e148ea..f9410e41121a 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -1046,15 +1046,15 @@ struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar) | |||
1046 | { | 1046 | { |
1047 | struct ath6kl_vif *vif; | 1047 | struct ath6kl_vif *vif; |
1048 | 1048 | ||
1049 | spin_lock(&ar->list_lock); | 1049 | spin_lock_bh(&ar->list_lock); |
1050 | if (list_empty(&ar->vif_list)) { | 1050 | if (list_empty(&ar->vif_list)) { |
1051 | spin_unlock(&ar->list_lock); | 1051 | spin_unlock_bh(&ar->list_lock); |
1052 | return NULL; | 1052 | return NULL; |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | vif = list_first_entry(&ar->vif_list, struct ath6kl_vif, list); | 1055 | vif = list_first_entry(&ar->vif_list, struct ath6kl_vif, list); |
1056 | 1056 | ||
1057 | spin_unlock(&ar->list_lock); | 1057 | spin_unlock_bh(&ar->list_lock); |
1058 | 1058 | ||
1059 | return vif; | 1059 | return vif; |
1060 | } | 1060 | } |
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 9dfd7f56d043..06e4912f0321 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -470,10 +470,10 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, | |||
470 | 470 | ||
471 | stop_adhoc_netq: | 471 | stop_adhoc_netq: |
472 | /* FIXME: Locking */ | 472 | /* FIXME: Locking */ |
473 | spin_lock(&ar->list_lock); | 473 | spin_lock_bh(&ar->list_lock); |
474 | list_for_each_entry(vif, &ar->vif_list, list) { | 474 | list_for_each_entry(vif, &ar->vif_list, list) { |
475 | if (vif->nw_type == ADHOC_NETWORK) { | 475 | if (vif->nw_type == ADHOC_NETWORK) { |
476 | spin_unlock(&ar->list_lock); | 476 | spin_unlock_bh(&ar->list_lock); |
477 | 477 | ||
478 | spin_lock_bh(&vif->if_lock); | 478 | spin_lock_bh(&vif->if_lock); |
479 | set_bit(NETQ_STOPPED, &vif->flags); | 479 | set_bit(NETQ_STOPPED, &vif->flags); |
@@ -483,7 +483,7 @@ stop_adhoc_netq: | |||
483 | return action; | 483 | return action; |
484 | } | 484 | } |
485 | } | 485 | } |
486 | spin_unlock(&ar->list_lock); | 486 | spin_unlock_bh(&ar->list_lock); |
487 | 487 | ||
488 | return action; | 488 | return action; |
489 | } | 489 | } |
@@ -637,16 +637,16 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) | |||
637 | __skb_queue_purge(&skb_queue); | 637 | __skb_queue_purge(&skb_queue); |
638 | 638 | ||
639 | /* FIXME: Locking */ | 639 | /* FIXME: Locking */ |
640 | spin_lock(&ar->list_lock); | 640 | spin_lock_bh(&ar->list_lock); |
641 | list_for_each_entry(vif, &ar->vif_list, list) { | 641 | list_for_each_entry(vif, &ar->vif_list, list) { |
642 | if (test_bit(CONNECTED, &vif->flags) && | 642 | if (test_bit(CONNECTED, &vif->flags) && |
643 | !flushing[vif->fw_vif_idx]) { | 643 | !flushing[vif->fw_vif_idx]) { |
644 | spin_unlock(&ar->list_lock); | 644 | spin_unlock_bh(&ar->list_lock); |
645 | netif_wake_queue(vif->ndev); | 645 | netif_wake_queue(vif->ndev); |
646 | spin_lock(&ar->list_lock); | 646 | spin_lock_bh(&ar->list_lock); |
647 | } | 647 | } |
648 | } | 648 | } |
649 | spin_unlock(&ar->list_lock); | 649 | spin_unlock_bh(&ar->list_lock); |
650 | 650 | ||
651 | if (wake_event) | 651 | if (wake_event) |
652 | wake_up(&ar->event_wq); | 652 | wake_up(&ar->event_wq); |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index d3db5b3c40bc..ece67a5c37b3 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -89,14 +89,14 @@ struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx) | |||
89 | return NULL; | 89 | return NULL; |
90 | 90 | ||
91 | /* FIXME: Locking */ | 91 | /* FIXME: Locking */ |
92 | spin_lock(&ar->list_lock); | 92 | spin_lock_bh(&ar->list_lock); |
93 | list_for_each_entry(vif, &ar->vif_list, list) { | 93 | list_for_each_entry(vif, &ar->vif_list, list) { |
94 | if (vif->fw_vif_idx == if_idx) { | 94 | if (vif->fw_vif_idx == if_idx) { |
95 | found = vif; | 95 | found = vif; |
96 | break; | 96 | break; |
97 | } | 97 | } |
98 | } | 98 | } |
99 | spin_unlock(&ar->list_lock); | 99 | spin_unlock_bh(&ar->list_lock); |
100 | 100 | ||
101 | return found; | 101 | return found; |
102 | } | 102 | } |