summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2018-11-05 21:11:39 +0100
committerFelix Fietkau <nbd@nbd.name>2018-11-30 12:29:32 +0100
commit79d1c94c9c78ea2f90a7218e16946a1dde2527a0 (patch)
tree77c965da15fa0bd63e6e7bf9fa8f1aed8e4206e7 /drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
parent4ece1e0a86b35bbb43d8d3e5268e68c6b4c6294e (diff)
mt76: avoid queue/status spinlocks while passing tx status to mac80211
There is some code in the mac80211 tx status processing code that could potentially call back into the tx codepath. To avoid deadlocks, make sure that no tx related spinlocks are taken during the ieee80211_tx_status call. Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt76x02_mac.c')
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76x02_mac.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
index 59b336e34cb5..4c35d3f7fb15 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -438,12 +438,13 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
struct mt76_wcid *wcid = NULL;
struct mt76x02_sta *msta = NULL;
struct mt76_dev *mdev = &dev->mt76;
+ struct sk_buff_head list;
if (stat->pktid == MT_PACKET_ID_NO_ACK)
return;
rcu_read_lock();
- spin_lock_bh(&mdev->status_list.lock);
+ mt76_tx_status_lock(mdev, &list);
if (stat->wcid < ARRAY_SIZE(dev->mt76.wcid))
wcid = rcu_dereference(dev->mt76.wcid[stat->wcid]);
@@ -459,7 +460,7 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
if (wcid) {
if (stat->pktid)
status.skb = mt76_tx_status_skb_get(mdev, wcid,
- stat->pktid);
+ stat->pktid, &list);
if (status.skb)
status.info = IEEE80211_SKB_CB(status.skb);
}
@@ -490,12 +491,12 @@ void mt76x02_send_tx_status(struct mt76x02_dev *dev,
}
if (status.skb)
- mt76_tx_status_skb_done(mdev, status.skb);
+ mt76_tx_status_skb_done(mdev, status.skb, &list);
else
ieee80211_tx_status_ext(mt76_hw(dev), &status);
out:
- spin_unlock_bh(&mdev->status_list.lock);
+ mt76_tx_status_unlock(mdev, &list);
rcu_read_unlock();
}
@@ -818,7 +819,7 @@ void mt76x02_mac_work(struct work_struct *work)
if (!dev->beacon_mask)
mt76x02_check_mac_err(dev);
- mt76_tx_status_check(&dev->mt76);
+ mt76_tx_status_check(&dev->mt76, NULL, false);
ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work,
MT_CALIBRATE_INTERVAL);