On Fri, 22 Sep 2006, Rafael J. Wysocki wrote: > I have tested 2.6.18-rc6-mm2 with your patch applied (it is called 2.6.18-rc6 > in the attached dmesg outputs, but that's because I have a "customized" > 2.6.18-rc6-mm2 installed and I didn't want to replace it). > > I have tested both with and without CONFIG_USB_SUSPEND set. In either case > I booted the system without my USB mouse. Then, I plugged the mouse in > and checked if it worked. Next, I suspended and resumed the system twice > checking if the mouse worked after each resume, without unplugging it. > Finally, after the second resume I unplugged and replugged the mouse. > > The results are the following: > > 1) The kernel compiled without CONFIG_USB_SUSPEND works just fine, suspends > and resumes correctly, and the mouse always works (ie. is correctly detected > every time).
Good. > 2) The kernel compiled with CONFIG_USB_SUSPEND set doesn't detect the mouse > plugged in after a fresh boot. However, if the mouse is connected to a USB > port during an entire suspend/resume cycle, it works after the resume, but > when it's unplugged after the resume and replugged, the kernel fails to detect > it. > > The outputs of dmesg for each case are attached. This helped. I think I figured out the problem. Below is a new version of the patch I asked you to try. It's the same as before except that I removed a bunch of extra code. Some weird interactions between the driver and usbcore prevented status-change interrupts from being enabled; hence the connect-change events just get lost. Anyway, this should solve the problem. If it doesn't, we can settle on a single test case: CONFIG_USB_SUSPEND set, mouse not plugged in during boot, mouse not detected when plugged in after boot-up. Alan Stern Index: mm/drivers/usb/core/hub.c =================================================================== --- mm.orig/drivers/usb/core/hub.c +++ mm/drivers/usb/core/hub.c @@ -1063,6 +1063,12 @@ void usb_root_hub_lost_power(struct usb_ unsigned long flags; dev_warn(&rhdev->dev, "root hub lost power or was reset\n"); + + /* Make sure no potential wakeup events get lost, + * by forcing the root hub to be resumed. + */ + rhdev->dev.power.prev_state.event = PM_EVENT_ON; + spin_lock_irqsave(&device_state_lock, flags); hub = hdev_to_hub(rhdev); for (port1 = 1; port1 <= rhdev->maxchild; ++port1) { Index: mm/drivers/usb/core/driver.c =================================================================== --- mm.orig/drivers/usb/core/driver.c +++ mm/drivers/usb/core/driver.c @@ -1079,11 +1079,12 @@ int usb_resume_both(struct usb_device *u PM_EVENT_ON) status = -EHOSTUNREACH; } - if (status == 0 && udev->state == USB_STATE_SUSPENDED) + if (status == 0) status = resume_device(udev); if (parent) mutex_unlock(&parent->pm_mutex); - } + } else + status = resume_device(udev); /* Now the parent won't suspend until we are finished */ Index: mm/drivers/usb/host/ohci-hub.c =================================================================== --- mm.orig/drivers/usb/host/ohci-hub.c +++ mm/drivers/usb/host/ohci-hub.c @@ -41,6 +41,8 @@ static void ohci_rhsc_enable (struct usb { struct ohci_hcd *ohci = hcd_to_ohci (hcd); + ohci_vdbg (ohci, "rhsc enable\n"); + hcd->poll_rh = 0; ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); } @@ -379,29 +381,11 @@ ohci_hub_status_data (struct usb_hcd *hc & ohci->hc_control) == OHCI_USB_OPER; #endif - if (hcd->uses_new_polling) { - hcd->poll_rh = 0; - /* use INTR_RHSC iff INTR_RD won't apply */ - if (!can_suspend) - ohci_writel (ohci, OHCI_INTR_RHSC, - &ohci->regs->intrenable); - } } done: spin_unlock_irqrestore (&ohci->lock, flags); -#ifdef CONFIG_PM - /* save power by autosuspending idle root hubs; - * INTR_RD wakes us when there's work - */ - if (can_suspend && usb_trylock_device (hcd->self.root_hub) == 0) { - ohci_vdbg (ohci, "autosuspend\n"); - (void) ohci_bus_suspend (hcd); - usb_unlock_device (hcd->self.root_hub); - } -#endif - return changed ? length : 0; } @@ -572,9 +556,6 @@ static int ohci_hub_control ( break; case USB_PORT_FEAT_SUSPEND: temp = RH_PS_POCI; - if ((ohci->hc_control & OHCI_CTRL_HCFS) - != OHCI_USB_OPER) - usb_hcd_resume_root_hub(hcd); break; case USB_PORT_FEAT_C_SUSPEND: temp = RH_PS_PSSC; Index: mm/drivers/usb/host/ohci-hcd.c =================================================================== --- mm.orig/drivers/usb/host/ohci-hcd.c +++ mm/drivers/usb/host/ohci-hcd.c @@ -107,7 +107,7 @@ /*-------------------------------------------------------------------------*/ -#undef OHCI_VERBOSE_DEBUG /* not always helpful */ +#define OHCI_VERBOSE_DEBUG /* not always helpful */ /* For initializing controller (mask in an HCFS mode too) */ #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR Index: mm/drivers/usb/core/hcd.c =================================================================== --- mm.orig/drivers/usb/core/hcd.c +++ mm/drivers/usb/core/hcd.c @@ -835,8 +835,7 @@ void usb_enable_root_hub_irq (struct usb struct usb_hcd *hcd; hcd = container_of (bus, struct usb_hcd, self); - if (hcd->driver->hub_irq_enable && !hcd->poll_rh && - hcd->state != HC_STATE_HALT) + if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT) hcd->driver->hub_irq_enable (hcd); } ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel