aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/usb/usbnet.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 5fd06e2..912ff11 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -68,6 +68,7 @@
(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 DONE_QLEN(dev) (RX_QLEN(dev) + TX_QLEN(dev))
// reawaken network queue this soon after stopping; else watchdog barks
#define TX_TIMEOUT_JIFFIES (5*HZ)
@@ -329,6 +330,13 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
dev->udev->bus->dma_align)
net_ip_align = 0;
+ if (dev->rxq.qlen >= RX_QLEN(dev)) {
+ netif_dbg(dev, rx_err, dev->net, "rx queue full\n");
+ usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
+ usb_free_urb (urb);
+ return -ENOMEM;
+ }
+
if ((skb = alloc_skb (size + net_ip_align, flags)) == NULL) {
netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
@@ -493,7 +501,8 @@ block:
if (urb) {
if (netif_running (dev->net) &&
- !test_bit (EVENT_RX_HALT, &dev->flags)) {
+ !test_bit (EVENT_RX_HALT, &dev->flags) &&
+ (dev->done.qlen < DONE_QLEN(dev))) {
rx_submit (dev, urb, GFP_ATOMIC);
return;
}