aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2005-04-09 17:29:00 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-27 17:43:43 -0400
commita8bed8b6be75bc5a46aa599ab360d5f1db291c8f (patch)
treeef6375ec4109d670f95ee0f8481543d10d5c4a5e
parentc8f4fe4358c5e0a79b4bd47b814d19f1d1d06f21 (diff)
[PATCH] USB UHCI: Add root-hub suspend/resume support
This patch implements (finally!) separate suspend and resume routines for the root hub and the controller in the UHCI driver. It also changes the sequence used to reset the controller during initial probing, so as to preserve the existing state during a Resume-From-Disk. (This new sequence is what should be used in the PCI Quirks code for early USB handoffs, incidentally.) Lastly it adds a notion of the controller being "inaccessible" while in a PCI low-power state, when normal I/O operations shouldn't be allowed. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/host/uhci-hcd.c288
-rw-r--r--drivers/usb/host/uhci-hcd.h10
-rw-r--r--drivers/usb/host/uhci-hub.c6
3 files changed, 202 insertions, 102 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 57b36dcea5d0..730ba3a621ae 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -109,28 +109,113 @@ 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
112/*
113 * Make sure the controller is completely inactive, unable to
114 * generate interrupts or do DMA.
115 */
112static void reset_hc(struct uhci_hcd *uhci) 116static void reset_hc(struct uhci_hcd *uhci)
113{ 117{
114 unsigned long io_addr = uhci->io_addr; 118 /* Turn off PIRQ enable and SMI enable. (This also turns off the
119 * BIOS's USB Legacy Support.) Turn off all the R/WC bits too.
120 */
121 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
122 USBLEGSUP_RWC);
115 123
116 /* Turn off PIRQ, SMI, and all interrupts. This also turns off 124 /* Reset the HC - this will force us to get a
117 * the BIOS's USB Legacy Support. 125 * new notification of any already connected
126 * ports due to the virtual disconnect that it
127 * implies.
118 */ 128 */
119 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); 129 outw(USBCMD_HCRESET, uhci->io_addr + USBCMD);
120 outw(0, uhci->io_addr + USBINTR); 130 mb();
131 udelay(5);
132 if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET)
133 dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n");
121 134
122 /* Global reset for 50ms */ 135 /* Just to be safe, disable interrupt requests and
123 outw(USBCMD_GRESET, io_addr + USBCMD); 136 * make sure the controller is stopped.
124 msleep(50); 137 */
125 outw(0, io_addr + USBCMD); 138 outw(0, uhci->io_addr + USBINTR);
139 outw(0, uhci->io_addr + USBCMD);
126 140
127 /* Another 10ms delay */
128 msleep(10);
129 uhci->resume_detect = 0; 141 uhci->resume_detect = 0;
130 uhci->is_stopped = UHCI_IS_STOPPED; 142 uhci->port_c_suspend = uhci->suspended_ports =
143 uhci->resuming_ports = 0;
131 uhci->rh_state = UHCI_RH_RESET; 144 uhci->rh_state = UHCI_RH_RESET;
145 uhci->is_stopped = UHCI_IS_STOPPED;
146 uhci_to_hcd(uhci)->state = HC_STATE_HALT;
132} 147}
133 148
149/*
150 * Initialize a controller that was newly discovered or has just been
151 * resumed. In either case we can't be sure of its previous state.
152 */
153static void check_and_reset_hc(struct uhci_hcd *uhci)
154{
155 u16 legsup;
156 unsigned int cmd, intr;
157
158 /*
159 * When restarting a suspended controller, we expect all the
160 * settings to be the same as we left them:
161 *
162 * PIRQ and SMI disabled, no R/WC bits set in USBLEGSUP;
163 * Controller is stopped and configured with EGSM set;
164 * No interrupts enabled except possibly Resume Detect.
165 *
166 * If any of these conditions are violated we do a complete reset.
167 */
168 pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup);
169 if (legsup & ~USBLEGSUP_RO) {
170 dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n",
171 __FUNCTION__, legsup);
172 goto reset_needed;
173 }
174
175 cmd = inw(uhci->io_addr + USBCMD);
176 if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) {
177 dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n",
178 __FUNCTION__, cmd);
179 goto reset_needed;
180 }
181
182 intr = inw(uhci->io_addr + USBINTR);
183 if (intr & (~USBINTR_RESUME)) {
184 dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n",
185 __FUNCTION__, intr);
186 goto reset_needed;
187 }
188 return;
189
190reset_needed:
191 dev_dbg(uhci_dev(uhci), "Performing full reset\n");
192 reset_hc(uhci);
193}
194
195/*
196 * Store the basic register settings needed by the controller.
197 */
198static void configure_hc(struct uhci_hcd *uhci)
199{
200 /* Set the frame length to the default: 1 ms exactly */
201 outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
202
203 /* Store the frame list base address */
204 outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
205
206 /* Set the current frame number */
207 outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
208
209 /* Mark controller as running before we enable interrupts */
210 uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
211 mb();
212
213 /* Enable PIRQ */
214 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
215 USBLEGSUP_DEFAULT);
216}
217
218
134static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci) 219static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
135{ 220{
136 int port; 221 int port;
@@ -163,7 +248,7 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci)
163 return 0; 248 return 0;
164} 249}
165 250
166static void suspend_hc(struct uhci_hcd *uhci, enum uhci_rh_state new_state) 251static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state)
167__releases(uhci->lock) 252__releases(uhci->lock)
168__acquires(uhci->lock) 253__acquires(uhci->lock)
169{ 254{
@@ -189,6 +274,7 @@ __acquires(uhci->lock)
189 0 : USBINTR_RESUME); 274 0 : USBINTR_RESUME);
190 outw(int_enable, uhci->io_addr + USBINTR); 275 outw(int_enable, uhci->io_addr + USBINTR);
191 outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); 276 outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD);
277 mb();
192 udelay(5); 278 udelay(5);
193 279
194 /* If we're auto-stopping then no devices have been attached 280 /* If we're auto-stopping then no devices have been attached
@@ -215,7 +301,22 @@ __acquires(uhci->lock)
215 uhci_scan_schedule(uhci, NULL); 301 uhci_scan_schedule(uhci, NULL);
216} 302}
217 303
218static void wakeup_hc(struct uhci_hcd *uhci) 304static void start_rh(struct uhci_hcd *uhci)
305{
306 uhci->rh_state = UHCI_RH_RUNNING;
307 uhci->is_stopped = 0;
308 smp_wmb();
309
310 /* Mark it configured and running with a 64-byte max packet.
311 * All interrupts are enabled, even though RESUME won't do anything.
312 */
313 outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr + USBCMD);
314 outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
315 uhci->io_addr + USBINTR);
316 mb();
317}
318
319static void wakeup_rh(struct uhci_hcd *uhci)
219__releases(uhci->lock) 320__releases(uhci->lock)
220__acquires(uhci->lock) 321__acquires(uhci->lock)
221{ 322{
@@ -237,62 +338,13 @@ __acquires(uhci->lock)
237 338
238 /* End Global Resume and wait for EOP to be sent */ 339 /* End Global Resume and wait for EOP to be sent */
239 outw(USBCMD_CF, uhci->io_addr + USBCMD); 340 outw(USBCMD_CF, uhci->io_addr + USBCMD);
341 mb();
240 udelay(4); 342 udelay(4);
241 if (inw(uhci->io_addr + USBCMD) & USBCMD_FGR) 343 if (inw(uhci->io_addr + USBCMD) & USBCMD_FGR)
242 dev_warn(uhci_dev(uhci), "FGR not stopped yet!\n"); 344 dev_warn(uhci_dev(uhci), "FGR not stopped yet!\n");
243 } 345 }
244 346
245 uhci->rh_state = UHCI_RH_RUNNING; 347 start_rh(uhci);
246 uhci->is_stopped = 0;
247 smp_wmb();
248
249 /* Mark it configured and running with a 64-byte max packet.
250 * All interrupts are enabled, even though RD won't do anything.
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);
255}
256
257static int start_hc(struct uhci_hcd *uhci)
258{
259 unsigned long io_addr = uhci->io_addr;
260 int timeout = 10;
261
262 /*
263 * Reset the HC - this will force us to get a
264 * new notification of any already connected
265 * ports due to the virtual disconnect that it
266 * implies.
267 */
268 outw(USBCMD_HCRESET, io_addr + USBCMD);
269 while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
270 if (--timeout < 0) {
271 dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n");
272 return -ETIMEDOUT;
273 }
274 msleep(1);
275 }
276
277 /* Mark controller as running before we enable interrupts */
278 uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
279
280 /* Turn on PIRQ and all interrupts */
281 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP,
282 USBLEGSUP_DEFAULT);
283 outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
284 io_addr + USBINTR);
285
286 /* Start at frame 0 */
287 outw(0, io_addr + USBFRNUM);
288 outl(uhci->fl->dma_handle, io_addr + USBFLBASEADD);
289
290 /* Run and mark it configured with a 64-byte max packet */
291 uhci->rh_state = UHCI_RH_RUNNING;
292 outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
293 uhci->is_stopped = 0;
294
295 return 0;
296} 348}
297 349
298static void rh_state_transitions(struct uhci_hcd *uhci) 350static void rh_state_transitions(struct uhci_hcd *uhci)
@@ -311,13 +363,13 @@ static void rh_state_transitions(struct uhci_hcd *uhci)
311 if (any_ports_active(uhci)) 363 if (any_ports_active(uhci))
312 uhci->rh_state = UHCI_RH_RUNNING; 364 uhci->rh_state = UHCI_RH_RUNNING;
313 else if (time_after_eq(jiffies, uhci->auto_stop_time)) 365 else if (time_after_eq(jiffies, uhci->auto_stop_time))
314 suspend_hc(uhci, UHCI_RH_AUTO_STOPPED); 366 suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
315 break; 367 break;
316 368
317 case UHCI_RH_AUTO_STOPPED: 369 case UHCI_RH_AUTO_STOPPED:
318 /* wakeup if requested by a device */ 370 /* wakeup if requested by a device */
319 if (uhci->resume_detect) 371 if (uhci->resume_detect)
320 wakeup_hc(uhci); 372 wakeup_rh(uhci);
321 break; 373 break;
322 374
323 default: 375 default:
@@ -336,7 +388,7 @@ static void stall_callback(unsigned long _uhci)
336 388
337 /* Poll for and perform state transitions */ 389 /* Poll for and perform state transitions */
338 rh_state_transitions(uhci); 390 rh_state_transitions(uhci);
339 if (unlikely(uhci->suspended_ports)) 391 if (uhci->suspended_ports && !uhci->hc_inaccessible)
340 uhci_check_ports(uhci); 392 uhci_check_ports(uhci);
341 393
342 restart_timer(uhci); 394 restart_timer(uhci);
@@ -346,7 +398,6 @@ static void stall_callback(unsigned long _uhci)
346static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) 398static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
347{ 399{
348 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 400 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
349 unsigned long io_addr = uhci->io_addr;
350 unsigned short status; 401 unsigned short status;
351 402
352 /* 403 /*
@@ -354,10 +405,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
354 * interrupt cause. Contrary to the UHCI specification, the 405 * interrupt cause. Contrary to the UHCI specification, the
355 * "HC Halted" status bit is persistent: it is RO, not R/WC. 406 * "HC Halted" status bit is persistent: it is RO, not R/WC.
356 */ 407 */
357 status = inw(io_addr + USBSTS); 408 status = inw(uhci->io_addr + USBSTS);
358 if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */ 409 if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */
359 return IRQ_NONE; 410 return IRQ_NONE;
360 outw(status, io_addr + USBSTS); /* Clear it */ 411 outw(status, uhci->io_addr + USBSTS); /* Clear it */
361 412
362 if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { 413 if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
363 if (status & USBSTS_HSE) 414 if (status & USBSTS_HSE)
@@ -440,10 +491,10 @@ static int uhci_reset(struct usb_hcd *hcd)
440 491
441 uhci->io_addr = (unsigned long) hcd->rsrc_start; 492 uhci->io_addr = (unsigned long) hcd->rsrc_start;
442 493
443 /* Kick BIOS off this hardware and reset, so we won't get 494 /* Kick BIOS off this hardware and reset if the controller
444 * interrupts from any previous setup. 495 * isn't already safely quiescent.
445 */ 496 */
446 reset_hc(uhci); 497 check_and_reset_hc(uhci);
447 return 0; 498 return 0;
448} 499}
449 500
@@ -634,11 +685,12 @@ static int uhci_start(struct usb_hcd *hcd)
634 685
635 /* 686 /*
636 * Some architectures require a full mb() to enforce completion of 687 * Some architectures require a full mb() to enforce completion of
637 * the memory writes above before the I/O transfers in start_hc(). 688 * the memory writes above before the I/O transfers in configure_hc().
638 */ 689 */
639 mb(); 690 mb();
640 if ((retval = start_hc(uhci)) != 0) 691
641 goto err_alloc_skelqh; 692 configure_hc(uhci);
693 start_rh(uhci);
642 694
643 restart_timer(uhci); 695 restart_timer(uhci);
644 696
@@ -656,9 +708,8 @@ static int uhci_start(struct usb_hcd *hcd)
656 * error exits: 708 * error exits:
657 */ 709 */
658err_start_root_hub: 710err_start_root_hub:
659 reset_hc(uhci);
660
661 del_timer_sync(&uhci->stall_timer); 711 del_timer_sync(&uhci->stall_timer);
712 reset_hc(uhci);
662 713
663err_alloc_skelqh: 714err_alloc_skelqh:
664 for (i = 0; i < UHCI_NUM_SKELQH; i++) 715 for (i = 0; i < UHCI_NUM_SKELQH; i++)
@@ -699,9 +750,9 @@ static void uhci_stop(struct usb_hcd *hcd)
699 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 750 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
700 751
701 del_timer_sync(&uhci->stall_timer); 752 del_timer_sync(&uhci->stall_timer);
702 reset_hc(uhci);
703 753
704 spin_lock_irq(&uhci->lock); 754 spin_lock_irq(&uhci->lock);
755 reset_hc(uhci);
705 uhci_scan_schedule(uhci, NULL); 756 uhci_scan_schedule(uhci, NULL);
706 spin_unlock_irq(&uhci->lock); 757 spin_unlock_irq(&uhci->lock);
707 758
@@ -709,12 +760,47 @@ static void uhci_stop(struct usb_hcd *hcd)
709} 760}
710 761
711#ifdef CONFIG_PM 762#ifdef CONFIG_PM
763static int uhci_rh_suspend(struct usb_hcd *hcd)
764{
765 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
766
767 spin_lock_irq(&uhci->lock);
768 suspend_rh(uhci, UHCI_RH_SUSPENDED);
769 spin_unlock_irq(&uhci->lock);
770 return 0;
771}
772
773static int uhci_rh_resume(struct usb_hcd *hcd)
774{
775 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
776
777 spin_lock_irq(&uhci->lock);
778 wakeup_rh(uhci);
779 spin_unlock_irq(&uhci->lock);
780 return 0;
781}
782
712static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) 783static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
713{ 784{
714 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 785 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
715 786
787 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
788
716 spin_lock_irq(&uhci->lock); 789 spin_lock_irq(&uhci->lock);
717 suspend_hc(uhci, UHCI_RH_SUSPENDED); 790
791#ifndef CONFIG_USB_SUSPEND
792 /* Otherwise this would never happen */
793 suspend_rh(uhci, UHCI_RH_SUSPENDED);
794#endif
795
796 /* All PCI host controllers are required to disable IRQ generation
797 * at the source, so we must turn off PIRQ.
798 */
799 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
800 uhci->hc_inaccessible = 1;
801
802 /* FIXME: Enable non-PME# remote wakeup? */
803
718 spin_unlock_irq(&uhci->lock); 804 spin_unlock_irq(&uhci->lock);
719 return 0; 805 return 0;
720} 806}
@@ -723,28 +809,28 @@ static int uhci_resume(struct usb_hcd *hcd)
723{ 809{
724 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 810 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
725 811
812 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
813
726 spin_lock_irq(&uhci->lock); 814 spin_lock_irq(&uhci->lock);
727 if (uhci->rh_state == UHCI_RH_SUSPENDED) {
728 815
729 /* 816 /* FIXME: Disable non-PME# remote wakeup? */
730 * Some systems don't maintain the UHCI register values 817
731 * during a PM suspend/resume cycle, so reinitialize 818 uhci->hc_inaccessible = 0;
732 * the Frame Number, Framelist Base Address, Interrupt 819
733 * Enable, and Legacy Support registers. 820 /* The BIOS may have changed the controller settings during a
734 */ 821 * system wakeup. Check it and reconfigure to avoid problems.
735 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 822 */
736 0); 823 check_and_reset_hc(uhci);
737 outw(uhci->frame_number, uhci->io_addr + USBFRNUM); 824 configure_hc(uhci);
738 outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); 825
739 outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | 826#ifndef CONFIG_USB_SUSPEND
740 USBINTR_SP, uhci->io_addr + USBINTR); 827 /* Otherwise this would never happen */
741 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 828 wakeup_rh(uhci);
742 USBLEGSUP_DEFAULT); 829#endif
743 wakeup_hc(uhci); 830 if (uhci->rh_state == UHCI_RH_RESET)
744 } 831 suspend_rh(uhci, UHCI_RH_SUSPENDED);
745 spin_unlock_irq(&uhci->lock);
746 832
747 hcd->state = HC_STATE_RUNNING; 833 spin_unlock_irq(&uhci->lock);
748 return 0; 834 return 0;
749} 835}
750#endif 836#endif
@@ -792,6 +878,8 @@ static const struct hc_driver uhci_driver = {
792#ifdef CONFIG_PM 878#ifdef CONFIG_PM
793 .suspend = uhci_suspend, 879 .suspend = uhci_suspend,
794 .resume = uhci_resume, 880 .resume = uhci_resume,
881 .hub_suspend = uhci_rh_suspend,
882 .hub_resume = uhci_rh_resume,
795#endif 883#endif
796 .stop = uhci_stop, 884 .stop = uhci_stop,
797 885
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 4bac57c74ec2..827df5e06800 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -41,6 +41,7 @@
41#define USBFRNUM 6 41#define USBFRNUM 6
42#define USBFLBASEADD 8 42#define USBFLBASEADD 8
43#define USBSOF 12 43#define USBSOF 12
44#define USBSOF_DEFAULT 64 /* Frame length is exactly 1 ms */
44 45
45/* USB port status and control registers */ 46/* USB port status and control registers */
46#define USBPORTSC1 16 47#define USBPORTSC1 16
@@ -66,6 +67,8 @@
66/* Legacy support register */ 67/* Legacy support register */
67#define USBLEGSUP 0xc0 68#define USBLEGSUP 0xc0
68#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ 69#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
70#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
71#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
69 72
70#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */ 73#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */
71 74
@@ -325,8 +328,9 @@ static inline int __interval_to_skel(int interval)
325 */ 328 */
326enum uhci_rh_state { 329enum uhci_rh_state {
327 /* In the next 4 states the HC must be halted */ 330 /* In the next 4 states the HC must be halted */
328 UHCI_RH_RESET, 331 UHCI_RH_RESET, /* These two must come first */
329 UHCI_RH_SUSPENDED, 332 UHCI_RH_SUSPENDED,
333
330 UHCI_RH_AUTO_STOPPED, 334 UHCI_RH_AUTO_STOPPED,
331 UHCI_RH_RESUMING, 335 UHCI_RH_RESUMING,
332 336
@@ -334,7 +338,8 @@ enum uhci_rh_state {
334 * can legally appear either way */ 338 * can legally appear either way */
335 UHCI_RH_SUSPENDING, 339 UHCI_RH_SUSPENDING,
336 340
337 /* In the next two states it's an error if the HC is halted */ 341 /* In the next two states it's an error if the HC is halted.
342 * These two must come last */
338 UHCI_RH_RUNNING, /* The normal state */ 343 UHCI_RH_RUNNING, /* The normal state */
339 UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */ 344 UHCI_RH_RUNNING_NODEVS, /* Running with no devices attached */
340}; 345};
@@ -376,6 +381,7 @@ struct uhci_hcd {
376 unsigned int scan_in_progress:1; /* Schedule scan is running */ 381 unsigned int scan_in_progress:1; /* Schedule scan is running */
377 unsigned int need_rescan:1; /* Redo the schedule scan */ 382 unsigned int need_rescan:1; /* Redo the schedule scan */
378 unsigned int resume_detect:1; /* Need a Global Resume */ 383 unsigned int resume_detect:1; /* Need a Global Resume */
384 unsigned int hc_inaccessible:1; /* HC is suspended or dead */
379 385
380 /* Support for port suspend/resume/reset */ 386 /* Support for port suspend/resume/reset */
381 unsigned long port_c_suspend; /* Bit-arrays of ports */ 387 unsigned long port_c_suspend; /* Bit-arrays of ports */
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index fc34fee2ab07..13652de52203 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -54,6 +54,9 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
54 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 54 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
55 int port; 55 int port;
56 56
57 if (uhci->hc_inaccessible)
58 return 0;
59
57 *buf = 0; 60 *buf = 0;
58 for (port = 0; port < uhci->rh_numports; ++port) { 61 for (port = 0; port < uhci->rh_numports; ++port) {
59 if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) || 62 if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
@@ -150,6 +153,9 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
150 u16 wPortChange, wPortStatus; 153 u16 wPortChange, wPortStatus;
151 unsigned long flags; 154 unsigned long flags;
152 155
156 if (uhci->hc_inaccessible)
157 return -ETIMEDOUT;
158
153 spin_lock_irqsave(&uhci->lock, flags); 159 spin_lock_irqsave(&uhci->lock, flags);
154 switch (typeReq) { 160 switch (typeReq) {
155 161