aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-hub.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2005-12-06 17:31:30 -0500
committerLen Brown <len.brown@intel.com>2005-12-06 17:31:30 -0500
commit3d5271f9883cba7b54762bc4fe027d4172f06db7 (patch)
treeab8a881a14478598a0c8bda0d26c62cdccfffd6d /drivers/usb/host/ohci-hub.c
parent378b2556f4e09fa6f87ff0cb5c4395ff28257d02 (diff)
parent9115a6c787596e687df03010d97fccc5e0762506 (diff)
Pull release into acpica branch
Diffstat (limited to 'drivers/usb/host/ohci-hub.c')
-rw-r--r--drivers/usb/host/ohci-hub.c76
1 files changed, 37 insertions, 39 deletions
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index ce7b28da7a15..72e3b12a1926 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -36,7 +36,7 @@
36 36
37/*-------------------------------------------------------------------------*/ 37/*-------------------------------------------------------------------------*/
38 38
39#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM) 39#ifdef CONFIG_PM
40 40
41#define OHCI_SCHED_ENABLES \ 41#define OHCI_SCHED_ENABLES \
42 (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) 42 (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE)
@@ -45,7 +45,7 @@ static void dl_done_list (struct ohci_hcd *, struct pt_regs *);
45static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *); 45static void finish_unlinks (struct ohci_hcd *, u16 , struct pt_regs *);
46static int ohci_restart (struct ohci_hcd *ohci); 46static int ohci_restart (struct ohci_hcd *ohci);
47 47
48static int ohci_hub_suspend (struct usb_hcd *hcd) 48static int ohci_bus_suspend (struct usb_hcd *hcd)
49{ 49{
50 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 50 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
51 int status = 0; 51 int status = 0;
@@ -53,6 +53,11 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
53 53
54 spin_lock_irqsave (&ohci->lock, flags); 54 spin_lock_irqsave (&ohci->lock, flags);
55 55
56 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
57 spin_unlock_irqrestore (&ohci->lock, flags);
58 return -ESHUTDOWN;
59 }
60
56 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); 61 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
57 switch (ohci->hc_control & OHCI_CTRL_HCFS) { 62 switch (ohci->hc_control & OHCI_CTRL_HCFS) {
58 case OHCI_USB_RESUME: 63 case OHCI_USB_RESUME:
@@ -73,7 +78,6 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
73 ohci_dbg (ohci, "suspend root hub\n"); 78 ohci_dbg (ohci, "suspend root hub\n");
74 79
75 /* First stop any processing */ 80 /* First stop any processing */
76 hcd->state = HC_STATE_QUIESCING;
77 if (ohci->hc_control & OHCI_SCHED_ENABLES) { 81 if (ohci->hc_control & OHCI_SCHED_ENABLES) {
78 int limit; 82 int limit;
79 83
@@ -108,7 +112,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
108 else 112 else
109 ohci->hc_control &= ~OHCI_CTRL_RWE; 113 ohci->hc_control &= ~OHCI_CTRL_RWE;
110 114
111 /* Suspend hub */ 115 /* Suspend hub ... this is the "global (to this bus) suspend" mode,
116 * which doesn't imply ports will first be individually suspended.
117 */
112 ohci->hc_control &= ~OHCI_CTRL_HCFS; 118 ohci->hc_control &= ~OHCI_CTRL_HCFS;
113 ohci->hc_control |= OHCI_USB_SUSPEND; 119 ohci->hc_control |= OHCI_USB_SUSPEND;
114 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); 120 ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
@@ -118,8 +124,9 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
118 ohci->next_statechange = jiffies + msecs_to_jiffies (5); 124 ohci->next_statechange = jiffies + msecs_to_jiffies (5);
119 125
120done: 126done:
127 /* external suspend vs self autosuspend ... same effect */
121 if (status == 0) 128 if (status == 0)
122 hcd->state = HC_STATE_SUSPENDED; 129 usb_hcd_suspend_root_hub(hcd);
123 spin_unlock_irqrestore (&ohci->lock, flags); 130 spin_unlock_irqrestore (&ohci->lock, flags);
124 return status; 131 return status;
125} 132}
@@ -133,20 +140,28 @@ static inline struct ed *find_head (struct ed *ed)
133} 140}
134 141
135/* caller has locked the root hub */ 142/* caller has locked the root hub */
136static int ohci_hub_resume (struct usb_hcd *hcd) 143static int ohci_bus_resume (struct usb_hcd *hcd)
137{ 144{
138 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 145 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
139 u32 temp, enables; 146 u32 temp, enables;
140 int status = -EINPROGRESS; 147 int status = -EINPROGRESS;
148 unsigned long flags;
141 149
142 if (time_before (jiffies, ohci->next_statechange)) 150 if (time_before (jiffies, ohci->next_statechange))
143 msleep(5); 151 msleep(5);
144 152
145 spin_lock_irq (&ohci->lock); 153 spin_lock_irqsave (&ohci->lock, flags);
154
155 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) {
156 spin_unlock_irqrestore (&ohci->lock, flags);
157 return -ESHUTDOWN;
158 }
159
160
146 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); 161 ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
147 162
148 if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { 163 if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
149 /* this can happen after suspend-to-disk */ 164 /* this can happen after resuming a swsusp snapshot */
150 if (hcd->state == HC_STATE_RESUMING) { 165 if (hcd->state == HC_STATE_RESUMING) {
151 ohci_dbg (ohci, "BIOS/SMM active, control %03x\n", 166 ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
152 ohci->hc_control); 167 ohci->hc_control);
@@ -169,14 +184,15 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
169 ohci_info (ohci, "wakeup\n"); 184 ohci_info (ohci, "wakeup\n");
170 break; 185 break;
171 case OHCI_USB_OPER: 186 case OHCI_USB_OPER:
172 ohci_dbg (ohci, "already resumed\n"); 187 /* this can happen after resuming a swsusp snapshot */
173 status = 0; 188 ohci_dbg (ohci, "snapshot resume? reinit\n");
189 status = -EBUSY;
174 break; 190 break;
175 default: /* RESET, we lost power */ 191 default: /* RESET, we lost power */
176 ohci_dbg (ohci, "root hub hardware reset\n"); 192 ohci_dbg (ohci, "lost power\n");
177 status = -EBUSY; 193 status = -EBUSY;
178 } 194 }
179 spin_unlock_irq (&ohci->lock); 195 spin_unlock_irqrestore (&ohci->lock, flags);
180 if (status == -EBUSY) { 196 if (status == -EBUSY) {
181 (void) ohci_init (ohci); 197 (void) ohci_init (ohci);
182 return ohci_restart (ohci); 198 return ohci_restart (ohci);
@@ -198,8 +214,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
198 } 214 }
199 215
200 /* Some controllers (lucent erratum) need extra-long delays */ 216 /* Some controllers (lucent erratum) need extra-long delays */
201 hcd->state = HC_STATE_RESUMING; 217 msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
202 mdelay (20 /* usb 11.5.1.10 */ + 15);
203 218
204 temp = ohci_readl (ohci, &ohci->regs->control); 219 temp = ohci_readl (ohci, &ohci->regs->control);
205 temp &= OHCI_CTRL_HCFS; 220 temp &= OHCI_CTRL_HCFS;
@@ -273,28 +288,10 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
273 (void) ohci_readl (ohci, &ohci->regs->control); 288 (void) ohci_readl (ohci, &ohci->regs->control);
274 } 289 }
275 290
276 hcd->state = HC_STATE_RUNNING;
277 return 0; 291 return 0;
278} 292}
279 293
280static void ohci_rh_resume (void *_hcd) 294#endif /* CONFIG_PM */
281{
282 struct usb_hcd *hcd = _hcd;
283
284 usb_lock_device (hcd->self.root_hub);
285 (void) ohci_hub_resume (hcd);
286 usb_unlock_device (hcd->self.root_hub);
287}
288
289#else
290
291static void ohci_rh_resume (void *_hcd)
292{
293 struct ohci_hcd *ohci = hcd_to_ohci (_hcd);
294 ohci_dbg(ohci, "rh_resume ??\n");
295}
296
297#endif /* CONFIG_USB_SUSPEND || CONFIG_PM */
298 295
299/*-------------------------------------------------------------------------*/ 296/*-------------------------------------------------------------------------*/
300 297
@@ -313,8 +310,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
313 /* handle autosuspended root: finish resuming before 310 /* handle autosuspended root: finish resuming before
314 * letting khubd or root hub timer see state changes. 311 * letting khubd or root hub timer see state changes.
315 */ 312 */
316 if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER 313 if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
317 || !HC_IS_RUNNING(hcd->state)) { 314 || !HC_IS_RUNNING(hcd->state))) {
318 can_suspend = 0; 315 can_suspend = 0;
319 goto done; 316 goto done;
320 } 317 }
@@ -367,7 +364,6 @@ done:
367#ifdef CONFIG_PM 364#ifdef CONFIG_PM
368 /* save power by suspending idle root hubs; 365 /* save power by suspending idle root hubs;
369 * INTR_RD wakes us when there's work 366 * INTR_RD wakes us when there's work
370 * NOTE: if we can do this, we don't need a root hub timer!
371 */ 367 */
372 if (can_suspend 368 if (can_suspend
373 && !changed 369 && !changed
@@ -379,8 +375,7 @@ done:
379 && usb_trylock_device (hcd->self.root_hub) 375 && usb_trylock_device (hcd->self.root_hub)
380 ) { 376 ) {
381 ohci_vdbg (ohci, "autosuspend\n"); 377 ohci_vdbg (ohci, "autosuspend\n");
382 (void) ohci_hub_suspend (hcd); 378 (void) ohci_bus_suspend (hcd);
383 hcd->state = HC_STATE_RUNNING;
384 usb_unlock_device (hcd->self.root_hub); 379 usb_unlock_device (hcd->self.root_hub);
385 } 380 }
386#endif 381#endif
@@ -526,6 +521,9 @@ static int ohci_hub_control (
526 u32 temp; 521 u32 temp;
527 int retval = 0; 522 int retval = 0;
528 523
524 if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)))
525 return -ESHUTDOWN;
526
529 switch (typeReq) { 527 switch (typeReq) {
530 case ClearHubFeature: 528 case ClearHubFeature:
531 switch (wValue) { 529 switch (wValue) {
@@ -554,7 +552,7 @@ static int ohci_hub_control (
554 temp = RH_PS_POCI; 552 temp = RH_PS_POCI;
555 if ((ohci->hc_control & OHCI_CTRL_HCFS) 553 if ((ohci->hc_control & OHCI_CTRL_HCFS)
556 != OHCI_USB_OPER) 554 != OHCI_USB_OPER)
557 schedule_work (&ohci->rh_resume); 555 usb_hcd_resume_root_hub(hcd);
558 break; 556 break;
559 case USB_PORT_FEAT_C_SUSPEND: 557 case USB_PORT_FEAT_C_SUSPEND:
560 temp = RH_PS_PSSC; 558 temp = RH_PS_PSSC;