Message ID | 1558366269-17787-1-git-send-email-3ernd.Eckstein@gmail.com (mailing list archive) |
---|---|
State | Mainlined |
Commit | 94d250fae48e6f873d8362308f5c4d02cd1b1fd2 |
Headers | show |
Series | usbnet: ipheth: fix racing condition | expand |
From: Bernd Eckstein <3erndeckstein@gmail.com> Date: Mon, 20 May 2019 17:31:09 +0200 > Fix a racing condition in ipheth.c that can lead to slow performance. > > Bug: In ipheth_tx(), netif_wake_queue() may be called on the callback > ipheth_sndbulk_callback(), _before_ netif_stop_queue() is called. > When this happens, the queue is stopped longer than it needs to be, > thus reducing network performance. > > Fix: Move netif_stop_queue() in front of usb_submit_urb(). Now the order > is always correct. In case, usb_submit_urb() fails, the queue is woken up > again as callback will not fire. > > Testing: This racing condition is usually not noticeable, as it has to > occur very frequently to slowdown the network. The callback from the USB > is usually triggered slow enough, so the situation does not appear. > However, on a Ubuntu Linux on VMWare Workstation, running on Windows 10, > the we loose the race quite often and the following speedup can be noticed: > > Without this patch: Download: 4.10 Mbit/s, Upload: 4.01 Mbit/s > With this patch: Download: 36.23 Mbit/s, Upload: 17.61 Mbit/s > > Signed-off-by: Oliver Zweigle <Oliver.Zweigle@faro.com> > Signed-off-by: Bernd Eckstein <3ernd.Eckstein@gmail.com> Applied.
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index c247aed..8c01fbf 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -383,17 +383,18 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net) dev); dev->tx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + netif_stop_queue(net); retval = usb_submit_urb(dev->tx_urb, GFP_ATOMIC); if (retval) { dev_err(&dev->intf->dev, "%s: usb_submit_urb: %d\n", __func__, retval); dev->net->stats.tx_errors++; dev_kfree_skb_any(skb); + netif_wake_queue(net); } else { dev->net->stats.tx_packets++; dev->net->stats.tx_bytes += skb->len; dev_consume_skb_any(skb); - netif_stop_queue(net); } return NETDEV_TX_OK;