diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2008-08-20 15:20:20 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-08-20 15:20:20 -0700 |
| commit | 6d85f7c32e82625d4e9bd2533badf25d09044a2d (patch) | |
| tree | 1acefed9d68391710f67b5c304d80ddbc18d46a8 /usb.current | |
| parent | a143996a4992ef622674f7dc7139362add57061d (diff) | |
| download | patches-6d85f7c32e82625d4e9bd2533badf25d09044a2d.tar.gz | |
usb patch
Diffstat (limited to 'usb.current')
| -rw-r--r-- | usb.current/usb-automatically-enable-rhsc-interrupts.patch | 419 |
1 files changed, 419 insertions, 0 deletions
diff --git a/usb.current/usb-automatically-enable-rhsc-interrupts.patch b/usb.current/usb-automatically-enable-rhsc-interrupts.patch new file mode 100644 index 00000000000000..d5e23e15a9a50b --- /dev/null +++ b/usb.current/usb-automatically-enable-rhsc-interrupts.patch @@ -0,0 +1,419 @@ +From stern@rowland.harvard.edu Wed Aug 20 15:16:23 2008 +From: Alan Stern <stern@rowland.harvard.edu> +Date: Wed, 20 Aug 2008 17:22:05 -0400 (EDT) +Subject: USB: automatically enable RHSC interrupts +To: Greg KH <greg@kroah.com> +Cc: USB list <linux-usb@vger.kernel.org> +Message-ID: <Pine.LNX.4.44L0.0808201713110.14505-100000@iolanthe.rowland.org> + + +This patch (as1069c) changes the way OHCI root-hub status-change +interrupts are enabled. Currently a special HCD method, +hub_irq_enable(), is called when the hub driver is finished using a +root hub. This approach turns out to be subject to races, resulting +in unnecessary polling. + +The patch does away with the method entirely. Instead, the driver +automatically enables the RHSC interrupt when no more status changes +are present. This scheme is safe with controllers using +level-triggered semantics for their interrupt flags. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hcd.c | 9 ------ + drivers/usb/core/hcd.h | 4 --- + 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, 31 insertions(+), 72 deletions(-) + +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -924,15 +924,6 @@ static int register_root_hub(struct usb_ + 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); +-} +- + + /*-------------------------------------------------------------------------*/ + +--- a/drivers/usb/core/hcd.h ++++ b/drivers/usb/core/hcd.h +@@ -212,8 +212,6 @@ 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); +@@ -379,8 +377,6 @@ extern struct list_head usb_bus_list; + extern struct mutex usb_bus_list_lock; + extern wait_queue_head_t usb_kill_urb_queue; + +-extern void usb_enable_root_hub_irq(struct usb_bus *bus); +- + extern int usb_find_interface_driver(struct usb_device *dev, + struct usb_interface *interface); + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2102,8 +2102,6 @@ int usb_port_resume(struct usb_device *u + } + + clear_bit(port1, hub->busy_bits); +- if (!hub->hdev->parent && !hub->busy_bits[0]) +- usb_enable_root_hub_irq(hub->hdev->bus); + + status = check_port_resume_type(udev, + hub, port1, status, portchange, portstatus); +@@ -3081,11 +3079,6 @@ static void hub_events(void) + } + } + +- /* 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)) +@@ -3311,8 +3304,6 @@ static int usb_reset_and_verify_device(s + 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; +--- a/drivers/usb/host/ohci-at91.c ++++ b/drivers/usb/host/ohci-at91.c +@@ -260,7 +260,6 @@ static const struct hc_driver ohci_at91_ + */ + .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, +--- a/drivers/usb/host/ohci-au1xxx.c ++++ b/drivers/usb/host/ohci-au1xxx.c +@@ -163,7 +163,6 @@ static const struct hc_driver ohci_au1xx + */ + .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, +--- a/drivers/usb/host/ohci-ep93xx.c ++++ b/drivers/usb/host/ohci-ep93xx.c +@@ -134,7 +134,6 @@ static struct hc_driver ohci_ep93xx_hc_d + .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, +--- a/drivers/usb/host/ohci-hub.c ++++ b/drivers/usb/host/ohci-hub.c +@@ -36,18 +36,6 @@ + + /*-------------------------------------------------------------------------*/ + +-/* 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) + +@@ -374,18 +362,28 @@ static int ohci_root_hub_state_changes(s + 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: +- /* keep on polling until we know a device is connected +- * and RHSC is enabled */ ++ /* 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. ++ */ + if (!ohci->autostop) { + if (any_connected || + !device_may_wakeup(&ohci_to_hcd(ohci) + ->self.root_hub->dev)) { +- if (ohci_readl(ohci, &ohci->regs->intrenable) & +- OHCI_INTR_RHSC) ++ if (rhsc) + poll_rh = 0; + } else { + ohci->autostop = 1; +@@ -398,12 +396,13 @@ static int ohci_root_hub_state_changes(s + ohci->autostop = 0; + ohci->next_statechange = jiffies + + STATECHANGE_DELAY; +- } else if (time_after_eq(jiffies, ++ } else if (rhsc && 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; +@@ -417,6 +416,12 @@ static int ohci_root_hub_state_changes(s + 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; + } +@@ -438,12 +443,16 @@ static inline int ohci_rh_resume(struct + static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, + int any_connected) + { +- int poll_rh = 1; +- +- /* keep on polling until RHSC is enabled */ ++ /* If RHSC is enabled, don't poll */ + if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) +- poll_rh = 0; +- return poll_rh; ++ return 0; ++ ++ /* 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; + } + + #endif /* CONFIG_PM */ +--- a/drivers/usb/host/ohci-lh7a404.c ++++ b/drivers/usb/host/ohci-lh7a404.c +@@ -193,7 +193,6 @@ static const struct hc_driver ohci_lh7a4 + */ + .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, +--- a/drivers/usb/host/ohci-omap.c ++++ b/drivers/usb/host/ohci-omap.c +@@ -470,7 +470,6 @@ static const struct hc_driver ohci_omap_ + */ + .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, +--- a/drivers/usb/host/ohci-pci.c ++++ b/drivers/usb/host/ohci-pci.c +@@ -459,7 +459,6 @@ static const struct hc_driver ohci_pci_h + */ + .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, +--- a/drivers/usb/host/ohci-pnx4008.c ++++ b/drivers/usb/host/ohci-pnx4008.c +@@ -277,7 +277,6 @@ static const struct hc_driver ohci_pnx40 + */ + .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, +--- a/drivers/usb/host/ohci-pnx8550.c ++++ b/drivers/usb/host/ohci-pnx8550.c +@@ -201,7 +201,6 @@ static const struct hc_driver ohci_pnx85 + */ + .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, +--- a/drivers/usb/host/ohci-ppc-of.c ++++ b/drivers/usb/host/ohci-ppc-of.c +@@ -72,7 +72,6 @@ static const struct hc_driver ohci_ppc_o + */ + .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, +--- a/drivers/usb/host/ohci-ppc-soc.c ++++ b/drivers/usb/host/ohci-ppc-soc.c +@@ -172,7 +172,6 @@ static const struct hc_driver ohci_ppc_s + */ + .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, +--- a/drivers/usb/host/ohci-ps3.c ++++ b/drivers/usb/host/ohci-ps3.c +@@ -68,7 +68,6 @@ static const struct hc_driver ps3_ohci_h + .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, +--- a/drivers/usb/host/ohci-pxa27x.c ++++ b/drivers/usb/host/ohci-pxa27x.c +@@ -298,7 +298,6 @@ static const struct hc_driver ohci_pxa27 + */ + .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, +--- a/drivers/usb/host/ohci-s3c2410.c ++++ b/drivers/usb/host/ohci-s3c2410.c +@@ -466,7 +466,6 @@ static const struct hc_driver ohci_s3c24 + */ + .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, +--- a/drivers/usb/host/ohci-sa1111.c ++++ b/drivers/usb/host/ohci-sa1111.c +@@ -231,7 +231,6 @@ static const struct hc_driver ohci_sa111 + */ + .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, +--- a/drivers/usb/host/ohci-sh.c ++++ b/drivers/usb/host/ohci-sh.c +@@ -68,7 +68,6 @@ static const struct hc_driver ohci_sh_hc + */ + .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, +--- a/drivers/usb/host/ohci-sm501.c ++++ b/drivers/usb/host/ohci-sm501.c +@@ -75,7 +75,6 @@ static const struct hc_driver ohci_sm501 + */ + .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, +--- a/drivers/usb/host/ohci-ssb.c ++++ b/drivers/usb/host/ohci-ssb.c +@@ -81,7 +81,6 @@ static const struct hc_driver ssb_ohci_h + + .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, +--- a/drivers/usb/host/u132-hcd.c ++++ b/drivers/usb/host/u132-hcd.c +@@ -2934,16 +2934,6 @@ static int u132_start_port_reset(struct + 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) +@@ -2995,7 +2985,6 @@ 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, + }; + + /* |
