aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/ehci-hub.c4
-rw-r--r--drivers/usb/host/ehci-pci.c25
-rw-r--r--drivers/usb/host/ehci.h3
3 files changed, 30 insertions, 2 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 69b0b9be7a64..d03e3cad5ca8 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -359,6 +359,8 @@ static int ehci_hub_control (
359 case USB_PORT_FEAT_SUSPEND: 359 case USB_PORT_FEAT_SUSPEND:
360 if (temp & PORT_RESET) 360 if (temp & PORT_RESET)
361 goto error; 361 goto error;
362 if (ehci->no_selective_suspend)
363 break;
362 if (temp & PORT_SUSPEND) { 364 if (temp & PORT_SUSPEND) {
363 if ((temp & PORT_PE) == 0) 365 if ((temp & PORT_PE) == 0)
364 goto error; 366 goto error;
@@ -514,6 +516,8 @@ static int ehci_hub_control (
514 temp &= ~PORT_RWC_BITS; 516 temp &= ~PORT_RWC_BITS;
515 switch (wValue) { 517 switch (wValue) {
516 case USB_PORT_FEAT_SUSPEND: 518 case USB_PORT_FEAT_SUSPEND:
519 if (ehci->no_selective_suspend)
520 break;
517 if ((temp & PORT_PE) == 0 521 if ((temp & PORT_PE) == 0
518 || (temp & PORT_RESET) != 0) 522 || (temp & PORT_RESET) != 0)
519 goto error; 523 goto error;
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 3a6687df5594..1e03f1a5a5fd 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -106,11 +106,11 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
106 } 106 }
107 break; 107 break;
108 case PCI_VENDOR_ID_NVIDIA: 108 case PCI_VENDOR_ID_NVIDIA:
109 switch (pdev->device) {
109 /* NVidia reports that certain chips don't handle 110 /* NVidia reports that certain chips don't handle
110 * QH, ITD, or SITD addresses above 2GB. (But TD, 111 * QH, ITD, or SITD addresses above 2GB. (But TD,
111 * data buffer, and periodic schedule are normal.) 112 * data buffer, and periodic schedule are normal.)
112 */ 113 */
113 switch (pdev->device) {
114 case 0x003c: /* MCP04 */ 114 case 0x003c: /* MCP04 */
115 case 0x005b: /* CK804 */ 115 case 0x005b: /* CK804 */
116 case 0x00d8: /* CK8 */ 116 case 0x00d8: /* CK8 */
@@ -120,6 +120,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
120 ehci_warn(ehci, "can't enable NVidia " 120 ehci_warn(ehci, "can't enable NVidia "
121 "workaround for >2GB RAM\n"); 121 "workaround for >2GB RAM\n");
122 break; 122 break;
123 /* Some NForce2 chips have problems with selective suspend;
124 * fixed in newer silicon.
125 */
126 case 0x0068:
127 pci_read_config_dword(pdev, PCI_REVISION_ID, &temp);
128 if ((temp & 0xff) < 0xa4)
129 ehci->no_selective_suspend = 1;
130 break;
123 } 131 }
124 break; 132 break;
125 } 133 }
@@ -163,6 +171,21 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
163 device_init_wakeup(&pdev->dev, 1); 171 device_init_wakeup(&pdev->dev, 1);
164 } 172 }
165 173
174#ifdef CONFIG_USB_SUSPEND
175 /* REVISIT: the controller works fine for wakeup iff the root hub
176 * itself is "globally" suspended, but usbcore currently doesn't
177 * understand such things.
178 *
179 * System suspend currently expects to be able to suspend the entire
180 * device tree, device-at-a-time. If we failed selective suspend
181 * reports, system suspend would fail; so the root hub code must claim
182 * success. That's lying to usbcore, and it matters for for runtime
183 * PM scenarios with selective suspend and remote wakeup...
184 */
185 if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev))
186 ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
187#endif
188
166 retval = ehci_pci_reinit(ehci, pdev); 189 retval = ehci_pci_reinit(ehci, pdev);
167done: 190done:
168 return retval; 191 return retval;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 18e257c2bdb5..86af41c41de1 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -89,6 +89,8 @@ struct ehci_hcd { /* one per controller */
89 u32 command; 89 u32 command;
90 90
91 unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */ 91 unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */
92 unsigned no_selective_suspend:1;
93 u8 sbrn; /* packed release number */
92 94
93 /* irq statistics */ 95 /* irq statistics */
94#ifdef EHCI_STATS 96#ifdef EHCI_STATS
@@ -97,7 +99,6 @@ struct ehci_hcd { /* one per controller */
97#else 99#else
98# define COUNT(x) do {} while (0) 100# define COUNT(x) do {} while (0)
99#endif 101#endif
100 u8 sbrn; /* packed release number */
101}; 102};
102 103
103/* convert between an HCD pointer and the corresponding EHCI_HCD */ 104/* convert between an HCD pointer and the corresponding EHCI_HCD */