提交 11f6e40d 编写于 作者: V Vasanthakumar Thiagarajan 提交者: Kalle Valo

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: NKalle Valo <kvalo@qca.qualcomm.com>
Signed-off-by: NVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Signed-off-by: NKalle Valo <kvalo@qca.qualcomm.com>
上级 b4b2a0b1
...@@ -1320,9 +1320,9 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy, ...@@ -1320,9 +1320,9 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
struct ath6kl *ar = wiphy_priv(wiphy); struct ath6kl *ar = wiphy_priv(wiphy);
struct ath6kl_vif *vif = netdev_priv(ndev); struct ath6kl_vif *vif = netdev_priv(ndev);
spin_lock(&ar->list_lock); spin_lock_bh(&ar->list_lock);
list_del(&vif->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)); 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, ...@@ -2437,9 +2437,9 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
if (type == NL80211_IFTYPE_ADHOC) if (type == NL80211_IFTYPE_ADHOC)
ar->ibss_if_active = true; ar->ibss_if_active = true;
spin_lock(&ar->list_lock); spin_lock_bh(&ar->list_lock);
list_add_tail(&vif->list, &ar->vif_list); list_add_tail(&vif->list, &ar->vif_list);
spin_unlock(&ar->list_lock); spin_unlock_bh(&ar->list_lock);
return ndev; return ndev;
......
...@@ -1685,17 +1685,17 @@ void ath6kl_stop_txrx(struct ath6kl *ar) ...@@ -1685,17 +1685,17 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
return; 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_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) {
list_del(&vif->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)); ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
rtnl_lock(); rtnl_lock();
ath6kl_deinit_if_data(vif); ath6kl_deinit_if_data(vif);
rtnl_unlock(); 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); clear_bit(WMI_READY, &ar->flag);
......
...@@ -1046,15 +1046,15 @@ struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar) ...@@ -1046,15 +1046,15 @@ struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar)
{ {
struct ath6kl_vif *vif; struct ath6kl_vif *vif;
spin_lock(&ar->list_lock); spin_lock_bh(&ar->list_lock);
if (list_empty(&ar->vif_list)) { if (list_empty(&ar->vif_list)) {
spin_unlock(&ar->list_lock); spin_unlock_bh(&ar->list_lock);
return NULL; return NULL;
} }
vif = list_first_entry(&ar->vif_list, struct ath6kl_vif, list); vif = list_first_entry(&ar->vif_list, struct ath6kl_vif, list);
spin_unlock(&ar->list_lock); spin_unlock_bh(&ar->list_lock);
return vif; return vif;
} }
......
...@@ -470,10 +470,10 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, ...@@ -470,10 +470,10 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
stop_adhoc_netq: stop_adhoc_netq:
/* FIXME: Locking */ /* FIXME: Locking */
spin_lock(&ar->list_lock); spin_lock_bh(&ar->list_lock);
list_for_each_entry(vif, &ar->vif_list, list) { list_for_each_entry(vif, &ar->vif_list, list) {
if (vif->nw_type == ADHOC_NETWORK) { if (vif->nw_type == ADHOC_NETWORK) {
spin_unlock(&ar->list_lock); spin_unlock_bh(&ar->list_lock);
spin_lock_bh(&vif->if_lock); spin_lock_bh(&vif->if_lock);
set_bit(NETQ_STOPPED, &vif->flags); set_bit(NETQ_STOPPED, &vif->flags);
...@@ -483,7 +483,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, ...@@ -483,7 +483,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
return action; return action;
} }
} }
spin_unlock(&ar->list_lock); spin_unlock_bh(&ar->list_lock);
return action; return action;
} }
...@@ -637,16 +637,16 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue) ...@@ -637,16 +637,16 @@ void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
__skb_queue_purge(&skb_queue); __skb_queue_purge(&skb_queue);
/* FIXME: Locking */ /* FIXME: Locking */
spin_lock(&ar->list_lock); spin_lock_bh(&ar->list_lock);
list_for_each_entry(vif, &ar->vif_list, list) { list_for_each_entry(vif, &ar->vif_list, list) {
if (test_bit(CONNECTED, &vif->flags) && if (test_bit(CONNECTED, &vif->flags) &&
!flushing[vif->fw_vif_idx]) { !flushing[vif->fw_vif_idx]) {
spin_unlock(&ar->list_lock); spin_unlock_bh(&ar->list_lock);
netif_wake_queue(vif->ndev); 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) if (wake_event)
wake_up(&ar->event_wq); wake_up(&ar->event_wq);
......
...@@ -89,14 +89,14 @@ struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx) ...@@ -89,14 +89,14 @@ struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx)
return NULL; return NULL;
/* FIXME: Locking */ /* FIXME: Locking */
spin_lock(&ar->list_lock); spin_lock_bh(&ar->list_lock);
list_for_each_entry(vif, &ar->vif_list, list) { list_for_each_entry(vif, &ar->vif_list, list) {
if (vif->fw_vif_idx == if_idx) { if (vif->fw_vif_idx == if_idx) {
found = vif; found = vif;
break; break;
} }
} }
spin_unlock(&ar->list_lock); spin_unlock_bh(&ar->list_lock);
return found; return found;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册