mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 09:31:14 +00:00
mt76: usb: use a linear buffer for tx/rx datapath if sg is not supported
Use linear fragment and not a single usb scatter-gather buffer in mt76u {tx,rx} datapath if the usb controller has sg data length constraints Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
d704d16f20
commit
f752294946
1 changed files with 54 additions and 33 deletions
|
@ -432,10 +432,11 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
|
mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf)
|
||||||
{
|
{
|
||||||
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
|
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
|
||||||
u8 *data = sg_virt(&urb->sg[0]);
|
struct urb *urb = buf->urb;
|
||||||
|
u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : buf->buf;
|
||||||
int data_len, len, nsgs = 1;
|
int data_len, len, nsgs = 1;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
@ -446,7 +447,8 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
data_len = min_t(int, len, urb->sg[0].length - MT_DMA_HDR_LEN);
|
data_len = urb->num_sgs ? urb->sg[0].length : buf->len;
|
||||||
|
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))
|
if (MT_DMA_HDR_LEN + data_len > SKB_WITH_OVERHEAD(q->buf_size))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -458,7 +460,7 @@ mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
|
||||||
__skb_put(skb, data_len);
|
__skb_put(skb, data_len);
|
||||||
len -= data_len;
|
len -= data_len;
|
||||||
|
|
||||||
while (len > 0) {
|
while (len > 0 && urb->num_sgs) {
|
||||||
data_len = min_t(int, len, urb->sg[nsgs].length);
|
data_len = min_t(int, len, urb->sg[nsgs].length);
|
||||||
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
||||||
sg_page(&urb->sg[nsgs]),
|
sg_page(&urb->sg[nsgs]),
|
||||||
|
@ -503,12 +505,26 @@ out:
|
||||||
spin_unlock_irqrestore(&q->lock, flags);
|
spin_unlock_irqrestore(&q->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q,
|
||||||
|
struct mt76u_buf *buf, int nsgs)
|
||||||
|
{
|
||||||
|
if (dev->usb.sg_en) {
|
||||||
|
return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size,
|
||||||
|
SKB_WITH_OVERHEAD(q->buf_size));
|
||||||
|
} else {
|
||||||
|
buf->buf = page_frag_alloc(&q->rx_page, q->buf_size,
|
||||||
|
GFP_ATOMIC);
|
||||||
|
return buf->buf ? 0 : -ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void mt76u_rx_tasklet(unsigned long data)
|
static void mt76u_rx_tasklet(unsigned long data)
|
||||||
{
|
{
|
||||||
struct mt76_dev *dev = (struct mt76_dev *)data;
|
struct mt76_dev *dev = (struct mt76_dev *)data;
|
||||||
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
|
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
|
||||||
int err, nsgs, buf_len = q->buf_size;
|
|
||||||
struct mt76u_buf *buf;
|
struct mt76u_buf *buf;
|
||||||
|
int err, count;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
|
@ -517,11 +533,9 @@ static void mt76u_rx_tasklet(unsigned long data)
|
||||||
if (!buf)
|
if (!buf)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
nsgs = mt76u_process_rx_entry(dev, buf->urb);
|
count = mt76u_process_rx_entry(dev, buf);
|
||||||
if (nsgs > 0) {
|
if (count > 0) {
|
||||||
err = mt76u_fill_rx_sg(dev, buf, nsgs,
|
err = mt76u_refill_rx(dev, q, buf, count);
|
||||||
buf_len,
|
|
||||||
SKB_WITH_OVERHEAD(buf_len));
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -559,7 +573,7 @@ EXPORT_SYMBOL_GPL(mt76u_submit_rx_buffers);
|
||||||
static int mt76u_alloc_rx(struct mt76_dev *dev)
|
static int mt76u_alloc_rx(struct mt76_dev *dev)
|
||||||
{
|
{
|
||||||
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
|
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
|
||||||
int i, err, nsgs;
|
int i, err;
|
||||||
|
|
||||||
spin_lock_init(&q->rx_page_lock);
|
spin_lock_init(&q->rx_page_lock);
|
||||||
spin_lock_init(&q->lock);
|
spin_lock_init(&q->lock);
|
||||||
|
@ -569,20 +583,19 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
|
||||||
if (!q->entry)
|
if (!q->entry)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (dev->usb.sg_en) {
|
q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
|
||||||
q->buf_size = MT_RX_BUF_SIZE;
|
|
||||||
nsgs = MT_SG_MAX_SIZE;
|
|
||||||
} else {
|
|
||||||
q->buf_size = PAGE_SIZE;
|
|
||||||
nsgs = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
q->ndesc = MT_NUM_RX_ENTRIES;
|
q->ndesc = MT_NUM_RX_ENTRIES;
|
||||||
for (i = 0; i < q->ndesc; i++) {
|
for (i = 0; i < q->ndesc; i++) {
|
||||||
err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf,
|
if (dev->usb.sg_en)
|
||||||
nsgs, q->buf_size,
|
err = mt76u_buf_alloc_sg(dev, &q->entry[i].ubuf,
|
||||||
SKB_WITH_OVERHEAD(q->buf_size),
|
MT_SG_MAX_SIZE, q->buf_size,
|
||||||
GFP_KERNEL);
|
SKB_WITH_OVERHEAD(q->buf_size),
|
||||||
|
GFP_KERNEL);
|
||||||
|
else
|
||||||
|
err = mt76u_buf_alloc(dev, &q->entry[i].ubuf,
|
||||||
|
q->buf_size,
|
||||||
|
SKB_WITH_OVERHEAD(q->buf_size),
|
||||||
|
GFP_KERNEL);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -730,7 +743,7 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||||
{
|
{
|
||||||
struct usb_interface *intf = to_usb_interface(dev->dev);
|
struct usb_interface *intf = to_usb_interface(dev->dev);
|
||||||
struct usb_device *udev = interface_to_usbdev(intf);
|
struct usb_device *udev = interface_to_usbdev(intf);
|
||||||
u8 ep = q2ep(q->hw_idx);
|
u8 *data = NULL, ep = q2ep(q->hw_idx);
|
||||||
struct mt76u_buf *buf;
|
struct mt76u_buf *buf;
|
||||||
u16 idx = q->tail;
|
u16 idx = q->tail;
|
||||||
unsigned int pipe;
|
unsigned int pipe;
|
||||||
|
@ -747,12 +760,16 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
|
||||||
buf = &q->entry[idx].ubuf;
|
buf = &q->entry[idx].ubuf;
|
||||||
buf->done = false;
|
buf->done = false;
|
||||||
|
|
||||||
err = mt76u_tx_build_sg(skb, buf->urb);
|
if (dev->usb.sg_en) {
|
||||||
if (err < 0)
|
err = mt76u_tx_build_sg(skb, buf->urb);
|
||||||
return err;
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
} else {
|
||||||
|
data = skb->data;
|
||||||
|
}
|
||||||
|
|
||||||
pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[ep]);
|
pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[ep]);
|
||||||
usb_fill_bulk_urb(buf->urb, udev, pipe, NULL, skb->len,
|
usb_fill_bulk_urb(buf->urb, udev, pipe, data, skb->len,
|
||||||
mt76u_complete_tx, buf);
|
mt76u_complete_tx, buf);
|
||||||
|
|
||||||
q->tail = (q->tail + 1) % q->ndesc;
|
q->tail = (q->tail + 1) % q->ndesc;
|
||||||
|
@ -788,10 +805,8 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
|
||||||
{
|
{
|
||||||
struct mt76u_buf *buf;
|
struct mt76u_buf *buf;
|
||||||
struct mt76_queue *q;
|
struct mt76_queue *q;
|
||||||
size_t size;
|
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
size = MT_SG_MAX_SIZE * sizeof(struct scatterlist);
|
|
||||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||||
q = &dev->q_tx[i];
|
q = &dev->q_tx[i];
|
||||||
spin_lock_init(&q->lock);
|
spin_lock_init(&q->lock);
|
||||||
|
@ -813,9 +828,15 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
|
||||||
if (!buf->urb)
|
if (!buf->urb)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
buf->urb->sg = devm_kzalloc(dev->dev, size, GFP_KERNEL);
|
if (dev->usb.sg_en) {
|
||||||
if (!buf->urb->sg)
|
size_t size = MT_SG_MAX_SIZE *
|
||||||
return -ENOMEM;
|
sizeof(struct scatterlist);
|
||||||
|
|
||||||
|
buf->urb->sg = devm_kzalloc(dev->dev, size,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!buf->urb->sg)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue