net: usbnet: Add mechanism to throttle usb0 RX traffic in USB SS

ECM traffic is non-aggregated which makes it send huge number of
packets in high throughput usecases. This causes the CPU to
dedicate majority of the cycles to ISR context and the softIRQ
contexts stay suspended.

The rx_complete (hardIRQ) keeps adding SKBs to the 'done' list. The
usbnet_bh (tasklet) is supposed to dequeue SKBs from 'done' list and
provide them to NW stack so that they can be consumed. Because of the
above issue, the 'done' list keeps increasing and the system
eventually runs out of memory. When the WD_pet task also does not get
a chance to run because of hardIRQ storm, WD bite is also observed.

Introduce a mechanism to balance the time between hardIRQ and softIRQ
contexts. Add module parameter 'usb0_rx_skb_threshold' to stop the
submission of URBs to HW from the ISR. This will allow the usbnet_bh
to run and consume SKBs, thereby avoiding the OOM scenario and the
WD_pet task also gets a chance to pet the WD. The default value of
this threshold is 500, which can be changed runtime to suit the
requirements according to CPU load.

Since in the failing case, ASIX AX88179/178A USB 3.0/2.0 to Gigabit
Ethernet adapters are being used, throttle handling has been added in
that driver.

Usage:
echo <threshold> > /sys/module/usbnet/parameters/usb0_rx_skb_threshold

Change-Id: I4667f0ad67d5605b132a0e6062be27e01ef75a08
Signed-off-by: Ajay Agarwal <ajaya@codeaurora.org>
Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
This commit is contained in:
Krishna Kurapati 2022-11-13 19:40:39 +05:30 committed by Gerrit - the friendly Code Review server
parent 9927b09f7f
commit 6da027eb3a
3 changed files with 20 additions and 11 deletions

View File

@ -1698,7 +1698,7 @@ static const struct driver_info ax88179_info = {
.link_reset = ax88179_link_reset,
.reset = ax88179_reset,
.stop = ax88179_stop,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP | FLAG_THROTTLE_RX,
.rx_fixup = ax88179_rx_fixup,
.tx_fixup = ax88179_tx_fixup,
};
@ -1711,7 +1711,7 @@ static const struct driver_info ax88178a_info = {
.link_reset = ax88179_link_reset,
.reset = ax88179_reset,
.stop = ax88179_stop,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP | FLAG_THROTTLE_RX,
.rx_fixup = ax88179_rx_fixup,
.tx_fixup = ax88179_tx_fixup,
};
@ -1724,7 +1724,7 @@ static const struct driver_info cypress_GX3_info = {
.link_reset = ax88179_link_reset,
.reset = ax88179_reset,
.stop = ax88179_stop,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP | FLAG_THROTTLE_RX,
.rx_fixup = ax88179_rx_fixup,
.tx_fixup = ax88179_tx_fixup,
};
@ -1737,7 +1737,7 @@ static const struct driver_info dlink_dub1312_info = {
.link_reset = ax88179_link_reset,
.reset = ax88179_reset,
.stop = ax88179_stop,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP | FLAG_THROTTLE_RX,
.rx_fixup = ax88179_rx_fixup,
.tx_fixup = ax88179_tx_fixup,
};
@ -1750,7 +1750,7 @@ static const struct driver_info sitecom_info = {
.link_reset = ax88179_link_reset,
.reset = ax88179_reset,
.stop = ax88179_stop,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP | FLAG_THROTTLE_RX,
.rx_fixup = ax88179_rx_fixup,
.tx_fixup = ax88179_tx_fixup,
};
@ -1763,7 +1763,7 @@ static const struct driver_info samsung_info = {
.link_reset = ax88179_link_reset,
.reset = ax88179_reset,
.stop = ax88179_stop,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP | FLAG_THROTTLE_RX,
.rx_fixup = ax88179_rx_fixup,
.tx_fixup = ax88179_tx_fixup,
};
@ -1776,7 +1776,7 @@ static const struct driver_info lenovo_info = {
.link_reset = ax88179_link_reset,
.reset = ax88179_reset,
.stop = ax88179_stop,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP | FLAG_THROTTLE_RX,
.rx_fixup = ax88179_rx_fixup,
.tx_fixup = ax88179_tx_fixup,
};
@ -1789,7 +1789,7 @@ static const struct driver_info belkin_info = {
.link_reset = ax88179_link_reset,
.reset = ax88179_reset,
.stop = ax88179_stop,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP,
.flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_SEND_ZLP | FLAG_THROTTLE_RX,
.rx_fixup = ax88179_rx_fixup,
.tx_fixup = ax88179_tx_fixup,
};

View File

@ -75,6 +75,10 @@ static int msg_level = -1;
module_param (msg_level, int, 0);
MODULE_PARM_DESC (msg_level, "Override default message level");
static int usb0_rx_skb_threshold = 500;
module_param(usb0_rx_skb_threshold, int, 0644);
MODULE_PARM_DESC(usb0_rx_skb_threshold, "Throttle rx traffic in USB3");
/*-------------------------------------------------------------------------*/
/* handles CDC Ethernet and many other network "bulk data" interfaces */
@ -654,9 +658,13 @@ block:
if (netif_running (dev->net) &&
!test_bit (EVENT_RX_HALT, &dev->flags) &&
state != unlink_start) {
rx_submit (dev, urb, GFP_ATOMIC);
usb_mark_last_busy(dev->udev);
return;
if ((!(dev->driver_info->flags & FLAG_THROTTLE_RX)) ||
((dev->driver_info->flags & FLAG_THROTTLE_RX) &&
(dev->done.qlen < usb0_rx_skb_threshold))) {
rx_submit(dev, urb, GFP_ATOMIC);
usb_mark_last_busy(dev->udev);
return;
}
}
usb_free_urb (urb);
}

View File

@ -129,6 +129,7 @@ struct driver_info {
#define FLAG_MULTI_PACKET 0x2000
#define FLAG_RX_ASSEMBLE 0x4000 /* rx packets may span >1 frames */
#define FLAG_NOARP 0x8000 /* device can't do ARP */
#define FLAG_THROTTLE_RX 0x10000 /* Throttle RX traffic in USB SS */
/* init device ... can sleep, or cause probe() failure */
int (*bind)(struct usbnet *, struct usb_interface *);