This should be rebased on latest patches, for now sent as RFC.
Significant change is remove mt76u_buf and use urb directly
and allocate urb and sg as linear data for better cache usage.
Other that that, set consist only of some minor cleanups.
Stanislaw Gruszka (12):
mt76usb: change mt76u_submit_buf
mt76: remove rx_page_lock
mt76usb: change mt76u_fill_rx_sg arguments
mt76usb: use usb_dev private data
mt76usb: remove mt76u_buf redundant fileds
mt76usb: move mt76u_buf->done to queue entry
mt76usb: remove mt76u_buf and use urb directly
mt76usb: remove MT_RXQ_MAIN queue from mt76u_urb_alloc
mt76usb: resue mt76u_urb_alloc for tx
mt76usb: remove unneded sg_init_table
mt76usb: allocate urb and sg as linear data
mt76usb: remove queue variable from rx_tasklet
drivers/net/wireless/mediatek/mt76/mt76.h | 15 +-
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 4 +-
drivers/net/wireless/mediatek/mt76/usb.c | 231 +++++++++++-------------
4 files changed, 111 insertions(+), 141 deletions(-)
--
1.9.3
Remove unnecessery arguments and change the function name since is
now used only for RX.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/usb.c | 30 ++++++++++++------------------
1 file changed, 12 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index c5f3b2cdd9b1..661a65cb9c35 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -394,18 +394,6 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
complete_fn, context);
}
-static int
-mt76u_submit_buf(struct mt76_dev *dev, int dir, int index,
- struct mt76u_buf *buf, gfp_t gfp,
- usb_complete_t complete_fn, void *context)
-{
- mt76u_fill_bulk_urb(dev, dir, index, buf, complete_fn,
- context);
- trace_submit_urb(dev, buf->urb);
-
- return usb_submit_urb(buf->urb, gfp);
-}
-
static inline struct mt76u_buf
*mt76u_get_next_rx_entry(struct mt76_queue *q)
{
@@ -513,6 +501,16 @@ static void mt76u_complete_rx(struct urb *urb)
spin_unlock_irqrestore(&q->lock, flags);
}
+static int
+mt76u_submit_rx_buf(struct mt76_dev *dev, struct mt76u_buf *buf)
+{
+ mt76u_fill_bulk_urb(dev, USB_DIR_IN, MT_EP_IN_PKT_RX, buf,
+ mt76u_complete_rx, dev);
+ trace_submit_urb(dev, buf->urb);
+
+ return usb_submit_urb(buf->urb, GFP_ATOMIC);
+}
+
static void mt76u_rx_tasklet(unsigned long data)
{
struct mt76_dev *dev = (struct mt76_dev *)data;
@@ -534,9 +532,7 @@ static void mt76u_rx_tasklet(unsigned long data)
if (err < 0)
break;
}
- mt76u_submit_buf(dev, USB_DIR_IN, MT_EP_IN_PKT_RX,
- buf, GFP_ATOMIC,
- mt76u_complete_rx, dev);
+ mt76u_submit_rx_buf(dev, buf);
}
mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL);
@@ -551,9 +547,7 @@ int mt76u_submit_rx_buffers(struct mt76_dev *dev)
spin_lock_irqsave(&q->lock, flags);
for (i = 0; i < q->ndesc; i++) {
- err = mt76u_submit_buf(dev, USB_DIR_IN, MT_EP_IN_PKT_RX,
- &q->entry[i].ubuf, GFP_ATOMIC,
- mt76u_complete_rx, dev);
+ err = mt76u_submit_rx_buf(dev, &q->entry[i].ubuf);
if (err < 0)
break;
}
--
1.9.3
We can not run mt76u_alloc_buf() concurently, rx_tasklet is stooped
when mt76u_submit_rx_buffers(). We can remove rx_page_lock.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 1 -
drivers/net/wireless/mediatek/mt76/usb.c | 8 +-------
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 3d3f0a5fc426..424f9090680d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -132,7 +132,6 @@ struct mt76_queue {
dma_addr_t desc_dma;
struct sk_buff *rx_head;
struct page_frag_cache rx_page;
- spinlock_t rx_page_lock;
};
struct mt76_sw_queue {
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 661a65cb9c35..883e8a2b519f 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -292,7 +292,6 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
struct urb *urb = buf->urb;
int i;
- spin_lock_bh(&q->rx_page_lock);
for (i = 0; i < nsgs; i++) {
struct page *page;
void *data;
@@ -306,7 +305,6 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
offset = data - page_address(page);
sg_set_page(&urb->sg[i], page, sglen, offset);
}
- spin_unlock_bh(&q->rx_page_lock);
if (i < nsgs) {
int j;
@@ -569,7 +567,6 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
if (!usb->mcu.data)
return -ENOMEM;
- spin_lock_init(&q->rx_page_lock);
spin_lock_init(&q->lock);
q->entry = devm_kcalloc(dev->dev,
MT_NUM_RX_ENTRIES, sizeof(*q->entry),
@@ -597,15 +594,12 @@ static void mt76u_free_rx(struct mt76_dev *dev)
for (i = 0; i < q->ndesc; i++)
mt76u_buf_free(&q->entry[i].ubuf);
- spin_lock_bh(&q->rx_page_lock);
if (!q->rx_page.va)
- goto out;
+ return;
page = virt_to_page(q->rx_page.va);
__page_frag_cache_drain(page, q->rx_page.pagecnt_bias);
memset(&q->rx_page, 0, sizeof(q->rx_page));
-out:
- spin_unlock_bh(&q->rx_page_lock);
}
static void mt76u_stop_rx(struct mt76_dev *dev)
--
1.9.3
We do not need to pass len and sglen to the function.
Additionally pass gfp to control allocation context.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/usb.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 883e8a2b519f..dbabf7971798 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -285,11 +285,13 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
}
static int
-mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf,
- int nsgs, int len, int sglen)
+mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, int nsgs,
+ gfp_t gfp)
{
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
+ int sglen = SKB_WITH_OVERHEAD(q->buf_size);
struct urb *urb = buf->urb;
+
int i;
for (i = 0; i < nsgs; i++) {
@@ -297,7 +299,7 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
void *data;
int offset;
- data = page_frag_alloc(&q->rx_page, len, GFP_ATOMIC);
+ data = page_frag_alloc(&q->rx_page, q->buf_size, gfp);
if (!data)
break;
@@ -326,8 +328,7 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
struct mt76u_buf *buf, int nsgs, gfp_t gfp)
{
if (dev->usb.sg_en) {
- return mt76u_fill_rx_sg(dev, buf, nsgs, q->buf_size,
- SKB_WITH_OVERHEAD(q->buf_size));
+ return mt76u_fill_rx_sg(dev, buf, nsgs, gfp);
} else {
buf->buf = page_frag_alloc(&q->rx_page, q->buf_size, gfp);
return buf->buf ? 0 : -ENOMEM;
--
1.9.3
Setup usb device private data. This allows to remove mt76u_buf->dev
and simplify some routines as no longer we need to get usb device
through usb interface.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 4 +---
drivers/net/wireless/mediatek/mt76/mt76x0/usb.c | 2 +-
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 4 +++-
drivers/net/wireless/mediatek/mt76/usb.c | 13 ++++---------
4 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 424f9090680d..89cdfe4abf33 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -84,7 +84,6 @@ struct mt76_queue_buf {
};
struct mt76u_buf {
- struct mt76_dev *dev;
struct urb *urb;
size_t len;
void *buf;
@@ -744,8 +743,7 @@ static inline u8 q2ep(u8 qid)
mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
int timeout)
{
- struct usb_interface *intf = to_usb_interface(dev->dev);
- struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_device *udev = to_usb_device(dev->dev);
struct mt76_usb *usb = &dev->usb;
unsigned int pipe;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
index 69d6328a098d..1ef00e971cfa 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -234,7 +234,7 @@ static int mt76x0u_probe(struct usb_interface *usb_intf,
u32 mac_rev;
int ret;
- mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops,
+ mdev = mt76_alloc_device(&usb_dev->dev, sizeof(*dev), &mt76x0u_ops,
&drv_ops);
if (!mdev)
return -ENOMEM;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
index 47fe536bf896..0a7df308b2f8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
@@ -50,7 +50,7 @@ static int mt76x2u_probe(struct usb_interface *intf,
struct mt76_dev *mdev;
int err;
- mdev = mt76_alloc_device(&intf->dev, sizeof(*dev), &mt76x2u_ops,
+ mdev = mt76_alloc_device(&udev->dev, sizeof(*dev), &mt76x2u_ops,
&drv_ops);
if (!mdev)
return -ENOMEM;
@@ -60,6 +60,8 @@ static int mt76x2u_probe(struct usb_interface *intf,
udev = usb_get_dev(udev);
usb_reset_device(udev);
+ usb_set_intfdata(intf, dev);
+
mt76x02u_init_mcu(mdev);
err = mt76u_init(mdev, intf);
if (err < 0)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index dbabf7971798..954feb311620 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -31,8 +31,7 @@ static int __mt76u_vendor_request(struct mt76_dev *dev, u8 req,
u8 req_type, u16 val, u16 offset,
void *buf, size_t len)
{
- struct usb_interface *intf = to_usb_interface(dev->dev);
- struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_device *udev = to_usb_device(dev->dev);
unsigned int pipe;
int i, ret;
@@ -247,8 +246,7 @@ void mt76u_single_wr(struct mt76_dev *dev, const u8 req,
static bool mt76u_check_sg(struct mt76_dev *dev)
{
- struct usb_interface *intf = to_usb_interface(dev->dev);
- struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_device *udev = to_usb_device(dev->dev);
return (!disable_usb_sg && udev->bus->sg_tablesize > 0 &&
(udev->bus->no_sg_constraint ||
@@ -341,7 +339,6 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
buf->len = SKB_WITH_OVERHEAD(q->buf_size);
- buf->dev = dev;
buf->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!buf->urb)
@@ -379,8 +376,7 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
struct mt76u_buf *buf, usb_complete_t complete_fn,
void *context)
{
- struct usb_interface *intf = to_usb_interface(dev->dev);
- struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_device *udev = to_usb_device(dev->dev);
u8 *data = buf->urb->num_sgs ? NULL : buf->buf;
unsigned int pipe;
@@ -694,8 +690,8 @@ static void mt76u_tx_status_data(struct work_struct *work)
static void mt76u_complete_tx(struct urb *urb)
{
+ struct mt76_dev *dev = dev_get_drvdata(&urb->dev->dev);
struct mt76u_buf *buf = urb->context;
- struct mt76_dev *dev = buf->dev;
if (mt76u_urb_error(urb))
dev_err(dev->dev, "tx urb failed: %d\n", urb->status);
@@ -806,7 +802,6 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
q->ndesc = MT_NUM_TX_ENTRIES;
for (j = 0; j < q->ndesc; j++) {
buf = &q->entry[j].ubuf;
- buf->dev = dev;
buf->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!buf->urb)
--
1.9.3
Remove mt76u_buf->{len, buf} fields and operate on corresponding
urb fields directly.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 2 --
drivers/net/wireless/mediatek/mt76/usb.c | 40 +++++++++++++++++--------------
2 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 89cdfe4abf33..476cb39c99b7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -85,8 +85,6 @@ struct mt76_queue_buf {
struct mt76u_buf {
struct urb *urb;
- size_t len;
- void *buf;
bool done;
};
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 954feb311620..86bf852c6e3d 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -315,7 +315,7 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
}
urb->num_sgs = max_t(int, i, urb->num_sgs);
- buf->len = urb->num_sgs * sglen,
+ urb->transfer_buffer_length = urb->num_sgs * sglen,
sg_init_marker(urb->sg, urb->num_sgs);
return i ? : -ENOMEM;
@@ -328,8 +328,11 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
if (dev->usb.sg_en) {
return mt76u_fill_rx_sg(dev, buf, nsgs, gfp);
} else {
- buf->buf = page_frag_alloc(&q->rx_page, q->buf_size, gfp);
- return buf->buf ? 0 : -ENOMEM;
+ buf->urb->transfer_buffer_length =
+ SKB_WITH_OVERHEAD(q->buf_size);
+ buf->urb->transfer_buffer =
+ page_frag_alloc(&q->rx_page, q->buf_size, gfp);
+ return buf->urb->transfer_buffer ? 0 : -ENOMEM;
}
}
@@ -338,8 +341,6 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
{
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
- buf->len = SKB_WITH_OVERHEAD(q->buf_size);
-
buf->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!buf->urb)
return -ENOMEM;
@@ -365,8 +366,8 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
for (i = 0; i < urb->num_sgs; i++)
skb_free_frag(sg_virt(&urb->sg[i]));
- if (buf->buf)
- skb_free_frag(buf->buf);
+ if (urb->transfer_buffer)
+ skb_free_frag(urb->transfer_buffer);
usb_free_urb(buf->urb);
}
@@ -377,7 +378,6 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
void *context)
{
struct usb_device *udev = to_usb_device(dev->dev);
- u8 *data = buf->urb->num_sgs ? NULL : buf->buf;
unsigned int pipe;
if (dir == USB_DIR_IN)
@@ -385,8 +385,10 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
else
pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]);
- usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len,
- complete_fn, context);
+ buf->urb->dev = udev;
+ buf->urb->pipe = pipe;
+ buf->urb->complete = complete_fn;
+ buf->urb->context = context;
}
static inline struct mt76u_buf
@@ -426,7 +428,7 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
{
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
struct urb *urb = buf->urb;
- u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : buf->buf;
+ u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : urb->transfer_buffer;
int data_len, len, nsgs = 1;
struct sk_buff *skb;
@@ -437,7 +439,7 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
if (len < 0)
return 0;
- data_len = urb->num_sgs ? urb->sg[0].length : buf->len;
+ data_len = urb->num_sgs ? urb->sg[0].length : INT_MAX;
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))
return 0;
@@ -731,14 +733,16 @@ static void mt76u_complete_tx(struct urb *urb)
return err;
buf = &q->entry[idx].ubuf;
- buf->buf = skb->data;
- buf->len = skb->len;
+ if (!dev->usb.sg_en) {
+ buf->urb->transfer_buffer = skb->data;
+ } else {
+ err = mt76u_tx_build_sg(dev, skb, buf->urb);
+ if (err < 0)
+ return err;
+ }
+ buf->urb->transfer_buffer_length = skb->len;
buf->done = false;
- err = mt76u_tx_build_sg(dev, skb, buf->urb);
- if (err < 0)
- return err;
-
mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q2ep(q->hw_idx),
buf, mt76u_complete_tx, buf);
--
1.9.3
mt76_queue_entry has alreay one bool variable, adding new one will
not increase it's size. Removing ->done filed from mt76u_buf will
allow to use urb directly in mt76usb code.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 2 +-
drivers/net/wireless/mediatek/mt76/usb.c | 12 +++++-------
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 476cb39c99b7..998505064dee 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -85,7 +85,6 @@ struct mt76_queue_buf {
struct mt76u_buf {
struct urb *urb;
- bool done;
};
struct mt76_queue_entry {
@@ -99,6 +98,7 @@ struct mt76_queue_entry {
};
enum mt76_txq_id qid;
bool schedule;
+ bool done;
};
struct mt76_queue_regs {
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 86bf852c6e3d..a4ef9bb1603d 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -615,7 +615,6 @@ static void mt76u_tx_tasklet(unsigned long data)
struct mt76_dev *dev = (struct mt76_dev *)data;
struct mt76_queue_entry entry;
struct mt76_sw_queue *sq;
- struct mt76u_buf *buf;
struct mt76_queue *q;
bool wake;
int i;
@@ -626,8 +625,7 @@ static void mt76u_tx_tasklet(unsigned long data)
spin_lock_bh(&q->lock);
while (true) {
- buf = &q->entry[q->head].ubuf;
- if (!buf->done || !q->queued)
+ if (!q->entry[q->head].done || !q->queued)
break;
if (q->entry[q->head].schedule) {
@@ -693,11 +691,11 @@ static void mt76u_tx_status_data(struct work_struct *work)
static void mt76u_complete_tx(struct urb *urb)
{
struct mt76_dev *dev = dev_get_drvdata(&urb->dev->dev);
- struct mt76u_buf *buf = urb->context;
+ struct mt76_queue_entry *e = urb->context;
if (mt76u_urb_error(urb))
dev_err(dev->dev, "tx urb failed: %d\n", urb->status);
- buf->done = true;
+ e->done = true;
tasklet_schedule(&dev->usb.tx_tasklet);
}
@@ -732,6 +730,7 @@ static void mt76u_complete_tx(struct urb *urb)
if (err < 0)
return err;
+ q->entry[idx].done = false;
buf = &q->entry[idx].ubuf;
if (!dev->usb.sg_en) {
buf->urb->transfer_buffer = skb->data;
@@ -741,10 +740,9 @@ static void mt76u_complete_tx(struct urb *urb)
return err;
}
buf->urb->transfer_buffer_length = skb->len;
- buf->done = false;
mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q2ep(q->hw_idx),
- buf, mt76u_complete_tx, buf);
+ buf, mt76u_complete_tx, &q->entry[idx]);
q->tail = (q->tail + 1) % q->ndesc;
q->entry[idx].skb = skb;
--
1.9.3
Put urb pointer in mt76_queue_entry directly instead of mt76u_buf
structure.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt76.h | 6 +-
drivers/net/wireless/mediatek/mt76/usb.c | 132 +++++++++++++++---------------
2 files changed, 65 insertions(+), 73 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 998505064dee..859d0325583b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -83,10 +83,6 @@ struct mt76_queue_buf {
int len;
};
-struct mt76u_buf {
- struct urb *urb;
-};
-
struct mt76_queue_entry {
union {
void *buf;
@@ -94,7 +90,7 @@ struct mt76_queue_entry {
};
union {
struct mt76_txwi_cache *txwi;
- struct mt76u_buf ubuf;
+ struct urb *urb;
};
enum mt76_txq_id qid;
bool schedule;
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index a4ef9bb1603d..2c21f4773a19 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -283,12 +283,11 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
}
static int
-mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, int nsgs,
+mt76u_fill_rx_sg(struct mt76_dev *dev, struct urb *urb, int nsgs,
gfp_t gfp)
{
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
int sglen = SKB_WITH_OVERHEAD(q->buf_size);
- struct urb *urb = buf->urb;
int i;
@@ -323,44 +322,43 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
static int
mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q,
- struct mt76u_buf *buf, int nsgs, gfp_t gfp)
+ struct urb *urb, int nsgs, gfp_t gfp)
{
if (dev->usb.sg_en) {
- return mt76u_fill_rx_sg(dev, buf, nsgs, gfp);
+ return mt76u_fill_rx_sg(dev, urb, nsgs, gfp);
} else {
- buf->urb->transfer_buffer_length =
- SKB_WITH_OVERHEAD(q->buf_size);
- buf->urb->transfer_buffer =
- page_frag_alloc(&q->rx_page, q->buf_size, gfp);
- return buf->urb->transfer_buffer ? 0 : -ENOMEM;
+ urb->transfer_buffer_length = SKB_WITH_OVERHEAD(q->buf_size);
+ urb->transfer_buffer = page_frag_alloc(&q->rx_page,
+ q->buf_size, gfp);
+ return urb->transfer_buffer ? 0 : -ENOMEM;
}
}
static int
-mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf)
+mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e)
{
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
+ struct urb *urb;
- buf->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!buf->urb)
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
return -ENOMEM;
+ e->urb = urb;
if (dev->usb.sg_en) {
- buf->urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE,
- sizeof(*buf->urb->sg),
- GFP_KERNEL);
- if (!buf->urb->sg)
+ urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE,
+ sizeof(urb->sg), GFP_KERNEL);
+ if (!urb->sg)
return -ENOMEM;
- sg_init_table(buf->urb->sg, MT_SG_MAX_SIZE);
+ sg_init_table(urb->sg, MT_SG_MAX_SIZE);
}
- return mt76u_refill_rx(dev, q, buf, MT_SG_MAX_SIZE, GFP_KERNEL);
+ return mt76u_refill_rx(dev, q, urb, MT_SG_MAX_SIZE, GFP_KERNEL);
}
-static void mt76u_buf_free(struct mt76u_buf *buf)
+static void mt76u_urb_free(struct urb *urb)
{
- struct urb *urb = buf->urb;
int i;
for (i = 0; i < urb->num_sgs; i++)
@@ -369,12 +367,12 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
if (urb->transfer_buffer)
skb_free_frag(urb->transfer_buffer);
- usb_free_urb(buf->urb);
+ usb_free_urb(urb);
}
static void
mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index,
- struct mt76u_buf *buf, usb_complete_t complete_fn,
+ struct urb *urb, usb_complete_t complete_fn,
void *context)
{
struct usb_device *udev = to_usb_device(dev->dev);
@@ -385,27 +383,27 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
else
pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]);
- buf->urb->dev = udev;
- buf->urb->pipe = pipe;
- buf->urb->complete = complete_fn;
- buf->urb->context = context;
+ urb->dev = udev;
+ urb->pipe = pipe;
+ urb->complete = complete_fn;
+ urb->context = context;
}
-static inline struct mt76u_buf
-*mt76u_get_next_rx_entry(struct mt76_queue *q)
+static inline struct urb *
+mt76u_get_next_rx_entry(struct mt76_queue *q)
{
- struct mt76u_buf *buf = NULL;
+ struct urb *urb = NULL;
unsigned long flags;
spin_lock_irqsave(&q->lock, flags);
if (q->queued > 0) {
- buf = &q->entry[q->head].ubuf;
+ urb = q->entry[q->head].urb;
q->head = (q->head + 1) % q->ndesc;
q->queued--;
}
spin_unlock_irqrestore(&q->lock, flags);
- return buf;
+ return urb;
}
static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
@@ -424,10 +422,9 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
}
static int
-mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf)
+mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
{
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
- struct urb *urb = buf->urb;
u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : urb->transfer_buffer;
int data_len, len, nsgs = 1;
struct sk_buff *skb;
@@ -488,7 +485,7 @@ static void mt76u_complete_rx(struct urb *urb)
}
spin_lock_irqsave(&q->lock, flags);
- if (WARN_ONCE(q->entry[q->tail].ubuf.urb != urb, "rx urb mismatch"))
+ if (WARN_ONCE(q->entry[q->tail].urb != urb, "rx urb mismatch"))
goto out;
q->tail = (q->tail + 1) % q->ndesc;
@@ -499,37 +496,37 @@ static void mt76u_complete_rx(struct urb *urb)
}
static int
-mt76u_submit_rx_buf(struct mt76_dev *dev, struct mt76u_buf *buf)
+mt76u_submit_rx_buf(struct mt76_dev *dev, struct urb *urb)
{
- mt76u_fill_bulk_urb(dev, USB_DIR_IN, MT_EP_IN_PKT_RX, buf,
+ mt76u_fill_bulk_urb(dev, USB_DIR_IN, MT_EP_IN_PKT_RX, urb,
mt76u_complete_rx, dev);
- trace_submit_urb(dev, buf->urb);
+ trace_submit_urb(dev, urb);
- return usb_submit_urb(buf->urb, GFP_ATOMIC);
+ return usb_submit_urb(urb, GFP_ATOMIC);
}
static void mt76u_rx_tasklet(unsigned long data)
{
struct mt76_dev *dev = (struct mt76_dev *)data;
struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
- struct mt76u_buf *buf;
+ struct urb *urb;
int err, count;
rcu_read_lock();
while (true) {
- buf = mt76u_get_next_rx_entry(q);
- if (!buf)
+ urb = mt76u_get_next_rx_entry(q);
+ if (!urb)
break;
- count = mt76u_process_rx_entry(dev, buf);
+ count = mt76u_process_rx_entry(dev, urb);
if (count > 0) {
- err = mt76u_refill_rx(dev, q, buf, count,
+ err = mt76u_refill_rx(dev, q, urb, count,
GFP_ATOMIC);
if (err < 0)
break;
}
- mt76u_submit_rx_buf(dev, buf);
+ mt76u_submit_rx_buf(dev, urb);
}
mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL);
@@ -544,7 +541,7 @@ int mt76u_submit_rx_buffers(struct mt76_dev *dev)
spin_lock_irqsave(&q->lock, flags);
for (i = 0; i < q->ndesc; i++) {
- err = mt76u_submit_rx_buf(dev, &q->entry[i].ubuf);
+ err = mt76u_submit_rx_buf(dev, q->entry[i].urb);
if (err < 0)
break;
}
@@ -576,7 +573,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
q->ndesc = MT_NUM_RX_ENTRIES;
for (i = 0; i < q->ndesc; i++) {
- err = mt76u_buf_alloc(dev, &q->entry[i].ubuf);
+ err = mt76u_urb_alloc(dev, &q->entry[i]);
if (err < 0)
return err;
}
@@ -591,7 +588,7 @@ static void mt76u_free_rx(struct mt76_dev *dev)
int i;
for (i = 0; i < q->ndesc; i++)
- mt76u_buf_free(&q->entry[i].ubuf);
+ mt76u_urb_free(q->entry[i].urb);
if (!q->rx_page.va)
return;
@@ -607,7 +604,7 @@ static void mt76u_stop_rx(struct mt76_dev *dev)
int i;
for (i = 0; i < q->ndesc; i++)
- usb_kill_urb(q->entry[i].ubuf.urb);
+ usb_kill_urb(q->entry[i].urb);
}
static void mt76u_tx_tasklet(unsigned long data)
@@ -718,7 +715,7 @@ static void mt76u_complete_tx(struct urb *urb)
struct ieee80211_sta *sta)
{
struct mt76_queue *q = dev->q_tx[qid].q;
- struct mt76u_buf *buf;
+ struct urb *urb;
u16 idx = q->tail;
int err;
@@ -731,18 +728,18 @@ static void mt76u_complete_tx(struct urb *urb)
return err;
q->entry[idx].done = false;
- buf = &q->entry[idx].ubuf;
+ urb = q->entry[idx].urb;
if (!dev->usb.sg_en) {
- buf->urb->transfer_buffer = skb->data;
+ urb->transfer_buffer = skb->data;
} else {
- err = mt76u_tx_build_sg(dev, skb, buf->urb);
+ err = mt76u_tx_build_sg(dev, skb, urb);
if (err < 0)
return err;
}
- buf->urb->transfer_buffer_length = skb->len;
+ urb->transfer_buffer_length = skb->len;
mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q2ep(q->hw_idx),
- buf, mt76u_complete_tx, &q->entry[idx]);
+ urb, mt76u_complete_tx, &q->entry[idx]);
q->tail = (q->tail + 1) % q->ndesc;
q->entry[idx].skb = skb;
@@ -753,14 +750,14 @@ static void mt76u_complete_tx(struct urb *urb)
static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q)
{
- struct mt76u_buf *buf;
+ struct urb *urb;
int err;
while (q->first != q->tail) {
- buf = &q->entry[q->first].ubuf;
+ urb = q->entry[q->first].urb;
- trace_submit_urb(dev, buf->urb);
- err = usb_submit_urb(buf->urb, GFP_ATOMIC);
+ trace_submit_urb(dev, urb);
+ err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) {
if (err == -ENODEV)
set_bit(MT76_REMOVED, &dev->state);
@@ -775,7 +772,7 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q)
static int mt76u_alloc_tx(struct mt76_dev *dev)
{
- struct mt76u_buf *buf;
+ struct urb *urb;
struct mt76_queue *q;
int i, j;
@@ -803,19 +800,18 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
q->ndesc = MT_NUM_TX_ENTRIES;
for (j = 0; j < q->ndesc; j++) {
- buf = &q->entry[j].ubuf;
-
- buf->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!buf->urb)
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb)
return -ENOMEM;
+ q->entry[j].urb = urb;
if (dev->usb.sg_en) {
size_t size = MT_SG_MAX_SIZE *
sizeof(struct scatterlist);
- buf->urb->sg = devm_kzalloc(dev->dev, size,
- GFP_KERNEL);
- if (!buf->urb->sg)
+ urb->sg = devm_kzalloc(dev->dev, size,
+ GFP_KERNEL);
+ if (!urb->sg)
return -ENOMEM;
}
}
@@ -831,7 +827,7 @@ static void mt76u_free_tx(struct mt76_dev *dev)
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
q = dev->q_tx[i].q;
for (j = 0; j < q->ndesc; j++)
- usb_free_urb(q->entry[j].ubuf.urb);
+ usb_free_urb(q->entry[j].urb);
}
}
@@ -843,7 +839,7 @@ static void mt76u_stop_tx(struct mt76_dev *dev)
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
q = dev->q_tx[i].q;
for (j = 0; j < q->ndesc; j++)
- usb_kill_urb(q->entry[j].ubuf.urb);
+ usb_kill_urb(q->entry[j].urb);
}
}
--
1.9.3
Get the RX queue inside mt76u_refill_rx. This will allow to reuse
mt76u_urb_alloc for TX allocations.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/usb.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 2c21f4773a19..ca62ddc03be2 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -283,12 +283,10 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
}
static int
-mt76u_fill_rx_sg(struct mt76_dev *dev, struct urb *urb, int nsgs,
- gfp_t gfp)
+mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76_queue *q, struct urb *urb,
+ int nsgs, gfp_t gfp)
{
- struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
int sglen = SKB_WITH_OVERHEAD(q->buf_size);
-
int i;
for (i = 0; i < nsgs; i++) {
@@ -321,11 +319,12 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
}
static int
-mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q,
- struct urb *urb, int nsgs, gfp_t gfp)
+mt76u_refill_rx(struct mt76_dev *dev, struct urb *urb, int nsgs, gfp_t gfp)
{
+ struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
+
if (dev->usb.sg_en) {
- return mt76u_fill_rx_sg(dev, urb, nsgs, gfp);
+ return mt76u_fill_rx_sg(dev, q, urb, nsgs, gfp);
} else {
urb->transfer_buffer_length = SKB_WITH_OVERHEAD(q->buf_size);
urb->transfer_buffer = page_frag_alloc(&q->rx_page,
@@ -337,7 +336,6 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
static int
mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e)
{
- struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
struct urb *urb;
urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -354,7 +352,7 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
sg_init_table(urb->sg, MT_SG_MAX_SIZE);
}
- return mt76u_refill_rx(dev, q, urb, MT_SG_MAX_SIZE, GFP_KERNEL);
+ return mt76u_refill_rx(dev, urb, MT_SG_MAX_SIZE, GFP_KERNEL);
}
static void mt76u_urb_free(struct urb *urb)
@@ -521,8 +519,7 @@ static void mt76u_rx_tasklet(unsigned long data)
count = mt76u_process_rx_entry(dev, urb);
if (count > 0) {
- err = mt76u_refill_rx(dev, q, urb, count,
- GFP_ATOMIC);
+ err = mt76u_refill_rx(dev, urb, count, GFP_ATOMIC);
if (err < 0)
break;
}
--
1.9.3
Add new rx_urb_alloc routine and reuse common urb_alloc for tx
allocations.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/usb.c | 36 ++++++++++++++++----------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index ca62ddc03be2..64fac91f1a72 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -352,7 +352,19 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
sg_init_table(urb->sg, MT_SG_MAX_SIZE);
}
- return mt76u_refill_rx(dev, urb, MT_SG_MAX_SIZE, GFP_KERNEL);
+ return 0;
+}
+
+static int
+mt76u_rx_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e)
+{
+ int err;
+
+ err = mt76u_urb_alloc(dev, e);
+ if (err)
+ return err;
+
+ return mt76u_refill_rx(dev, e->urb, MT_SG_MAX_SIZE, GFP_KERNEL);
}
static void mt76u_urb_free(struct urb *urb)
@@ -570,7 +582,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
q->ndesc = MT_NUM_RX_ENTRIES;
for (i = 0; i < q->ndesc; i++) {
- err = mt76u_urb_alloc(dev, &q->entry[i]);
+ err = mt76u_rx_urb_alloc(dev, &q->entry[i]);
if (err < 0)
return err;
}
@@ -769,9 +781,8 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q)
static int mt76u_alloc_tx(struct mt76_dev *dev)
{
- struct urb *urb;
struct mt76_queue *q;
- int i, j;
+ int i, j, err;
for (i = 0; i <= MT_TXQ_PSD; i++) {
INIT_LIST_HEAD(&dev->q_tx[i].swq);
@@ -797,20 +808,9 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
q->ndesc = MT_NUM_TX_ENTRIES;
for (j = 0; j < q->ndesc; j++) {
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
- return -ENOMEM;
- q->entry[j].urb = urb;
-
- if (dev->usb.sg_en) {
- size_t size = MT_SG_MAX_SIZE *
- sizeof(struct scatterlist);
-
- urb->sg = devm_kzalloc(dev->dev, size,
- GFP_KERNEL);
- if (!urb->sg)
- return -ENOMEM;
- }
+ err = mt76u_urb_alloc(dev, &q->entry[j]);
+ if (err < 0)
+ return err;
}
}
return 0;
--
1.9.3
We already allocate with GFP_ZERO and sg marker is set later for
both RX and TX.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/usb.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 64fac91f1a72..0b9f0b5fd37d 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -348,8 +348,6 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
sizeof(urb->sg), GFP_KERNEL);
if (!urb->sg)
return -ENOMEM;
-
- sg_init_table(urb->sg, MT_SG_MAX_SIZE);
}
return 0;
--
1.9.3
Alloc sg table at the end of urb structure. This will increase
cache usage.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/usb.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index 0b9f0b5fd37d..dd487f65f44e 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -336,19 +336,19 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
static int
mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e)
{
- struct urb *urb;
+ unsigned int size = sizeof(struct urb);
+
+ if (dev->usb.sg_en)
+ size += MT_SG_MAX_SIZE * sizeof(struct scatterlist);
- urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!urb)
+ e->urb = kzalloc(size, GFP_KERNEL);
+ if (!e->urb)
return -ENOMEM;
- e->urb = urb;
- if (dev->usb.sg_en) {
- urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE,
- sizeof(urb->sg), GFP_KERNEL);
- if (!urb->sg)
- return -ENOMEM;
- }
+ usb_init_urb(e->urb);
+
+ if (dev->usb.sg_en)
+ e->urb->sg = (struct scatterlist *)((u8 *)e->urb + sizeof(struct urb));
return 0;
}
--
1.9.3
Since now only mt76u_get_next_rx_entry use queue argument move
it to this function.
Signed-off-by: Stanislaw Gruszka <[email protected]>
---
drivers/net/wireless/mediatek/mt76/usb.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
index dd487f65f44e..6a23e1852d2a 100644
--- a/drivers/net/wireless/mediatek/mt76/usb.c
+++ b/drivers/net/wireless/mediatek/mt76/usb.c
@@ -398,8 +398,9 @@ static void mt76u_urb_free(struct urb *urb)
}
static inline struct urb *
-mt76u_get_next_rx_entry(struct mt76_queue *q)
+mt76u_get_next_rx_entry(struct mt76_dev *dev)
{
+ struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
struct urb *urb = NULL;
unsigned long flags;
@@ -516,14 +517,13 @@ static void mt76u_complete_rx(struct urb *urb)
static void mt76u_rx_tasklet(unsigned long data)
{
struct mt76_dev *dev = (struct mt76_dev *)data;
- struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
struct urb *urb;
int err, count;
rcu_read_lock();
while (true) {
- urb = mt76u_get_next_rx_entry(q);
+ urb = mt76u_get_next_rx_entry(dev);
if (!urb)
break;
--
1.9.3
> Remove mt76u_buf->{len, buf} fields and operate on corresponding
> urb fields directly.
>
> Signed-off-by: Stanislaw Gruszka <[email protected]>
> ---
> drivers/net/wireless/mediatek/mt76/mt76.h | 2 --
> drivers/net/wireless/mediatek/mt76/usb.c | 40 +++++++++++++++++--------------
> 2 files changed, 22 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 89cdfe4abf33..476cb39c99b7 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -85,8 +85,6 @@ struct mt76_queue_buf {
>
[...]
> @@ -377,7 +378,6 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
> void *context)
> {
> struct usb_device *udev = to_usb_device(dev->dev);
> - u8 *data = buf->urb->num_sgs ? NULL : buf->buf;
> unsigned int pipe;
>
> if (dir == USB_DIR_IN)
> @@ -385,8 +385,10 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
> else
> pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]);
>
> - usb_fill_bulk_urb(buf->urb, udev, pipe, data, buf->len,
> - complete_fn, context);
> + buf->urb->dev = udev;
> + buf->urb->pipe = pipe;
> + buf->urb->complete = complete_fn;
> + buf->urb->context = context;
> }
>
> static inline struct mt76u_buf
> @@ -426,7 +428,7 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
> {
> struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
> struct urb *urb = buf->urb;
> - u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : buf->buf;
> + u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : urb->transfer_buffer;
> int data_len, len, nsgs = 1;
> struct sk_buff *skb;
>
> @@ -437,7 +439,7 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
> if (len < 0)
> return 0;
>
> - data_len = urb->num_sgs ? urb->sg[0].length : buf->len;
> + data_len = urb->num_sgs ? urb->sg[0].length : INT_MAX;
In this way we only use len, maybe better to do:
data_len = urb->num_sgs ? urb->sg[0].length :
SKB_WITH_OVERHEAD(q->buf_size)
> 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))
> return 0;
> @@ -731,14 +733,16 @@ static void mt76u_complete_tx(struct urb *urb)
> return err;
>
> buf = &q->entry[idx].ubuf;
> - buf->buf = skb->data;
> - buf->len = skb->len;
> + if (!dev->usb.sg_en) {
> + buf->urb->transfer_buffer = skb->data;
I think you can move this in mt76u_tx_build_sg or remove the if condition in
mt76u_tx_build_sg()
Regards,
Lorenzo
> + } else {
> + err = mt76u_tx_build_sg(dev, skb, buf->urb);
> + if (err < 0)
> + return err;
> + }
> + buf->urb->transfer_buffer_length = skb->len;
> buf->done = false;
>
> - err = mt76u_tx_build_sg(dev, skb, buf->urb);
> - if (err < 0)
> - return err;
> -
> mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q2ep(q->hw_idx),
> buf, mt76u_complete_tx, buf);
>
> --
> 1.9.3
>
> Put urb pointer in mt76_queue_entry directly instead of mt76u_buf
> structure.
>
> Signed-off-by: Stanislaw Gruszka <[email protected]>
> ---
> drivers/net/wireless/mediatek/mt76/mt76.h | 6 +-
> drivers/net/wireless/mediatek/mt76/usb.c | 132 +++++++++++++++---------------
> 2 files changed, 65 insertions(+), 73 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
> index 998505064dee..859d0325583b 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76.h
> @@ -83,10 +83,6 @@ struct mt76_queue_buf {
> int len;
> };
>
> -struct mt76u_buf {
> - struct urb *urb;
> -};
> -
> struct mt76_queue_entry {
> union {
> void *buf;
> @@ -94,7 +90,7 @@ struct mt76_queue_entry {
> };
> union {
> struct mt76_txwi_cache *txwi;
> - struct mt76u_buf ubuf;
> + struct urb *urb;
> };
> enum mt76_txq_id qid;
> bool schedule;
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> index a4ef9bb1603d..2c21f4773a19 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -283,12 +283,11 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
> }
>
> static int
> -mt76u_fill_rx_sg(struct mt76_dev *dev, struct mt76u_buf *buf, int nsgs,
> +mt76u_fill_rx_sg(struct mt76_dev *dev, struct urb *urb, int nsgs,
> gfp_t gfp)
> {
> struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
> int sglen = SKB_WITH_OVERHEAD(q->buf_size);
> - struct urb *urb = buf->urb;
>
> int i;
>
> @@ -323,44 +322,43 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
>
> static int
> mt76u_refill_rx(struct mt76_dev *dev, struct mt76_queue *q,
> - struct mt76u_buf *buf, int nsgs, gfp_t gfp)
> + struct urb *urb, int nsgs, gfp_t gfp)
> {
> if (dev->usb.sg_en) {
> - return mt76u_fill_rx_sg(dev, buf, nsgs, gfp);
> + return mt76u_fill_rx_sg(dev, urb, nsgs, gfp);
> } else {
> - buf->urb->transfer_buffer_length =
> - SKB_WITH_OVERHEAD(q->buf_size);
> - buf->urb->transfer_buffer =
> - page_frag_alloc(&q->rx_page, q->buf_size, gfp);
> - return buf->urb->transfer_buffer ? 0 : -ENOMEM;
> + urb->transfer_buffer_length = SKB_WITH_OVERHEAD(q->buf_size);
> + urb->transfer_buffer = page_frag_alloc(&q->rx_page,
> + q->buf_size, gfp);
> + return urb->transfer_buffer ? 0 : -ENOMEM;
> }
> }
>
> static int
> -mt76u_buf_alloc(struct mt76_dev *dev, struct mt76u_buf *buf)
> +mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e)
> {
> struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
> + struct urb *urb;
>
> - buf->urb = usb_alloc_urb(0, GFP_KERNEL);
> - if (!buf->urb)
> + urb = usb_alloc_urb(0, GFP_KERNEL);
I guess here you can do:
e->urb = usb_alloc_urb(0, GFP_KERNEL);
if (!e->urb)
return -ENOMEM;
Regards,
Lorenzo
> + if (!urb)
> return -ENOMEM;
> + e->urb = urb;
>
> if (dev->usb.sg_en) {
> - buf->urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE,
> - sizeof(*buf->urb->sg),
> - GFP_KERNEL);
> - if (!buf->urb->sg)
> + urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE,
> + sizeof(urb->sg), GFP_KERNEL);
> + if (!urb->sg)
> return -ENOMEM;
>
> - sg_init_table(buf->urb->sg, MT_SG_MAX_SIZE);
> + sg_init_table(urb->sg, MT_SG_MAX_SIZE);
> }
>
> - return mt76u_refill_rx(dev, q, buf, MT_SG_MAX_SIZE, GFP_KERNEL);
> + return mt76u_refill_rx(dev, q, urb, MT_SG_MAX_SIZE, GFP_KERNEL);
> }
>
> -static void mt76u_buf_free(struct mt76u_buf *buf)
> +static void mt76u_urb_free(struct urb *urb)
> {
> - struct urb *urb = buf->urb;
> int i;
>
> for (i = 0; i < urb->num_sgs; i++)
> @@ -369,12 +367,12 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
> if (urb->transfer_buffer)
> skb_free_frag(urb->transfer_buffer);
>
> - usb_free_urb(buf->urb);
> + usb_free_urb(urb);
> }
>
> static void
> mt76u_fill_bulk_urb(struct mt76_dev *dev, int dir, int index,
> - struct mt76u_buf *buf, usb_complete_t complete_fn,
> + struct urb *urb, usb_complete_t complete_fn,
> void *context)
> {
> struct usb_device *udev = to_usb_device(dev->dev);
> @@ -385,27 +383,27 @@ static void mt76u_buf_free(struct mt76u_buf *buf)
> else
> pipe = usb_sndbulkpipe(udev, dev->usb.out_ep[index]);
>
> - buf->urb->dev = udev;
> - buf->urb->pipe = pipe;
> - buf->urb->complete = complete_fn;
> - buf->urb->context = context;
> + urb->dev = udev;
> + urb->pipe = pipe;
> + urb->complete = complete_fn;
> + urb->context = context;
> }
>
> -static inline struct mt76u_buf
> -*mt76u_get_next_rx_entry(struct mt76_queue *q)
> +static inline struct urb *
> +mt76u_get_next_rx_entry(struct mt76_queue *q)
> {
> - struct mt76u_buf *buf = NULL;
> + struct urb *urb = NULL;
> unsigned long flags;
>
> spin_lock_irqsave(&q->lock, flags);
> if (q->queued > 0) {
> - buf = &q->entry[q->head].ubuf;
> + urb = q->entry[q->head].urb;
> q->head = (q->head + 1) % q->ndesc;
> q->queued--;
> }
> spin_unlock_irqrestore(&q->lock, flags);
>
> - return buf;
> + return urb;
> }
>
> static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
> @@ -424,10 +422,9 @@ static int mt76u_get_rx_entry_len(u8 *data, u32 data_len)
> }
>
> static int
> -mt76u_process_rx_entry(struct mt76_dev *dev, struct mt76u_buf *buf)
> +mt76u_process_rx_entry(struct mt76_dev *dev, struct urb *urb)
> {
> struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
> - struct urb *urb = buf->urb;
> u8 *data = urb->num_sgs ? sg_virt(&urb->sg[0]) : urb->transfer_buffer;
> int data_len, len, nsgs = 1;
> struct sk_buff *skb;
> @@ -488,7 +485,7 @@ static void mt76u_complete_rx(struct urb *urb)
> }
>
> spin_lock_irqsave(&q->lock, flags);
> - if (WARN_ONCE(q->entry[q->tail].ubuf.urb != urb, "rx urb mismatch"))
> + if (WARN_ONCE(q->entry[q->tail].urb != urb, "rx urb mismatch"))
> goto out;
>
> q->tail = (q->tail + 1) % q->ndesc;
> @@ -499,37 +496,37 @@ static void mt76u_complete_rx(struct urb *urb)
> }
>
> static int
> -mt76u_submit_rx_buf(struct mt76_dev *dev, struct mt76u_buf *buf)
> +mt76u_submit_rx_buf(struct mt76_dev *dev, struct urb *urb)
> {
> - mt76u_fill_bulk_urb(dev, USB_DIR_IN, MT_EP_IN_PKT_RX, buf,
> + mt76u_fill_bulk_urb(dev, USB_DIR_IN, MT_EP_IN_PKT_RX, urb,
> mt76u_complete_rx, dev);
> - trace_submit_urb(dev, buf->urb);
> + trace_submit_urb(dev, urb);
>
> - return usb_submit_urb(buf->urb, GFP_ATOMIC);
> + return usb_submit_urb(urb, GFP_ATOMIC);
> }
>
> static void mt76u_rx_tasklet(unsigned long data)
> {
> struct mt76_dev *dev = (struct mt76_dev *)data;
> struct mt76_queue *q = &dev->q_rx[MT_RXQ_MAIN];
> - struct mt76u_buf *buf;
> + struct urb *urb;
> int err, count;
>
> rcu_read_lock();
>
> while (true) {
> - buf = mt76u_get_next_rx_entry(q);
> - if (!buf)
> + urb = mt76u_get_next_rx_entry(q);
> + if (!urb)
> break;
>
> - count = mt76u_process_rx_entry(dev, buf);
> + count = mt76u_process_rx_entry(dev, urb);
> if (count > 0) {
> - err = mt76u_refill_rx(dev, q, buf, count,
> + err = mt76u_refill_rx(dev, q, urb, count,
> GFP_ATOMIC);
> if (err < 0)
> break;
> }
> - mt76u_submit_rx_buf(dev, buf);
> + mt76u_submit_rx_buf(dev, urb);
> }
> mt76_rx_poll_complete(dev, MT_RXQ_MAIN, NULL);
>
> @@ -544,7 +541,7 @@ int mt76u_submit_rx_buffers(struct mt76_dev *dev)
>
> spin_lock_irqsave(&q->lock, flags);
> for (i = 0; i < q->ndesc; i++) {
> - err = mt76u_submit_rx_buf(dev, &q->entry[i].ubuf);
> + err = mt76u_submit_rx_buf(dev, q->entry[i].urb);
> if (err < 0)
> break;
> }
> @@ -576,7 +573,7 @@ static int mt76u_alloc_rx(struct mt76_dev *dev)
> q->buf_size = dev->usb.sg_en ? MT_RX_BUF_SIZE : PAGE_SIZE;
> q->ndesc = MT_NUM_RX_ENTRIES;
> for (i = 0; i < q->ndesc; i++) {
> - err = mt76u_buf_alloc(dev, &q->entry[i].ubuf);
> + err = mt76u_urb_alloc(dev, &q->entry[i]);
> if (err < 0)
> return err;
> }
> @@ -591,7 +588,7 @@ static void mt76u_free_rx(struct mt76_dev *dev)
> int i;
>
> for (i = 0; i < q->ndesc; i++)
> - mt76u_buf_free(&q->entry[i].ubuf);
> + mt76u_urb_free(q->entry[i].urb);
>
> if (!q->rx_page.va)
> return;
> @@ -607,7 +604,7 @@ static void mt76u_stop_rx(struct mt76_dev *dev)
> int i;
>
> for (i = 0; i < q->ndesc; i++)
> - usb_kill_urb(q->entry[i].ubuf.urb);
> + usb_kill_urb(q->entry[i].urb);
> }
>
> static void mt76u_tx_tasklet(unsigned long data)
> @@ -718,7 +715,7 @@ static void mt76u_complete_tx(struct urb *urb)
> struct ieee80211_sta *sta)
> {
> struct mt76_queue *q = dev->q_tx[qid].q;
> - struct mt76u_buf *buf;
> + struct urb *urb;
> u16 idx = q->tail;
> int err;
>
> @@ -731,18 +728,18 @@ static void mt76u_complete_tx(struct urb *urb)
> return err;
>
> q->entry[idx].done = false;
> - buf = &q->entry[idx].ubuf;
> + urb = q->entry[idx].urb;
> if (!dev->usb.sg_en) {
> - buf->urb->transfer_buffer = skb->data;
> + urb->transfer_buffer = skb->data;
> } else {
> - err = mt76u_tx_build_sg(dev, skb, buf->urb);
> + err = mt76u_tx_build_sg(dev, skb, urb);
> if (err < 0)
> return err;
> }
> - buf->urb->transfer_buffer_length = skb->len;
> + urb->transfer_buffer_length = skb->len;
>
> mt76u_fill_bulk_urb(dev, USB_DIR_OUT, q2ep(q->hw_idx),
> - buf, mt76u_complete_tx, &q->entry[idx]);
> + urb, mt76u_complete_tx, &q->entry[idx]);
>
> q->tail = (q->tail + 1) % q->ndesc;
> q->entry[idx].skb = skb;
> @@ -753,14 +750,14 @@ static void mt76u_complete_tx(struct urb *urb)
>
> static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q)
> {
> - struct mt76u_buf *buf;
> + struct urb *urb;
> int err;
>
> while (q->first != q->tail) {
> - buf = &q->entry[q->first].ubuf;
> + urb = q->entry[q->first].urb;
>
> - trace_submit_urb(dev, buf->urb);
> - err = usb_submit_urb(buf->urb, GFP_ATOMIC);
> + trace_submit_urb(dev, urb);
> + err = usb_submit_urb(urb, GFP_ATOMIC);
> if (err < 0) {
> if (err == -ENODEV)
> set_bit(MT76_REMOVED, &dev->state);
> @@ -775,7 +772,7 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q)
>
> static int mt76u_alloc_tx(struct mt76_dev *dev)
> {
> - struct mt76u_buf *buf;
> + struct urb *urb;
> struct mt76_queue *q;
> int i, j;
>
> @@ -803,19 +800,18 @@ static int mt76u_alloc_tx(struct mt76_dev *dev)
>
> q->ndesc = MT_NUM_TX_ENTRIES;
> for (j = 0; j < q->ndesc; j++) {
> - buf = &q->entry[j].ubuf;
> -
> - buf->urb = usb_alloc_urb(0, GFP_KERNEL);
> - if (!buf->urb)
> + urb = usb_alloc_urb(0, GFP_KERNEL);
> + if (!urb)
> return -ENOMEM;
> + q->entry[j].urb = urb;
>
> if (dev->usb.sg_en) {
> size_t size = MT_SG_MAX_SIZE *
> sizeof(struct scatterlist);
>
> - buf->urb->sg = devm_kzalloc(dev->dev, size,
> - GFP_KERNEL);
> - if (!buf->urb->sg)
> + urb->sg = devm_kzalloc(dev->dev, size,
> + GFP_KERNEL);
> + if (!urb->sg)
> return -ENOMEM;
> }
> }
> @@ -831,7 +827,7 @@ static void mt76u_free_tx(struct mt76_dev *dev)
> for (i = 0; i < IEEE80211_NUM_ACS; i++) {
> q = dev->q_tx[i].q;
> for (j = 0; j < q->ndesc; j++)
> - usb_free_urb(q->entry[j].ubuf.urb);
> + usb_free_urb(q->entry[j].urb);
> }
> }
>
> @@ -843,7 +839,7 @@ static void mt76u_stop_tx(struct mt76_dev *dev)
> for (i = 0; i < IEEE80211_NUM_ACS; i++) {
> q = dev->q_tx[i].q;
> for (j = 0; j < q->ndesc; j++)
> - usb_kill_urb(q->entry[j].ubuf.urb);
> + usb_kill_urb(q->entry[j].urb);
> }
> }
>
> --
> 1.9.3
>
> Alloc sg table at the end of urb structure. This will increase
> cache usage.
>
I am curious, have you observed any performance improvement doing so?
> Signed-off-by: Stanislaw Gruszka <[email protected]>
> ---
> drivers/net/wireless/mediatek/mt76/usb.c | 20 ++++++++++----------
> 1 file changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c
> index 0b9f0b5fd37d..dd487f65f44e 100644
> --- a/drivers/net/wireless/mediatek/mt76/usb.c
> +++ b/drivers/net/wireless/mediatek/mt76/usb.c
> @@ -336,19 +336,19 @@ static bool mt76u_check_sg(struct mt76_dev *dev)
> static int
> mt76u_urb_alloc(struct mt76_dev *dev, struct mt76_queue_entry *e)
> {
> - struct urb *urb;
> + unsigned int size = sizeof(struct urb);
> +
> + if (dev->usb.sg_en)
> + size += MT_SG_MAX_SIZE * sizeof(struct scatterlist);
>
> - urb = usb_alloc_urb(0, GFP_KERNEL);
> - if (!urb)
> + e->urb = kzalloc(size, GFP_KERNEL);
> + if (!e->urb)
> return -ENOMEM;
> - e->urb = urb;
>
> - if (dev->usb.sg_en) {
> - urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE,
> - sizeof(urb->sg), GFP_KERNEL);
> - if (!urb->sg)
> - return -ENOMEM;
> - }
> + usb_init_urb(e->urb);
> +
> + if (dev->usb.sg_en)
> + e->urb->sg = (struct scatterlist *)((u8 *)e->urb + sizeof(struct urb));
You can avoid u8 cast doing:
(struct scatterlist *)(e->urb + 1)
Regards,
Lorenzo
>
> return 0;
> }
> --
> 1.9.3
>
On Tue, Mar 12, 2019 at 05:25:50PM +0100, Lorenzo Bianconi wrote:
> > buf = &q->entry[idx].ubuf;
> > - buf->buf = skb->data;
> > - buf->len = skb->len;
> > + if (!dev->usb.sg_en) {
> > + buf->urb->transfer_buffer = skb->data;
>
> I think you can move this in mt76u_tx_build_sg or remove the if condition in
> mt76u_tx_build_sg()
I'll rename mt76u_tx_build_sg() to mt76u_tx_setup_bufffers() then,
which will more corresponding the what the function do.
Stanislaw
On Tue, Mar 12, 2019 at 05:27:43PM +0100, Lorenzo Bianconi wrote:
> I guess here you can do:
> e->urb = usb_alloc_urb(0, GFP_KERNEL);
> if (!e->urb)
> return -ENOMEM;
Done in later patch.
Stanislaw
On Tue, Mar 12, 2019 at 05:34:32PM +0100, Lorenzo Bianconi wrote:
> > Alloc sg table at the end of urb structure. This will increase
> > cache usage.
> >
>
> I am curious, have you observed any performance improvement doing so?
It's hard to measure that. Stressing net transfer with about 175 Mbit/s
by netperf (what is max I can get) only took about 15% of CPU for me
and net performance fluctuate so CPU pref stats vary too.
> > - if (dev->usb.sg_en) {
> > - urb->sg = devm_kcalloc(dev->dev, MT_SG_MAX_SIZE,
> > - sizeof(urb->sg), GFP_KERNEL);
FTR: Here is bug it should be sizeof(*urb->sg).
> > - if (!urb->sg)
> > - return -ENOMEM;
> > - }
> > + usb_init_urb(e->urb);
> > +
> > + if (dev->usb.sg_en)
> > + e->urb->sg = (struct scatterlist *)((u8 *)e->urb + sizeof(struct urb));
>
> You can avoid u8 cast doing:
> (struct scatterlist *)(e->urb + 1)
Cool trick!
Stanislaw