diff options
author | Felix Fietkau <nbd@nbd.name> | 2018-04-25 11:11:21 +0200 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2018-04-30 13:21:27 +0300 |
commit | c3d7c82a8bb017e43cafe8eaf7c8309f85ceb781 (patch) | |
tree | 08034ee5b1b7e346957224a0a66e169086bf09cc /drivers/net/wireless/mediatek | |
parent | 97389373d555cdc03ed346d7dc6f714a1586c705 (diff) |
mt76: fix concurrent rx calls on A-MPDU release
Add a spinlock in mt76_rx_complete. Without this, multiple stats updates
could happen in parallel, which can lead to deadlocks. There are
probably more corner cases fixed by this change.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/mediatek')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mac80211.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt76.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt76x2_init.c | 1 |
3 files changed, 4 insertions, 0 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index eb49e0a6758c..915e61733131 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -561,6 +561,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, if (queue >= 0) napi = &dev->napi[queue]; + spin_lock(&dev->rx_lock); while ((skb = __skb_dequeue(frames)) != NULL) { if (mt76_check_ccmp_pn(skb)) { dev_kfree_skb(skb); @@ -570,6 +571,7 @@ void mt76_rx_complete(struct mt76_dev *dev, struct sk_buff_head *frames, sta = mt76_rx_convert(skb); ieee80211_rx_napi(dev->hw, sta, skb, napi); } + spin_unlock(&dev->rx_lock); } void mt76_rx_poll_complete(struct mt76_dev *dev, enum mt76_rxq_id q) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 065ff78059c3..a74e6eef51e9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -241,6 +241,7 @@ struct mt76_dev { struct device *dev; struct net_device napi_dev; + spinlock_t rx_lock; struct napi_struct napi[__MT_RXQ_MAX]; struct sk_buff_head rx_skb[__MT_RXQ_MAX]; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2_init.c index 359b105235b3..d21e4a7c1bb9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2_init.c @@ -645,6 +645,7 @@ struct mt76x2_dev *mt76x2_alloc_device(struct device *pdev) dev->mt76.drv = &drv_ops; mutex_init(&dev->mutex); spin_lock_init(&dev->irq_lock); + spin_lock_init(&dev->mt76.rx_lock); return dev; } |