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

Reply via email to