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);