]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 5.2
authorSasha Levin <sashal@kernel.org>
Fri, 30 Aug 2019 14:53:15 +0000 (10:53 -0400)
committerSasha Levin <sashal@kernel.org>
Fri, 30 Aug 2019 14:53:15 +0000 (10:53 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.2/mt76-usb-fix-rx-a-msdu-support.patch [new file with mode: 0644]
queue-5.2/series

diff --git a/queue-5.2/mt76-usb-fix-rx-a-msdu-support.patch b/queue-5.2/mt76-usb-fix-rx-a-msdu-support.patch
new file mode 100644 (file)
index 0000000..fed1a60
--- /dev/null
@@ -0,0 +1,107 @@
+From 7e00c8d6c543e69fd04591e249a92613c1c9008e Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Sat, 15 Jun 2019 16:03:32 +0200
+Subject: mt76: usb: fix rx A-MSDU support
+
+[ Upstream commit 2a92b08b18553c101115423bd34963b1a59a45a3 ]
+
+Commit f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes
+for rx") breaks A-MSDU support. When A-MSDU is enable the device can
+receive frames up to q->buf_size but they will be discarded in
+mt76u_process_rx_entry since there is no enough room for
+skb_shared_info. Fix the issue reallocating the skb and copying in the
+linear area the first 128B of the received frames and in the frag_list
+the remaining part
+
+Fixes: f8f527b16db5 ("mt76: usb: use EP max packet aligned buffer sizes for rx")
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mediatek/mt76/mt76.h |  1 +
+ drivers/net/wireless/mediatek/mt76/usb.c  | 46 ++++++++++++++++++-----
+ 2 files changed, 38 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
+index 8ecbf81a906f5..889b76deb7037 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76.h
+@@ -30,6 +30,7 @@
+ #define MT_TX_RING_SIZE     256
+ #define MT_MCU_RING_SIZE    32
+ #define MT_RX_BUF_SIZE      2048
++#define MT_SKB_HEAD_LEN     128
+ struct mt76_dev;
+ struct mt76_wcid;
+diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
+index bbaa1365bbda2..dd90427b2d672 100644
+--- a/drivers/net/wireless/mediatek/mt76/usb.c
++++ b/drivers/net/wireless/mediatek/mt76/usb.c
+@@ -429,6 +429,42 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
+       return dma_len;
+ }
++static struct sk_buff *
++mt76u_build_rx_skb(void *data, int len, int buf_size)
++{
++      struct sk_buff *skb;
++
++      if (SKB_WITH_OVERHEAD(buf_size) < MT_DMA_HDR_LEN + len) {
++              struct page *page;
++
++              /* slow path, not enough space for data and
++               * skb_shared_info
++               */
++              skb = alloc_skb(MT_SKB_HEAD_LEN, GFP_ATOMIC);
++              if (!skb)
++                      return NULL;
++
++              skb_put_data(skb, data + MT_DMA_HDR_LEN, MT_SKB_HEAD_LEN);
++              data += (MT_DMA_HDR_LEN + MT_SKB_HEAD_LEN);
++              page = virt_to_head_page(data);
++              skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
++                              page, data - page_address(page),
++                              len - MT_SKB_HEAD_LEN, buf_size);
++
++              return skb;
++      }
++
++      /* fast path */
++      skb = build_skb(data, buf_size);
++      if (!skb)
++              return NULL;
++
++      skb_reserve(skb, MT_DMA_HDR_LEN);
++      __skb_put(skb, len);
++
++      return skb;
++}
++
+ static int
+ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
+ {
+@@ -446,19 +482,11 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
+               return 0;
+       data_len = min_t(int, len, data_len - MT_DMA_HDR_LEN);
+-      if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size)) {
+-              dev_err_ratelimited(dev->dev, "rx data too big %d\n", data_len);
+-              return 0;
+-      }
+-
+-      skb = build_skb(data, q->buf_size);
++      skb = mt76u_build_rx_skb(data, data_len, q->buf_size);
+       if (!skb)
+               return 0;
+-      skb_reserve(skb, MT_DMA_HDR_LEN);
+-      __skb_put(skb, data_len);
+       len -= data_len;
+-
+       while (len > 0 && nsgs < urb->num_sgs) {
+               data_len = min_t(int, len, urb->sg[nsgs].length);
+               skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+-- 
+2.20.1
+
index e325a9209bb0d13a6a939b21612eb8ccee853bcb..c65a6ba1c93fa5246668ae167f5a39ebac87b070 100644 (file)
@@ -45,3 +45,4 @@ lcoking-rwsem-add-missing-acquire-to-read_slowpath-s.patch
 watchdog-bcm2835_wdt-fix-module-autoload.patch
 selftests-bpf-install-files-test_xdp_vlan.sh.patch
 drm-bridge-tfp410-fix-memleak-in-get_modes.patch
+mt76-usb-fix-rx-a-msdu-support.patch