[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#677472: [3.1->3.2 regression] Immediate wake on suspend, associated with OHCI on MCP51



On 2012年12月13日 04:28, Frank Schäfer wrote:
> Am 12.12.2012 09:23, schrieb Lan Tianyu:
>> On 2012年12月12日 05:59, Frank Schäfer wrote:
>>> Am 11.12.2012 17:48, schrieb Alan Stern:
>>>
>>> [snip]
>>>> We really need to know which component is bad: the host controller or 
>>>> the device.
>>> It happens with all USB 1.1 devices I have (several mice and a HP
>>> Deskjet 960c printer).
>>> The same devices do not cause other machines to wake up, so I assume
>>> it's the host controller.
>> Good information. Attaching device makes hc work abnormally during
>> entering into s3 since without device it can work, right?
> 
> Right.
> The system successfully enters S3 (machine switches off = fan stops,
> light off etc.) but it resumes immediately.
> No errors in the log, it looks like this:
> 
> <snip>
> ...
> [24685.640361] PM: Syncing filesystems ... done.
> [24686.022132] PM: Preparing system for mem sleep
> [24686.110208] Freezing user space processes ... (elapsed 0.01 seconds)
> done.
> [24686.123851] Freezing remaining freezable tasks ... (elapsed 0.01
> seconds) done.
> [24686.134818] PM: Entering mem sleep
> [24686.134840] Suspending console(s) (use no_console_suspend to debug)
> [24686.135751] sd 1:0:0:0: [sda] Synchronizing SCSI cache
> [24686.136509] sd 1:0:0:0: [sda] Stopping disk
> [24686.150741] i8042 kbd 00:0b: wake-up capability enabled by ACPI
> [24686.150833] i8042 aux 00:0a: wake-up capability disabled by ACPI
> [24686.150926] parport_pc 00:09: disabled
> [24686.151029] serial 00:08: disabled
> [24686.151056] serial 00:08: wake-up capability disabled by ACPI
> [24686.151219] ACPI handle has no context!
> [24686.151299] [drm] nouveau 0000:00:0d.0: Disabling display...
> [24686.151302] [drm] nouveau 0000:00:0d.0: Disabling fbcon...
> [24686.151311] [drm] nouveau 0000:00:0d.0: Unpinning framebuffer(s)...
> [24686.151341] [drm] nouveau 0000:00:0d.0: Evicting buffers...
> [24686.255063] usb 1-5: reset high-speed USB device number 3 using ehci_hcd
> [24686.346351] [drm] nouveau 0000:00:0d.0: Idling channels...
> [24686.346668] [drm] nouveau 0000:00:0d.0: Suspending GPU objects...
> [24686.447591] [drm] nouveau 0000:00:0d.0: And we're gone!
> [24687.547695] PM: suspend of devices complete after 1412.642 msecs
> [24687.547853] PM: late suspend of devices complete after 0.153 msecs
> [24687.548029] forcedeth 0000:00:07.0: wake-up capability enabled by ACPI
> [24687.559652] ehci_hcd 0000:00:02.1: wake-up capability enabled by ACPI
> [24687.570602] ohci_hcd 0000:00:02.0: wake-up capability enabled by ACPI
> [24687.581671] PM: noirq suspend of devices complete after 33.815 msecs
> [24687.581735] ACPI: Preparing to enter system sleep state S3
> [24687.582536] PM: Saving platform NVS memory
> [24687.582591] Disabling non-boot CPUs ...
> [24687.583984] smpboot: CPU 1 is now offline
> [24687.584703] Extended CMOS year: 2000
> [24687.584703] ACPI: Low-level resume complete
> [24687.584703] PM: Restoring platform NVS memory
> [24687.584703] Extended CMOS year: 2000
> [24687.586196] Enabling non-boot CPUs ...
> [24687.589496] smpboot: Booting Node 0 Processor 1 APIC 0x1
> [24687.583795] Initializing CPU#1
> [24687.583795] process: Switch to broadcast mode on CPU1
> [24687.601153] CPU1 is up
> [24687.601538] ACPI: Waking up from system sleep state S3
> [24687.613683] ohci_hcd 0000:00:02.0: wake-up capability disabled by ACPI
> [24687.624693] ehci_hcd 0000:00:02.1: wake-up capability disabled by ACPI
> [24687.624746] pci 0000:00:00.0: Found enabled HT MSI Mapping
> [24687.635726] pci 0000:00:00.0: Found enabled HT MSI Mapping
> [24687.657735] pci 0000:00:00.0: Found enabled HT MSI Mapping
> [24687.668730] pci 0000:00:00.0: Found enabled HT MSI Mapping
> [24687.679730] pci 0000:00:00.0: Found enabled HT MSI Mapping
> [24687.679803] pci 0000:00:00.0: Found enabled HT MSI Mapping
> [24687.679878] pci 0000:00:00.0: Found enabled HT MSI Mapping
> [24687.679956] pci 0000:00:00.0: Found enabled HT MSI Mapping
> [24687.773804] PM: noirq resume of devices complete after 171.507 msecs
> [24687.773907] PM: early resume of devices complete after 0.056 msecs
> [24687.773980] ohci_hcd 0000:00:02.0: setting latency timer to 64
> [24687.774001] ehci_hcd 0000:00:02.1: setting latency timer to 64
> [24687.774023] pci 0000:00:04.0: setting latency timer to 64
> ...
> <snip>
> 
> 
> When I disconnect all USB 1.1 devices, suspend works fine.
> 
>> I am curious about whether disabling usb device's wakeup rather than usb
>> hc's would make suspend work. Can you do a test?
>>
>> Go to /sys/bus/usb/devices/ and enter the usb 1,1 device
>> directory(normally it will be something like"1-1.1".)
>> run "echo disabled > power/wakeup".
> 
> Are you sure the file is called 'wakeup' for the devices ? I have no
> such file in the power directory...
Oh. That means the device doesn't support wakeup function.
Non-wakeupable devices also will cause the issue. Now Confirm this is
hcd problem.

I write a quirk patch. Can you test?
I just find one MCP51 and two MCP79 OHCI id. Can you provide more buggy
hcd id via "lspci -nnvvv"?
Thanks.


diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index f034716..9335f1b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2509,7 +2509,8 @@ int usb_add_hcd(struct usb_hcd *hcd,
 	 * they only forward requests from the root hub.  Therefore
 	 * controllers should always be enabled for remote wakeup.
 	 */
-	device_wakeup_enable(hcd->self.controller);
+	if (!usb_hcd_wakeup_quirks(hcd->self.controller))
+		device_wakeup_enable(hcd->self.controller);
 	return retval;

 error_create_attr_group:
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index fdefd9c..ba847d3 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -12,6 +12,7 @@
  */

 #include <linux/usb.h>
+#include <linux/pci.h>
 #include <linux/usb/quirks.h>
 #include "usb.h"

@@ -226,3 +227,33 @@ void usb_detect_interface_quirks(struct usb_device
*udev)
 		quirks);
 	udev->quirks |= quirks;
 }
+
+struct pci_hcd {
+	u32 vendor;
+	u32 device;
+};
+
+static struct pci_hcd hcd_wakeup_qrk[] = {
+	{PCI_VENDOR_ID_NVIDIA, 0x026d}, /* MCP51 OHCI */
+	{PCI_VENDOR_ID_NVIDIA, 0x0aa5}, /* MCP79 OHCI */
+	{PCI_VENDOR_ID_NVIDIA, 0x0aa7}, /* MCP79 OHCI */
+	{ }
+};
+
+int usb_hcd_wakeup_quirks(struct device *dev)
+{
+	struct pci_dev *pdev;
+	int i;
+
+	if (dev->bus != (struct bus_type *)&pci_bus_type)
+		return 0;
+
+	pdev = to_pci_dev(dev);
+	for (i = 0; hcd_wakeup_qrk[i].vendor || hcd_wakeup_qrk[i].device; i++)
+		if ((hcd_wakeup_qrk[i].vendor == pdev->vendor) &&
+			(hcd_wakeup_qrk[i].device == pdev->device)) {
+			return 1;
+		}
+
+	return 0;
+}
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 1c528c1..eb2da6a 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -164,6 +164,8 @@ extern void usbfs_conn_disc_event(void);
 extern int usb_devio_init(void);
 extern void usb_devio_cleanup(void);

+extern int usb_hcd_wakeup_quirks(struct device *dev);
+
 /* internal notify stuff */
 extern void usb_notify_add_device(struct usb_device *udev);
 extern void usb_notify_remove_device(struct usb_device *udev);

> 

> Regards,
> Frank
> 


-- 
Best regards
Tianyu Lan
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index f034716..9335f1b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2509,7 +2509,8 @@ int usb_add_hcd(struct usb_hcd *hcd,
 	 * they only forward requests from the root hub.  Therefore
 	 * controllers should always be enabled for remote wakeup.
 	 */
-	device_wakeup_enable(hcd->self.controller);
+	if (!usb_hcd_wakeup_quirks(hcd->self.controller))
+		device_wakeup_enable(hcd->self.controller);
 	return retval;
 
 error_create_attr_group:
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index fdefd9c..ba847d3 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/usb.h>
+#include <linux/pci.h>
 #include <linux/usb/quirks.h>
 #include "usb.h"
 
@@ -226,3 +227,33 @@ void usb_detect_interface_quirks(struct usb_device *udev)
 		quirks);
 	udev->quirks |= quirks;
 }
+
+struct pci_hcd {
+	u32 vendor;
+	u32 device;
+};
+
+static struct pci_hcd hcd_wakeup_qrk[] = {
+	{PCI_VENDOR_ID_NVIDIA, 0x026d}, /* MCP51 OHCI */
+	{PCI_VENDOR_ID_NVIDIA, 0x0aa5}, /* MCP79 OHCI */
+	{PCI_VENDOR_ID_NVIDIA, 0x0aa7}, /* MCP79 OHCI */
+	{ }
+};
+
+int usb_hcd_wakeup_quirks(struct device *dev)
+{
+	struct pci_dev *pdev;
+	int i;
+
+	if (dev->bus != (struct bus_type *)&pci_bus_type)
+		return 0;
+
+	pdev = to_pci_dev(dev);
+	for (i = 0; hcd_wakeup_qrk[i].vendor || hcd_wakeup_qrk[i].device; i++)
+		if ((hcd_wakeup_qrk[i].vendor == pdev->vendor) &&
+			(hcd_wakeup_qrk[i].device == pdev->device)) {
+			return 1;
+		}
+
+	return 0;
+}
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 1c528c1..eb2da6a 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -164,6 +164,8 @@ extern void usbfs_conn_disc_event(void);
 extern int usb_devio_init(void);
 extern void usb_devio_cleanup(void);
 
+extern int usb_hcd_wakeup_quirks(struct device *dev);
+
 /* internal notify stuff */
 extern void usb_notify_add_device(struct usb_device *udev);
 extern void usb_notify_remove_device(struct usb_device *udev);

Reply to: