Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wifi: mt76: fix crash with WED rx support enabled

If WED rx is enabled, rx buffers are added to a buffer pool that can be
filled from multiple page pools. Because buffers freed from rx poll are
not guaranteed to belong to the processed queue's page pool, lockless
caching must not be used in this case.

Cc: stable@vger.kernel.org
Fixes: 2f5c3c77fc9b ("wifi: mt76: switch to page_pool allocator")
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20231208075004.69843-1-nbd@nbd.name

authored by

Felix Fietkau and committed by
Kalle Valo
cd607f2c ce038edf

+6 -4
+6 -4
drivers/net/wireless/mediatek/mt76/dma.c
··· 783 783 784 784 static void 785 785 mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data, 786 - int len, bool more, u32 info) 786 + int len, bool more, u32 info, bool allow_direct) 787 787 { 788 788 struct sk_buff *skb = q->rx_head; 789 789 struct skb_shared_info *shinfo = skb_shinfo(skb); ··· 795 795 796 796 skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size); 797 797 } else { 798 - mt76_put_page_pool_buf(data, true); 798 + mt76_put_page_pool_buf(data, allow_direct); 799 799 } 800 800 801 801 if (more) ··· 815 815 struct sk_buff *skb; 816 816 unsigned char *data; 817 817 bool check_ddone = false; 818 + bool allow_direct = !mt76_queue_is_wed_rx(q); 818 819 bool more; 819 820 820 821 if (IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED) && ··· 856 855 } 857 856 858 857 if (q->rx_head) { 859 - mt76_add_fragment(dev, q, data, len, more, info); 858 + mt76_add_fragment(dev, q, data, len, more, info, 859 + allow_direct); 860 860 continue; 861 861 } 862 862 ··· 886 884 continue; 887 885 888 886 free_frag: 889 - mt76_put_page_pool_buf(data, true); 887 + mt76_put_page_pool_buf(data, allow_direct); 890 888 } 891 889 892 890 mt76_dma_rx_fill(dev, q, true);