diff options
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-pci.c | 25 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 3 |
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); |
167 | done: | 190 | done: |
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 */ |