aboutsummaryrefslogtreecommitdiffstats
path: root/usb.current
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2008-08-20 15:20:20 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2008-08-20 15:20:20 -0700
commit6d85f7c32e82625d4e9bd2533badf25d09044a2d (patch)
tree1acefed9d68391710f67b5c304d80ddbc18d46a8 /usb.current
parenta143996a4992ef622674f7dc7139362add57061d (diff)
downloadpatches-6d85f7c32e82625d4e9bd2533badf25d09044a2d.tar.gz
usb patch
Diffstat (limited to 'usb.current')
-rw-r--r--usb.current/usb-automatically-enable-rhsc-interrupts.patch419
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,
+ };
+
+ /*