diff options
Diffstat (limited to 'drivers/usb/host')
| -rw-r--r-- | drivers/usb/host/ehci-hcd.c | 32 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-hub.c | 27 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-q.c | 7 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-sched.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/ehci.h | 3 | ||||
| -rw-r--r-- | drivers/usb/host/hc_crisv10.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/isp116x-hcd.c | 88 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-dbg.c | 9 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-hcd.c | 14 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-hub.c | 22 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-ppc-soc.c | 24 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-pxa27x.c | 48 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-s3c2410.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/ohci.h | 1 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-hcd.c | 62 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-hcd.h | 11 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-hub.c | 11 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-q.c | 2 |
18 files changed, 165 insertions, 208 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 149b13fc0a71..b948ffd94f45 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
| @@ -400,6 +400,23 @@ static int ehci_hc_reset (struct usb_hcd *hcd) | |||
| 400 | return -EIO; | 400 | return -EIO; |
| 401 | } | 401 | } |
| 402 | break; | 402 | break; |
| 403 | case PCI_VENDOR_ID_NVIDIA: | ||
| 404 | /* NVidia reports that certain chips don't handle | ||
| 405 | * QH, ITD, or SITD addresses above 2GB. (But TD, | ||
| 406 | * data buffer, and periodic schedule are normal.) | ||
| 407 | */ | ||
| 408 | switch (pdev->device) { | ||
| 409 | case 0x003c: /* MCP04 */ | ||
| 410 | case 0x005b: /* CK804 */ | ||
| 411 | case 0x00d8: /* CK8 */ | ||
| 412 | case 0x00e8: /* CK8S */ | ||
| 413 | if (pci_set_consistent_dma_mask(pdev, | ||
| 414 | DMA_31BIT_MASK) < 0) | ||
| 415 | ehci_warn (ehci, "can't enable NVidia " | ||
| 416 | "workaround for >2GB RAM\n"); | ||
| 417 | break; | ||
| 418 | } | ||
| 419 | break; | ||
| 403 | } | 420 | } |
| 404 | 421 | ||
| 405 | /* optional debug port, normally in the first BAR */ | 422 | /* optional debug port, normally in the first BAR */ |
| @@ -549,7 +566,9 @@ static int ehci_start (struct usb_hcd *hcd) | |||
| 549 | hcd->can_wakeup = (port_wake & 1) != 0; | 566 | hcd->can_wakeup = (port_wake & 1) != 0; |
| 550 | 567 | ||
| 551 | /* help hc dma work well with cachelines */ | 568 | /* help hc dma work well with cachelines */ |
| 552 | pci_set_mwi (pdev); | 569 | retval = pci_set_mwi(pdev); |
| 570 | if (retval) | ||
| 571 | ehci_dbg(ehci, "unable to enable MWI - not fatal.\n"); | ||
| 553 | } | 572 | } |
| 554 | #endif | 573 | #endif |
| 555 | 574 | ||
| @@ -757,12 +776,16 @@ static int ehci_resume (struct usb_hcd *hcd) | |||
| 757 | if (time_before (jiffies, ehci->next_statechange)) | 776 | if (time_before (jiffies, ehci->next_statechange)) |
| 758 | msleep (100); | 777 | msleep (100); |
| 759 | 778 | ||
| 760 | /* If any port is suspended, we know we can/must resume the HC. */ | 779 | /* If any port is suspended (or owned by the companion), |
| 780 | * we know we can/must resume the HC (and mustn't reset it). | ||
| 781 | */ | ||
| 761 | for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { | 782 | for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) { |
| 762 | u32 status; | 783 | u32 status; |
| 763 | port--; | 784 | port--; |
| 764 | status = readl (&ehci->regs->port_status [port]); | 785 | status = readl (&ehci->regs->port_status [port]); |
| 765 | if (status & PORT_SUSPEND) { | 786 | if (!(status & PORT_POWER)) |
| 787 | continue; | ||
| 788 | if (status & (PORT_SUSPEND | PORT_OWNER)) { | ||
| 766 | down (&hcd->self.root_hub->serialize); | 789 | down (&hcd->self.root_hub->serialize); |
| 767 | retval = ehci_hub_resume (hcd); | 790 | retval = ehci_hub_resume (hcd); |
| 768 | up (&hcd->self.root_hub->serialize); | 791 | up (&hcd->self.root_hub->serialize); |
| @@ -1124,8 +1147,7 @@ rescan: | |||
| 1124 | case QH_STATE_UNLINK: /* wait for hw to finish? */ | 1147 | case QH_STATE_UNLINK: /* wait for hw to finish? */ |
| 1125 | idle_timeout: | 1148 | idle_timeout: |
| 1126 | spin_unlock_irqrestore (&ehci->lock, flags); | 1149 | spin_unlock_irqrestore (&ehci->lock, flags); |
| 1127 | set_current_state (TASK_UNINTERRUPTIBLE); | 1150 | schedule_timeout_uninterruptible(1); |
| 1128 | schedule_timeout (1); | ||
| 1129 | goto rescan; | 1151 | goto rescan; |
| 1130 | case QH_STATE_IDLE: /* fully unlinked */ | 1152 | case QH_STATE_IDLE: /* fully unlinked */ |
| 1131 | if (list_empty (&qh->qtd_list)) { | 1153 | if (list_empty (&qh->qtd_list)) { |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 36cc1f2218d5..18d3f2270316 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
| @@ -54,7 +54,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd) | |||
| 54 | /* suspend any active/unsuspended ports, maybe allow wakeup */ | 54 | /* suspend any active/unsuspended ports, maybe allow wakeup */ |
| 55 | while (port--) { | 55 | while (port--) { |
| 56 | u32 __iomem *reg = &ehci->regs->port_status [port]; | 56 | u32 __iomem *reg = &ehci->regs->port_status [port]; |
| 57 | u32 t1 = readl (reg); | 57 | u32 t1 = readl (reg) & ~PORT_RWC_BITS; |
| 58 | u32 t2 = t1; | 58 | u32 t2 = t1; |
| 59 | 59 | ||
| 60 | if ((t1 & PORT_PE) && !(t1 & PORT_OWNER)) | 60 | if ((t1 & PORT_PE) && !(t1 & PORT_OWNER)) |
| @@ -115,7 +115,8 @@ static int ehci_hub_resume (struct usb_hcd *hcd) | |||
| 115 | i = HCS_N_PORTS (ehci->hcs_params); | 115 | i = HCS_N_PORTS (ehci->hcs_params); |
| 116 | while (i--) { | 116 | while (i--) { |
| 117 | temp = readl (&ehci->regs->port_status [i]); | 117 | temp = readl (&ehci->regs->port_status [i]); |
| 118 | temp &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); | 118 | temp &= ~(PORT_RWC_BITS |
| 119 | | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); | ||
| 119 | if (temp & PORT_SUSPEND) { | 120 | if (temp & PORT_SUSPEND) { |
| 120 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); | 121 | ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); |
| 121 | temp |= PORT_RESUME; | 122 | temp |= PORT_RESUME; |
| @@ -128,7 +129,7 @@ static int ehci_hub_resume (struct usb_hcd *hcd) | |||
| 128 | temp = readl (&ehci->regs->port_status [i]); | 129 | temp = readl (&ehci->regs->port_status [i]); |
| 129 | if ((temp & PORT_SUSPEND) == 0) | 130 | if ((temp & PORT_SUSPEND) == 0) |
| 130 | continue; | 131 | continue; |
| 131 | temp &= ~PORT_RESUME; | 132 | temp &= ~(PORT_RWC_BITS | PORT_RESUME); |
| 132 | writel (temp, &ehci->regs->port_status [i]); | 133 | writel (temp, &ehci->regs->port_status [i]); |
| 133 | ehci_vdbg (ehci, "resumed port %d\n", i + 1); | 134 | ehci_vdbg (ehci, "resumed port %d\n", i + 1); |
| 134 | } | 135 | } |
| @@ -191,6 +192,7 @@ static int check_reset_complete ( | |||
| 191 | 192 | ||
| 192 | // what happens if HCS_N_CC(params) == 0 ? | 193 | // what happens if HCS_N_CC(params) == 0 ? |
| 193 | port_status |= PORT_OWNER; | 194 | port_status |= PORT_OWNER; |
| 195 | port_status &= ~PORT_RWC_BITS; | ||
| 194 | writel (port_status, &ehci->regs->port_status [index]); | 196 | writel (port_status, &ehci->regs->port_status [index]); |
| 195 | 197 | ||
| 196 | } else | 198 | } else |
| @@ -233,7 +235,8 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
| 233 | if (temp & PORT_OWNER) { | 235 | if (temp & PORT_OWNER) { |
| 234 | /* don't report this in GetPortStatus */ | 236 | /* don't report this in GetPortStatus */ |
| 235 | if (temp & PORT_CSC) { | 237 | if (temp & PORT_CSC) { |
| 236 | temp &= ~PORT_CSC; | 238 | temp &= ~PORT_RWC_BITS; |
| 239 | temp |= PORT_CSC; | ||
| 237 | writel (temp, &ehci->regs->port_status [i]); | 240 | writel (temp, &ehci->regs->port_status [i]); |
| 238 | } | 241 | } |
| 239 | continue; | 242 | continue; |
| @@ -343,7 +346,7 @@ static int ehci_hub_control ( | |||
| 343 | &ehci->regs->port_status [wIndex]); | 346 | &ehci->regs->port_status [wIndex]); |
| 344 | break; | 347 | break; |
| 345 | case USB_PORT_FEAT_C_ENABLE: | 348 | case USB_PORT_FEAT_C_ENABLE: |
| 346 | writel (temp | PORT_PEC, | 349 | writel((temp & ~PORT_RWC_BITS) | PORT_PEC, |
| 347 | &ehci->regs->port_status [wIndex]); | 350 | &ehci->regs->port_status [wIndex]); |
| 348 | break; | 351 | break; |
| 349 | case USB_PORT_FEAT_SUSPEND: | 352 | case USB_PORT_FEAT_SUSPEND: |
| @@ -353,7 +356,8 @@ static int ehci_hub_control ( | |||
| 353 | if ((temp & PORT_PE) == 0) | 356 | if ((temp & PORT_PE) == 0) |
| 354 | goto error; | 357 | goto error; |
| 355 | /* resume signaling for 20 msec */ | 358 | /* resume signaling for 20 msec */ |
| 356 | writel ((temp & ~PORT_WAKE_BITS) | PORT_RESUME, | 359 | temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); |
| 360 | writel (temp | PORT_RESUME, | ||
| 357 | &ehci->regs->port_status [wIndex]); | 361 | &ehci->regs->port_status [wIndex]); |
| 358 | ehci->reset_done [wIndex] = jiffies | 362 | ehci->reset_done [wIndex] = jiffies |
| 359 | + msecs_to_jiffies (20); | 363 | + msecs_to_jiffies (20); |
| @@ -364,15 +368,15 @@ static int ehci_hub_control ( | |||
| 364 | break; | 368 | break; |
| 365 | case USB_PORT_FEAT_POWER: | 369 | case USB_PORT_FEAT_POWER: |
| 366 | if (HCS_PPC (ehci->hcs_params)) | 370 | if (HCS_PPC (ehci->hcs_params)) |
| 367 | writel (temp & ~PORT_POWER, | 371 | writel (temp & ~(PORT_RWC_BITS | PORT_POWER), |
| 368 | &ehci->regs->port_status [wIndex]); | 372 | &ehci->regs->port_status [wIndex]); |
| 369 | break; | 373 | break; |
| 370 | case USB_PORT_FEAT_C_CONNECTION: | 374 | case USB_PORT_FEAT_C_CONNECTION: |
| 371 | writel (temp | PORT_CSC, | 375 | writel((temp & ~PORT_RWC_BITS) | PORT_CSC, |
| 372 | &ehci->regs->port_status [wIndex]); | 376 | &ehci->regs->port_status [wIndex]); |
| 373 | break; | 377 | break; |
| 374 | case USB_PORT_FEAT_C_OVER_CURRENT: | 378 | case USB_PORT_FEAT_C_OVER_CURRENT: |
| 375 | writel (temp | PORT_OCC, | 379 | writel((temp & ~PORT_RWC_BITS) | PORT_OCC, |
| 376 | &ehci->regs->port_status [wIndex]); | 380 | &ehci->regs->port_status [wIndex]); |
| 377 | break; | 381 | break; |
| 378 | case USB_PORT_FEAT_C_RESET: | 382 | case USB_PORT_FEAT_C_RESET: |
| @@ -416,7 +420,7 @@ static int ehci_hub_control ( | |||
| 416 | 420 | ||
| 417 | /* stop resume signaling */ | 421 | /* stop resume signaling */ |
| 418 | temp = readl (&ehci->regs->port_status [wIndex]); | 422 | temp = readl (&ehci->regs->port_status [wIndex]); |
| 419 | writel (temp & ~PORT_RESUME, | 423 | writel (temp & ~(PORT_RWC_BITS | PORT_RESUME), |
| 420 | &ehci->regs->port_status [wIndex]); | 424 | &ehci->regs->port_status [wIndex]); |
| 421 | retval = handshake ( | 425 | retval = handshake ( |
| 422 | &ehci->regs->port_status [wIndex], | 426 | &ehci->regs->port_status [wIndex], |
| @@ -437,7 +441,7 @@ static int ehci_hub_control ( | |||
| 437 | ehci->reset_done [wIndex] = 0; | 441 | ehci->reset_done [wIndex] = 0; |
| 438 | 442 | ||
| 439 | /* force reset to complete */ | 443 | /* force reset to complete */ |
| 440 | writel (temp & ~PORT_RESET, | 444 | writel (temp & ~(PORT_RWC_BITS | PORT_RESET), |
| 441 | &ehci->regs->port_status [wIndex]); | 445 | &ehci->regs->port_status [wIndex]); |
| 442 | /* REVISIT: some hardware needs 550+ usec to clear | 446 | /* REVISIT: some hardware needs 550+ usec to clear |
| 443 | * this bit; seems too long to spin routinely... | 447 | * this bit; seems too long to spin routinely... |
| @@ -500,6 +504,7 @@ static int ehci_hub_control ( | |||
| 500 | if (temp & PORT_OWNER) | 504 | if (temp & PORT_OWNER) |
| 501 | break; | 505 | break; |
| 502 | 506 | ||
| 507 | temp &= ~PORT_RWC_BITS; | ||
| 503 | switch (wValue) { | 508 | switch (wValue) { |
| 504 | case USB_PORT_FEAT_SUSPEND: | 509 | case USB_PORT_FEAT_SUSPEND: |
| 505 | if ((temp & PORT_PE) == 0 | 510 | if ((temp & PORT_PE) == 0 |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 20df01a79b2e..940d38ca7d91 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
| @@ -677,6 +677,9 @@ qh_make ( | |||
| 677 | goto done; | 677 | goto done; |
| 678 | } | 678 | } |
| 679 | } else { | 679 | } else { |
| 680 | struct usb_tt *tt = urb->dev->tt; | ||
| 681 | int think_time; | ||
| 682 | |||
| 680 | /* gap is f(FS/LS transfer times) */ | 683 | /* gap is f(FS/LS transfer times) */ |
| 681 | qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed, | 684 | qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed, |
| 682 | is_input, 0, maxp) / (125 * 1000); | 685 | is_input, 0, maxp) / (125 * 1000); |
| @@ -690,6 +693,10 @@ qh_make ( | |||
| 690 | qh->c_usecs = HS_USECS (0); | 693 | qh->c_usecs = HS_USECS (0); |
| 691 | } | 694 | } |
| 692 | 695 | ||
| 696 | think_time = tt ? tt->think_time : 0; | ||
| 697 | qh->tt_usecs = NS_TO_US (think_time + | ||
| 698 | usb_calc_bus_time (urb->dev->speed, | ||
| 699 | is_input, 0, max_packet (maxp))); | ||
| 693 | qh->period = urb->interval; | 700 | qh->period = urb->interval; |
| 694 | } | 701 | } |
| 695 | } | 702 | } |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 4c972b57c7c3..ccc7300baa6d 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
| @@ -700,6 +700,7 @@ iso_stream_init ( | |||
| 700 | 700 | ||
| 701 | } else { | 701 | } else { |
| 702 | u32 addr; | 702 | u32 addr; |
| 703 | int think_time; | ||
| 703 | 704 | ||
| 704 | addr = dev->ttport << 24; | 705 | addr = dev->ttport << 24; |
| 705 | if (!ehci_is_TDI(ehci) | 706 | if (!ehci_is_TDI(ehci) |
| @@ -709,6 +710,9 @@ iso_stream_init ( | |||
| 709 | addr |= epnum << 8; | 710 | addr |= epnum << 8; |
| 710 | addr |= dev->devnum; | 711 | addr |= dev->devnum; |
| 711 | stream->usecs = HS_USECS_ISO (maxp); | 712 | stream->usecs = HS_USECS_ISO (maxp); |
| 713 | think_time = dev->tt ? dev->tt->think_time : 0; | ||
| 714 | stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time ( | ||
| 715 | dev->speed, is_input, 1, maxp)); | ||
| 712 | if (is_input) { | 716 | if (is_input) { |
| 713 | u32 tmp; | 717 | u32 tmp; |
| 714 | 718 | ||
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index a7542157534c..f34a0516d35f 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
| @@ -263,6 +263,7 @@ struct ehci_regs { | |||
| 263 | #define PORT_PE (1<<2) /* port enable */ | 263 | #define PORT_PE (1<<2) /* port enable */ |
| 264 | #define PORT_CSC (1<<1) /* connect status change */ | 264 | #define PORT_CSC (1<<1) /* connect status change */ |
| 265 | #define PORT_CONNECT (1<<0) /* device connected */ | 265 | #define PORT_CONNECT (1<<0) /* device connected */ |
| 266 | #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) | ||
| 266 | } __attribute__ ((packed)); | 267 | } __attribute__ ((packed)); |
| 267 | 268 | ||
| 268 | /* Appendix C, Debug port ... intended for use with special "debug devices" | 269 | /* Appendix C, Debug port ... intended for use with special "debug devices" |
| @@ -421,6 +422,7 @@ struct ehci_qh { | |||
| 421 | u8 usecs; /* intr bandwidth */ | 422 | u8 usecs; /* intr bandwidth */ |
| 422 | u8 gap_uf; /* uframes split/csplit gap */ | 423 | u8 gap_uf; /* uframes split/csplit gap */ |
| 423 | u8 c_usecs; /* ... split completion bw */ | 424 | u8 c_usecs; /* ... split completion bw */ |
| 425 | u16 tt_usecs; /* tt downstream bandwidth */ | ||
| 424 | unsigned short period; /* polling interval */ | 426 | unsigned short period; /* polling interval */ |
| 425 | unsigned short start; /* where polling starts */ | 427 | unsigned short start; /* where polling starts */ |
| 426 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ | 428 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ |
| @@ -479,6 +481,7 @@ struct ehci_iso_stream { | |||
| 479 | */ | 481 | */ |
| 480 | u8 interval; | 482 | u8 interval; |
| 481 | u8 usecs, c_usecs; | 483 | u8 usecs, c_usecs; |
| 484 | u16 tt_usecs; | ||
| 482 | u16 maxp; | 485 | u16 maxp; |
| 483 | u16 raw_mask; | 486 | u16 raw_mask; |
| 484 | unsigned bandwidth; | 487 | unsigned bandwidth; |
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c index 81f8f6b7fdce..a8267cf17db4 100644 --- a/drivers/usb/host/hc_crisv10.c +++ b/drivers/usb/host/hc_crisv10.c | |||
| @@ -178,8 +178,8 @@ static __u8 root_hub_hub_des[] = | |||
| 178 | 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ | 178 | 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ |
| 179 | }; | 179 | }; |
| 180 | 180 | ||
| 181 | static struct timer_list bulk_start_timer = TIMER_INITIALIZER(NULL, 0, 0); | 181 | static DEFINE_TIMER(bulk_start_timer, NULL, 0, 0); |
| 182 | static struct timer_list bulk_eot_timer = TIMER_INITIALIZER(NULL, 0, 0); | 182 | static DEFINE_TIMER(bulk_eot_timer, NULL, 0, 0); |
| 183 | 183 | ||
| 184 | /* We want the start timer to expire before the eot timer, because the former might start | 184 | /* We want the start timer to expire before the eot timer, because the former might start |
| 185 | traffic, thus making it unnecessary for the latter to time out. */ | 185 | traffic, thus making it unnecessary for the latter to time out. */ |
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 75128c371800..41bbae83fc71 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
| @@ -83,7 +83,7 @@ | |||
| 83 | #include "../core/hcd.h" | 83 | #include "../core/hcd.h" |
| 84 | #include "isp116x.h" | 84 | #include "isp116x.h" |
| 85 | 85 | ||
| 86 | #define DRIVER_VERSION "08 Apr 2005" | 86 | #define DRIVER_VERSION "05 Aug 2005" |
| 87 | #define DRIVER_DESC "ISP116x USB Host Controller Driver" | 87 | #define DRIVER_DESC "ISP116x USB Host Controller Driver" |
| 88 | 88 | ||
| 89 | MODULE_DESCRIPTION(DRIVER_DESC); | 89 | MODULE_DESCRIPTION(DRIVER_DESC); |
| @@ -629,14 +629,12 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
| 629 | ERR("Unrecoverable error\n"); | 629 | ERR("Unrecoverable error\n"); |
| 630 | /* What should we do here? Reset? */ | 630 | /* What should we do here? Reset? */ |
| 631 | } | 631 | } |
| 632 | if (intstat & HCINT_RHSC) { | 632 | if (intstat & HCINT_RHSC) |
| 633 | isp116x->rhstatus = | 633 | /* When root hub or any of its ports is going |
| 634 | isp116x_read_reg32(isp116x, HCRHSTATUS); | 634 | to come out of suspend, it may take more |
| 635 | isp116x->rhport[0] = | 635 | than 10ms for status bits to stabilize. */ |
| 636 | isp116x_read_reg32(isp116x, HCRHPORT1); | 636 | mod_timer(&hcd->rh_timer, jiffies |
| 637 | isp116x->rhport[1] = | 637 | + msecs_to_jiffies(20) + 1); |
| 638 | isp116x_read_reg32(isp116x, HCRHPORT2); | ||
| 639 | } | ||
| 640 | if (intstat & HCINT_RD) { | 638 | if (intstat & HCINT_RD) { |
| 641 | DBG("---- remote wakeup\n"); | 639 | DBG("---- remote wakeup\n"); |
| 642 | schedule_work(&isp116x->rh_resume); | 640 | schedule_work(&isp116x->rh_resume); |
| @@ -925,20 +923,27 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
| 925 | { | 923 | { |
| 926 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 924 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
| 927 | int ports, i, changed = 0; | 925 | int ports, i, changed = 0; |
| 926 | unsigned long flags; | ||
| 928 | 927 | ||
| 929 | if (!HC_IS_RUNNING(hcd->state)) | 928 | if (!HC_IS_RUNNING(hcd->state)) |
| 930 | return -ESHUTDOWN; | 929 | return -ESHUTDOWN; |
| 931 | 930 | ||
| 932 | ports = isp116x->rhdesca & RH_A_NDP; | 931 | /* Report no status change now, if we are scheduled to be |
| 932 | called later */ | ||
| 933 | if (timer_pending(&hcd->rh_timer)) | ||
| 934 | return 0; | ||
| 933 | 935 | ||
| 934 | /* init status */ | 936 | ports = isp116x->rhdesca & RH_A_NDP; |
| 937 | spin_lock_irqsave(&isp116x->lock, flags); | ||
| 938 | isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS); | ||
| 935 | if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC)) | 939 | if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC)) |
| 936 | buf[0] = changed = 1; | 940 | buf[0] = changed = 1; |
| 937 | else | 941 | else |
| 938 | buf[0] = 0; | 942 | buf[0] = 0; |
| 939 | 943 | ||
| 940 | for (i = 0; i < ports; i++) { | 944 | for (i = 0; i < ports; i++) { |
| 941 | u32 status = isp116x->rhport[i]; | 945 | u32 status = isp116x->rhport[i] = |
| 946 | isp116x_read_reg32(isp116x, i ? HCRHPORT2 : HCRHPORT1); | ||
| 942 | 947 | ||
| 943 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | 948 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC |
| 944 | | RH_PS_OCIC | RH_PS_PRSC)) { | 949 | | RH_PS_OCIC | RH_PS_PRSC)) { |
| @@ -947,6 +952,7 @@ static int isp116x_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
| 947 | continue; | 952 | continue; |
| 948 | } | 953 | } |
| 949 | } | 954 | } |
| 955 | spin_unlock_irqrestore(&isp116x->lock, flags); | ||
| 950 | return changed; | 956 | return changed; |
| 951 | } | 957 | } |
| 952 | 958 | ||
| @@ -1463,10 +1469,6 @@ static int isp116x_sw_reset(struct isp116x *isp116x) | |||
| 1463 | return ret; | 1469 | return ret; |
| 1464 | } | 1470 | } |
| 1465 | 1471 | ||
| 1466 | /* | ||
| 1467 | Reset. Tries to perform platform-specific hardware | ||
| 1468 | reset first; falls back to software reset. | ||
| 1469 | */ | ||
| 1470 | static int isp116x_reset(struct usb_hcd *hcd) | 1472 | static int isp116x_reset(struct usb_hcd *hcd) |
| 1471 | { | 1473 | { |
| 1472 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 1474 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
| @@ -1474,17 +1476,7 @@ static int isp116x_reset(struct usb_hcd *hcd) | |||
| 1474 | u16 clkrdy = 0; | 1476 | u16 clkrdy = 0; |
| 1475 | int ret = 0, timeout = 15 /* ms */ ; | 1477 | int ret = 0, timeout = 15 /* ms */ ; |
| 1476 | 1478 | ||
| 1477 | if (isp116x->board && isp116x->board->reset) { | 1479 | ret = isp116x_sw_reset(isp116x); |
| 1478 | /* Hardware reset */ | ||
| 1479 | isp116x->board->reset(hcd->self.controller, 1); | ||
| 1480 | msleep(10); | ||
| 1481 | if (isp116x->board->clock) | ||
| 1482 | isp116x->board->clock(hcd->self.controller, 1); | ||
| 1483 | msleep(1); | ||
| 1484 | isp116x->board->reset(hcd->self.controller, 0); | ||
| 1485 | } else | ||
| 1486 | ret = isp116x_sw_reset(isp116x); | ||
| 1487 | |||
| 1488 | if (ret) | 1480 | if (ret) |
| 1489 | return ret; | 1481 | return ret; |
| 1490 | 1482 | ||
| @@ -1501,10 +1493,7 @@ static int isp116x_reset(struct usb_hcd *hcd) | |||
| 1501 | ERR("Clock not ready after 20ms\n"); | 1493 | ERR("Clock not ready after 20ms\n"); |
| 1502 | /* After sw_reset the clock won't report to be ready, if | 1494 | /* After sw_reset the clock won't report to be ready, if |
| 1503 | H_WAKEUP pin is high. */ | 1495 | H_WAKEUP pin is high. */ |
| 1504 | if (!isp116x->board || !isp116x->board->reset) | 1496 | ERR("Please make sure that the H_WAKEUP pin is pulled low!\n"); |
| 1505 | ERR("The driver does not support hardware wakeup.\n"); | ||
| 1506 | ERR("Please make sure that the H_WAKEUP pin " | ||
| 1507 | "is pulled low!\n"); | ||
| 1508 | ret = -ENODEV; | 1497 | ret = -ENODEV; |
| 1509 | } | 1498 | } |
| 1510 | return ret; | 1499 | return ret; |
| @@ -1527,15 +1516,7 @@ static void isp116x_stop(struct usb_hcd *hcd) | |||
| 1527 | isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS); | 1516 | isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS); |
| 1528 | spin_unlock_irqrestore(&isp116x->lock, flags); | 1517 | spin_unlock_irqrestore(&isp116x->lock, flags); |
| 1529 | 1518 | ||
| 1530 | /* Put the chip into reset state */ | 1519 | isp116x_sw_reset(isp116x); |
| 1531 | if (isp116x->board && isp116x->board->reset) | ||
| 1532 | isp116x->board->reset(hcd->self.controller, 0); | ||
| 1533 | else | ||
| 1534 | isp116x_sw_reset(isp116x); | ||
| 1535 | |||
| 1536 | /* Stop the clock */ | ||
| 1537 | if (isp116x->board && isp116x->board->clock) | ||
| 1538 | isp116x->board->clock(hcd->self.controller, 0); | ||
| 1539 | } | 1520 | } |
| 1540 | 1521 | ||
| 1541 | /* | 1522 | /* |
| @@ -1561,6 +1542,9 @@ static int isp116x_start(struct usb_hcd *hcd) | |||
| 1561 | return -ENODEV; | 1542 | return -ENODEV; |
| 1562 | } | 1543 | } |
| 1563 | 1544 | ||
| 1545 | /* To be removed in future */ | ||
| 1546 | hcd->uses_new_polling = 1; | ||
| 1547 | |||
| 1564 | isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); | 1548 | isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE); |
| 1565 | isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); | 1549 | isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE); |
| 1566 | 1550 | ||
| @@ -1569,7 +1553,7 @@ static int isp116x_start(struct usb_hcd *hcd) | |||
| 1569 | if (board->sel15Kres) | 1553 | if (board->sel15Kres) |
| 1570 | val |= HCHWCFG_15KRSEL; | 1554 | val |= HCHWCFG_15KRSEL; |
| 1571 | /* Remote wakeup won't work without working clock */ | 1555 | /* Remote wakeup won't work without working clock */ |
| 1572 | if (board->clknotstop || board->remote_wakeup_enable) | 1556 | if (board->remote_wakeup_enable) |
| 1573 | val |= HCHWCFG_CLKNOTSTOP; | 1557 | val |= HCHWCFG_CLKNOTSTOP; |
| 1574 | if (board->oc_enable) | 1558 | if (board->oc_enable) |
| 1575 | val |= HCHWCFG_ANALOG_OC; | 1559 | val |= HCHWCFG_ANALOG_OC; |
| @@ -1580,16 +1564,13 @@ static int isp116x_start(struct usb_hcd *hcd) | |||
| 1580 | isp116x_write_reg16(isp116x, HCHWCFG, val); | 1564 | isp116x_write_reg16(isp116x, HCHWCFG, val); |
| 1581 | 1565 | ||
| 1582 | /* ----- Root hub conf */ | 1566 | /* ----- Root hub conf */ |
| 1583 | val = 0; | 1567 | val = (25 << 24) & RH_A_POTPGT; |
| 1584 | /* AN10003_1.pdf recommends NPS to be always 1 */ | 1568 | /* AN10003_1.pdf recommends RH_A_NPS (no power switching) to |
| 1585 | if (board->no_power_switching) | 1569 | be always set. Yet, instead, we request individual port |
| 1586 | val |= RH_A_NPS; | 1570 | power switching. */ |
| 1587 | if (board->power_switching_mode) | 1571 | val |= RH_A_PSM; |
| 1588 | val |= RH_A_PSM; | 1572 | /* Report overcurrent per port */ |
| 1589 | if (board->potpg) | 1573 | val |= RH_A_OCPM; |
| 1590 | val |= (board->potpg << 24) & RH_A_POTPGT; | ||
| 1591 | else | ||
| 1592 | val |= (25 << 24) & RH_A_POTPGT; | ||
| 1593 | isp116x_write_reg32(isp116x, HCRHDESCA, val); | 1574 | isp116x_write_reg32(isp116x, HCRHDESCA, val); |
| 1594 | isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA); | 1575 | isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA); |
| 1595 | 1576 | ||
| @@ -1619,9 +1600,6 @@ static int isp116x_start(struct usb_hcd *hcd) | |||
| 1619 | 1600 | ||
| 1620 | /* Go operational */ | 1601 | /* Go operational */ |
| 1621 | val = HCCONTROL_USB_OPER; | 1602 | val = HCCONTROL_USB_OPER; |
| 1622 | /* Remote wakeup connected - NOT SUPPORTED */ | ||
| 1623 | /* if (board->remote_wakeup_connected) | ||
| 1624 | val |= HCCONTROL_RWC; */ | ||
| 1625 | if (board->remote_wakeup_enable) | 1603 | if (board->remote_wakeup_enable) |
| 1626 | val |= HCCONTROL_RWE; | 1604 | val |= HCCONTROL_RWE; |
| 1627 | isp116x_write_reg32(isp116x, HCCONTROL, val); | 1605 | isp116x_write_reg32(isp116x, HCCONTROL, val); |
| @@ -1670,7 +1648,7 @@ static int __init_or_module isp116x_remove(struct device *dev) | |||
| 1670 | struct platform_device *pdev; | 1648 | struct platform_device *pdev; |
| 1671 | struct resource *res; | 1649 | struct resource *res; |
| 1672 | 1650 | ||
| 1673 | if(!hcd) | 1651 | if (!hcd) |
| 1674 | return 0; | 1652 | return 0; |
| 1675 | isp116x = hcd_to_isp116x(hcd); | 1653 | isp116x = hcd_to_isp116x(hcd); |
| 1676 | pdev = container_of(dev, struct platform_device, dev); | 1654 | pdev = container_of(dev, struct platform_device, dev); |
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 447f488f5d93..7924c74f958e 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c | |||
| @@ -228,23 +228,22 @@ ohci_dump_roothub ( | |||
| 228 | char **next, | 228 | char **next, |
| 229 | unsigned *size) | 229 | unsigned *size) |
| 230 | { | 230 | { |
| 231 | u32 temp, ndp, i; | 231 | u32 temp, i; |
| 232 | 232 | ||
| 233 | temp = roothub_a (controller); | 233 | temp = roothub_a (controller); |
| 234 | if (temp == ~(u32)0) | 234 | if (temp == ~(u32)0) |
| 235 | return; | 235 | return; |
| 236 | ndp = (temp & RH_A_NDP); | ||
| 237 | 236 | ||
| 238 | if (verbose) { | 237 | if (verbose) { |
| 239 | ohci_dbg_sw (controller, next, size, | 238 | ohci_dbg_sw (controller, next, size, |
| 240 | "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp, | 239 | "roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d(%d)\n", temp, |
| 241 | ((temp & RH_A_POTPGT) >> 24) & 0xff, | 240 | ((temp & RH_A_POTPGT) >> 24) & 0xff, |
| 242 | (temp & RH_A_NOCP) ? " NOCP" : "", | 241 | (temp & RH_A_NOCP) ? " NOCP" : "", |
| 243 | (temp & RH_A_OCPM) ? " OCPM" : "", | 242 | (temp & RH_A_OCPM) ? " OCPM" : "", |
| 244 | (temp & RH_A_DT) ? " DT" : "", | 243 | (temp & RH_A_DT) ? " DT" : "", |
| 245 | (temp & RH_A_NPS) ? " NPS" : "", | 244 | (temp & RH_A_NPS) ? " NPS" : "", |
| 246 | (temp & RH_A_PSM) ? " PSM" : "", | 245 | (temp & RH_A_PSM) ? " PSM" : "", |
| 247 | ndp | 246 | (temp & RH_A_NDP), controller->num_ports |
| 248 | ); | 247 | ); |
| 249 | temp = roothub_b (controller); | 248 | temp = roothub_b (controller); |
| 250 | ohci_dbg_sw (controller, next, size, | 249 | ohci_dbg_sw (controller, next, size, |
| @@ -266,7 +265,7 @@ ohci_dump_roothub ( | |||
| 266 | ); | 265 | ); |
| 267 | } | 266 | } |
| 268 | 267 | ||
| 269 | for (i = 0; i < ndp; i++) { | 268 | for (i = 0; i < controller->num_ports; i++) { |
| 270 | temp = roothub_portstatus (controller, i); | 269 | temp = roothub_portstatus (controller, i); |
| 271 | dbg_port_sw (controller, i, temp, next, size); | 270 | dbg_port_sw (controller, i, temp, next, size); |
| 272 | } | 271 | } |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 56b43f2a0e52..67c1aa5eb1c1 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
| @@ -382,8 +382,7 @@ sanitize: | |||
| 382 | goto sanitize; | 382 | goto sanitize; |
| 383 | } | 383 | } |
| 384 | spin_unlock_irqrestore (&ohci->lock, flags); | 384 | spin_unlock_irqrestore (&ohci->lock, flags); |
| 385 | set_current_state (TASK_UNINTERRUPTIBLE); | 385 | schedule_timeout_uninterruptible(1); |
| 386 | schedule_timeout (1); | ||
| 387 | goto rescan; | 386 | goto rescan; |
| 388 | case ED_IDLE: /* fully unlinked */ | 387 | case ED_IDLE: /* fully unlinked */ |
| 389 | if (list_empty (&ed->td_list)) { | 388 | if (list_empty (&ed->td_list)) { |
| @@ -485,6 +484,10 @@ static int ohci_init (struct ohci_hcd *ohci) | |||
| 485 | // flush the writes | 484 | // flush the writes |
| 486 | (void) ohci_readl (ohci, &ohci->regs->control); | 485 | (void) ohci_readl (ohci, &ohci->regs->control); |
| 487 | 486 | ||
| 487 | /* Read the number of ports unless overridden */ | ||
| 488 | if (ohci->num_ports == 0) | ||
| 489 | ohci->num_ports = roothub_a(ohci) & RH_A_NDP; | ||
| 490 | |||
| 488 | if (ohci->hcca) | 491 | if (ohci->hcca) |
| 489 | return 0; | 492 | return 0; |
| 490 | 493 | ||
| @@ -561,10 +564,8 @@ static int ohci_run (struct ohci_hcd *ohci) | |||
| 561 | msleep(temp); | 564 | msleep(temp); |
| 562 | temp = roothub_a (ohci); | 565 | temp = roothub_a (ohci); |
| 563 | if (!(temp & RH_A_NPS)) { | 566 | if (!(temp & RH_A_NPS)) { |
| 564 | unsigned ports = temp & RH_A_NDP; | ||
| 565 | |||
| 566 | /* power down each port */ | 567 | /* power down each port */ |
| 567 | for (temp = 0; temp < ports; temp++) | 568 | for (temp = 0; temp < ohci->num_ports; temp++) |
| 568 | ohci_writel (ohci, RH_PS_LSDA, | 569 | ohci_writel (ohci, RH_PS_LSDA, |
| 569 | &ohci->regs->roothub.portstatus [temp]); | 570 | &ohci->regs->roothub.portstatus [temp]); |
| 570 | } | 571 | } |
| @@ -720,6 +721,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs) | |||
| 720 | 721 | ||
| 721 | if (ints & OHCI_INTR_RD) { | 722 | if (ints & OHCI_INTR_RD) { |
| 722 | ohci_vdbg (ohci, "resume detect\n"); | 723 | ohci_vdbg (ohci, "resume detect\n"); |
| 724 | ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus); | ||
| 723 | if (hcd->state != HC_STATE_QUIESCING) | 725 | if (hcd->state != HC_STATE_QUIESCING) |
| 724 | schedule_work(&ohci->rh_resume); | 726 | schedule_work(&ohci->rh_resume); |
| 725 | } | 727 | } |
| @@ -861,7 +863,7 @@ static int ohci_restart (struct ohci_hcd *ohci) | |||
| 861 | * and that if we try to turn them back on the root hub | 863 | * and that if we try to turn them back on the root hub |
| 862 | * will respond to CSC processing. | 864 | * will respond to CSC processing. |
| 863 | */ | 865 | */ |
| 864 | i = roothub_a (ohci) & RH_A_NDP; | 866 | i = ohci->num_ports; |
| 865 | while (i--) | 867 | while (i--) |
| 866 | ohci_writel (ohci, RH_PS_PSS, | 868 | ohci_writel (ohci, RH_PS_PSS, |
| 867 | &ohci->regs->roothub.portstatus [temp]); | 869 | &ohci->regs->roothub.portstatus [temp]); |
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 83ca4549a50e..ce7b28da7a15 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
| @@ -184,7 +184,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd) | |||
| 184 | if (status != -EINPROGRESS) | 184 | if (status != -EINPROGRESS) |
| 185 | return status; | 185 | return status; |
| 186 | 186 | ||
| 187 | temp = roothub_a (ohci) & RH_A_NDP; | 187 | temp = ohci->num_ports; |
| 188 | enables = 0; | 188 | enables = 0; |
| 189 | while (temp--) { | 189 | while (temp--) { |
| 190 | u32 stat = ohci_readl (ohci, | 190 | u32 stat = ohci_readl (ohci, |
| @@ -304,7 +304,7 @@ static int | |||
| 304 | ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | 304 | ohci_hub_status_data (struct usb_hcd *hcd, char *buf) |
| 305 | { | 305 | { |
| 306 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 306 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
| 307 | int ports, i, changed = 0, length = 1; | 307 | int i, changed = 0, length = 1; |
| 308 | int can_suspend = hcd->can_wakeup; | 308 | int can_suspend = hcd->can_wakeup; |
| 309 | unsigned long flags; | 309 | unsigned long flags; |
| 310 | 310 | ||
| @@ -319,9 +319,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
| 319 | goto done; | 319 | goto done; |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | ports = roothub_a (ohci) & RH_A_NDP; | 322 | /* undocumented erratum seen on at least rev D */ |
| 323 | if (ports > MAX_ROOT_PORTS) { | 323 | if ((ohci->flags & OHCI_QUIRK_AMD756) |
| 324 | ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports, | 324 | && (roothub_a (ohci) & RH_A_NDP) > MAX_ROOT_PORTS) { |
| 325 | ohci_warn (ohci, "bogus NDP, rereads as NDP=%d\n", | ||
| 325 | ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); | 326 | ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP); |
| 326 | /* retry later; "should not happen" */ | 327 | /* retry later; "should not happen" */ |
| 327 | goto done; | 328 | goto done; |
| @@ -332,13 +333,13 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
| 332 | buf [0] = changed = 1; | 333 | buf [0] = changed = 1; |
| 333 | else | 334 | else |
| 334 | buf [0] = 0; | 335 | buf [0] = 0; |
| 335 | if (ports > 7) { | 336 | if (ohci->num_ports > 7) { |
| 336 | buf [1] = 0; | 337 | buf [1] = 0; |
| 337 | length++; | 338 | length++; |
| 338 | } | 339 | } |
| 339 | 340 | ||
| 340 | /* look at each port */ | 341 | /* look at each port */ |
| 341 | for (i = 0; i < ports; i++) { | 342 | for (i = 0; i < ohci->num_ports; i++) { |
| 342 | u32 status = roothub_portstatus (ohci, i); | 343 | u32 status = roothub_portstatus (ohci, i); |
| 343 | 344 | ||
| 344 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | 345 | if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC |
| @@ -395,15 +396,14 @@ ohci_hub_descriptor ( | |||
| 395 | struct usb_hub_descriptor *desc | 396 | struct usb_hub_descriptor *desc |
| 396 | ) { | 397 | ) { |
| 397 | u32 rh = roothub_a (ohci); | 398 | u32 rh = roothub_a (ohci); |
| 398 | int ports = rh & RH_A_NDP; | ||
| 399 | u16 temp; | 399 | u16 temp; |
| 400 | 400 | ||
| 401 | desc->bDescriptorType = 0x29; | 401 | desc->bDescriptorType = 0x29; |
| 402 | desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24; | 402 | desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24; |
| 403 | desc->bHubContrCurrent = 0; | 403 | desc->bHubContrCurrent = 0; |
| 404 | 404 | ||
| 405 | desc->bNbrPorts = ports; | 405 | desc->bNbrPorts = ohci->num_ports; |
| 406 | temp = 1 + (ports / 8); | 406 | temp = 1 + (ohci->num_ports / 8); |
| 407 | desc->bDescLength = 7 + 2 * temp; | 407 | desc->bDescLength = 7 + 2 * temp; |
| 408 | 408 | ||
| 409 | temp = 0; | 409 | temp = 0; |
| @@ -421,7 +421,7 @@ ohci_hub_descriptor ( | |||
| 421 | rh = roothub_b (ohci); | 421 | rh = roothub_b (ohci); |
| 422 | memset(desc->bitmap, 0xff, sizeof(desc->bitmap)); | 422 | memset(desc->bitmap, 0xff, sizeof(desc->bitmap)); |
| 423 | desc->bitmap [0] = rh & RH_B_DR; | 423 | desc->bitmap [0] = rh & RH_B_DR; |
| 424 | if (ports > 7) { | 424 | if (ohci->num_ports > 7) { |
| 425 | desc->bitmap [1] = (rh & RH_B_DR) >> 8; | 425 | desc->bitmap [1] = (rh & RH_B_DR) >> 8; |
| 426 | desc->bitmap [2] = 0xff; | 426 | desc->bitmap [2] = 0xff; |
| 427 | } else | 427 | } else |
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index 17964c39d06a..251533363028 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c | |||
| @@ -14,8 +14,6 @@ | |||
| 14 | * This file is licenced under the GPL. | 14 | * This file is licenced under the GPL. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include <asm/usb.h> | ||
| 18 | |||
| 19 | /* configure so an HC device and id are always provided */ | 17 | /* configure so an HC device and id are always provided */ |
| 20 | /* always called with process context; sleeping is OK */ | 18 | /* always called with process context; sleeping is OK */ |
| 21 | 19 | ||
| @@ -23,9 +21,7 @@ | |||
| 23 | * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs | 21 | * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs |
| 24 | * Context: !in_interrupt() | 22 | * Context: !in_interrupt() |
| 25 | * | 23 | * |
| 26 | * Allocates basic resources for this USB host controller, and | 24 | * Allocates basic resources for this USB host controller. |
| 27 | * then invokes the start() method for the HCD associated with it | ||
| 28 | * through the hotplug entry's driver_data. | ||
| 29 | * | 25 | * |
| 30 | * Store this function in the HCD's struct pci_driver as probe(). | 26 | * Store this function in the HCD's struct pci_driver as probe(). |
| 31 | */ | 27 | */ |
| @@ -37,7 +33,6 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, | |||
| 37 | struct ohci_hcd *ohci; | 33 | struct ohci_hcd *ohci; |
| 38 | struct resource *res; | 34 | struct resource *res; |
| 39 | int irq; | 35 | int irq; |
| 40 | struct usb_hcd_platform_data *pd = pdev->dev.platform_data; | ||
| 41 | 36 | ||
| 42 | pr_debug("initializing PPC-SOC USB Controller\n"); | 37 | pr_debug("initializing PPC-SOC USB Controller\n"); |
| 43 | 38 | ||
| @@ -73,9 +68,6 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, | |||
| 73 | goto err2; | 68 | goto err2; |
| 74 | } | 69 | } |
| 75 | 70 | ||
| 76 | if (pd->start && (retval = pd->start(pdev))) | ||
| 77 | goto err3; | ||
| 78 | |||
| 79 | ohci = hcd_to_ohci(hcd); | 71 | ohci = hcd_to_ohci(hcd); |
| 80 | ohci->flags |= OHCI_BIG_ENDIAN; | 72 | ohci->flags |= OHCI_BIG_ENDIAN; |
| 81 | ohci_hcd_init(ohci); | 73 | ohci_hcd_init(ohci); |
| @@ -85,9 +77,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, | |||
| 85 | return retval; | 77 | return retval; |
| 86 | 78 | ||
| 87 | pr_debug("Removing PPC-SOC USB Controller\n"); | 79 | pr_debug("Removing PPC-SOC USB Controller\n"); |
| 88 | if (pd && pd->stop) | 80 | |
| 89 | pd->stop(pdev); | ||
| 90 | err3: | ||
| 91 | iounmap(hcd->regs); | 81 | iounmap(hcd->regs); |
| 92 | err2: | 82 | err2: |
| 93 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 83 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
| @@ -105,25 +95,21 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver, | |||
| 105 | * @pdev: USB Host Controller being removed | 95 | * @pdev: USB Host Controller being removed |
| 106 | * Context: !in_interrupt() | 96 | * Context: !in_interrupt() |
| 107 | * | 97 | * |
| 108 | * Reverses the effect of usb_hcd_ppc_soc_probe(), first invoking | 98 | * Reverses the effect of usb_hcd_ppc_soc_probe(). |
| 109 | * the HCD's stop() method. It is always called from a thread | 99 | * It is always called from a thread |
| 110 | * context, normally "rmmod", "apmd", or something similar. | 100 | * context, normally "rmmod", "apmd", or something similar. |
| 111 | * | 101 | * |
| 112 | */ | 102 | */ |
| 113 | static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd, | 103 | static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd, |
| 114 | struct platform_device *pdev) | 104 | struct platform_device *pdev) |
| 115 | { | 105 | { |
| 116 | struct usb_hcd_platform_data *pd = pdev->dev.platform_data; | ||
| 117 | |||
| 118 | usb_remove_hcd(hcd); | 106 | usb_remove_hcd(hcd); |
| 119 | 107 | ||
| 120 | pr_debug("stopping PPC-SOC USB Controller\n"); | 108 | pr_debug("stopping PPC-SOC USB Controller\n"); |
| 121 | if (pd && pd->stop) | ||
| 122 | pd->stop(pdev); | ||
| 123 | 109 | ||
| 124 | iounmap(hcd->regs); | 110 | iounmap(hcd->regs); |
| 125 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 111 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
| 126 | usb_hcd_put(hcd); | 112 | usb_put_hcd(hcd); |
| 127 | } | 113 | } |
| 128 | 114 | ||
| 129 | static int __devinit | 115 | static int __devinit |
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index e5bc1789d18a..2fdb262d4726 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c | |||
| @@ -75,33 +75,6 @@ static int pxa27x_ohci_select_pmm( int mode ) | |||
| 75 | return 0; | 75 | return 0; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | /* | ||
| 79 | If you select PMM_PERPORT_MODE, you should set the port power | ||
| 80 | */ | ||
| 81 | static int pxa27x_ohci_set_port_power( int port ) | ||
| 82 | { | ||
| 83 | if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE) | ||
| 84 | && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) { | ||
| 85 | UHCRHPS(port) |= 0x100; | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | return -1; | ||
| 89 | } | ||
| 90 | |||
| 91 | /* | ||
| 92 | If you select PMM_PERPORT_MODE, you should set the port power | ||
| 93 | */ | ||
| 94 | static int pxa27x_ohci_clear_port_power( int port ) | ||
| 95 | { | ||
| 96 | if ( (pxa27x_ohci_pmm_state==PMM_PERPORT_MODE) | ||
| 97 | && (port>0) && (port<PXA_UHC_MAX_PORTNUM) ) { | ||
| 98 | UHCRHPS(port) |= 0x200; | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | return -1; | ||
| 103 | } | ||
| 104 | |||
| 105 | extern int usb_disabled(void); | 78 | extern int usb_disabled(void); |
| 106 | 79 | ||
| 107 | /*-------------------------------------------------------------------------*/ | 80 | /*-------------------------------------------------------------------------*/ |
| @@ -130,11 +103,17 @@ static void pxa27x_start_hc(struct platform_device *dev) | |||
| 130 | Polarity Low to active low. Supply power to USB ports. */ | 103 | Polarity Low to active low. Supply power to USB ports. */ |
| 131 | UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & | 104 | UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & |
| 132 | ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); | 105 | ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); |
| 106 | |||
| 107 | pxa27x_ohci_pmm_state = PMM_PERPORT_MODE; | ||
| 133 | } | 108 | } |
| 134 | 109 | ||
| 135 | UHCHR &= ~UHCHR_SSE; | 110 | UHCHR &= ~UHCHR_SSE; |
| 136 | 111 | ||
| 137 | UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE); | 112 | UHCHIE = (UHCHIE_UPRIE | UHCHIE_RWIE); |
| 113 | |||
| 114 | /* Clear any OTG Pin Hold */ | ||
| 115 | if (PSSR & PSSR_OTGPH) | ||
| 116 | PSSR |= PSSR_OTGPH; | ||
| 138 | } | 117 | } |
| 139 | 118 | ||
| 140 | static void pxa27x_stop_hc(struct platform_device *dev) | 119 | static void pxa27x_stop_hc(struct platform_device *dev) |
| @@ -198,17 +177,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, | |||
| 198 | pxa27x_start_hc(dev); | 177 | pxa27x_start_hc(dev); |
| 199 | 178 | ||
| 200 | /* Select Power Management Mode */ | 179 | /* Select Power Management Mode */ |
| 201 | pxa27x_ohci_select_pmm( PMM_PERPORT_MODE ); | 180 | pxa27x_ohci_select_pmm(pxa27x_ohci_pmm_state); |
| 202 | |||
| 203 | /* If choosing PMM_PERPORT_MODE, we should set the port power before we use it. */ | ||
| 204 | if (pxa27x_ohci_set_port_power(1) < 0) | ||
| 205 | printk(KERN_ERR "Setting port 1 power failed.\n"); | ||
| 206 | |||
| 207 | if (pxa27x_ohci_clear_port_power(2) < 0) | ||
| 208 | printk(KERN_ERR "Setting port 2 power failed.\n"); | ||
| 209 | |||
| 210 | if (pxa27x_ohci_clear_port_power(3) < 0) | ||
| 211 | printk(KERN_ERR "Setting port 3 power failed.\n"); | ||
| 212 | 181 | ||
| 213 | ohci_hcd_init(hcd_to_ohci(hcd)); | 182 | ohci_hcd_init(hcd_to_ohci(hcd)); |
| 214 | 183 | ||
| @@ -258,6 +227,9 @@ ohci_pxa27x_start (struct usb_hcd *hcd) | |||
| 258 | 227 | ||
| 259 | ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci); | 228 | ohci_dbg (ohci, "ohci_pxa27x_start, ohci:%p", ohci); |
| 260 | 229 | ||
| 230 | /* The value of NDP in roothub_a is incorrect on this hardware */ | ||
| 231 | ohci->num_ports = 3; | ||
| 232 | |||
| 261 | if ((ret = ohci_init(ohci)) < 0) | 233 | if ((ret = ohci_init(ohci)) < 0) |
| 262 | return ret; | 234 | return ret; |
| 263 | 235 | ||
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index e9401662503c..3d9bcf78a9a4 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c | |||
| @@ -129,7 +129,7 @@ static void s3c2410_usb_set_power(struct s3c2410_hcd_info *info, | |||
| 129 | 129 | ||
| 130 | if (info->power_control != NULL) { | 130 | if (info->power_control != NULL) { |
| 131 | info->port[port-1].power = to; | 131 | info->port[port-1].power = to; |
| 132 | (info->power_control)(port, to); | 132 | (info->power_control)(port-1, to); |
| 133 | } | 133 | } |
| 134 | } | 134 | } |
| 135 | 135 | ||
| @@ -339,8 +339,8 @@ int usb_hcd_s3c2410_probe (const struct hc_driver *driver, | |||
| 339 | struct usb_hcd *hcd = NULL; | 339 | struct usb_hcd *hcd = NULL; |
| 340 | int retval; | 340 | int retval; |
| 341 | 341 | ||
| 342 | s3c2410_usb_set_power(dev->dev.platform_data, 0, 1); | ||
| 343 | s3c2410_usb_set_power(dev->dev.platform_data, 1, 1); | 342 | s3c2410_usb_set_power(dev->dev.platform_data, 1, 1); |
| 343 | s3c2410_usb_set_power(dev->dev.platform_data, 2, 1); | ||
| 344 | 344 | ||
| 345 | hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx"); | 345 | hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx"); |
| 346 | if (hcd == NULL) | 346 | if (hcd == NULL) |
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 71cdd2262860..8a9b9d9209e9 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
| @@ -383,6 +383,7 @@ struct ohci_hcd { | |||
| 383 | /* | 383 | /* |
| 384 | * driver state | 384 | * driver state |
| 385 | */ | 385 | */ |
| 386 | int num_ports; | ||
| 386 | int load [NUM_INTS]; | 387 | int load [NUM_INTS]; |
| 387 | u32 hc_control; /* copy of hc control reg */ | 388 | u32 hc_control; /* copy of hc control reg */ |
| 388 | unsigned long next_statechange; /* suspend/resume */ | 389 | unsigned long next_statechange; /* suspend/resume */ |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 0d5d2545bf07..0c024898cbea 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
| @@ -97,14 +97,9 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | |||
| 97 | /* to make sure it doesn't hog all of the bandwidth */ | 97 | /* to make sure it doesn't hog all of the bandwidth */ |
| 98 | #define DEPTH_INTERVAL 5 | 98 | #define DEPTH_INTERVAL 5 |
| 99 | 99 | ||
| 100 | static inline void restart_timer(struct uhci_hcd *uhci) | ||
| 101 | { | ||
| 102 | mod_timer(&uhci->stall_timer, jiffies + msecs_to_jiffies(100)); | ||
| 103 | } | ||
| 104 | |||
| 105 | #include "uhci-hub.c" | ||
| 106 | #include "uhci-debug.c" | 100 | #include "uhci-debug.c" |
| 107 | #include "uhci-q.c" | 101 | #include "uhci-q.c" |
| 102 | #include "uhci-hub.c" | ||
| 108 | 103 | ||
| 109 | /* | 104 | /* |
| 110 | * Make sure the controller is completely inactive, unable to | 105 | * Make sure the controller is completely inactive, unable to |
| @@ -160,7 +155,6 @@ static void hc_died(struct uhci_hcd *uhci) | |||
| 160 | { | 155 | { |
| 161 | reset_hc(uhci); | 156 | reset_hc(uhci); |
| 162 | uhci->hc_inaccessible = 1; | 157 | uhci->hc_inaccessible = 1; |
| 163 | del_timer(&uhci->stall_timer); | ||
| 164 | } | 158 | } |
| 165 | 159 | ||
| 166 | /* | 160 | /* |
| @@ -287,8 +281,11 @@ __acquires(uhci->lock) | |||
| 287 | /* Enable resume-detect interrupts if they work. | 281 | /* Enable resume-detect interrupts if they work. |
| 288 | * Then enter Global Suspend mode, still configured. | 282 | * Then enter Global Suspend mode, still configured. |
| 289 | */ | 283 | */ |
| 290 | int_enable = (resume_detect_interrupts_are_broken(uhci) ? | 284 | uhci->working_RD = 1; |
| 291 | 0 : USBINTR_RESUME); | 285 | int_enable = USBINTR_RESUME; |
| 286 | if (resume_detect_interrupts_are_broken(uhci)) { | ||
| 287 | uhci->working_RD = int_enable = 0; | ||
| 288 | } | ||
| 292 | outw(int_enable, uhci->io_addr + USBINTR); | 289 | outw(int_enable, uhci->io_addr + USBINTR); |
| 293 | outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); | 290 | outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); |
| 294 | mb(); | 291 | mb(); |
| @@ -315,7 +312,6 @@ __acquires(uhci->lock) | |||
| 315 | 312 | ||
| 316 | uhci->rh_state = new_state; | 313 | uhci->rh_state = new_state; |
| 317 | uhci->is_stopped = UHCI_IS_STOPPED; | 314 | uhci->is_stopped = UHCI_IS_STOPPED; |
| 318 | del_timer(&uhci->stall_timer); | ||
| 319 | uhci_to_hcd(uhci)->poll_rh = !int_enable; | 315 | uhci_to_hcd(uhci)->poll_rh = !int_enable; |
| 320 | 316 | ||
| 321 | uhci_scan_schedule(uhci, NULL); | 317 | uhci_scan_schedule(uhci, NULL); |
| @@ -335,7 +331,6 @@ static void start_rh(struct uhci_hcd *uhci) | |||
| 335 | mb(); | 331 | mb(); |
| 336 | uhci->rh_state = UHCI_RH_RUNNING; | 332 | uhci->rh_state = UHCI_RH_RUNNING; |
| 337 | uhci_to_hcd(uhci)->poll_rh = 1; | 333 | uhci_to_hcd(uhci)->poll_rh = 1; |
| 338 | restart_timer(uhci); | ||
| 339 | } | 334 | } |
| 340 | 335 | ||
| 341 | static void wakeup_rh(struct uhci_hcd *uhci) | 336 | static void wakeup_rh(struct uhci_hcd *uhci) |
| @@ -374,20 +369,6 @@ __acquires(uhci->lock) | |||
| 374 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); | 369 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); |
| 375 | } | 370 | } |
| 376 | 371 | ||
| 377 | static void stall_callback(unsigned long _uhci) | ||
| 378 | { | ||
| 379 | struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci; | ||
| 380 | unsigned long flags; | ||
| 381 | |||
| 382 | spin_lock_irqsave(&uhci->lock, flags); | ||
| 383 | uhci_scan_schedule(uhci, NULL); | ||
| 384 | check_fsbr(uhci); | ||
| 385 | |||
| 386 | if (!uhci->is_stopped) | ||
| 387 | restart_timer(uhci); | ||
| 388 | spin_unlock_irqrestore(&uhci->lock, flags); | ||
| 389 | } | ||
| 390 | |||
| 391 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | 372 | static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) |
| 392 | { | 373 | { |
| 393 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 374 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
| @@ -418,8 +399,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
| 418 | "host controller halted, " | 399 | "host controller halted, " |
| 419 | "very bad!\n"); | 400 | "very bad!\n"); |
| 420 | hc_died(uhci); | 401 | hc_died(uhci); |
| 421 | spin_unlock_irqrestore(&uhci->lock, flags); | 402 | |
| 422 | return IRQ_HANDLED; | 403 | /* Force a callback in case there are |
| 404 | * pending unlinks */ | ||
| 405 | mod_timer(&hcd->rh_timer, jiffies); | ||
| 423 | } | 406 | } |
| 424 | spin_unlock_irqrestore(&uhci->lock, flags); | 407 | spin_unlock_irqrestore(&uhci->lock, flags); |
| 425 | } | 408 | } |
| @@ -427,10 +410,11 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
| 427 | 410 | ||
| 428 | if (status & USBSTS_RD) | 411 | if (status & USBSTS_RD) |
| 429 | usb_hcd_poll_rh_status(hcd); | 412 | usb_hcd_poll_rh_status(hcd); |
| 430 | 413 | else { | |
| 431 | spin_lock_irqsave(&uhci->lock, flags); | 414 | spin_lock_irqsave(&uhci->lock, flags); |
| 432 | uhci_scan_schedule(uhci, regs); | 415 | uhci_scan_schedule(uhci, regs); |
| 433 | spin_unlock_irqrestore(&uhci->lock, flags); | 416 | spin_unlock_irqrestore(&uhci->lock, flags); |
| 417 | } | ||
| 434 | 418 | ||
| 435 | return IRQ_HANDLED; | 419 | return IRQ_HANDLED; |
| 436 | } | 420 | } |
| @@ -595,10 +579,6 @@ static int uhci_start(struct usb_hcd *hcd) | |||
| 595 | 579 | ||
| 596 | init_waitqueue_head(&uhci->waitqh); | 580 | init_waitqueue_head(&uhci->waitqh); |
| 597 | 581 | ||
| 598 | init_timer(&uhci->stall_timer); | ||
| 599 | uhci->stall_timer.function = stall_callback; | ||
| 600 | uhci->stall_timer.data = (unsigned long) uhci; | ||
| 601 | |||
| 602 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | 582 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), |
| 603 | &dma_handle, 0); | 583 | &dma_handle, 0); |
| 604 | if (!uhci->fl) { | 584 | if (!uhci->fl) { |
| @@ -745,11 +725,11 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
| 745 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 725 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
| 746 | 726 | ||
| 747 | spin_lock_irq(&uhci->lock); | 727 | spin_lock_irq(&uhci->lock); |
| 748 | reset_hc(uhci); | 728 | if (!uhci->hc_inaccessible) |
| 729 | reset_hc(uhci); | ||
| 749 | uhci_scan_schedule(uhci, NULL); | 730 | uhci_scan_schedule(uhci, NULL); |
| 750 | spin_unlock_irq(&uhci->lock); | 731 | spin_unlock_irq(&uhci->lock); |
| 751 | 732 | ||
| 752 | del_timer_sync(&uhci->stall_timer); | ||
| 753 | release_uhci(uhci); | 733 | release_uhci(uhci); |
| 754 | } | 734 | } |
| 755 | 735 | ||
| @@ -811,13 +791,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
| 811 | */ | 791 | */ |
| 812 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); | 792 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); |
| 813 | uhci->hc_inaccessible = 1; | 793 | uhci->hc_inaccessible = 1; |
| 794 | hcd->poll_rh = 0; | ||
| 814 | 795 | ||
| 815 | /* FIXME: Enable non-PME# remote wakeup? */ | 796 | /* FIXME: Enable non-PME# remote wakeup? */ |
| 816 | 797 | ||
| 817 | done: | 798 | done: |
| 818 | spin_unlock_irq(&uhci->lock); | 799 | spin_unlock_irq(&uhci->lock); |
| 819 | if (rc == 0) | ||
| 820 | del_timer_sync(&hcd->rh_timer); | ||
| 821 | return rc; | 800 | return rc; |
| 822 | } | 801 | } |
| 823 | 802 | ||
| @@ -850,8 +829,11 @@ static int uhci_resume(struct usb_hcd *hcd) | |||
| 850 | 829 | ||
| 851 | spin_unlock_irq(&uhci->lock); | 830 | spin_unlock_irq(&uhci->lock); |
| 852 | 831 | ||
| 853 | if (hcd->poll_rh) | 832 | if (!uhci->working_RD) { |
| 833 | /* Suspended root hub needs to be polled */ | ||
| 834 | hcd->poll_rh = 1; | ||
| 854 | usb_hcd_poll_rh_status(hcd); | 835 | usb_hcd_poll_rh_status(hcd); |
| 836 | } | ||
| 855 | return 0; | 837 | return 0; |
| 856 | } | 838 | } |
| 857 | #endif | 839 | #endif |
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index bf9c5f9b508b..282f40b75881 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h | |||
| @@ -345,9 +345,6 @@ enum uhci_rh_state { | |||
| 345 | 345 | ||
| 346 | /* | 346 | /* |
| 347 | * This describes the full uhci information. | 347 | * This describes the full uhci information. |
| 348 | * | ||
| 349 | * Note how the "proper" USB information is just | ||
| 350 | * a subset of what the full implementation needs. | ||
| 351 | */ | 348 | */ |
| 352 | struct uhci_hcd { | 349 | struct uhci_hcd { |
| 353 | 350 | ||
| @@ -360,8 +357,6 @@ struct uhci_hcd { | |||
| 360 | struct dma_pool *qh_pool; | 357 | struct dma_pool *qh_pool; |
| 361 | struct dma_pool *td_pool; | 358 | struct dma_pool *td_pool; |
| 362 | 359 | ||
| 363 | struct usb_bus *bus; | ||
| 364 | |||
| 365 | struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ | 360 | struct uhci_td *term_td; /* Terminating TD, see UHCI bug */ |
| 366 | struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ | 361 | struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ |
| 367 | 362 | ||
| @@ -380,6 +375,8 @@ struct uhci_hcd { | |||
| 380 | unsigned int scan_in_progress:1; /* Schedule scan is running */ | 375 | unsigned int scan_in_progress:1; /* Schedule scan is running */ |
| 381 | unsigned int need_rescan:1; /* Redo the schedule scan */ | 376 | unsigned int need_rescan:1; /* Redo the schedule scan */ |
| 382 | unsigned int hc_inaccessible:1; /* HC is suspended or dead */ | 377 | unsigned int hc_inaccessible:1; /* HC is suspended or dead */ |
| 378 | unsigned int working_RD:1; /* Suspended root hub doesn't | ||
| 379 | need to be polled */ | ||
| 383 | 380 | ||
| 384 | /* Support for port suspend/resume/reset */ | 381 | /* Support for port suspend/resume/reset */ |
| 385 | unsigned long port_c_suspend; /* Bit-arrays of ports */ | 382 | unsigned long port_c_suspend; /* Bit-arrays of ports */ |
| @@ -405,9 +402,7 @@ struct uhci_hcd { | |||
| 405 | /* List of URB's awaiting completion callback */ | 402 | /* List of URB's awaiting completion callback */ |
| 406 | struct list_head complete_list; /* P: uhci->lock */ | 403 | struct list_head complete_list; /* P: uhci->lock */ |
| 407 | 404 | ||
| 408 | int rh_numports; | 405 | int rh_numports; /* Number of root-hub ports */ |
| 409 | |||
| 410 | struct timer_list stall_timer; | ||
| 411 | 406 | ||
| 412 | wait_queue_head_t waitqh; /* endpoint_disable waiters */ | 407 | wait_queue_head_t waitqh; /* endpoint_disable waiters */ |
| 413 | }; | 408 | }; |
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 4eace2b19ddb..a71e48a66805 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
| @@ -145,15 +145,16 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
| 145 | { | 145 | { |
| 146 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 146 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
| 147 | unsigned long flags; | 147 | unsigned long flags; |
| 148 | int status; | 148 | int status = 0; |
| 149 | 149 | ||
| 150 | spin_lock_irqsave(&uhci->lock, flags); | 150 | spin_lock_irqsave(&uhci->lock, flags); |
| 151 | if (uhci->hc_inaccessible) { | ||
| 152 | status = 0; | ||
| 153 | goto done; | ||
| 154 | } | ||
| 155 | 151 | ||
| 152 | uhci_scan_schedule(uhci, NULL); | ||
| 153 | if (uhci->hc_inaccessible) | ||
| 154 | goto done; | ||
| 155 | check_fsbr(uhci); | ||
| 156 | uhci_check_ports(uhci); | 156 | uhci_check_ports(uhci); |
| 157 | |||
| 157 | status = get_hub_status_data(uhci, buf); | 158 | status = get_hub_status_data(uhci, buf); |
| 158 | 159 | ||
| 159 | switch (uhci->rh_state) { | 160 | switch (uhci->rh_state) { |
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index bbb36cd6ed61..ea0d168a8c67 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c | |||
| @@ -33,7 +33,7 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci); | |||
| 33 | static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) | 33 | static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci) |
| 34 | { | 34 | { |
| 35 | if (uhci->is_stopped) | 35 | if (uhci->is_stopped) |
| 36 | mod_timer(&uhci->stall_timer, jiffies); | 36 | mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies); |
| 37 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); | 37 | uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); |
| 38 | } | 38 | } |
| 39 | 39 | ||
