Commit dacb3975 authored by David S. Miller's avatar David S. Miller

usbnet: rx_submit() should return an error code.

This patch makes rx_submit() return an error code, and makes some call sites
that care check the return value. This is important because it lets us properly
handle cases where the device isn't ready to handle URB submissions (e.g., when
it is autosuspended under some drivers); previously, we would attempt and fail
to submit URBs and reschedule ourselves to try and fail again. This patch is
against Linus's 2.6 repo commit 45d7f32c.
Signed-Off-By: default avatarElizabeth Jones <ellyjones@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 68fd26b5
...@@ -315,7 +315,7 @@ EXPORT_SYMBOL_GPL(usbnet_defer_kevent); ...@@ -315,7 +315,7 @@ EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
static void rx_complete (struct urb *urb); static void rx_complete (struct urb *urb);
static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct skb_data *entry; struct skb_data *entry;
...@@ -327,7 +327,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) ...@@ -327,7 +327,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
usbnet_defer_kevent (dev, EVENT_RX_MEMORY); usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
usb_free_urb (urb); usb_free_urb (urb);
return; return -ENOMEM;
} }
skb_reserve (skb, NET_IP_ALIGN); skb_reserve (skb, NET_IP_ALIGN);
...@@ -357,6 +357,9 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) ...@@ -357,6 +357,9 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
netif_dbg(dev, ifdown, dev->net, "device gone\n"); netif_dbg(dev, ifdown, dev->net, "device gone\n");
netif_device_detach (dev->net); netif_device_detach (dev->net);
break; break;
case -EHOSTUNREACH:
retval = -ENOLINK;
break;
default: default:
netif_dbg(dev, rx_err, dev->net, netif_dbg(dev, rx_err, dev->net,
"rx submit, %d\n", retval); "rx submit, %d\n", retval);
...@@ -374,6 +377,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) ...@@ -374,6 +377,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
dev_kfree_skb_any (skb); dev_kfree_skb_any (skb);
usb_free_urb (urb); usb_free_urb (urb);
} }
return retval;
} }
...@@ -912,6 +916,7 @@ kevent (struct work_struct *work) ...@@ -912,6 +916,7 @@ kevent (struct work_struct *work)
/* tasklet could resubmit itself forever if memory is tight */ /* tasklet could resubmit itself forever if memory is tight */
if (test_bit (EVENT_RX_MEMORY, &dev->flags)) { if (test_bit (EVENT_RX_MEMORY, &dev->flags)) {
struct urb *urb = NULL; struct urb *urb = NULL;
int resched = 1;
if (netif_running (dev->net)) if (netif_running (dev->net))
urb = usb_alloc_urb (0, GFP_KERNEL); urb = usb_alloc_urb (0, GFP_KERNEL);
...@@ -922,10 +927,12 @@ kevent (struct work_struct *work) ...@@ -922,10 +927,12 @@ kevent (struct work_struct *work)
status = usb_autopm_get_interface(dev->intf); status = usb_autopm_get_interface(dev->intf);
if (status < 0) if (status < 0)
goto fail_lowmem; goto fail_lowmem;
rx_submit (dev, urb, GFP_KERNEL); if (rx_submit (dev, urb, GFP_KERNEL) == -ENOLINK)
resched = 0;
usb_autopm_put_interface(dev->intf); usb_autopm_put_interface(dev->intf);
fail_lowmem: fail_lowmem:
tasklet_schedule (&dev->bh); if (resched)
tasklet_schedule (&dev->bh);
} }
} }
...@@ -1175,8 +1182,11 @@ static void usbnet_bh (unsigned long param) ...@@ -1175,8 +1182,11 @@ static void usbnet_bh (unsigned long param)
// don't refill the queue all at once // don't refill the queue all at once
for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) { for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) {
urb = usb_alloc_urb (0, GFP_ATOMIC); urb = usb_alloc_urb (0, GFP_ATOMIC);
if (urb != NULL) if (urb != NULL) {
rx_submit (dev, urb, GFP_ATOMIC); if (rx_submit (dev, urb, GFP_ATOMIC) ==
-ENOLINK)
return;
}
} }
if (temp != dev->rxq.qlen) if (temp != dev->rxq.qlen)
netif_dbg(dev, link, dev->net, netif_dbg(dev, link, dev->net,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment