Skip to content

Commit 4b49f58

Browse files
Ming Leidavem330
Ming Lei
authored andcommitted
usbnet: handle link change
The link change is detected via the interrupt pipe, and bulk pipes are responsible for transfering packets, so it is reasonable to stop bulk transfer after link is reported as off. Two adavantages may be obtained with stopping bulk transfer after link becomes off: - USB bus bandwidth is saved(USB bus is shared bus except for USB3.0), for example, lots of 'IN' token packets and 'NYET' handshake packets is transfered on 2.0 bus. - probabaly power might be saved for usb host controller since cancelling bulk transfer may disable the asynchronous schedule of host controller. With this patch, when link becomes off, about ~10% performance boost can be found on bulk transfer of anther usb device which is attached to same bus with the usbnet device, see below test on next-20130410: - read from usb mass storage(Sandisk Extreme USB 3.0) on pandaboard with below command after unplugging ethernet cable: dd if=/dev/sda iflag=direct of=/dev/null bs=1M count=800 - without the patch 1, 838860800 bytes (839 MB) copied, 36.2216 s, 23.2 MB/s 2, 838860800 bytes (839 MB) copied, 35.8368 s, 23.4 MB/s 3, 838860800 bytes (839 MB) copied, 35.823 s, 23.4 MB/s 4, 838860800 bytes (839 MB) copied, 35.937 s, 23.3 MB/s 5, 838860800 bytes (839 MB) copied, 35.7365 s, 23.5 MB/s average: 23.6MB/s - with the patch 1, 838860800 bytes (839 MB) copied, 32.3817 s, 25.9 MB/s 2, 838860800 bytes (839 MB) copied, 31.7389 s, 26.4 MB/s 3, 838860800 bytes (839 MB) copied, 32.438 s, 25.9 MB/s 4, 838860800 bytes (839 MB) copied, 32.5492 s, 25.8 MB/s 5, 838860800 bytes (839 MB) copied, 31.6178 s, 26.5 MB/s average: 26.1MB/s Signed-off-by: Ming Lei <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0162c55 commit 4b49f58

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

drivers/net/usb/usbnet.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,27 @@ static const struct ethtool_ops usbnet_ethtool_ops = {
938938

939939
/*-------------------------------------------------------------------------*/
940940

941+
static void __handle_link_change(struct usbnet *dev)
942+
{
943+
if (!test_bit(EVENT_DEV_OPEN, &dev->flags))
944+
return;
945+
946+
if (!netif_carrier_ok(dev->net)) {
947+
/* kill URBs for reading packets to save bus bandwidth */
948+
unlink_urbs(dev, &dev->rxq);
949+
950+
/*
951+
* tx_timeout will unlink URBs for sending packets and
952+
* tx queue is stopped by netcore after link becomes off
953+
*/
954+
} else {
955+
/* submitting URBs for reading packets */
956+
tasklet_schedule(&dev->bh);
957+
}
958+
959+
clear_bit(EVENT_LINK_CHANGE, &dev->flags);
960+
}
961+
941962
/* work that cannot be done in interrupt context uses keventd.
942963
*
943964
* NOTE: with 2.5 we could do more of this using completion callbacks,
@@ -1035,8 +1056,14 @@ kevent (struct work_struct *work)
10351056
} else {
10361057
usb_autopm_put_interface(dev->intf);
10371058
}
1059+
1060+
/* handle link change from link resetting */
1061+
__handle_link_change(dev);
10381062
}
10391063

1064+
if (test_bit (EVENT_LINK_CHANGE, &dev->flags))
1065+
__handle_link_change(dev);
1066+
10401067
if (dev->flags)
10411068
netdev_dbg(dev->net, "kevent done, flags = 0x%lx\n", dev->flags);
10421069
}
@@ -1286,6 +1313,7 @@ static void usbnet_bh (unsigned long param)
12861313
// or are we maybe short a few urbs?
12871314
} else if (netif_running (dev->net) &&
12881315
netif_device_present (dev->net) &&
1316+
netif_carrier_ok(dev->net) &&
12891317
!timer_pending (&dev->delay) &&
12901318
!test_bit (EVENT_RX_HALT, &dev->flags)) {
12911319
int temp = dev->rxq.qlen;
@@ -1663,6 +1691,8 @@ void usbnet_link_change(struct usbnet *dev, bool link, bool need_reset)
16631691

16641692
if (need_reset && link)
16651693
usbnet_defer_kevent(dev, EVENT_LINK_RESET);
1694+
else
1695+
usbnet_defer_kevent(dev, EVENT_LINK_CHANGE);
16661696
}
16671697
EXPORT_SYMBOL(usbnet_link_change);
16681698

include/linux/usb/usbnet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ struct usbnet {
7272
# define EVENT_DEVICE_REPORT_IDLE 8
7373
# define EVENT_NO_RUNTIME_PM 9
7474
# define EVENT_RX_KILL 10
75+
# define EVENT_LINK_CHANGE 11
7576
};
7677

7778
static inline struct usb_driver *driver_of(struct usb_interface *intf)

0 commit comments

Comments
 (0)