On Thu, Apr 21, 2011 at 7:03 AM, Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote: > On Tue, 19 Apr 2011, Paul Stewart wrote: > >> Set a flag if the interrupt URB completes with ENOENT as this >> occurs legitimately during system suspend. When the >> usbnet_resume is called, test this flag and try once to resubmit >> the interrupt URB. > > I still don't think this is the best way to go. > >> This version of the patch moves the urb submit directly into >> usbnet_resume. Is it okay to submit a GFP_KERNEL urb from >> usbnet_resume()? > > Yes, it is. > >> Signed-off-by: Paul Stewart <pstew@xxxxxxxxxxxx> >> --- >> drivers/net/usb/usbnet.c | 13 ++++++++++++- >> include/linux/usb/usbnet.h | 1 + >> 2 files changed, 13 insertions(+), 1 deletions(-) >> >> diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c >> index 02d25c7..3651a48 100644 >> --- a/drivers/net/usb/usbnet.c >> +++ b/drivers/net/usb/usbnet.c >> @@ -482,6 +482,7 @@ static void intr_complete (struct urb *urb) >> case -ESHUTDOWN: /* hardware gone */ >> if (netif_msg_ifdown (dev)) >> devdbg (dev, "intr shutdown, code %d", status); >> + set_bit(EVENT_INTR_HALT, &dev->flags); > > Is this new flag really needed? > >> return; >> >> /* NOTE: not throttling like RX/TX, since this endpoint >> @@ -1294,9 +1295,19 @@ int usbnet_resume (struct usb_interface *intf) >> { >> struct usbnet *dev = usb_get_intfdata(intf); >> >> - if (!--dev->suspend_count) >> + if (!--dev->suspend_count) { >> tasklet_schedule (&dev->bh); >> >> + /* resubmit interrupt URB if it was halted by suspend */ >> + if (dev->interrupt && netif_running(dev->net) && >> + netif_device_present(dev->net) && >> + test_bit(EVENT_INTR_HALT, &dev->flags)) { > > Why do you need the test_bit()? If the other conditions are all true, > don't you want to resubmit the interrupt URB regardless? I'm trying to handle two separate issues, one of which I can't say I fully understand. The first, which is the most straightforward, is for systems in which USB devices remained powered across suspend-resume. For this case for sure, we don't need a flag. The interrupt URBs are halted (either done so by the HCD as I've observed, or the drive can choose to kill them in usbnet_suspend()). On system resume, we're guaranteed URBs have stopped, and we can just submit one. In a second scenario, for other systems USB devices go unpowered during suspend. At resume time, there's a quick succession where the device appears to detach and reattach and enumerate. This is where things get strange. It appears that since the enumeration happens in the course of system resume, when usbnet_open() gets called, and usb_autopm_get_interface(), there's a call path that leads to usbnet_resume(). If there's no flag, then we submit the interrupt urb from usbnet_resume(), so the submit_urb() in usbnet_open() fails in an error. This makes actions like "ifconfig eth0 up" fail on the interface after resume from suspend. > >> + clear_bit(EVENT_INTR_HALT, &dev->flags); >> + usb_submit_urb(dev->interrupt, GFP_KERNEL); >> + } >> + } >> +} >> + >> return 0; >> } > > Alan Stern > > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html