This is a note to let you know that I've just added the patch titled

    ehci: Check individual port status registers on resume

to my usb git tree which can be found at
    git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git
in the usb-next branch.

The patch will show up in the next release of the linux-next tree
(usually sometime within the next 24 hours during the week.)

The patch will also will be merged in the next major kernel release
during the merge window.

If you have any questions about this process, please let me know.


>From 294d95f2cbc2aef5346258f216cd9df570e271a5 Mon Sep 17 00:00:00 2001
From: Matthew Garrett <[email protected]>
Date: Tue, 11 Jan 2011 12:26:48 -0500
Subject: ehci: Check individual port status registers on resume

If a device plug/unplug is detected on an ATI SB700 USB controller in D3,
it appears to set the port status register but not the controller status
register. As a result we'll fail to detect the plug event. Check the port
status register on resume as well in order to catch this case.

Signed-off-by: Matthew Garrett <[email protected]>
Cc: stable <[email protected]> [after .39-rc1 is out]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
 drivers/usb/host/ehci-hub.c |   23 ++++++++++++++++++++++-
 1 files changed, 22 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index c0b37fe..ae0140d 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -106,6 +106,27 @@ static void ehci_handover_companion_ports(struct ehci_hcd 
*ehci)
        ehci->owned_ports = 0;
 }
 
+static int ehci_port_change(struct ehci_hcd *ehci)
+{
+       int i = HCS_N_PORTS(ehci->hcs_params);
+
+       /* First check if the controller indicates a change event */
+
+       if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)
+               return 1;
+
+       /*
+        * Not all controllers appear to update this while going from D3 to D0,
+        * so check the individual port status registers as well
+        */
+
+       while (i--)
+               if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC)
+                       return 1;
+
+       return 0;
+}
+
 static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
                bool suspending, bool do_wakeup)
 {
@@ -173,7 +194,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd 
*ehci,
        }
 
        /* Does the root hub have a port wakeup pending? */
-       if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD))
+       if (!suspending && ehci_port_change(ehci))
                usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
 
        spin_unlock_irqrestore(&ehci->lock, flags);
-- 
1.7.3.2


_______________________________________________
stable mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/stable

Reply via email to