From 129bd474a80726247e5b1c61fe66a413e63053bc Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 20 May 2008 19:08:53 +0200 Subject: USB: ehci-orion: the Orion EHCI root hub does have a Transaction Translator Commit 7329e211b987a493cbcfca0e98c60eb108ab42df ("USB: root hubs don't lie about their number of TTs") requires the various platform EHCI glue modules to set ->has_tt if the root hub has a Transaction Translator. The Orion EHCI root hub does have a Transaction Translator, so set ->has_tt in ehci_orion_setup(). This fixes oopsing on plugging in a low speed device. Signed-off-by: Lennert Buytenhek Acked-by: Nicolas Pitre Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-orion.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index d187d0313742..3adfda813a7b 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -115,6 +115,8 @@ static int ehci_orion_setup(struct usb_hcd *hcd) if (retval) return retval; + hcd->has_tt = 1; + ehci_reset(ehci); ehci_port_power(ehci, 0); -- cgit v1.2.3 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/core/hcd.h | 2 ++ drivers/usb/core/hub.c | 6 +++++- 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 + 11 files changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 1e4b81e9eb50..a0bf5df6cb6f 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -213,6 +213,8 @@ struct hc_driver { /* force handover of high-speed port to full-speed companion */ void (*relinquish_port)(struct usb_hcd *, int); + /* has a port been handed over to a companion? */ + int (*port_handed_over)(struct usb_hcd *, int); }; extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1a3d2879bc1d..8eb4da332f56 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2753,7 +2753,11 @@ loop: if ((status == -ENOTCONN) || (status == -ENOTSUPP)) break; } - dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1); + if (hub->hdev->parent || + !hcd->driver->port_handed_over || + !(hcd->driver->port_handed_over)(hcd, port1)) + dev_err(hub_dev, "unable to enumerate USB device on port %d\n", + port1); done: hub_port_disable(hub, port1, 1); 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 From 3ee38d8bf46b364b1ca364ddb7c379a4afcd8bbb Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sun, 8 Jun 2008 17:20:11 +0100 Subject: OHCI: Fix problem if SM501 and another platform driver is selected If the SM501 and another platform driver, such as the SM501 then we end up defining PLATFORM_DRIVER twice. This patch seperated the SM501 onto a seperate define of SM501_OHCI_DRIVER so that it can be selected without overwriting the original definition. Signed-off-by: Ben Dooks Acked-by: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 33f1c1c32edf..a8160d65f32b 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1054,7 +1054,7 @@ MODULE_LICENSE ("GPL"); #ifdef CONFIG_MFD_SM501 #include "ohci-sm501.c" -#define PLATFORM_DRIVER ohci_hcd_sm501_driver +#define SM501_OHCI_DRIVER ohci_hcd_sm501_driver #endif #if !defined(PCI_DRIVER) && \ @@ -1062,6 +1062,7 @@ MODULE_LICENSE ("GPL"); !defined(OF_PLATFORM_DRIVER) && \ !defined(SA1111_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && \ + !defined(SM501_OHCI_DRIVER) && \ !defined(SSB_OHCI_DRIVER) #error "missing bus glue for ohci-hcd" #endif @@ -1121,9 +1122,18 @@ static int __init ohci_hcd_mod_init(void) goto error_ssb; #endif +#ifdef SM501_OHCI_DRIVER + retval = platform_driver_register(&SM501_OHCI_DRIVER); + if (retval < 0) + goto error_sm501; +#endif + return retval; /* Error path */ +#ifdef SM501_OHCI_DRIVER + error_sm501: +#endif #ifdef SSB_OHCI_DRIVER error_ssb: #endif @@ -1159,6 +1169,9 @@ module_init(ohci_hcd_mod_init); static void __exit ohci_hcd_mod_exit(void) { +#ifdef SM501_OHCI_DRIVER + platform_driver_unregister(&SM501_OHCI_DRIVER); +#endif #ifdef SSB_OHCI_DRIVER ssb_driver_unregister(&SSB_OHCI_DRIVER); #endif -- cgit v1.2.3 From 056761e55c8687ddf3db14226213f2e8dc2689bc Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 13 Jun 2008 23:56:48 -0700 Subject: USB: ehci - fix timer regression This patch fixes a regression in the EHCI driver's TIMER_IO_WATCHDOG behavior. The patch "USB: EHCI: add separate IAA watchdog timer" changed how that timer is handled, so that short timeouts on the remaining timer (unfortunately, overloaded) would never be used. This takes a more direct approach, reorganizing the code slightly to be explicit about only the I/O watchdog role now being overridable. It also replaces a now-obsolete comment describing older timer behavior. Signed-off-by: David Brownell Cc: Alan Stern Cc: Leonid Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 35a03095757e..90245fd8bac4 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -177,6 +177,15 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) static inline void timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) { + /* Don't override timeouts which shrink or (later) disable + * the async ring; just the I/O watchdog. Note that if a + * SHRINK were pending, OFF would never be requested. + */ + if (timer_pending(&ehci->watchdog) + && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) + & ehci->actions)) + return; + if (!test_and_set_bit (action, &ehci->actions)) { unsigned long t; @@ -192,15 +201,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) t = EHCI_SHRINK_JIFFIES; break; } - t += jiffies; - // all timings except IAA watchdog can be overridden. - // async queue SHRINK often precedes IAA. while it's ready - // to go OFF neither can matter, and afterwards the IO - // watchdog stops unless there's still periodic traffic. - if (time_before_eq(t, ehci->watchdog.expires) - && timer_pending (&ehci->watchdog)) - return; - mod_timer (&ehci->watchdog, t); + mod_timer(&ehci->watchdog, t + jiffies); } } -- cgit v1.2.3 From 29c8f6a727a683b5988877dd80dbdefd49e64a51 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 13 Jun 2008 23:59:54 -0700 Subject: USB: ohci - record data toggle after unlink This patch fixes a problem with OHCI where canceling bulk or interrupt URBs may lose track of the right data toggle. This seems to be a longstanding bug, possibly dating back to the Linux 2.4 kernel, which stayed hidden because (a) about half the time the data toggle bit was correct; (b) canceling such URBs is unusual; and (c) the few drivers which cancel these URBs either [1] do it only as part of shutting down, or [2] have fault recovery logic, which recovers. For those transfer types, the toggle is normally written back into the ED when each TD is retired. But canceling bypasses the mechanism used to retire TDs ... so on average, half the time the toggle bit will be invalid after cancelation. The fix is simple: the toggle state of any canceled TDs are propagated back to the ED in the finish_unlinks function. (Issue found by leonidv11@gmail.com ...) Signed-off-by: David Brownell Cc: Leonid Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-q.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 9c9f3b59186f..9b547407c934 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -952,6 +952,7 @@ rescan_this: struct urb *urb; urb_priv_t *urb_priv; __hc32 savebits; + u32 tdINFO; td = list_entry (entry, struct td, td_list); urb = td->urb; @@ -966,6 +967,17 @@ rescan_this: savebits = *prev & ~cpu_to_hc32 (ohci, TD_MASK); *prev = td->hwNextTD | savebits; + /* If this was unlinked, the TD may not have been + * retired ... so manually save the data toggle. + * The controller ignores the value we save for + * control and ISO endpoints. + */ + tdINFO = hc32_to_cpup(ohci, &td->hwINFO); + if ((tdINFO & TD_T) == TD_T_DATA0) + ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_C); + else if ((tdINFO & TD_T) == TD_T_DATA1) + ed->hwHeadP |= cpu_to_hc32(ohci, ED_C); + /* HC may have partly processed this TD */ td_done (ohci, urb, td); urb_priv->td_cnt++; -- cgit v1.2.3 From 09ca8adbe9f724a7e96f512c0039c4c4a1c5dcc0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 6 Jul 2008 10:27:25 -0700 Subject: Revert "USB: don't explicitly reenable root-hub status interrupts" This reverts commit e872154921a6b5256a3c412dd69158ac0b135176. Andrey Borzenkov reports that it resulted in a totally hung machine for him when loading the OHCI driver. Extensive netconsole capture with SysRq output shows that modprobe gets stuck in ohci_hub_status_data() when probing and enabling the OHCI controller, see for example http://lkml.org/lkml/2008/7/5/236 for an analysis. The problem appears to be an interrupt flood triggered by the commit that gets reverted, and Andrey confirmed that the revert makes things work for him again. Reported-and-tested-by: Andrey Borzenkov Acked-by: Alan Stern Acked-by: David Brownell Cc: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/usb/core/hcd.c | 9 +++++++ drivers/usb/core/hcd.h | 2 ++ drivers/usb/core/hub.c | 9 +++++++ drivers/usb/host/ohci-at91.c | 1 + drivers/usb/host/ohci-au1xxx.c | 1 + drivers/usb/host/ohci-ep93xx.c | 1 + drivers/usb/host/ohci-hub.c | 53 +++++++++++++++++------------------------ drivers/usb/host/ohci-lh7a404.c | 1 + drivers/usb/host/ohci-omap.c | 1 + drivers/usb/host/ohci-pci.c | 1 + drivers/usb/host/ohci-pnx4008.c | 1 + drivers/usb/host/ohci-pnx8550.c | 1 + drivers/usb/host/ohci-ppc-of.c | 1 + drivers/usb/host/ohci-ppc-soc.c | 1 + drivers/usb/host/ohci-ps3.c | 1 + drivers/usb/host/ohci-pxa27x.c | 1 + drivers/usb/host/ohci-s3c2410.c | 1 + drivers/usb/host/ohci-sa1111.c | 1 + drivers/usb/host/ohci-sh.c | 1 + drivers/usb/host/ohci-sm501.c | 1 + drivers/usb/host/ohci-ssb.c | 1 + drivers/usb/host/u132-hcd.c | 11 +++++++++ 22 files changed, 70 insertions(+), 31 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 7158dbb6e4b4..42a436478b78 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -924,6 +924,15 @@ static int register_root_hub(struct usb_hcd *hcd) return retval; } +void usb_enable_root_hub_irq (struct usb_bus *bus) +{ + struct usb_hcd *hcd; + + hcd = container_of (bus, struct usb_hcd, self); + if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT) + hcd->driver->hub_irq_enable (hcd); +} + /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index a0bf5df6cb6f..b9de1569b39e 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -210,6 +210,8 @@ struct hc_driver { int (*bus_suspend)(struct usb_hcd *); int (*bus_resume)(struct usb_hcd *); int (*start_port_reset)(struct usb_hcd *, unsigned port_num); + void (*hub_irq_enable)(struct usb_hcd *); + /* Needed only if port-change IRQs are level-triggered */ /* force handover of high-speed port to full-speed companion */ void (*relinquish_port)(struct usb_hcd *, int); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 512d2d57d41e..4cfe32a16c37 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2073,6 +2073,8 @@ int usb_port_resume(struct usb_device *udev) } clear_bit(port1, hub->busy_bits); + if (!hub->hdev->parent && !hub->busy_bits[0]) + usb_enable_root_hub_irq(hub->hdev->bus); if (status == 0) status = finish_port_resume(udev); @@ -3002,6 +3004,11 @@ static void hub_events(void) hub->activating = 0; + /* If this is a root hub, tell the HCD it's okay to + * re-enable port-change interrupts now. */ + if (!hdev->parent && !hub->busy_bits[0]) + usb_enable_root_hub_irq(hdev->bus); + loop_autopm: /* Allow autosuspend if we're not going to run again */ if (list_empty(&hub->event_list)) @@ -3227,6 +3234,8 @@ int usb_reset_device(struct usb_device *udev) break; } clear_bit(port1, parent_hub->busy_bits); + if (!parent_hdev->parent && !parent_hub->busy_bits[0]) + usb_enable_root_hub_irq(parent_hdev->bus); if (ret < 0) goto re_enumerate; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index c96db1153dcf..e534f9de0f05 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -261,6 +261,7 @@ static const struct hc_driver ohci_at91_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index 1b9abdba920b..f90fe0c7373f 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c @@ -288,6 +288,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 06aadfb0ec29..5adaf36e47d0 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -135,6 +135,7 @@ static struct hc_driver ohci_ep93xx_hc_driver = { .get_frame_number = ohci_get_frame, .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 79a78029f896..b56739221d11 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -36,6 +36,18 @@ /*-------------------------------------------------------------------------*/ +/* hcd->hub_irq_enable() */ +static void ohci_rhsc_enable (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + + spin_lock_irq(&ohci->lock); + if (!ohci->autostop) + del_timer(&hcd->rh_timer); /* Prevent next poll */ + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + spin_unlock_irq(&ohci->lock); +} + #define OHCI_SCHED_ENABLES \ (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) @@ -362,28 +374,18 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) { int poll_rh = 1; - int rhsc; - rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC; switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_OPER: - /* If no status changes are pending, enable status-change - * interrupts. - */ - if (!rhsc && !changed) { - rhsc = OHCI_INTR_RHSC; - ohci_writel(ohci, rhsc, &ohci->regs->intrenable); - } - - /* Keep on polling until we know a device is connected - * and RHSC is enabled, or until we autostop. - */ + /* keep on polling until we know a device is connected + * and RHSC is enabled */ if (!ohci->autostop) { if (any_connected || !device_may_wakeup(&ohci_to_hcd(ohci) ->self.root_hub->dev)) { - if (rhsc) + if (ohci_readl(ohci, &ohci->regs->intrenable) & + OHCI_INTR_RHSC) poll_rh = 0; } else { ohci->autostop = 1; @@ -396,13 +398,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, ohci->autostop = 0; ohci->next_statechange = jiffies + STATECHANGE_DELAY; - } else if (rhsc && time_after_eq(jiffies, + } else if (time_after_eq(jiffies, ohci->next_statechange) && !ohci->ed_rm_list && !(ohci->hc_control & OHCI_SCHED_ENABLES)) { ohci_rh_suspend(ohci, 1); - poll_rh = 0; } } break; @@ -416,12 +417,6 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, else usb_hcd_resume_root_hub(ohci_to_hcd(ohci)); } else { - if (!rhsc && (ohci->autostop || - ohci_to_hcd(ohci)->self.root_hub-> - do_remote_wakeup)) - ohci_writel(ohci, OHCI_INTR_RHSC, - &ohci->regs->intrenable); - /* everything is idle, no need for polling */ poll_rh = 0; } @@ -443,16 +438,12 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci) static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) { - /* If RHSC is enabled, don't poll */ - if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) - return 0; + int poll_rh = 1; - /* If no status changes are pending, enable status-change interrupts */ - if (!changed) { - ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); - return 0; - } - return 1; + /* keep on polling until RHSC is enabled */ + if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) + poll_rh = 0; + return poll_rh; } #endif /* CONFIG_PM */ diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 96d14fa1d833..13c12ed22252 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c @@ -193,6 +193,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 6859fb5f1d6f..3a7c24c03671 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -466,6 +466,7 @@ static const struct hc_driver ohci_omap_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 3bf175d95a23..4696cc912e16 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -327,6 +327,7 @@ static const struct hc_driver ohci_pci_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index 664f07ee8732..28b458f20cc3 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c @@ -280,6 +280,7 @@ static const struct hc_driver ohci_pnx4008_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c index 28467e288a93..605d59cba28e 100644 --- a/drivers/usb/host/ohci-pnx8550.c +++ b/drivers/usb/host/ohci-pnx8550.c @@ -201,6 +201,7 @@ static const struct hc_driver ohci_pnx8550_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 50e55db13636..a67252791223 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -72,6 +72,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index cd3398b675b2..523c30125577 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c @@ -172,6 +172,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index bfdeb0d22d05..c1935ae537f8 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -68,6 +68,7 @@ static const struct hc_driver ps3_ohci_hc_driver = { .get_frame_number = ohci_get_frame, .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, .start_port_reset = ohci_start_port_reset, #if defined(CONFIG_PM) .bus_suspend = ohci_bus_suspend, diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 70b0d4b459e7..d4ee27d92be8 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -298,6 +298,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index a73d2ff322e2..ead4772f0f27 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -466,6 +466,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { */ .hub_status_data = ohci_s3c2410_hub_status_data, .hub_control = ohci_s3c2410_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index 99438c65981b..0f48f2d99226 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -231,6 +231,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c index 60f03cc7ec4f..e7ee607278fe 100644 --- a/drivers/usb/host/ohci-sh.c +++ b/drivers/usb/host/ohci-sh.c @@ -68,6 +68,7 @@ static const struct hc_driver ohci_sh_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index e899a77dfb83..e610698c6b60 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -75,6 +75,7 @@ static const struct hc_driver ohci_sm501_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c index c4265caec780..7275186db315 100644 --- a/drivers/usb/host/ohci-ssb.c +++ b/drivers/usb/host/ohci-ssb.c @@ -81,6 +81,7 @@ static const struct hc_driver ssb_ohci_hc_driver = { .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, + .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index f29307405bb3..9b6323f768b2 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -2934,6 +2934,16 @@ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num) return 0; } +static void u132_hub_irq_enable(struct usb_hcd *hcd) +{ + struct u132 *u132 = hcd_to_u132(hcd); + if (u132->going > 1) { + dev_err(&u132->platform_dev->dev, "device has been removed %d\n" + , u132->going); + } else if (u132->going > 0) + dev_err(&u132->platform_dev->dev, "device is being removed\n"); +} + #ifdef CONFIG_PM static int u132_bus_suspend(struct usb_hcd *hcd) @@ -2985,6 +2995,7 @@ static struct hc_driver u132_hc_driver = { .bus_suspend = u132_bus_suspend, .bus_resume = u132_bus_resume, .start_port_reset = u132_start_port_reset, + .hub_irq_enable = u132_hub_irq_enable, }; /* -- cgit v1.2.3 From ac310bb5db057963548e067037d68c9be41d0dd0 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 10 Jul 2008 17:30:46 -0700 Subject: Fix name of Russell King in various comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch was created by git grep -E -l 'Rus(el|s?e)l King' | xargs -r -t perl -p -i -e 's/Rus(el|s?e)l King/Russell King/g' Signed-off-by: Uwe Kleine-König Most-Definitely-Acked-by: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/usb/host/ohci-au1xxx.c | 2 +- drivers/usb/host/ohci-lh7a404.c | 2 +- drivers/usb/host/ohci-s3c2410.c | 2 +- drivers/usb/host/ohci-sa1111.c | 2 +- include/asm-avr32/setup.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index f90fe0c7373f..68c17f5ea8ea 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c @@ -8,7 +8,7 @@ * Bus Glue for AMD Alchemy Au1xxx * * Written by Christopher Hoover - * Based on fragments of previous driver by Rusell King et al. + * Based on fragments of previous driver by Russell King et al. * * Modified for LH7A404 from ohci-sa1111.c * by Durgesh Pattamatta diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 13c12ed22252..1ef5d482c145 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c @@ -8,7 +8,7 @@ * Bus Glue for Sharp LH7A404 * * Written by Christopher Hoover - * Based on fragments of previous driver by Rusell King et al. + * Based on fragments of previous driver by Russell King et al. * * Modified for LH7A404 from ohci-sa1111.c * by Durgesh Pattamatta diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index ead4772f0f27..3c7a740cfe0c 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -8,7 +8,7 @@ * USB Bus Glue for Samsung S3C2410 * * Written by Christopher Hoover - * Based on fragments of previous driver by Rusell King et al. + * Based on fragments of previous driver by Russell King et al. * * Modified for S3C2410 from ohci-sa1111.c, ohci-omap.c and ohci-lh7a40.c * by Ben Dooks, diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index 0f48f2d99226..2e9dceb9bb99 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -8,7 +8,7 @@ * SA1111 Bus Glue * * Written by Christopher Hoover - * Based on fragments of previous driver by Rusell King et al. + * Based on fragments of previous driver by Russell King et al. * * This file is licenced under the GPL. */ diff --git a/include/asm-avr32/setup.h b/include/asm-avr32/setup.h index ea3070ff13a5..ff5b7cf6be4d 100644 --- a/include/asm-avr32/setup.h +++ b/include/asm-avr32/setup.h @@ -2,7 +2,7 @@ * Copyright (C) 2004-2006 Atmel Corporation * * Based on linux/include/asm-arm/setup.h - * Copyright (C) 1997-1999 Russel King + * Copyright (C) 1997-1999 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as -- cgit v1.2.3