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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel