mt76: usb: reduce locking in mt76u_tx_tasklet
Subsystems (2)
A message that is not in the archive (sent off-list or not yet received): [email protected]
Lorenzo Bianconi
maintainerPATCH 1/1 mt76: usb: reduce locking in mt76u_tx_tasklet
Similar to pci counterpart, reduce locking in mt76u_tx_tasklet since q->head is managed just in mt76u_tx_tasklet and q->queued is updated holding q->lock
---
Changes since RFC:
- reset done to false in mt76u_tx_tasklet instead of in mt76u_tx_queue_skb
--- drivers/net/wireless/mediatek/mt76/usb.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
drivers/net/wireless/mediatek/mt76/usb.c +14 -8
@@ -624,28 +624,35 @@ static void mt76u_tx_tasklet(unsigned long data)int i;for (i =0 ; i <IEEE80211_NUM_ACS ; i++) { +u32 n_queued =0 , n_sw_queued =0 ; +int idx; + sq = &dev->q_tx[i]; q = sq->q; -spin_lock_bh (&q->lock); -while (true) { -if (!q->entry[q->head].done || !q->queued) +while (q->queued > n_queued) { +if (!q->entry[q->head].done)break ;if (q->entry[q->head].schedule) { q->entry[q->head].schedule = false; - sq->swq_queued--; + n_sw_queued++; } + idx = q->head; entry = q->entry[q->head]; q->head = (q->head +1 ) % q->ndesc; - q->queued--; + n_queued++; -spin_unlock_bh (&q->lock); dev->drv->tx_complete_skb (dev, i, &entry); -spin_lock_bh (&q->lock); + q->entry[idx].done = false; } +spin_lock_bh (&q->lock); + + sq->swq_queued -= n_sw_queued; + q->queued -= n_queued; + wake = q->stopped && q->queued < q->ndesc -8 ;if (wake) q->stopped = false;
@@ -741,7 +748,6 @@ mt76u_tx_queue_skb(struct mt76_dev *dev, enum mt76_txq_id qid,if (err <0 )return err; - q->entry[idx].done = false; urb = q->entry[idx].urb; err =mt76u_tx_setup_buffers (dev, skb, urb);if (err <0 )
Signature · 1 line
2.20.1
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 635
Quoted 11 lines · Lorenzo Bianconi
drivers/net/wireless/mediatek/mt76/usb.c +4
-3+int idx; + sq = &dev->q_tx[i]; q = sq->q; -spin_lock_bh (&q->lock); -while (true) { -if (!q->entry[q->head].done || !q->queued) +while (q->queued > n_queued) { +if (!q->entry[q->head].done)break ;
If you place done = false here you will not need additional idx variable.
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 651
Quoted 6 lines
drivers/net/wireless/mediatek/mt76/usb.c +2
-1dev->drv->tx_complete_skb (dev, i, &entry); -spin_lock_bh (&q->lock); + q->entry[idx].done = false; } +spin_lock_bh (&q->lock);
This patch does not apply for me as there is missing mt76_txq_schedule(dev, sq);
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 655
Quoted 4 lines
drivers/net/wireless/mediatek/mt76/usb.c +4
-0+ + sq->swq_queued -= n_sw_queued; + q->queued -= n_queued; +
Naming is confusing, it should rather be n_dequeued, n_sw_dequeued.
Stanislaw
Quoted 6 lines · Lorenzo Bianconi
Quoted 5 lines
drivers/net/wireless/mediatek/mt76/usb.c +2
-0+int idx; + sq = &dev->q_tx[i]; q = sq->q;
Quoted 8 lines
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 635
Quoted 6 lines
drivers/net/wireless/mediatek/mt76/usb.c +2
-3-spin_lock_bh (&q->lock); -while (true) { -if (!q->entry[q->head].done || !q->queued) +while (q->queued > n_queued) { +if (!q->entry[q->head].done)break ;If you place done = false here you will not need additional idx variable.
As Felix suggested, I would set done to false at the end of the loop, after tx_complete_skb
Quoted 9 lines
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 651
Quoted 7 lines
drivers/net/wireless/mediatek/mt76/usb.c +2
-1dev->drv->tx_complete_skb (dev, i, &entry); -spin_lock_bh (&q->lock); + q->entry[idx].done = false; } +spin_lock_bh (&q->lock);This patch does not apply for me as there is missing
mt76_txq_schedule(dev, sq);
Sorry I forgot to mention this patch is based on
https://patchwork.kernel.org/patch/10856027/. Have you applied it?
Quoted 6 lines
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 655
Quoted 5 lines
drivers/net/wireless/mediatek/mt76/usb.c +4
-0+ + sq->swq_queued -= n_sw_queued; + q->queued -= n_queued; +Naming is confusing, it should rather be
n_dequeued,n_sw_dequeued.
I just followed dma counterpart naming convention, but I can modify it.
Regards,
Lorenzo
Quoted 2 lines
Stanislaw
Quoted 15 lines · Lorenzo Bianconi
Quoted 6 lines · Lorenzo Bianconi
Quoted 5 lines
drivers/net/wireless/mediatek/mt76/usb.c +2
-0+int idx; + sq = &dev->q_tx[i]; q = sq->q;Quoted 8 lines
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 635
Quoted 6 lines
drivers/net/wireless/mediatek/mt76/usb.c +2
-3-spin_lock_bh (&q->lock); -while (true) { -if (!q->entry[q->head].done || !q->queued) +while (q->queued > n_queued) { +if (!q->entry[q->head].done)break ;If you place done = false here you will not need additional idx variable.
Quoted 2 lines
As Felix suggested, I would set done to false at the end of the loop, after
tx_complete_skb
Why this is needed?
Quoted 11 lines
Quoted 8 lines
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 651
Quoted 6 lines
drivers/net/wireless/mediatek/mt76/usb.c +2
-1dev->drv->tx_complete_skb (dev, i, &entry); -spin_lock_bh (&q->lock); + q->entry[idx].done = false; } +spin_lock_bh (&q->lock);This patch does not apply for me as there is missing
mt76_txq_schedule(dev, sq);Sorry I forgot to mention this patch is based on
https://patchwork.kernel.org/patch/10856027/. Have you applied it?
No.
Stanislaw
Quoted 16 lines · Lorenzo Bianconi
Quoted 15 lines
Quoted 14 lines · Lorenzo Bianconi
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 635
Quoted 11 lines
drivers/net/wireless/mediatek/mt76/usb.c +4
-3+int idx; + sq = &dev->q_tx[i]; q = sq->q; -spin_lock_bh (&q->lock); -while (true) { -if (!q->entry[q->head].done || !q->queued) +while (q->queued > n_queued) { +if (!q->entry[q->head].done)break ;If you place done = false here you will not need additional idx variable.
Quoted 3 lines
Quoted 2 lines
As Felix suggested, I would set done to false at the end of the loop, after
tx_complete_skbWhy this is needed?
logically I think it should be the last thing to do on the current skb but probably moving it before tx_complete_skb will not make any difference
Quoted 16 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/net/wireless/mediatek/mt76/usb.c +1
-1dev->drv->tx_complete_skb (dev, i, &entry); -spin_lock_bh (&q->lock); + q->entry[idx].done = false; }Quoted 6 lines
Quoted 3 lines
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 651
Quoted 1 line
drivers/net/wireless/mediatek/mt76/usb.c +1
-0+spin_lock_bh (&q->lock);This patch does not apply for me as there is missing
mt76_txq_schedule(dev, sq);Sorry I forgot to mention this patch is based on
https://patchwork.kernel.org/patch/10856027/. Have you applied it?No.
Stanislaw
Quoted 16 lines · Lorenzo Bianconi
Quoted 16 lines · Lorenzo Bianconi
Quoted 15 lines
Quoted 14 lines · Lorenzo Bianconi
drivers/net/wireless/mediatek/mt76/usb.c static void mt76u_tx_tasklet(unsigned long data) · line 635
Quoted 11 lines
drivers/net/wireless/mediatek/mt76/usb.c +4
-3+int idx; + sq = &dev->q_tx[i]; q = sq->q; -spin_lock_bh (&q->lock); -while (true) { -if (!q->entry[q->head].done || !q->queued) +while (q->queued > n_queued) { +if (!q->entry[q->head].done)break ;If you place done = false here you will not need additional idx variable.
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
As Felix suggested, I would set done to false at the end of the loop, after
tx_complete_skbWhy this is needed?
logically I think it should be the last thing to do on the current skb but
Why? This is only marker that urb complete was done.
Quoted 1 line
probably moving it before
tx_complete_skbwill not make any difference
It will not, since code is performed in the same tasklet.
Stanislaw