summaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/usbnet.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/usb/usbnet.c')
-rw-r--r--drivers/net/usb/usbnet.c58
1 files changed, 50 insertions, 8 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 27a00b00603..7b331e613e0 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -59,15 +59,13 @@
* For high speed, each frame comfortably fits almost 36 max size
* Ethernet packets (so queues should be bigger).
*
- * REVISIT qlens should be members of 'struct usbnet'; the goal is to
- * let the USB host controller be busy for 5msec or more before an irq
- * is required, under load. Jumbograms change the equation.
+ * The goal is to let the USB host controller be busy for 5msec or
+ * more before an irq is required, under load. Jumbograms change
+ * the equation.
*/
-#define RX_MAX_QUEUE_MEMORY (60 * 1518)
-#define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
- (RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4)
-#define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
- (RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4)
+#define MAX_QUEUE_MEMORY (60 * 1518)
+#define RX_QLEN(dev) ((dev)->rx_qlen)
+#define TX_QLEN(dev) ((dev)->tx_qlen)
// reawaken network queue this soon after stopping; else watchdog barks
#define TX_TIMEOUT_JIFFIES (5*HZ)
@@ -347,6 +345,31 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(usbnet_skb_return);
+/* must be called if hard_mtu or rx_urb_size changed */
+void usbnet_update_max_qlen(struct usbnet *dev)
+{
+ enum usb_device_speed speed = dev->udev->speed;
+
+ switch (speed) {
+ case USB_SPEED_HIGH:
+ dev->rx_qlen = MAX_QUEUE_MEMORY / dev->rx_urb_size;
+ dev->tx_qlen = MAX_QUEUE_MEMORY / dev->hard_mtu;
+ break;
+ case USB_SPEED_SUPER:
+ /*
+ * Not take default 5ms qlen for super speed HC to
+ * save memory, and iperf tests show 2.5ms qlen can
+ * work well
+ */
+ dev->rx_qlen = 5 * MAX_QUEUE_MEMORY / dev->rx_urb_size;
+ dev->tx_qlen = 5 * MAX_QUEUE_MEMORY / dev->hard_mtu;
+ break;
+ default:
+ dev->rx_qlen = dev->tx_qlen = 4;
+ }
+}
+EXPORT_SYMBOL_GPL(usbnet_update_max_qlen);
+
/*-------------------------------------------------------------------------
*
@@ -375,6 +398,9 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu)
usbnet_unlink_rx_urbs(dev);
}
+ /* max qlen depend on hard_mtu and rx_urb_size */
+ usbnet_update_max_qlen(dev);
+
return 0;
}
EXPORT_SYMBOL_GPL(usbnet_change_mtu);
@@ -843,6 +869,9 @@ int usbnet_open (struct net_device *net)
goto done;
}
+ /* hard_mtu or rx_urb_size may change in reset() */
+ usbnet_update_max_qlen(dev);
+
// insist peer be connected
if (info->check_connect && (retval = info->check_connect (dev)) < 0) {
netif_dbg(dev, ifup, dev->net, "can't open; %d\n", retval);
@@ -927,6 +956,9 @@ int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd)
if (dev->driver_info->link_reset)
dev->driver_info->link_reset(dev);
+ /* hard_mtu or rx_urb_size may change in link_reset() */
+ usbnet_update_max_qlen(dev);
+
return retval;
}
@@ -1020,6 +1052,9 @@ static void __handle_link_change(struct usbnet *dev)
tasklet_schedule(&dev->bh);
}
+ /* hard_mtu or rx_urb_size may change during link change */
+ usbnet_update_max_qlen(dev);
+
clear_bit(EVENT_LINK_CHANGE, &dev->flags);
}
@@ -1632,11 +1667,18 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
dev->rx_urb_size = dev->hard_mtu;
dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
+ /* let userspace know we have a random address */
+ if (ether_addr_equal(net->dev_addr, node_id))
+ net->addr_assign_type = NET_ADDR_RANDOM;
+
if ((dev->driver_info->flags & FLAG_WLAN) != 0)
SET_NETDEV_DEVTYPE(net, &wlan_type);
if ((dev->driver_info->flags & FLAG_WWAN) != 0)
SET_NETDEV_DEVTYPE(net, &wwan_type);
+ /* initialize max rx_qlen and tx_qlen */
+ usbnet_update_max_qlen(dev);
+
status = register_netdev (net);
if (status)
goto out4;