diff options
author | Ruslan Bilovol <ruslan.bilovol@ti.com> | 2012-07-31 17:30:34 +0300 |
---|---|---|
committer | Dmytro Kedrovskyi <x0169235@ti.com> | 2012-08-08 20:16:59 +0300 |
commit | 6b67035734f91d50bf8f1a5a8e6956247fe2182c (patch) | |
tree | 4ef1da6cd7531af9018933859500be2c45ad55a3 /drivers/net/usb | |
parent | 2d343dcecb3bab6cfc919e99669d42b79058d4e9 (diff) | |
download | kernel_samsung_espresso10-6b67035734f91d50bf8f1a5a8e6956247fe2182c.tar.gz kernel_samsung_espresso10-6b67035734f91d50bf8f1a5a8e6956247fe2182c.tar.bz2 kernel_samsung_espresso10-6b67035734f91d50bf8f1a5a8e6956247fe2182c.zip |
net: usbnet: limit 'tx' and 'done' queue size
The dev->done queue size was not controlled
Thus under heavy load (usually UDP transfers)
if upper layer reads the data from this queue
slowly, it may be increased to fatal size, eating
all accessible memory.
Now the 'done' queue size is limited by RX_QLEN + TX_QLEN
Change-Id: Ie6253c07d6fa7adfccab3af66c19448c920e42a1
Signed-off-by: Ruslan Bilovol <ruslan.bilovol@ti.com>
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/usbnet.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 5fd06e230c0..912ff115e99 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; } |