ath6kl: Fix lockdep warning
authorVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Tue, 1 Nov 2011 11:08:50 +0000 (16:38 +0530)
committerKalle Valo <kvalo@qca.qualcomm.com>
Fri, 11 Nov 2011 10:59:00 +0000 (12:59 +0200)
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>
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/ath6kl/txrx.c
drivers/net/wireless/ath/ath6kl/wmi.c

index 5dab4f20146a05fa682ccef1c59a6f7ddd30bf84..4a880b4dda5b785c059ddfb7198b2e5a642f0f97 100644 (file)
@@ -1320,9 +1320,9 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
        struct ath6kl *ar = wiphy_priv(wiphy);
        struct ath6kl_vif *vif = netdev_priv(ndev);
 
-       spin_lock(&ar->list_lock);
+       spin_lock_bh(&ar->list_lock);
        list_del(&vif->list);
-       spin_unlock(&ar->list_lock);
+       spin_unlock_bh(&ar->list_lock);
 
        ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
 
@@ -2437,9 +2437,9 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
        if (type == NL80211_IFTYPE_ADHOC)
                ar->ibss_if_active = true;
 
-       spin_lock(&ar->list_lock);
+       spin_lock_bh(&ar->list_lock);
        list_add_tail(&vif->list, &ar->vif_list);
-       spin_unlock(&ar->list_lock);
+       spin_unlock_bh(&ar->list_lock);
 
        return ndev;
 
index 83b4f165eebf6d0dc195f3df6d5a3f19fcd87adb..bb2254d3b43926abe41f5ddebcc5996ffcc4920b 100644 (file)
@@ -1685,17 +1685,17 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
                return;
        }
 
-       spin_lock(&ar->list_lock);
+       spin_lock_bh(&ar->list_lock);
        list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) {
                list_del(&vif->list);
-               spin_unlock(&ar->list_lock);
+               spin_unlock_bh(&ar->list_lock);
                ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
                rtnl_lock();
                ath6kl_deinit_if_data(vif);
                rtnl_unlock();
-               spin_lock(&ar->list_lock);
+               spin_lock_bh(&ar->list_lock);
        }
-       spin_unlock(&ar->list_lock);
+       spin_unlock_bh(&ar->list_lock);
 
        clear_bit(WMI_READY, &ar->flag);
 
index 23da82e148eadc0cd3586b3fb33616b69a762671..f9410e41121afc43dc28bb19ebcb124ecd669b2c 100644 (file)
@@ -1046,15 +1046,15 @@ struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar)
 {
        struct ath6kl_vif *vif;
 
-       spin_lock(&ar->list_lock);
+       spin_lock_bh(&ar->list_lock);
        if (list_empty(&ar->vif_list)) {
-               spin_unlock(&ar->list_lock);
+               spin_unlock_bh(&ar->list_lock);
                return NULL;
        }
 
        vif = list_first_entry(&ar->vif_list, struct ath6kl_vif, list);
 
-       spin_unlock(&ar->list_lock);
+       spin_unlock_bh(&ar->list_lock);
 
        return vif;
 }
index 9dfd7f56d043d68c0f741cb0b500cea83ec500a5..06e4912f03216d161ac4ff1a662a808fc4954eec 100644 (file)
@@ -470,10 +470,10 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
 
 stop_adhoc_netq:
        /* FIXME: Locking */
-       spin_lock(&ar->list_lock);
+       spin_lock_bh(&ar->list_lock);
        list_for_each_entry(vif, &ar->vif_list, list) {
                if (vif->nw_type == ADHOC_NETWORK) {
-                       spin_unlock(&ar->list_lock);
+                       spin_unlock_bh(&ar->list_lock);
 
                        spin_lock_bh(&vif->if_lock);
                        set_bit(NETQ_STOPPED, &vif->flags);
@@ -483,7 +483,7 @@ stop_adhoc_netq:
                        return action;
                }
        }
-       spin_unlock(&ar->list_lock);
+       spin_unlock_bh(&ar->list_lock);
 
        return action;
 }
@@ -637,16 +637,16 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
        __skb_queue_purge(&skb_queue);
 
        /* FIXME: Locking */
-       spin_lock(&ar->list_lock);
+       spin_lock_bh(&ar->list_lock);
        list_for_each_entry(vif, &ar->vif_list, list) {
                if (test_bit(CONNECTED, &vif->flags) &&
                    !flushing[vif->fw_vif_idx]) {
-                       spin_unlock(&ar->list_lock);
+                       spin_unlock_bh(&ar->list_lock);
                        netif_wake_queue(vif->ndev);
-                       spin_lock(&ar->list_lock);
+                       spin_lock_bh(&ar->list_lock);
                }
        }
-       spin_unlock(&ar->list_lock);
+       spin_unlock_bh(&ar->list_lock);
 
        if (wake_event)
                wake_up(&ar->event_wq);
index d3db5b3c40bc58749c5e52132bc31b20d4a43520..ece67a5c37b31a19e7b40f9ec4a770d02decc4e3 100644 (file)
@@ -89,14 +89,14 @@ struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx)
                return NULL;
 
        /* FIXME: Locking */
-       spin_lock(&ar->list_lock);
+       spin_lock_bh(&ar->list_lock);
        list_for_each_entry(vif, &ar->vif_list, list) {
                if (vif->fw_vif_idx == if_idx) {
                        found = vif;
                        break;
                }
        }
-       spin_unlock(&ar->list_lock);
+       spin_unlock_bh(&ar->list_lock);
 
        return found;
 }