Hi and sorry for late comment. On Fri, May 31, 2019 at 11:38:22AM +0200, Lorenzo Bianconi wrote: > 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@xxxxxxxxxx> > --- > drivers/net/wireless/mediatek/mt76/mt76.h | 1 + > drivers/net/wireless/mediatek/mt76/usb.c | 52 +++++++++++++++++++---- > 2 files changed, 44 insertions(+), 9 deletions(-) > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h > index 97a1296562d0..74d4edf941d6 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 bbaa1365bbda..2bfc8214c0d8 100644 > --- a/drivers/net/wireless/mediatek/mt76/usb.c > +++ b/drivers/net/wireless/mediatek/mt76/usb.c > @@ -429,6 +429,48 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len) > return dma_len; > } > > +static struct sk_buff * > +mt76u_build_rx_skb(u8 *data, int len, int buf_size, > + int *nsgs) > +{ > + int data_len = min(len, MT_SKB_HEAD_LEN); > + struct sk_buff *skb; > + > + if (SKB_WITH_OVERHEAD(buf_size) >= MT_DMA_HDR_LEN + len) { > + /* 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; > + } > + > + /* slow path, not enough space for data and > + * skb_shared_info > + */ > + skb = alloc_skb(data_len, GFP_ATOMIC); > + if (!skb) > + return NULL; > + > + skb_put_data(skb, data + MT_DMA_HDR_LEN, data_len); mt7601u and iwlmvm just copy hdrlen + 8 and put the rest of the buffer in fragment, which supose to be more efficient, see comment in iwl_mvm_pass_packet_to_mac80211(). > + data += (data_len + MT_DMA_HDR_LEN); > + len -= data_len; > + if (len > 0) { > + struct page *page = virt_to_head_page(data); > + int offset = data - (u8 *)page_address(page); u8 cast not needed. > + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, > + page, offset, len, buf_size); > + } else { > + *nsgs = 0; This seems to be not necessary or a bug (use first buffer 2 times). Stanislaw