aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/ohci-au1xxx.c5
-rw-r--r--drivers/usb/host/ohci-dbg.c18
-rw-r--r--drivers/usb/host/ohci-ep93xx.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c26
-rw-r--r--drivers/usb/host/ohci-hub.c7
-rw-r--r--drivers/usb/host/ohci-omap.c1
-rw-r--r--drivers/usb/host/ohci-pci.c5
-rw-r--r--drivers/usb/host/ohci-pxa27x.c2
-rw-r--r--drivers/usb/host/ohci-q.c8
-rw-r--r--drivers/usb/host/ohci-sh.c1
-rw-r--r--drivers/usb/host/ohci-sm501.c1
-rw-r--r--drivers/usb/host/ohci-spear.c1
-rw-r--r--drivers/usb/host/ohci-tmio.c3
-rw-r--r--drivers/usb/host/ohci.h14
14 files changed, 45 insertions, 49 deletions
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index 9b66df8278f3..40d886adff53 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -173,12 +173,9 @@ static int ohci_hcd_au1xxx_drv_suspend(struct device *dev)
173 * mark HW unaccessible, bail out if RH has been resumed. Use 173 * mark HW unaccessible, bail out if RH has been resumed. Use
174 * the spinlock to properly synchronize with possible pending 174 * the spinlock to properly synchronize with possible pending
175 * RH suspend or resume activity. 175 * RH suspend or resume activity.
176 *
177 * This is still racy as hcd->state is manipulated outside of
178 * any locks =P But that will be a different fix.
179 */ 176 */
180 spin_lock_irqsave(&ohci->lock, flags); 177 spin_lock_irqsave(&ohci->lock, flags);
181 if (hcd->state != HC_STATE_SUSPENDED) { 178 if (ohci->rh_state != OHCI_RH_SUSPENDED) {
182 rc = -EINVAL; 179 rc = -EINVAL;
183 goto bail; 180 goto bail;
184 } 181 }
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index d7d34492934a..5179fcd73d8a 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -127,6 +127,19 @@ static char *hcfs2string (int state)
127 return "?"; 127 return "?";
128} 128}
129 129
130static const char *rh_state_string(struct ohci_hcd *ohci)
131{
132 switch (ohci->rh_state) {
133 case OHCI_RH_HALTED:
134 return "halted";
135 case OHCI_RH_SUSPENDED:
136 return "suspended";
137 case OHCI_RH_RUNNING:
138 return "running";
139 }
140 return "?";
141}
142
130// dump control and status registers 143// dump control and status registers
131static void 144static void
132ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size) 145ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
@@ -136,9 +149,10 @@ ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
136 149
137 temp = ohci_readl (controller, &regs->revision) & 0xff; 150 temp = ohci_readl (controller, &regs->revision) & 0xff;
138 ohci_dbg_sw (controller, next, size, 151 ohci_dbg_sw (controller, next, size,
139 "OHCI %d.%d, %s legacy support registers\n", 152 "OHCI %d.%d, %s legacy support registers, rh state %s\n",
140 0x03 & (temp >> 4), (temp & 0x0f), 153 0x03 & (temp >> 4), (temp & 0x0f),
141 (temp & 0x0100) ? "with" : "NO"); 154 (temp & 0x0100) ? "with" : "NO",
155 rh_state_string(controller));
142 156
143 temp = ohci_readl (controller, &regs->control); 157 temp = ohci_readl (controller, &regs->control);
144 ohci_dbg_sw (controller, next, size, 158 ohci_dbg_sw (controller, next, size,
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index dc45d489d00e..3d63574d2c7e 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -179,8 +179,6 @@ static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_
179 ohci->next_statechange = jiffies; 179 ohci->next_statechange = jiffies;
180 180
181 ep93xx_stop_hc(&pdev->dev); 181 ep93xx_stop_hc(&pdev->dev);
182 hcd->state = HC_STATE_SUSPENDED;
183
184 return 0; 182 return 0;
185} 183}
186 184
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 34efd479e068..03c4631dc27a 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -209,7 +209,7 @@ static int ohci_urb_enqueue (
209 retval = -ENODEV; 209 retval = -ENODEV;
210 goto fail; 210 goto fail;
211 } 211 }
212 if (!HC_IS_RUNNING(hcd->state)) { 212 if (ohci->rh_state != OHCI_RH_RUNNING) {
213 retval = -ENODEV; 213 retval = -ENODEV;
214 goto fail; 214 goto fail;
215 } 215 }
@@ -274,7 +274,7 @@ static int ohci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
274 rc = usb_hcd_check_unlink_urb(hcd, urb, status); 274 rc = usb_hcd_check_unlink_urb(hcd, urb, status);
275 if (rc) { 275 if (rc) {
276 ; /* Do nothing */ 276 ; /* Do nothing */
277 } else if (HC_IS_RUNNING(hcd->state)) { 277 } else if (ohci->rh_state == OHCI_RH_RUNNING) {
278 urb_priv_t *urb_priv; 278 urb_priv_t *urb_priv;
279 279
280 /* Unless an IRQ completed the unlink while it was being 280 /* Unless an IRQ completed the unlink while it was being
@@ -321,7 +321,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
321rescan: 321rescan:
322 spin_lock_irqsave (&ohci->lock, flags); 322 spin_lock_irqsave (&ohci->lock, flags);
323 323
324 if (!HC_IS_RUNNING (hcd->state)) { 324 if (ohci->rh_state != OHCI_RH_RUNNING) {
325sanitize: 325sanitize:
326 ed->state = ED_IDLE; 326 ed->state = ED_IDLE;
327 if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT) 327 if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT)
@@ -377,6 +377,7 @@ static void ohci_usb_reset (struct ohci_hcd *ohci)
377 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); 377 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
378 ohci->hc_control &= OHCI_CTRL_RWC; 378 ohci->hc_control &= OHCI_CTRL_RWC;
379 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 379 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
380 ohci->rh_state = OHCI_RH_HALTED;
380} 381}
381 382
382/* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and 383/* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and
@@ -503,7 +504,7 @@ static int ohci_init (struct ohci_hcd *ohci)
503 if (distrust_firmware) 504 if (distrust_firmware)
504 ohci->flags |= OHCI_QUIRK_HUB_POWER; 505 ohci->flags |= OHCI_QUIRK_HUB_POWER;
505 506
506 disable (ohci); 507 ohci->rh_state = OHCI_RH_HALTED;
507 ohci->regs = hcd->regs; 508 ohci->regs = hcd->regs;
508 509
509 /* REVISIT this BIOS handshake is now moved into PCI "quirks", and 510 /* REVISIT this BIOS handshake is now moved into PCI "quirks", and
@@ -578,7 +579,7 @@ static int ohci_run (struct ohci_hcd *ohci)
578 int first = ohci->fminterval == 0; 579 int first = ohci->fminterval == 0;
579 struct usb_hcd *hcd = ohci_to_hcd(ohci); 580 struct usb_hcd *hcd = ohci_to_hcd(ohci);
580 581
581 disable (ohci); 582 ohci->rh_state = OHCI_RH_HALTED;
582 583
583 /* boot firmware should have set this up (5.1.1.3.1) */ 584 /* boot firmware should have set this up (5.1.1.3.1) */
584 if (first) { 585 if (first) {
@@ -691,7 +692,7 @@ retry:
691 ohci->hc_control &= OHCI_CTRL_RWC; 692 ohci->hc_control &= OHCI_CTRL_RWC;
692 ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; 693 ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
693 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 694 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
694 hcd->state = HC_STATE_RUNNING; 695 ohci->rh_state = OHCI_RH_RUNNING;
695 696
696 /* wake on ConnectStatusChange, matching external hubs */ 697 /* wake on ConnectStatusChange, matching external hubs */
697 ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status); 698 ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status);
@@ -728,7 +729,6 @@ retry:
728 729
729 // POTPGT delay is bits 24-31, in 2 ms units. 730 // POTPGT delay is bits 24-31, in 2 ms units.
730 mdelay ((val >> 23) & 0x1fe); 731 mdelay ((val >> 23) & 0x1fe);
731 hcd->state = HC_STATE_RUNNING;
732 732
733 if (quirk_zfmicro(ohci)) { 733 if (quirk_zfmicro(ohci)) {
734 /* Create timer to watch for bad queue state on ZF Micro */ 734 /* Create timer to watch for bad queue state on ZF Micro */
@@ -764,7 +764,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
764 * of dead, unclocked, or unplugged (CardBus...) devices 764 * of dead, unclocked, or unplugged (CardBus...) devices
765 */ 765 */
766 if (ints == ~(u32)0) { 766 if (ints == ~(u32)0) {
767 disable (ohci); 767 ohci->rh_state = OHCI_RH_HALTED;
768 ohci_dbg (ohci, "device removed!\n"); 768 ohci_dbg (ohci, "device removed!\n");
769 usb_hc_died(hcd); 769 usb_hc_died(hcd);
770 return IRQ_HANDLED; 770 return IRQ_HANDLED;
@@ -774,7 +774,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
774 ints &= ohci_readl(ohci, &regs->intrenable); 774 ints &= ohci_readl(ohci, &regs->intrenable);
775 775
776 /* interrupt for some other device? */ 776 /* interrupt for some other device? */
777 if (ints == 0 || unlikely(hcd->state == HC_STATE_HALT)) 777 if (ints == 0 || unlikely(ohci->rh_state == OHCI_RH_HALTED))
778 return IRQ_NOTMINE; 778 return IRQ_NOTMINE;
779 779
780 if (ints & OHCI_INTR_UE) { 780 if (ints & OHCI_INTR_UE) {
@@ -789,8 +789,8 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
789 789
790 schedule_work (&ohci->nec_work); 790 schedule_work (&ohci->nec_work);
791 } else { 791 } else {
792 disable (ohci);
793 ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n"); 792 ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
793 ohci->rh_state = OHCI_RH_HALTED;
794 usb_hc_died(hcd); 794 usb_hc_died(hcd);
795 } 795 }
796 796
@@ -874,11 +874,11 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
874 if ((ints & OHCI_INTR_SF) != 0 874 if ((ints & OHCI_INTR_SF) != 0
875 && !ohci->ed_rm_list 875 && !ohci->ed_rm_list
876 && !ohci->ed_to_check 876 && !ohci->ed_to_check
877 && HC_IS_RUNNING(hcd->state)) 877 && ohci->rh_state == OHCI_RH_RUNNING)
878 ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable); 878 ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
879 spin_unlock (&ohci->lock); 879 spin_unlock (&ohci->lock);
880 880
881 if (HC_IS_RUNNING(hcd->state)) { 881 if (ohci->rh_state == OHCI_RH_RUNNING) {
882 ohci_writel (ohci, ints, &regs->intrstatus); 882 ohci_writel (ohci, ints, &regs->intrstatus);
883 ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable); 883 ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
884 // flush those writes 884 // flush those writes
@@ -932,7 +932,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
932 struct urb_priv *priv; 932 struct urb_priv *priv;
933 933
934 spin_lock_irq(&ohci->lock); 934 spin_lock_irq(&ohci->lock);
935 disable (ohci); 935 ohci->rh_state = OHCI_RH_HALTED;
936 936
937 /* Recycle any "live" eds/tds (and urbs). */ 937 /* Recycle any "live" eds/tds (and urbs). */
938 if (!list_empty (&ohci->pending)) 938 if (!list_empty (&ohci->pending))
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 2f00040fc408..836772dfabd3 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -111,6 +111,7 @@ __acquires(ohci->lock)
111 if (!autostop) { 111 if (!autostop) {
112 ohci->next_statechange = jiffies + msecs_to_jiffies (5); 112 ohci->next_statechange = jiffies + msecs_to_jiffies (5);
113 ohci->autostop = 0; 113 ohci->autostop = 0;
114 ohci->rh_state = OHCI_RH_SUSPENDED;
114 } 115 }
115 116
116done: 117done:
@@ -140,7 +141,7 @@ __acquires(ohci->lock)
140 141
141 if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { 142 if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
142 /* this can happen after resuming a swsusp snapshot */ 143 /* this can happen after resuming a swsusp snapshot */
143 if (hcd->state == HC_STATE_RESUMING) { 144 if (ohci->rh_state != OHCI_RH_RUNNING) {
144 ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", 145 ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
145 ohci->hc_control); 146 ohci->hc_control);
146 status = -EBUSY; 147 status = -EBUSY;
@@ -274,6 +275,7 @@ skip_resume:
274 (void) ohci_readl (ohci, &ohci->regs->control); 275 (void) ohci_readl (ohci, &ohci->regs->control);
275 } 276 }
276 277
278 ohci->rh_state = OHCI_RH_RUNNING;
277 return 0; 279 return 0;
278} 280}
279 281
@@ -336,11 +338,8 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd)
336 /* If needed, reinitialize and suspend the root hub */ 338 /* If needed, reinitialize and suspend the root hub */
337 if (need_reinit) { 339 if (need_reinit) {
338 spin_lock_irq(&ohci->lock); 340 spin_lock_irq(&ohci->lock);
339 hcd->state = HC_STATE_RESUMING;
340 ohci_rh_resume(ohci); 341 ohci_rh_resume(ohci);
341 hcd->state = HC_STATE_QUIESCING;
342 ohci_rh_suspend(ohci, 0); 342 ohci_rh_suspend(ohci, 0);
343 hcd->state = HC_STATE_SUSPENDED;
344 spin_unlock_irq(&ohci->lock); 343 spin_unlock_irq(&ohci->lock);
345 } 344 }
346 345
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index e4b8782cc6e2..db3968656d21 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -516,7 +516,6 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
516 ohci->next_statechange = jiffies; 516 ohci->next_statechange = jiffies;
517 517
518 omap_ohci_clock_power(0); 518 omap_ohci_clock_power(0);
519 ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
520 return 0; 519 return 0;
521} 520}
522 521
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index ad8166c681e2..847187df50a1 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -334,12 +334,9 @@ static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
334 * mark HW unaccessible, bail out if RH has been resumed. Use 334 * mark HW unaccessible, bail out if RH has been resumed. Use
335 * the spinlock to properly synchronize with possible pending 335 * the spinlock to properly synchronize with possible pending
336 * RH suspend or resume activity. 336 * RH suspend or resume activity.
337 *
338 * This is still racy as hcd->state is manipulated outside of
339 * any locks =P But that will be a different fix.
340 */ 337 */
341 spin_lock_irqsave (&ohci->lock, flags); 338 spin_lock_irqsave (&ohci->lock, flags);
342 if (hcd->state != HC_STATE_SUSPENDED) { 339 if (ohci->rh_state != OHCI_RH_SUSPENDED) {
343 rc = -EINVAL; 340 rc = -EINVAL;
344 goto bail; 341 goto bail;
345 } 342 }
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 29dfefe1c726..6313e4439f37 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -502,8 +502,6 @@ static int ohci_hcd_pxa27x_drv_suspend(struct device *dev)
502 ohci->ohci.next_statechange = jiffies; 502 ohci->ohci.next_statechange = jiffies;
503 503
504 pxa27x_stop_hc(ohci, dev); 504 pxa27x_stop_hc(ohci, dev);
505 hcd->state = HC_STATE_SUSPENDED;
506
507 return 0; 505 return 0;
508} 506}
509 507
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 15dc51ded61a..c5a1ea9145fa 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -912,7 +912,7 @@ rescan_all:
912 /* only take off EDs that the HC isn't using, accounting for 912 /* only take off EDs that the HC isn't using, accounting for
913 * frame counter wraps and EDs with partially retired TDs 913 * frame counter wraps and EDs with partially retired TDs
914 */ 914 */
915 if (likely (HC_IS_RUNNING(ohci_to_hcd(ohci)->state))) { 915 if (likely(ohci->rh_state == OHCI_RH_RUNNING)) {
916 if (tick_before (tick, ed->tick)) { 916 if (tick_before (tick, ed->tick)) {
917skip_ed: 917skip_ed:
918 last = &ed->ed_next; 918 last = &ed->ed_next;
@@ -1012,7 +1012,7 @@ rescan_this:
1012 1012
1013 /* but if there's work queued, reschedule */ 1013 /* but if there's work queued, reschedule */
1014 if (!list_empty (&ed->td_list)) { 1014 if (!list_empty (&ed->td_list)) {
1015 if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state)) 1015 if (ohci->rh_state == OHCI_RH_RUNNING)
1016 ed_schedule (ohci, ed); 1016 ed_schedule (ohci, ed);
1017 } 1017 }
1018 1018
@@ -1021,9 +1021,7 @@ rescan_this:
1021 } 1021 }
1022 1022
1023 /* maybe reenable control and bulk lists */ 1023 /* maybe reenable control and bulk lists */
1024 if (HC_IS_RUNNING(ohci_to_hcd(ohci)->state) 1024 if (ohci->rh_state == OHCI_RH_RUNNING && !ohci->ed_rm_list) {
1025 && ohci_to_hcd(ohci)->state != HC_STATE_QUIESCING
1026 && !ohci->ed_rm_list) {
1027 u32 command = 0, control = 0; 1025 u32 command = 0, control = 0;
1028 1026
1029 if (ohci->ed_controltail) { 1027 if (ohci->ed_controltail) {
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
index afc4eb6bb9d0..84686d90805b 100644
--- a/drivers/usb/host/ohci-sh.c
+++ b/drivers/usb/host/ohci-sh.c
@@ -29,7 +29,6 @@ static int ohci_sh_start(struct usb_hcd *hcd)
29 ohci_hcd_init(ohci); 29 ohci_hcd_init(ohci);
30 ohci_init(ohci); 30 ohci_init(ohci);
31 ohci_run(ohci); 31 ohci_run(ohci);
32 hcd->state = HC_STATE_RUNNING;
33 return 0; 32 return 0;
34} 33}
35 34
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index 968cea2b6d4e..5596ac2ba1ca 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -224,7 +224,6 @@ static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
224 ohci->next_statechange = jiffies; 224 ohci->next_statechange = jiffies;
225 225
226 sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0); 226 sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
227 ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
228 return 0; 227 return 0;
229} 228}
230 229
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index 69874654f3b5..95c16489e883 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -203,7 +203,6 @@ static int spear_ohci_hcd_drv_suspend(struct platform_device *dev,
203 ohci->next_statechange = jiffies; 203 ohci->next_statechange = jiffies;
204 204
205 spear_stop_ohci(ohci_p); 205 spear_stop_ohci(ohci_p);
206 ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
207 return 0; 206 return 0;
208} 207}
209 208
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
index 06331d931171..120bfe6ede38 100644
--- a/drivers/usb/host/ohci-tmio.c
+++ b/drivers/usb/host/ohci-tmio.c
@@ -318,9 +318,6 @@ static int ohci_hcd_tmio_drv_suspend(struct platform_device *dev, pm_message_t s
318 if (ret) 318 if (ret)
319 return ret; 319 return ret;
320 } 320 }
321
322 hcd->state = HC_STATE_SUSPENDED;
323
324 return 0; 321 return 0;
325} 322}
326 323
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 35e5fd640ce7..3a978a2130cb 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -344,6 +344,12 @@ typedef struct urb_priv {
344 * a subset of what the full implementation needs. (Linus) 344 * a subset of what the full implementation needs. (Linus)
345 */ 345 */
346 346
347enum ohci_rh_state {
348 OHCI_RH_HALTED,
349 OHCI_RH_SUSPENDED,
350 OHCI_RH_RUNNING
351};
352
347struct ohci_hcd { 353struct ohci_hcd {
348 spinlock_t lock; 354 spinlock_t lock;
349 355
@@ -384,6 +390,7 @@ struct ohci_hcd {
384 /* 390 /*
385 * driver state 391 * driver state
386 */ 392 */
393 enum ohci_rh_state rh_state;
387 int num_ports; 394 int num_ports;
388 int load [NUM_INTS]; 395 int load [NUM_INTS];
389 u32 hc_control; /* copy of hc control reg */ 396 u32 hc_control; /* copy of hc control reg */
@@ -680,11 +687,6 @@ static inline u16 ohci_hwPSW(const struct ohci_hcd *ohci,
680 687
681/*-------------------------------------------------------------------------*/ 688/*-------------------------------------------------------------------------*/
682 689
683static inline void disable (struct ohci_hcd *ohci)
684{
685 ohci_to_hcd(ohci)->state = HC_STATE_HALT;
686}
687
688#define FI 0x2edf /* 12000 bits per frame (-1) */ 690#define FI 0x2edf /* 12000 bits per frame (-1) */
689#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7)) 691#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
690#define FIT (1 << 31) 692#define FIT (1 << 31)
@@ -708,7 +710,7 @@ static inline void periodic_reinit (struct ohci_hcd *ohci)
708#define read_roothub(hc, register, mask) ({ \ 710#define read_roothub(hc, register, mask) ({ \
709 u32 temp = ohci_readl (hc, &hc->regs->roothub.register); \ 711 u32 temp = ohci_readl (hc, &hc->regs->roothub.register); \
710 if (temp == -1) \ 712 if (temp == -1) \
711 disable (hc); \ 713 hc->rh_state = OHCI_RH_HALTED; \
712 else if (hc->flags & OHCI_QUIRK_AMD756) \ 714 else if (hc->flags & OHCI_QUIRK_AMD756) \
713 while (temp & mask) \ 715 while (temp & mask) \
714 temp = ohci_readl (hc, &hc->regs->roothub.register); \ 716 temp = ohci_readl (hc, &hc->regs->roothub.register); \