summaryrefslogtreecommitdiffstats
path: root/drivers/usb/net/usbnet.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/net/usbnet.c')
-rw-r--r--drivers/usb/net/usbnet.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 54183e173a6d..17fc6ae5c075 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -61,8 +61,11 @@
* let the USB host controller be busy for 5msec or more before an irq
* is required, under load. Jumbograms change the equation.
*/
-#define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
-#define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
+#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)
// reawaken network queue this soon after stopping; else watchdog barks
#define TX_TIMEOUT_JIFFIES (5*HZ)
@@ -227,13 +230,23 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu)
{
struct usbnet *dev = netdev_priv(net);
int ll_mtu = new_mtu + net->hard_header_len;
+ int old_hard_mtu = dev->hard_mtu;
+ int old_rx_urb_size = dev->rx_urb_size;
- if (new_mtu <= 0 || ll_mtu > dev->hard_mtu)
+ if (new_mtu <= 0)
return -EINVAL;
// no second zero-length packet read wanted after mtu-sized packets
if ((ll_mtu % dev->maxpacket) == 0)
return -EDOM;
net->mtu = new_mtu;
+
+ dev->hard_mtu = net->mtu + net->hard_header_len;
+ if (dev->rx_urb_size == old_hard_mtu) {
+ dev->rx_urb_size = dev->hard_mtu;
+ if (dev->rx_urb_size > old_rx_urb_size)
+ usbnet_unlink_rx_urbs(dev);
+ }
+
return 0;
}
@@ -521,6 +534,17 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
return count;
}
+// Flush all pending rx urbs
+// minidrivers may need to do this when the MTU changes
+
+void usbnet_unlink_rx_urbs(struct usbnet *dev)
+{
+ if (netif_running(dev->net)) {
+ (void) unlink_urbs (dev, &dev->rxq);
+ tasklet_schedule(&dev->bh);
+ }
+}
+EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs);
/*-------------------------------------------------------------------------*/
OpenPOWER on IntegriCloud