diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/usb.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/usb.c | 66 |
1 files changed, 48 insertions, 18 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index bbaa1365bbda..fb87ce7fbdf6 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -267,12 +267,10 @@ mt76u_set_endpoints(struct usb_interface *intf, if (usb_endpoint_is_bulk_in(ep_desc) && in_ep < __MT_EP_IN_MAX) { usb->in_ep[in_ep] = usb_endpoint_num(ep_desc); - usb->in_max_packet = usb_endpoint_maxp(ep_desc); in_ep++; } else if (usb_endpoint_is_bulk_out(ep_desc) && out_ep < __MT_EP_OUT_MAX) { usb->out_ep[out_ep] = usb_endpoint_num(ep_desc); - usb->out_max_packet = usb_endpoint_maxp(ep_desc); out_ep++; } } @@ -333,12 +331,13 @@ mt76u_refill_rx(struct mt76_dev *dev, struct urb *urb, int nsgs, gfp_t gfp) } static int -mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) +mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e, + int sg_max_size) { unsigned int size = sizeof(struct urb); if (dev->usb.sg_en) - size += MT_SG_MAX_SIZE * sizeof(struct scatterlist); + size += sg_max_size * sizeof(struct scatterlist); e->urb = kzalloc(size, GFP_KERNEL); if (!e->urb) @@ -357,11 +356,12 @@ mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e) { int err; - err = mt76u_urb_alloc(dev, e); + err = mt76u_urb_alloc(dev, e, MT_RX_SG_MAX_SIZE); if (err) return err; - return mt76u_refill_rx(dev, e->urb, MT_SG_MAX_SIZE, GFP_KERNEL); + return mt76u_refill_rx(dev, e->urb, MT_RX_SG_MAX_SIZE, + GFP_KERNEL); } static void mt76u_urb_free(struct urb *urb) @@ -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, @@ -577,8 +605,9 @@ static int mt76u_alloc_rx(struct mt76_dev *dev) if (!q->entry) return -ENOMEM; - q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE; q->ndesc = MT_NUM_RX_ENTRIES; + q->buf_size = PAGE_SIZE; + for (i = 0; i < q->ndesc; i++) { err = mt76u_rx_urb_alloc(dev, &q->entry[i]); if (err < 0) @@ -735,7 +764,7 @@ mt76u_tx_setup_buffers(struct mt76_dev *dev, struct sk_buff *skb, urb->transfer_buffer = skb->data; return 0; } else { - sg_init_table(urb->sg, MT_SG_MAX_SIZE); + sg_init_table(urb->sg, MT_TX_SG_MAX_SIZE); urb->num_sgs = skb_to_sgvec(skb, urb->sg, 0, skb->len); if (urb->num_sgs == 0) return -ENOMEM; @@ -829,7 +858,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) q->ndesc = MT_NUM_TX_ENTRIES; for (j = 0; j < q->ndesc; j++) { - err = mt76u_urb_alloc(dev, &q->entry[j]); + err = mt76u_urb_alloc(dev, &q->entry[j], + MT_TX_SG_MAX_SIZE); if (err < 0) return err; } |