From a8e5177583e975fc1f7c621c93956f494df9b979 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 20 May 2008 16:58:11 -0400 Subject: USB: EHCI: fix up root-hub TT mess This patch (as1095) cleans up the HCD glue and several of the EHCI bus-glue files. The ehci->is_tdi_rh_tt flag is redundant, since it means the same thing as the hcd->has_tt flag, so it is removed and the other flag used in its place. Some of the bus-glue files didn't get the relinquish_port method added to their hc_driver structures. Although that routine currently doesn't do anything for controllers with an integrated TT, in the future it might. So the patch adds it where it is missing. Lastly, some of the bus-glue files have erroneous entries for their hc_driver's suspend and resume methods. These method pointers are specific to PCI and shouldn't be used otherwise. (The patch also includes an invisible whitespace fix.) Signed-off-by: Alan Stern Acked-by: David Brownell --- drivers/usb/host/ehci-fsl.c | 6 +----- drivers/usb/host/ehci-ixp4xx.c | 3 ++- drivers/usb/host/ehci-orion.c | 7 ++----- drivers/usb/host/ehci-pci.c | 3 +-- drivers/usb/host/ehci-ppc-of.c | 1 + drivers/usb/host/ehci.h | 3 +-- 6 files changed, 8 insertions(+), 15 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 6d9bed6c1f48..4843062e6e21 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -269,7 +269,7 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) if (retval) return retval; - ehci->is_tdi_rh_tt = 1; + hcd->has_tt = 1; ehci->sbrn = 0x20; @@ -295,10 +295,6 @@ static const struct hc_driver ehci_fsl_hc_driver = { */ .reset = ehci_fsl_setup, .start = ehci_run, -#ifdef CONFIG_PM - .suspend = ehci_bus_suspend, - .resume = ehci_bus_resume, -#endif .stop = ehci_stop, .shutdown = ehci_shutdown, diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index 601c8795a854..539257f15924 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c @@ -26,7 +26,7 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd) + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - ehci->is_tdi_rh_tt = 1; + hcd->has_tt = 1; ehci_reset(ehci); retval = ehci_init(hcd); @@ -58,6 +58,7 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, #endif + .relinquish_port = ehci_relinquish_port, }; static int ixp4xx_ehci_probe(struct platform_device *pdev) diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 3adfda813a7b..9c5266d02d6c 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -139,10 +139,6 @@ static const struct hc_driver ehci_orion_hc_driver = { */ .reset = ehci_orion_setup, .start = ehci_run, -#ifdef CONFIG_PM - .suspend = ehci_bus_suspend, - .resume = ehci_bus_resume, -#endif .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -165,6 +161,7 @@ static const struct hc_driver ehci_orion_hc_driver = { .hub_control = ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, + .relinquish_port = ehci_relinquish_port, }; static void __init @@ -250,7 +247,7 @@ static int __init ehci_orion_drv_probe(struct platform_device *pdev) ehci->regs = hcd->regs + 0x100 + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - ehci->is_tdi_rh_tt = 1; + hcd->has_tt = 1; ehci->sbrn = 0x20; /* diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 5bb7f6bb13f3..6ff453f935e7 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -129,7 +129,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) switch (pdev->vendor) { case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { - ehci->is_tdi_rh_tt = 1; hcd->has_tt = 1; tdi_reset(ehci); } @@ -379,7 +378,7 @@ static const struct hc_driver ehci_pci_hc_driver = { .hub_control = ehci_hub_control, .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, + .relinquish_port = ehci_relinquish_port, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index ee305b1f99ff..d94a2ef4944c 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -76,6 +76,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, #endif + .relinquish_port = ehci_relinquish_port, }; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index bf92d209a1a9..3cb482308343 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -112,7 +112,6 @@ struct ehci_hcd { /* one per controller */ u32 command; /* SILICON QUIRKS */ - unsigned is_tdi_rh_tt:1; /* TDI roothub with TT */ unsigned no_selective_suspend:1; unsigned has_fsl_port_bug:1; /* FreeScale */ unsigned big_endian_mmio:1; @@ -678,7 +677,7 @@ struct ehci_fstn { * needed (mostly in root hub code). */ -#define ehci_is_TDI(e) ((e)->is_tdi_rh_tt) +#define ehci_is_TDI(e) (ehci_to_hcd(e)->has_tt) /* Returns the speed of a device attached to a port on the root hub. */ static inline unsigned int -- cgit v1.2.3 From 3a31155cfff0935e4b178f3dca733d2d60d2eb8d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 20 May 2008 16:58:29 -0400 Subject: USB: EHCI: suppress unwanted error messages This patch (as1096) fixes an annoying problem: When a full-speed or low-speed device is plugged into an EHCI controller, it fails to enumerate at high speed and then is handed over to the companion controller. But usbcore logs a misleading and unwanted error message when the high-speed enumeration fails. The patch adds a new HCD method, port_handed_over, which asks whether a port has been handed over to a companion controller. If it has, the error message is suppressed. Signed-off-by: Alan Stern CC: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-au1xxx.c | 1 + drivers/usb/host/ehci-fsl.c | 1 + drivers/usb/host/ehci-hub.c | 10 ++++++++++ drivers/usb/host/ehci-ixp4xx.c | 1 + drivers/usb/host/ehci-orion.c | 1 + drivers/usb/host/ehci-pci.c | 1 + drivers/usb/host/ehci-ppc-of.c | 1 + drivers/usb/host/ehci-ppc-soc.c | 1 + drivers/usb/host/ehci-ps3.c | 1 + 9 files changed, 18 insertions(+) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 8b5f991e949c..08a4335401a9 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -223,6 +223,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 4843062e6e21..7370d6187c64 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -318,6 +318,7 @@ static const struct hc_driver ehci_fsl_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; static int ehci_fsl_drv_probe(struct platform_device *pdev) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 382587c4457c..d613dc9e9c05 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -875,3 +875,13 @@ static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) set_owner(ehci, --portnum, PORT_OWNER); } +static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + u32 __iomem *reg; + + if (ehci_is_TDI(ehci)) + return 0; + reg = &ehci->regs->port_status[portnum - 1]; + return ehci_readl(ehci, reg) & PORT_OWNER; +} diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index 539257f15924..9d042f220097 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c @@ -59,6 +59,7 @@ static const struct hc_driver ixp4xx_ehci_hc_driver = { .bus_resume = ehci_bus_resume, #endif .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; static int ixp4xx_ehci_probe(struct platform_device *pdev) diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 9c5266d02d6c..ab625f0ba1d9 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -162,6 +162,7 @@ static const struct hc_driver ehci_orion_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; static void __init diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 6ff453f935e7..c46a58f9181d 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -379,6 +379,7 @@ static const struct hc_driver ehci_pci_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index d94a2ef4944c..b018deed2e8f 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -77,6 +77,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { .bus_resume = ehci_bus_resume, #endif .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c index 6c76036783a1..529590eb4037 100644 --- a/drivers/usb/host/ehci-ppc-soc.c +++ b/drivers/usb/host/ehci-ppc-soc.c @@ -163,6 +163,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = { .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 69782221bcf3..37e6abeb794c 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -73,6 +73,7 @@ static const struct hc_driver ps3_ehci_hc_driver = { .bus_resume = ehci_bus_resume, #endif .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, }; static int ps3_ehci_probe(struct ps3_system_bus_device *dev) -- cgit v1.2.3 From d1f114d12bb4db3147e1b1342ae31083c5a79c84 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 20 May 2008 16:58:58 -0400 Subject: USB: EHCI: fix remote-wakeup regression This patch (as1097) fixes a bug in the remote-wakeup handling in ehci-hcd. The driver currently does not keep track of whether the change-suspend feature is enabled for each port; the feature is automatically reset the first time it is read. But recent changes to the hub driver require that the feature be read at least twice in order to work properly. A bit-vector is added for storing the change-suspend feature values. Signed-off-by: Alan Stern Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 6 ++++-- drivers/usb/host/ehci.h | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index d613dc9e9c05..740835bb8575 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -609,7 +609,7 @@ static int ehci_hub_control ( } break; case USB_PORT_FEAT_C_SUSPEND: - /* we auto-clear this feature */ + clear_bit(wIndex, &ehci->port_c_suspend); break; case USB_PORT_FEAT_POWER: if (HCS_PPC (ehci->hcs_params)) @@ -688,7 +688,7 @@ static int ehci_hub_control ( /* resume completed? */ else if (time_after_eq(jiffies, ehci->reset_done[wIndex])) { - status |= 1 << USB_PORT_FEAT_C_SUSPEND; + set_bit(wIndex, &ehci->port_c_suspend); ehci->reset_done[wIndex] = 0; /* stop resume signaling */ @@ -765,6 +765,8 @@ static int ehci_hub_control ( status |= 1 << USB_PORT_FEAT_RESET; if (temp & PORT_POWER) status |= 1 << USB_PORT_FEAT_POWER; + if (test_bit(wIndex, &ehci->port_c_suspend)) + status |= 1 << USB_PORT_FEAT_C_SUSPEND; #ifndef VERBOSE_DEBUG if (status & ~0xffff) /* only if wPortChange is interesting */ diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 3cb482308343..35a03095757e 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -97,6 +97,8 @@ struct ehci_hcd { /* one per controller */ dedicated to the companion controller */ unsigned long owned_ports; /* which ports are owned by the companion during a bus suspend */ + unsigned long port_c_suspend; /* which ports have + the change-suspend feature turned on */ /* per-HC memory pools (could be per-bus, but ...) */ struct dma_pool *qh_pool; /* qh per active urb */ -- cgit v1.2.3 From b40e43fcc532fa44a375a37d592e32cd0d50fe7a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 20 May 2008 16:59:10 -0400 Subject: USB: EHCI: fix bug in Iso scheduling This patch (as1098) changes the way ehci-hcd schedules its periodic Iso transfers. That the current scheduling code is wrong is clear on the face of it: Sometimes it returns -EL2NSYNC (meaning that an URB couldn't be scheduled because it was submitted too late), but it does this even when the URB_ISO_ASAP flag is set (meaning the URB should be scheduled as soon as possible). The new code properly implements as-soon-as-possible scheduling, assigning the next unexpired slot as the URB's starting point. It also is more careful about checking for Iso URB completion: It doesn't bother to check for activity during frames that are already over, and it allows for the possibility that some of the URB's packets may have raced the hardware when they were submitted and so never got used (the packet status is set to -EXDEV). This fixes problems several people have experienced with USB video applications. Signed-off-by: Alan Stern Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 67 ++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 23 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index be575e46eac3..b7853c8bac0f 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1349,18 +1349,27 @@ iso_stream_schedule ( /* when's the last uframe this urb could start? */ max = now + mod; - /* typical case: reuse current schedule. stream is still active, - * and no gaps from host falling behind (irq delays etc) + /* Typical case: reuse current schedule, stream is still active. + * Hopefully there are no gaps from the host falling behind + * (irq delays etc), but if there are we'll take the next + * slot in the schedule, implicitly assuming URB_ISO_ASAP. */ if (likely (!list_empty (&stream->td_list))) { start = stream->next_uframe; if (start < now) start += mod; - if (likely ((start + sched->span) < max)) - goto ready; - /* else fell behind; someday, try to reschedule */ - status = -EL2NSYNC; - goto fail; + + /* Fell behind (by up to twice the slop amount)? */ + if (start >= max - 2 * 8 * SCHEDULE_SLOP) + start += stream->interval * DIV_ROUND_UP( + max - start, stream->interval) - mod; + + /* Tried to schedule too far into the future? */ + if (unlikely((start + sched->span) >= max)) { + status = -EFBIG; + goto fail; + } + goto ready; } /* need to schedule; when's the next (u)frame we could start? @@ -1613,6 +1622,9 @@ itd_complete ( } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { desc->status = 0; desc->actual_length = EHCI_ITD_LENGTH (t); + } else { + /* URB was too late */ + desc->status = -EXDEV; } } @@ -2095,7 +2107,7 @@ done: static void scan_periodic (struct ehci_hcd *ehci) { - unsigned frame, clock, now_uframe, mod; + unsigned now_uframe, frame, clock, clock_frame, mod; unsigned modified; mod = ehci->periodic_size << 3; @@ -2111,6 +2123,7 @@ scan_periodic (struct ehci_hcd *ehci) else clock = now_uframe + mod - 1; clock %= mod; + clock_frame = clock >> 3; for (;;) { union ehci_shadow q, *q_p; @@ -2157,22 +2170,26 @@ restart: case Q_TYPE_ITD: /* If this ITD is still active, leave it for * later processing ... check the next entry. + * No need to check for activity unless the + * frame is current. */ - rmb (); - for (uf = 0; uf < 8 && live; uf++) { - if (0 == (q.itd->hw_transaction [uf] - & ITD_ACTIVE(ehci))) - continue; - incomplete = true; - q_p = &q.itd->itd_next; - hw_p = &q.itd->hw_next; - type = Q_NEXT_TYPE(ehci, + if (frame == clock_frame && live) { + rmb(); + for (uf = 0; uf < 8; uf++) { + if (q.itd->hw_transaction[uf] & + ITD_ACTIVE(ehci)) + break; + } + if (uf < 8) { + incomplete = true; + q_p = &q.itd->itd_next; + hw_p = &q.itd->hw_next; + type = Q_NEXT_TYPE(ehci, q.itd->hw_next); - q = *q_p; - break; + q = *q_p; + break; + } } - if (uf < 8 && live) - break; /* Take finished ITDs out of the schedule * and process them: recycle, maybe report @@ -2189,9 +2206,12 @@ restart: case Q_TYPE_SITD: /* If this SITD is still active, leave it for * later processing ... check the next entry. + * No need to check for activity unless the + * frame is current. */ - if ((q.sitd->hw_results & SITD_ACTIVE(ehci)) - && live) { + if (frame == clock_frame && live && + (q.sitd->hw_results & + SITD_ACTIVE(ehci))) { incomplete = true; q_p = &q.sitd->sitd_next; hw_p = &q.sitd->hw_next; @@ -2260,6 +2280,7 @@ restart: /* rescan the rest of this frame, then ... */ clock = now; + clock_frame = clock >> 3; } else { now_uframe++; now_uframe %= mod; -- cgit v1.2.3 From fa38dfcc56b5f6cce787f9aaa5d1830509213802 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 20 May 2008 16:59:33 -0400 Subject: USB: EHCI: fix performance regression This patch (as1099) fixes a performance regression in ehci-hcd. The fundamental problem is that queue headers get removed from the schedule too quickly, since the code checks for a counter advancing rather than making an actual time-based check. The latency involved in removing the queue header and then relinking it can severely degrade certain kinds of workloads. The patch replaces a simple counter with a timestamp derived from the controller's uframe value. In addition, the delay for unlinking an idle queue header is increased from 5 ms to 10 ms; since some controllers (nVidia) have a latency of up to 1 ms for unlinking, this reduces the relative impact from 20% to 10%. Finally, a logical error left over from the IAA watchdog-timer conversion is corrected. Now the driver will always either unlink an idle queue header or set up a timer to unlink it later. The old code would sometimes fail to do either. Signed-off-by: Alan Stern Cc: David Brownell Cc: Leonid Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 3 ++- drivers/usb/host/ehci-q.c | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 369a8a5ea7bb..3e3c5d3ea0ad 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -84,7 +84,8 @@ static const char hcd_name [] = "ehci_hcd"; #define EHCI_IAA_MSECS 10 /* arbitrary */ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ -#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ +#define EHCI_SHRINK_JIFFIES (HZ/100) /* async qh unlink delay */ +#define EHCI_SHRINK_UFRAMES (10*8) /* same value in uframes */ /* Initial IRQ latency: faster than hw default */ static int log2_irq_thresh = 0; // 0 to 6 diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index b85b54160cda..5200481deb27 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1116,8 +1116,7 @@ static void scan_async (struct ehci_hcd *ehci) struct ehci_qh *qh; enum ehci_timer_action action = TIMER_IO_WATCHDOG; - if (!++(ehci->stamp)) - ehci->stamp++; + ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index); timer_action_done (ehci, TIMER_ASYNC_SHRINK); rescan: qh = ehci->async->qh_next.qh; @@ -1148,12 +1147,14 @@ rescan: * doesn't stay idle for long. * (plus, avoids some kind of re-activation race.) */ - if (list_empty (&qh->qtd_list)) { - if (qh->stamp == ehci->stamp) + if (list_empty(&qh->qtd_list) && + qh->qh_state == QH_STATE_LINKED) { + if (!ehci->reclaim && + ((ehci->stamp - qh->stamp) & 8191) >= + EHCI_SHRINK_UFRAMES) + start_unlink_async(ehci, qh); + else action = TIMER_ASYNC_SHRINK; - else if (!ehci->reclaim - && qh->qh_state == QH_STATE_LINKED) - start_unlink_async (ehci, qh); } qh = qh->qh_next.qh; -- cgit v1.2.3 From bb7e6984ecaebe6989d0e781e303469255871432 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 29 May 2008 19:43:27 -0700 Subject: Revert "USB: EHCI: fix performance regression" This reverts commit fa38dfcc56b5f6cce787f9aaa5d1830509213802. It wasn't really a regression and David and Alan are still working through the issues reported. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 3 +-- drivers/usb/host/ehci-q.c | 15 +++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 3e3c5d3ea0ad..369a8a5ea7bb 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -84,8 +84,7 @@ static const char hcd_name [] = "ehci_hcd"; #define EHCI_IAA_MSECS 10 /* arbitrary */ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ -#define EHCI_SHRINK_JIFFIES (HZ/100) /* async qh unlink delay */ -#define EHCI_SHRINK_UFRAMES (10*8) /* same value in uframes */ +#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ /* Initial IRQ latency: faster than hw default */ static int log2_irq_thresh = 0; // 0 to 6 diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 5200481deb27..b85b54160cda 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1116,7 +1116,8 @@ static void scan_async (struct ehci_hcd *ehci) struct ehci_qh *qh; enum ehci_timer_action action = TIMER_IO_WATCHDOG; - ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index); + if (!++(ehci->stamp)) + ehci->stamp++; timer_action_done (ehci, TIMER_ASYNC_SHRINK); rescan: qh = ehci->async->qh_next.qh; @@ -1147,14 +1148,12 @@ rescan: * doesn't stay idle for long. * (plus, avoids some kind of re-activation race.) */ - if (list_empty(&qh->qtd_list) && - qh->qh_state == QH_STATE_LINKED) { - if (!ehci->reclaim && - ((ehci->stamp - qh->stamp) & 8191) >= - EHCI_SHRINK_UFRAMES) - start_unlink_async(ehci, qh); - else + if (list_empty (&qh->qtd_list)) { + if (qh->stamp == ehci->stamp) action = TIMER_ASYNC_SHRINK; + else if (!ehci->reclaim + && qh->qh_state == QH_STATE_LINKED) + start_unlink_async (ehci, qh); } qh = qh->qh_next.qh; -- cgit v1.2.3 From 6399e7acbf9193c7d48827329ca592a1c8dc9e69 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 2 Jun 2008 10:59:02 +0100 Subject: isp1760-if iomem annotations Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/usb/host/isp1760-if.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 440bf94f0d4c..c9db3fe98726 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -104,8 +104,8 @@ static u32 nxp_pci_io_base; static u32 iolength; static u32 pci_mem_phy0; static u32 length; -static u8 *chip_addr; -static u8 *iobase; +static u8 __iomem *chip_addr; +static u8 __iomem *iobase; static int __devinit isp1761_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -- cgit v1.2.3 From 77d11ba993bf1258f242b6a4ee0230aec8c6c8a4 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 9 Jun 2008 16:00:32 +0900 Subject: usb: r8a66597-hcd: Add support for SH7723 USB host R8A66597 is similar to SH7723 USB 2.0 Host/Function module. In addition, the USB of SH7366 is compatible with SH7723. It can support SH7723 USB host by changing Kconfig. Signed-off-by: Yoshihiro Shimoda Acked-by: Greg Kroah-Hartman Signed-off-by: Paul Mundt --- drivers/usb/host/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 1ef6df395e0c..228797e54f9c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -300,8 +300,8 @@ config USB_R8A66597_HCD module will be called r8a66597-hcd. config SUPERH_ON_CHIP_R8A66597 - boolean "Enable SuperH on-chip USB like the R8A66597" - depends on USB_R8A66597_HCD && CPU_SUBTYPE_SH7366 + boolean "Enable SuperH on-chip R8A66597 USB" + depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723) help - Renesas SuperH processor has USB like the R8A66597. - This driver supported processor is SH7366. + This driver enables support for the on-chip R8A66597 in the + SH7366 and SH7723 processors. -- cgit v1.2.3 From e6942d633be61f1638e08c56ab8244fc9f1c61e3 Mon Sep 17 00:00:00 2001 From: Nate Case Date: Wed, 21 May 2008 16:28:20 -0500 Subject: USB: isp1760: Assign resource fields before adding hcd This fixes the bogus "io mem 0x00000000" message printed during driver init due to hcd->rsrc_start being assigned after the call to usb_add_hcd(). Signed-off-by: Nate Case Acked-by: Sebastian Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index c9cec8738261..65aa5ecf569a 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2207,14 +2207,14 @@ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, goto err_put; } - ret = usb_add_hcd(hcd, irq, irqflags); - if (ret) - goto err_unmap; - hcd->irq = irq; hcd->rsrc_start = res_start; hcd->rsrc_len = res_len; + ret = usb_add_hcd(hcd, irq, irqflags); + if (ret) + goto err_unmap; + return hcd; err_unmap: -- cgit v1.2.3