summaryrefslogtreecommitdiff
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r--drivers/usb/host/ehci-hcd.c72
1 files changed, 27 insertions, 45 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 46ee7f4c0912..b62b3f79399b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -57,35 +57,6 @@
* Special thanks to Intel and VIA for providing host controllers to
* test this driver on, and Cypress (including In-System Design) for
* providing early devices for those host controllers to talk to!
- *
- * HISTORY:
- *
- * 2004-05-10 Root hub and PCI suspend/resume support; remote wakeup. (db)
- * 2004-02-24 Replace pci_* with generic dma_* API calls (dsaxena@plexity.net)
- * 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka,
- * <sojkam@centrum.cz>, updates by DB).
- *
- * 2002-11-29 Correct handling for hw async_next register.
- * 2002-08-06 Handling for bulk and interrupt transfers is mostly shared;
- * only scheduling is different, no arbitrary limitations.
- * 2002-07-25 Sanity check PCI reads, mostly for better cardbus support,
- * clean up HC run state handshaking.
- * 2002-05-24 Preliminary FS/LS interrupts, using scheduling shortcuts
- * 2002-05-11 Clear TT errors for FS/LS ctrl/bulk. Fill in some other
- * missing pieces: enabling 64bit dma, handoff from BIOS/SMM.
- * 2002-05-07 Some error path cleanups to report better errors; wmb();
- * use non-CVS version id; better iso bandwidth claim.
- * 2002-04-19 Control/bulk/interrupt submit no longer uses giveback() on
- * errors in submit path. Bugfixes to interrupt scheduling/processing.
- * 2002-03-05 Initial high-speed ISO support; reduce ITD memory; shift
- * more checking to generic hcd framework (db). Make it work with
- * Philips EHCI; reduce PCI traffic; shorten IRQ path (Rory Bolt).
- * 2002-01-14 Minor cleanup; version synch.
- * 2002-01-08 Fix roothub handoff of FS/LS to companion controllers.
- * 2002-01-04 Control/Bulk queuing behaves.
- *
- * 2001-12-12 Initial patch version for Linux 2.5.1 kernel.
- * 2001-June Works with usb-storage and NEC EHCI on 2.4
*/
#define DRIVER_VERSION "10 Dec 2004"
@@ -95,7 +66,7 @@
static const char hcd_name [] = "ehci_hcd";
-#undef EHCI_VERBOSE_DEBUG
+#undef VERBOSE_DEBUG
#undef EHCI_URB_TRACE
#ifdef DEBUG
@@ -174,6 +145,16 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
return -ETIMEDOUT;
}
+static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
+ u32 mask, u32 done, int usec)
+{
+ int error = handshake(ehci, ptr, mask, done, usec);
+ if (error)
+ ehci_to_hcd(ehci)->state = HC_STATE_HALT;
+
+ return error;
+}
+
/* force HC to halt state from unknown (EHCI spec section 2.3) */
static int ehci_halt (struct ehci_hcd *ehci)
{
@@ -246,11 +227,9 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
/* wait for any schedule enables/disables to take effect */
temp = ehci_readl(ehci, &ehci->regs->command) << 10;
temp &= STS_ASS | STS_PSS;
- if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
- temp, 16 * 125) != 0) {
- ehci_to_hcd(ehci)->state = HC_STATE_HALT;
+ if (handshake_on_error_set_halt(ehci, &ehci->regs->status,
+ STS_ASS | STS_PSS, temp, 16 * 125))
return;
- }
/* then disable anything that's still active */
temp = ehci_readl(ehci, &ehci->regs->command);
@@ -258,11 +237,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
ehci_writel(ehci, temp, &ehci->regs->command);
/* hardware can take 16 microframes to turn off ... */
- if (handshake (ehci, &ehci->regs->status, STS_ASS | STS_PSS,
- 0, 16 * 125) != 0) {
- ehci_to_hcd(ehci)->state = HC_STATE_HALT;
- return;
- }
+ handshake_on_error_set_halt(ehci, &ehci->regs->status,
+ STS_ASS | STS_PSS, 0, 16 * 125);
}
/*-------------------------------------------------------------------------*/
@@ -676,7 +652,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
cmd = ehci_readl(ehci, &ehci->regs->command);
bh = 0;
-#ifdef EHCI_VERBOSE_DEBUG
+#ifdef VERBOSE_DEBUG
/* unrequested/ignored: Frame List Rollover */
dbg_status (ehci, "irq", status);
#endif
@@ -710,6 +686,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* remote wakeup [4.3.1] */
if (status & STS_PCD) {
unsigned i = HCS_N_PORTS (ehci->hcs_params);
+
+ /* kick root hub later */
pcd_status = status;
/* resume root hub? */
@@ -738,8 +716,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* PCI errors [4.15.2.4] */
if (unlikely ((status & STS_FATAL) != 0)) {
- /* bogus "fatal" IRQs appear on some chips... why? */
- status = ehci_readl(ehci, &ehci->regs->status);
dbg_cmd (ehci, "fatal", ehci_readl(ehci,
&ehci->regs->command));
dbg_status (ehci, "fatal", status);
@@ -758,7 +734,7 @@ dead:
if (bh)
ehci_work (ehci);
spin_unlock (&ehci->lock);
- if (pcd_status & STS_PCD)
+ if (pcd_status)
usb_hcd_poll_rh_status(hcd);
return IRQ_HANDLED;
}
@@ -788,8 +764,14 @@ static int ehci_urb_enqueue (
INIT_LIST_HEAD (&qtd_list);
switch (usb_pipetype (urb->pipe)) {
- // case PIPE_CONTROL:
- // case PIPE_BULK:
+ case PIPE_CONTROL:
+ /* qh_completions() code doesn't handle all the fault cases
+ * in multi-TD control transfers. Even 1KB is rare anyway.
+ */
+ if (urb->transfer_buffer_length > (16 * 1024))
+ return -EMSGSIZE;
+ /* FALLTHROUGH */
+ /* case PIPE_BULK: */
default:
if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
return -ENOMEM;