Skip to content

Commit 7ff14c5

Browse files
simoschip2000kuba-moo
authored andcommitted
usbnet: Add support for Byte Queue Limits (BQL)
In the current implementation, usbnet uses a fixed tx_qlen of: USB2: 60 * 1518 bytes = 91.08 KB USB3: 60 * 5 * 1518 bytes = 454.80 KB Such large transmit queues can be problematic, especially for cellular modems. For example, with a typical celluar link speed of 10 Mbit/s, a fully occupied USB3 transmit queue results in: 454.80 KB / (10 Mbit/s / 8 bit/byte) = 363.84 ms of additional latency. This patch adds support for Byte Queue Limits (BQL) [1] to dynamically manage the transmit queue size and reduce latency without sacrificing throughput. Testing was performed on various devices using the usbnet driver for packet transmission: - DELOCK 66045: USB3 to 2.5 GbE adapter (ax88179_178a) - DELOCK 61969: USB2 to 1 GbE adapter (asix) - Quectel RM520: 5G modem (qmi_wwan) - USB2 Android tethering (cdc_ncm) No performance degradation was observed for iperf3 TCP or UDP traffic, while latency for a prioritized ping application was significantly reduced. For example, using the USB3 to 2.5 GbE adapter, which was fully utilized by iperf3 UDP traffic, the prioritized ping was improved from 1.6 ms to 0.6 ms. With the same setup but with a 100 Mbit/s Ethernet connection, the prioritized ping was improved from 35 ms to 5 ms. [1] https://lwn.net/Articles/469652/ Signed-off-by: Simon Schippers <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 23c52b5 commit 7ff14c5

File tree

2 files changed

+13
-0
lines changed

2 files changed

+13
-0
lines changed

drivers/net/usb/usbnet.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,7 @@ int usbnet_stop(struct net_device *net)
831831

832832
clear_bit(EVENT_DEV_OPEN, &dev->flags);
833833
netif_stop_queue (net);
834+
netdev_reset_queue(net);
834835

835836
netif_info(dev, ifdown, dev->net,
836837
"stop stats: rx/tx %lu/%lu, errs %lu/%lu\n",
@@ -939,6 +940,7 @@ int usbnet_open(struct net_device *net)
939940
}
940941

941942
set_bit(EVENT_DEV_OPEN, &dev->flags);
943+
netdev_reset_queue(net);
942944
netif_start_queue (net);
943945
netif_info(dev, ifup, dev->net,
944946
"open: enable queueing (rx %d, tx %d) mtu %d %s framing\n",
@@ -1500,6 +1502,7 @@ netdev_tx_t usbnet_start_xmit(struct sk_buff *skb, struct net_device *net)
15001502
case 0:
15011503
netif_trans_update(net);
15021504
__usbnet_queue_skb(&dev->txq, skb, tx_start);
1505+
netdev_sent_queue(net, skb->len);
15031506
if (dev->txq.qlen >= TX_QLEN (dev))
15041507
netif_stop_queue (net);
15051508
}
@@ -1563,6 +1566,7 @@ static inline void usb_free_skb(struct sk_buff *skb)
15631566
static void usbnet_bh(struct timer_list *t)
15641567
{
15651568
struct usbnet *dev = timer_container_of(dev, t, delay);
1569+
unsigned int bytes_compl = 0, pkts_compl = 0;
15661570
struct sk_buff *skb;
15671571
struct skb_data *entry;
15681572

@@ -1574,6 +1578,8 @@ static void usbnet_bh(struct timer_list *t)
15741578
usb_free_skb(skb);
15751579
continue;
15761580
case tx_done:
1581+
bytes_compl += skb->len;
1582+
pkts_compl++;
15771583
kfree(entry->urb->sg);
15781584
fallthrough;
15791585
case rx_cleanup:
@@ -1584,6 +1590,10 @@ static void usbnet_bh(struct timer_list *t)
15841590
}
15851591
}
15861592

1593+
spin_lock_bh(&dev->bql_spinlock);
1594+
netdev_completed_queue(dev->net, pkts_compl, bytes_compl);
1595+
spin_unlock_bh(&dev->bql_spinlock);
1596+
15871597
/* restart RX again after disabling due to high error rate */
15881598
clear_bit(EVENT_RX_KILL, &dev->flags);
15891599

@@ -1755,6 +1765,7 @@ usbnet_probe(struct usb_interface *udev, const struct usb_device_id *prod)
17551765
skb_queue_head_init (&dev->txq);
17561766
skb_queue_head_init (&dev->done);
17571767
skb_queue_head_init(&dev->rxq_pause);
1768+
spin_lock_init(&dev->bql_spinlock);
17581769
INIT_WORK(&dev->bh_work, usbnet_bh_work);
17591770
INIT_WORK (&dev->kevent, usbnet_deferred_kevent);
17601771
init_usb_anchor(&dev->deferred);

include/linux/usb/usbnet.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/skbuff.h>
1515
#include <linux/types.h>
1616
#include <linux/usb.h>
17+
#include <linux/spinlock.h>
1718

1819
/* interface from usbnet core to each USB networking link we handle */
1920
struct usbnet {
@@ -59,6 +60,7 @@ struct usbnet {
5960
struct mutex interrupt_mutex;
6061
struct usb_anchor deferred;
6162
struct work_struct bh_work;
63+
spinlock_t bql_spinlock;
6264

6365
struct work_struct kevent;
6466
unsigned long flags;

0 commit comments

Comments
 (0)