aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/uhci-debug.c32
-rw-r--r--drivers/usb/host/uhci-hcd.c285
-rw-r--r--drivers/usb/host/uhci-hcd.h49
-rw-r--r--drivers/usb/host/uhci-hub.c2
4 files changed, 212 insertions, 156 deletions
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 24c73c5a3435..4538a98b6f9d 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -237,6 +237,37 @@ static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
237 return out - buf; 237 return out - buf;
238} 238}
239 239
240static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len)
241{
242 char *out = buf;
243 char *rh_state;
244
245 /* Try to make sure there's enough memory */
246 if (len < 60)
247 return 0;
248
249 switch (uhci->rh_state) {
250 case UHCI_RH_RESET:
251 rh_state = "reset"; break;
252 case UHCI_RH_SUSPENDED:
253 rh_state = "suspended"; break;
254 case UHCI_RH_AUTO_STOPPED:
255 rh_state = "auto-stopped"; break;
256 case UHCI_RH_RESUMING:
257 rh_state = "resuming"; break;
258 case UHCI_RH_SUSPENDING:
259 rh_state = "suspending"; break;
260 case UHCI_RH_RUNNING:
261 rh_state = "running"; break;
262 case UHCI_RH_RUNNING_NODEVS:
263 rh_state = "running, no devs"; break;
264 default:
265 rh_state = "?"; break;
266 }
267 out += sprintf(out, "Root-hub state: %s\n", rh_state);
268 return out - buf;
269}
270
240static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) 271static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
241{ 272{
242 char *out = buf; 273 char *out = buf;
@@ -408,6 +439,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
408 439
409 spin_lock_irqsave(&uhci->lock, flags); 440 spin_lock_irqsave(&uhci->lock, flags);
410 441
442 out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
411 out += sprintf(out, "HC status\n"); 443 out += sprintf(out, "HC status\n");
412 out += uhci_show_status(uhci, out, len - (out - buf)); 444 out += uhci_show_status(uhci, out, len - (out - buf));
413 445
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index c17bd7ebc021..57b36dcea5d0 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -64,7 +64,7 @@
64/* 64/*
65 * Version Information 65 * Version Information
66 */ 66 */
67#define DRIVER_VERSION "v2.2" 67#define DRIVER_VERSION "v2.3"
68#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ 68#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
69Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ 69Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
70Alan Stern" 70Alan Stern"
@@ -109,33 +109,6 @@ static inline void restart_timer(struct uhci_hcd *uhci)
109#include "uhci-debug.c" 109#include "uhci-debug.c"
110#include "uhci-q.c" 110#include "uhci-q.c"
111 111
112static int suspend_allowed(struct uhci_hcd *uhci)
113{
114 unsigned long io_addr = uhci->io_addr;
115 int i;
116
117 if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL)
118 return 1;
119
120 /* Some of Intel's USB controllers have a bug that causes false
121 * resume indications if any port has an over current condition.
122 * To prevent problems, we will not allow a global suspend if
123 * any ports are OC.
124 *
125 * Some motherboards using Intel's chipsets (but not using all
126 * the USB ports) appear to hardwire the over current inputs active
127 * to disable the USB ports.
128 */
129
130 /* check for over current condition on any port */
131 for (i = 0; i < uhci->rh_numports; i++) {
132 if (inw(io_addr + USBPORTSC1 + i * 2) & USBPORTSC_OC)
133 return 0;
134 }
135
136 return 1;
137}
138
139static void reset_hc(struct uhci_hcd *uhci) 112static void reset_hc(struct uhci_hcd *uhci)
140{ 113{
141 unsigned long io_addr = uhci->io_addr; 114 unsigned long io_addr = uhci->io_addr;
@@ -147,7 +120,6 @@ static void reset_hc(struct uhci_hcd *uhci)
147 outw(0, uhci->io_addr + USBINTR); 120 outw(0, uhci->io_addr + USBINTR);
148 121
149 /* Global reset for 50ms */ 122 /* Global reset for 50ms */
150 uhci->state = UHCI_RESET;
151 outw(USBCMD_GRESET, io_addr + USBCMD); 123 outw(USBCMD_GRESET, io_addr + USBCMD);
152 msleep(50); 124 msleep(50);
153 outw(0, io_addr + USBCMD); 125 outw(0, io_addr + USBCMD);
@@ -156,63 +128,130 @@ static void reset_hc(struct uhci_hcd *uhci)
156 msleep(10); 128 msleep(10);
157 uhci->resume_detect = 0; 129 uhci->resume_detect = 0;
158 uhci->is_stopped = UHCI_IS_STOPPED; 130 uhci->is_stopped = UHCI_IS_STOPPED;
131 uhci->rh_state = UHCI_RH_RESET;
159} 132}
160 133
161static void suspend_hc(struct uhci_hcd *uhci) 134static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
162{ 135{
163 unsigned long io_addr = uhci->io_addr; 136 int port;
164 137
165 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); 138 switch (to_pci_dev(uhci_dev(uhci))->vendor) {
166 uhci->state = UHCI_SUSPENDED; 139 default:
167 uhci->resume_detect = 0; 140 break;
168 outw(USBCMD_EGSM, io_addr + USBCMD); 141
142 case PCI_VENDOR_ID_GENESYS:
143 /* Genesys Logic's GL880S controllers don't generate
144 * resume-detect interrupts.
145 */
146 return 1;
147
148 case PCI_VENDOR_ID_INTEL:
149 /* Some of Intel's USB controllers have a bug that causes
150 * resume-detect interrupts if any port has an over-current
151 * condition. To make matters worse, some motherboards
152 * hardwire unused USB ports' over-current inputs active!
153 * To prevent problems, we will not enable resume-detect
154 * interrupts if any ports are OC.
155 */
156 for (port = 0; port < uhci->rh_numports; ++port) {
157 if (inw(uhci->io_addr + USBPORTSC1 + port * 2) &
158 USBPORTSC_OC)
159 return 1;
160 }
161 break;
162 }
163 return 0;
164}
165
166static void suspend_hc(struct uhci_hcd *uhci, enum uhci_rh_state new_state)
167__releases(uhci->lock)
168__acquires(uhci->lock)
169{
170 int auto_stop;
171 int int_enable;
172
173 auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
174 dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__,
175 (auto_stop ? " (auto-stop)" : ""));
176
177 /* If we get a suspend request when we're already auto-stopped
178 * then there's nothing to do.
179 */
180 if (uhci->rh_state == UHCI_RH_AUTO_STOPPED) {
181 uhci->rh_state = new_state;
182 return;
183 }
184
185 /* Enable resume-detect interrupts if they work.
186 * Then enter Global Suspend mode, still configured.
187 */
188 int_enable = (resume_detect_interrupts_are_broken(uhci) ?
189 0 : USBINTR_RESUME);
190 outw(int_enable, uhci->io_addr + USBINTR);
191 outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
192 udelay(5);
193
194 /* If we're auto-stopping then no devices have been attached
195 * for a while, so there shouldn't be any active URBs and the
196 * controller should stop after a few microseconds. Otherwise
197 * we will give the controller one frame to stop.
198 */
199 if (!auto_stop && !(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) {
200 uhci->rh_state = UHCI_RH_SUSPENDING;
201 spin_unlock_irq(&uhci->lock);
202 msleep(1);
203 spin_lock_irq(&uhci->lock);
204 }
205 if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
206 dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
169 207
170 /* FIXME: Wait for the controller to actually stop */
171 uhci_get_current_frame_number(uhci); 208 uhci_get_current_frame_number(uhci);
209 smp_wmb();
210
211 uhci->rh_state = new_state;
172 uhci->is_stopped = UHCI_IS_STOPPED; 212 uhci->is_stopped = UHCI_IS_STOPPED;
213 uhci->resume_detect = 0;
173 214
174 uhci_scan_schedule(uhci, NULL); 215 uhci_scan_schedule(uhci, NULL);
175} 216}
176 217
177static void wakeup_hc(struct uhci_hcd *uhci) 218static void wakeup_hc(struct uhci_hcd *uhci)
219__releases(uhci->lock)
220__acquires(uhci->lock)
178{ 221{
179 unsigned long io_addr = uhci->io_addr; 222 dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__,
223 uhci->rh_state == UHCI_RH_AUTO_STOPPED ?
224 " (auto-start)" : "");
180 225
181 switch (uhci->state) { 226 /* If we are auto-stopped then no devices are attached so there's
182 case UHCI_SUSPENDED: /* Start the resume */ 227 * no need for wakeup signals. Otherwise we send Global Resume
183 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); 228 * for 20 ms.
184 229 */
185 /* Global resume for >= 20ms */ 230 if (uhci->rh_state == UHCI_RH_SUSPENDED) {
186 outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD); 231 uhci->rh_state = UHCI_RH_RESUMING;
187 uhci->state = UHCI_RESUMING_1; 232 outw(USBCMD_FGR | USBCMD_EGSM | USBCMD_CF,
188 uhci->state_end = jiffies + msecs_to_jiffies(20); 233 uhci->io_addr + USBCMD);
189 uhci->is_stopped = 0; 234 spin_unlock_irq(&uhci->lock);
190 break; 235 msleep(20);
236 spin_lock_irq(&uhci->lock);
191 237
192 case UHCI_RESUMING_1: /* End global resume */ 238 /* End Global Resume and wait for EOP to be sent */
193 uhci->state = UHCI_RESUMING_2; 239 outw(USBCMD_CF, uhci->io_addr + USBCMD);
194 outw(0, io_addr + USBCMD); 240 udelay(4);
195 /* Falls through */ 241 if (inw(uhci->io_addr + USBCMD) & USBCMD_FGR)
196 242 dev_warn(uhci_dev(uhci), "FGR not stopped yet!\n");
197 case UHCI_RESUMING_2: /* Wait for EOP to be sent */ 243 }
198 if (inw(io_addr + USBCMD) & USBCMD_FGR)
199 break;
200
201 /* Run for at least 1 second, and
202 * mark it configured with a 64-byte max packet */
203 uhci->state = UHCI_RUNNING_GRACE;
204 uhci->state_end = jiffies + HZ;
205 outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP,
206 io_addr + USBCMD);
207 break;
208 244
209 case UHCI_RUNNING_GRACE: /* Now allowed to suspend */ 245 uhci->rh_state = UHCI_RH_RUNNING;
210 uhci->state = UHCI_RUNNING; 246 uhci->is_stopped = 0;
211 break; 247 smp_wmb();
212 248
213 default: 249 /* Mark it configured and running with a 64-byte max packet.
214 break; 250 * All interrupts are enabled, even though RD won't do anything.
215 } 251 */
252 outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr + USBCMD);
253 outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
254 uhci->io_addr + USBINTR);
216} 255}
217 256
218static int start_hc(struct uhci_hcd *uhci) 257static int start_hc(struct uhci_hcd *uhci)
@@ -249,49 +288,40 @@ static int start_hc(struct uhci_hcd *uhci)
249 outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD); 288 outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
250 289
251 /* Run and mark it configured with a 64-byte max packet */ 290 /* Run and mark it configured with a 64-byte max packet */
252 uhci->state = UHCI_RUNNING_GRACE; 291 uhci->rh_state = UHCI_RH_RUNNING;
253 uhci->state_end = jiffies + HZ;
254 outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD); 292 outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
255 uhci->is_stopped = 0; 293 uhci->is_stopped = 0;
256 294
257 return 0; 295 return 0;
258} 296}
259 297
260static void hc_state_transitions(struct uhci_hcd *uhci) 298static void rh_state_transitions(struct uhci_hcd *uhci)
261{ 299{
262 switch (uhci->state) { 300 switch (uhci->rh_state) {
263 case UHCI_RUNNING: 301 case UHCI_RH_RUNNING:
264 302 /* are any devices attached? */
265 /* global suspend if nothing connected for 1 second */ 303 if (!any_ports_active(uhci)) {
266 if (!any_ports_active(uhci) && suspend_allowed(uhci)) { 304 uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
267 uhci->state = UHCI_SUSPENDING_GRACE; 305 uhci->auto_stop_time = jiffies + HZ;
268 uhci->state_end = jiffies + HZ; 306 }
269 } 307 break;
270 break; 308
271 309 case UHCI_RH_RUNNING_NODEVS:
272 case UHCI_SUSPENDING_GRACE: 310 /* auto-stop if nothing connected for 1 second */
273 if (any_ports_active(uhci)) 311 if (any_ports_active(uhci))
274 uhci->state = UHCI_RUNNING; 312 uhci->rh_state = UHCI_RH_RUNNING;
275 else if (time_after_eq(jiffies, uhci->state_end)) 313 else if (time_after_eq(jiffies, uhci->auto_stop_time))
276 suspend_hc(uhci); 314 suspend_hc(uhci, UHCI_RH_AUTO_STOPPED);
277 break; 315 break;
278 316
279 case UHCI_SUSPENDED: 317 case UHCI_RH_AUTO_STOPPED:
280 318 /* wakeup if requested by a device */
281 /* wakeup if requested by a device */ 319 if (uhci->resume_detect)
282 if (uhci->resume_detect) 320 wakeup_hc(uhci);
283 wakeup_hc(uhci); 321 break;
284 break; 322
285 323 default:
286 case UHCI_RESUMING_1: 324 break;
287 case UHCI_RESUMING_2:
288 case UHCI_RUNNING_GRACE:
289 if (time_after_eq(jiffies, uhci->state_end))
290 wakeup_hc(uhci);
291 break;
292
293 default:
294 break;
295 } 325 }
296} 326}
297 327
@@ -305,8 +335,8 @@ static void stall_callback(unsigned long _uhci)
305 check_fsbr(uhci); 335 check_fsbr(uhci);
306 336
307 /* Poll for and perform state transitions */ 337 /* Poll for and perform state transitions */
308 hc_state_transitions(uhci); 338 rh_state_transitions(uhci);
309 if (unlikely(uhci->suspended_ports && uhci->state != UHCI_SUSPENDED)) 339 if (unlikely(uhci->suspended_ports))
310 uhci_check_ports(uhci); 340 uhci_check_ports(uhci);
311 341
312 restart_timer(uhci); 342 restart_timer(uhci);
@@ -336,7 +366,8 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
336 if (status & USBSTS_HCPE) 366 if (status & USBSTS_HCPE)
337 dev_err(uhci_dev(uhci), "host controller process " 367 dev_err(uhci_dev(uhci), "host controller process "
338 "error, something bad happened!\n"); 368 "error, something bad happened!\n");
339 if ((status & USBSTS_HCH) && uhci->state > 0) { 369 if ((status & USBSTS_HCH) &&
370 uhci->rh_state >= UHCI_RH_RUNNING) {
340 dev_err(uhci_dev(uhci), "host controller halted, " 371 dev_err(uhci_dev(uhci), "host controller halted, "
341 "very bad!\n"); 372 "very bad!\n");
342 /* FIXME: Reset the controller, fix the offending TD */ 373 /* FIXME: Reset the controller, fix the offending TD */
@@ -683,17 +714,7 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
683 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 714 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
684 715
685 spin_lock_irq(&uhci->lock); 716 spin_lock_irq(&uhci->lock);
686 717 suspend_hc(uhci, UHCI_RH_SUSPENDED);
687 /* Don't try to suspend broken motherboards, reset instead */
688 if (suspend_allowed(uhci))
689 suspend_hc(uhci);
690 else {
691 spin_unlock_irq(&uhci->lock);
692 reset_hc(uhci);
693 spin_lock_irq(&uhci->lock);
694 uhci_scan_schedule(uhci, NULL);
695 }
696
697 spin_unlock_irq(&uhci->lock); 718 spin_unlock_irq(&uhci->lock);
698 return 0; 719 return 0;
699} 720}
@@ -701,13 +722,9 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
701static int uhci_resume(struct usb_hcd *hcd) 722static int uhci_resume(struct usb_hcd *hcd)
702{ 723{
703 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 724 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
704 int rc;
705
706 pci_set_master(to_pci_dev(uhci_dev(uhci)));
707 725
708 spin_lock_irq(&uhci->lock); 726 spin_lock_irq(&uhci->lock);
709 727 if (uhci->rh_state == UHCI_RH_SUSPENDED) {
710 if (uhci->state == UHCI_SUSPENDED) {
711 728
712 /* 729 /*
713 * Some systems don't maintain the UHCI register values 730 * Some systems don't maintain the UHCI register values
@@ -721,19 +738,13 @@ static int uhci_resume(struct usb_hcd *hcd)
721 outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); 738 outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
722 outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | 739 outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
723 USBINTR_SP, uhci->io_addr + USBINTR); 740 USBINTR_SP, uhci->io_addr + USBINTR);
724 uhci->resume_detect = 1;
725 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 741 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
726 USBLEGSUP_DEFAULT); 742 USBLEGSUP_DEFAULT);
727 } else { 743 wakeup_hc(uhci);
728 spin_unlock_irq(&uhci->lock);
729 reset_hc(uhci);
730 if ((rc = start_hc(uhci)) != 0)
731 return rc;
732 spin_lock_irq(&uhci->lock);
733 } 744 }
734 hcd->state = HC_STATE_RUNNING;
735
736 spin_unlock_irq(&uhci->lock); 745 spin_unlock_irq(&uhci->lock);
746
747 hcd->state = HC_STATE_RUNNING;
737 return 0; 748 return 0;
738} 749}
739#endif 750#endif
@@ -750,13 +761,15 @@ static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
750static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) 761static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
751{ 762{
752 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 763 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
753 int frame_number;
754 unsigned long flags; 764 unsigned long flags;
765 int is_stopped;
766 int frame_number;
755 767
756 /* Minimize latency by avoiding the spinlock */ 768 /* Minimize latency by avoiding the spinlock */
757 local_irq_save(flags); 769 local_irq_save(flags);
758 rmb(); 770 is_stopped = uhci->is_stopped;
759 frame_number = (uhci->is_stopped ? uhci->frame_number : 771 smp_rmb();
772 frame_number = (is_stopped ? uhci->frame_number :
760 inw(uhci->io_addr + USBFRNUM)); 773 inw(uhci->io_addr + USBFRNUM));
761 local_irq_restore(flags); 774 local_irq_restore(flags);
762 return frame_number; 775 return frame_number;
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 02255d69e1fe..4bac57c74ec2 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -314,26 +314,29 @@ static inline int __interval_to_skel(int interval)
314} 314}
315 315
316/* 316/*
317 * Device states for the host controller. 317 * States for the root hub.
318 * 318 *
319 * To prevent "bouncing" in the presence of electrical noise, 319 * To prevent "bouncing" in the presence of electrical noise,
320 * we insist on a 1-second "grace" period, before switching to 320 * when there are no devices attached we delay for 1 second in the
321 * the RUNNING or SUSPENDED states, during which the state is 321 * RUNNING_NODEVS state before switching to the AUTO_STOPPED state.
322 * not allowed to change. 322 *
323 * 323 * (Note that the AUTO_STOPPED state won't be necessary once the hub
324 * The resume process is divided into substates in order to avoid 324 * driver learns to autosuspend.)
325 * potentially length delays during the timer handler.
326 *
327 * States in which the host controller is halted must have values <= 0.
328 */ 325 */
329enum uhci_state { 326enum uhci_rh_state {
330 UHCI_RESET, 327 /* In the next 4 states the HC must be halted */
331 UHCI_RUNNING_GRACE, /* Before RUNNING */ 328 UHCI_RH_RESET,
332 UHCI_RUNNING, /* The normal state */ 329 UHCI_RH_SUSPENDED,
333 UHCI_SUSPENDING_GRACE, /* Before SUSPENDED */ 330 UHCI_RH_AUTO_STOPPED,
334 UHCI_SUSPENDED = -10, /* When no devices are attached */ 331 UHCI_RH_RESUMING,
335 UHCI_RESUMING_1, 332
336 UHCI_RESUMING_2 333 /* In the next state the HC changes from running to halted, so it
334 * can legally appear either way */
335 UHCI_RH_SUSPENDING,
336
337 /* In the next two states it's an error if the HC is halted */
338 UHCI_RH_RUNNING, /* The normal state */
339 UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */
337}; 340};
338 341
339/* 342/*
@@ -363,8 +366,9 @@ struct uhci_hcd {
363 int fsbr; /* Full-speed bandwidth reclamation */ 366 int fsbr; /* Full-speed bandwidth reclamation */
364 unsigned long fsbrtimeout; /* FSBR delay */ 367 unsigned long fsbrtimeout; /* FSBR delay */
365 368
366 enum uhci_state state; /* FIXME: needs a spinlock */ 369 enum uhci_rh_state rh_state;
367 unsigned long state_end; /* Time of next transition */ 370 unsigned long auto_stop_time; /* When to AUTO_STOP */
371
368 unsigned int frame_number; /* As of last check */ 372 unsigned int frame_number; /* As of last check */
369 unsigned int is_stopped; 373 unsigned int is_stopped;
370#define UHCI_IS_STOPPED 9999 /* Larger than a frame # */ 374#define UHCI_IS_STOPPED 9999 /* Larger than a frame # */
@@ -451,4 +455,11 @@ struct urb_priv {
451 * #2 urb->lock 455 * #2 urb->lock
452 */ 456 */
453 457
458
459/* Some special IDs */
460
461#define PCI_VENDOR_ID_GENESYS 0x17a0
462#define PCI_DEVICE_ID_GL880S_UHCI 0x8083
463#define PCI_DEVICE_ID_GL880S_EHCI 0x8084
464
454#endif 465#endif
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index ddb19cbf4b75..fc34fee2ab07 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -60,7 +60,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
60 test_bit(port, &uhci->port_c_suspend)) 60 test_bit(port, &uhci->port_c_suspend))
61 *buf |= (1 << (port + 1)); 61 *buf |= (1 << (port + 1));
62 } 62 }
63 if (*buf && uhci->state == UHCI_SUSPENDED) 63 if (*buf && uhci->is_stopped)
64 uhci->resume_detect = 1; 64 uhci->resume_detect = 1;
65 return !!*buf; 65 return !!*buf;
66} 66}