From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, stable@kernel.org, jejb@kernel.org
Cc: Justin Forbes <jmforbes@linuxtx.org>,
Zwane Mwaikambo <zwane@arm.linux.org.uk>,
"Theodore Ts'o" <tytso@mit.edu>,
Randy Dunlap <rdunlap@xenotime.net>,
Dave Jones <davej@redhat.com>,
Chuck Wolber <chuckw@quantumlinux.com>,
Chris Wedgwood <reviews@ml.cw.f00f.org>,
Michael Krufky <mkrufky@linuxtv.org>,
Chuck Ebbert <cebbert@redhat.com>,
Domenico Andreoli <cavokz@gmail.com>, Willy Tarreau <w@1wt.eu>,
Rodrigo Rubira Branco <rbranco@la.checkpoint.com>,
Jake Edge <jake@lwn.net>, Eugene Teo <eteo@redhat.com>,
torvalds@linux-foundation.org, akpm@linux-foundation.org,
alan@lxorguk.ukuu.org.uk, Alan Stern <stern@rowland.harvard.edu>
Subject: [patch 10/17] USB: OHCI: fix endless polling behavior
Date: Sat, 18 Oct 2008 11:34:19 -0700 [thread overview]
Message-ID: <20081018183418.GK14035@suse.de> (raw)
In-Reply-To: <20081018183334.GA14035@suse.de>
[-- Attachment #1: usb-ohci-fix-endless-polling-behavior.patch --]
[-- Type: text/plain, Size: 5417 bytes --]
2.6.27-stable review patch. If anyone has any objections, please let us
know.
------------------
From: Alan Stern <stern@rowland.harvard.edu>
commit 71b7497c078a97e2afb774ad7c1f8ff5bdda8a60 upstream
This patch (as1149) fixes an obscure problem in OHCI polling. In the
current code, if the RHSC interrupt status flag turns on at a time
when RHSC interrupts are disabled, it will remain on forever:
The interrupt handler is the only place where RHSC status
gets turned back off;
The interrupt handler won't turn RHSC status off because it
doesn't turn off status flags if the corresponding interrupt
isn't enabled;
RHSC interrupts will never get enabled because
ohci_root_hub_state_changes() doesn't reenable RHSC if RHSC
status is on!
As a result we will continue polling indefinitely instead of reverting
to interrupt-driven operation, and the root hub will not autosuspend.
This particular sequence of events is not at all unusual; in fact
plugging a USB device into an OHCI controller will usually cause it to
occur.
Of course, this is a bug. The proper thing to do is to turn off RHSC
status just before reading the actual port status values. That way
either a port status change will be detected (if it occurs before the
status read) or it will turn RHSC back on. Possibly both, but that
won't hurt anything.
We can still check for systems in which RHSC is totally broken, by
re-reading RHSC after clearing it and before reading the port
statuses. (This re-read has to be done anyway, to post the earlier
write.) If RHSC is on but no port-change statuses are set, then we
know that RHSC is broken and we can avoid re-enabling it.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/usb/host/ohci-hub.c | 51 +++++++++++++++++++++++++++-----------------
1 file changed, 32 insertions(+), 19 deletions(-)
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -359,17 +359,15 @@ static void ohci_finish_controller_resum
/* Carry out polling-, autostop-, and autoresume-related state changes */
static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
- int any_connected)
+ int any_connected, int rhsc_status)
{
int poll_rh = 1;
- int rhsc_status, rhsc_enable;
+ int rhsc_enable;
/* Some broken controllers never turn off RHCS in the interrupt
* status register. For their sake we won't re-enable RHSC
* interrupts if the interrupt bit is already active.
*/
- rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) &
- OHCI_INTR_RHSC;
rhsc_enable = ohci_readl(ohci, &ohci->regs->intrenable) &
OHCI_INTR_RHSC;
@@ -421,14 +419,23 @@ static int ohci_root_hub_state_changes(s
ohci_rh_resume(ohci);
else
usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
+
+ /* If remote wakeup is disabled, stop polling */
+ } else if (!ohci->autostop &&
+ !ohci_to_hcd(ohci)->self.root_hub->
+ do_remote_wakeup) {
+ poll_rh = 0;
+
} else {
- if (!rhsc_enable && !rhsc_status && (ohci->autostop ||
- ohci_to_hcd(ohci)->self.root_hub->
- do_remote_wakeup)) {
+ /* If no status changes are pending,
+ * enable RHSC interrupts
+ */
+ if (!rhsc_enable && !rhsc_status) {
rhsc_enable = OHCI_INTR_RHSC;
ohci_writel(ohci, rhsc_enable,
&ohci->regs->intrenable);
}
+ /* Keep polling until RHSC is enabled */
if (rhsc_enable)
poll_rh = 0;
}
@@ -448,22 +455,22 @@ static inline int ohci_rh_resume(struct
* autostop isn't used when CONFIG_PM is turned off.
*/
static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
- int any_connected)
+ int any_connected, int rhsc_status)
{
- int rhsc_status;
-
/* If RHSC is enabled, don't poll */
if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
return 0;
- /* If no status changes are pending, enable RHSC interrupts */
- rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) &
- OHCI_INTR_RHSC;
- if (!changed && !rhsc_status) {
- ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
- return 0;
- }
- return 1;
+ /* If status changes are pending, continue polling.
+ * Conversely, if no status changes are pending but the RHSC
+ * status bit was set, then RHSC may be broken so continue polling.
+ */
+ if (changed || rhsc_status)
+ return 1;
+
+ /* It's safe to re-enable RHSC interrupts */
+ ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+ return 0;
}
#endif /* CONFIG_PM */
@@ -478,6 +485,7 @@ ohci_hub_status_data (struct usb_hcd *hc
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int i, changed = 0, length = 1;
int any_connected = 0;
+ int rhsc_status;
unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags);
@@ -503,6 +511,11 @@ ohci_hub_status_data (struct usb_hcd *hc
length++;
}
+ /* Clear the RHSC status flag before reading the port statuses */
+ ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrstatus);
+ rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) &
+ OHCI_INTR_RHSC;
+
/* look at each port */
for (i = 0; i < ohci->num_ports; i++) {
u32 status = roothub_portstatus (ohci, i);
@@ -521,7 +534,7 @@ ohci_hub_status_data (struct usb_hcd *hc
}
hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
- any_connected);
+ any_connected, rhsc_status);
done:
spin_unlock_irqrestore (&ohci->lock, flags);
--
next prev parent reply other threads:[~2008-10-18 19:07 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20081018182721.521723254@mini.kroah.org>
2008-10-18 18:33 ` [patch 00/17] 2.6.27-stable review Greg KH
2008-10-18 18:33 ` [patch 01/17] fbcon_set_all_vcs: fix kernel crash when switching the rotated consoles Greg KH
2008-10-18 18:33 ` [patch 02/17] modules: fix module "notes" kobject leak Greg KH
2008-10-18 18:34 ` [patch 03/17] Driver core: Fix cleanup in device_create_vargs() Greg KH
2008-10-18 18:34 ` [patch 04/17] Driver core: Clarify device cleanup Greg KH
2008-10-18 18:34 ` [patch 05/17] ath9k/mac80211: disallow fragmentation in ath9k, report to userspace Greg KH
2008-10-18 18:34 ` [patch 06/17] md: Fix rdev_size_store with size == 0 Greg KH
2008-10-18 18:34 ` [patch 07/17] xfs: fix remount rw with unrecognized options Greg KH
2008-10-18 18:34 ` [patch 08/17] ath9k: fix oops on trying to hold the wrong spinlock Greg KH
2008-10-18 18:34 ` [patch 09/17] OHCI: Allow broken controllers to auto-stop Greg KH
2008-10-18 18:34 ` Greg KH [this message]
2008-10-18 18:34 ` [patch 11/17] USB: Fix s3c2410_udc usb speed handling Greg KH
2008-10-18 18:34 ` [patch 12/17] USB: EHCI: log a warning if ehci-hcd is not loaded first Greg KH
2008-10-18 18:34 ` [patch 13/17] usb gadget: cdc ethernet notification bugfix Greg KH
2008-10-18 18:34 ` [patch 14/17] usb: musb_hdrc build fixes Greg KH
2008-10-18 18:34 ` [patch 15/17] drm/i915: fix ioremap of a user address for non-root (CVE-2008-3831) Greg KH
2008-10-18 18:34 ` [patch 16/17] DVB: au0828: add support for another USB id for Hauppauge HVR950Q Greg KH
2008-10-18 18:34 ` [patch 17/17] DVB: sms1xxx: support two new revisions of the Hauppauge WinTV MiniStick Greg KH
2008-10-18 18:36 ` [patch 00/17] 2.6.27-stable review Greg KH
2008-10-23 1:01 ` Josh Boyer
2008-10-23 4:53 ` [stable] " Greg KH
2008-10-23 10:33 ` Josh Boyer
2008-10-23 15:33 ` Greg KH
2008-10-23 15:47 ` Josh Boyer
2008-10-23 15:51 ` Greg KH
2008-10-23 5:06 ` Willy Tarreau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20081018183418.GK14035@suse.de \
--to=gregkh@suse.de \
--cc=akpm@linux-foundation.org \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=cavokz@gmail.com \
--cc=cebbert@redhat.com \
--cc=chuckw@quantumlinux.com \
--cc=davej@redhat.com \
--cc=eteo@redhat.com \
--cc=jake@lwn.net \
--cc=jejb@kernel.org \
--cc=jmforbes@linuxtx.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mkrufky@linuxtv.org \
--cc=rbranco@la.checkpoint.com \
--cc=rdunlap@xenotime.net \
--cc=reviews@ml.cw.f00f.org \
--cc=stable@kernel.org \
--cc=stern@rowland.harvard.edu \
--cc=torvalds@linux-foundation.org \
--cc=tytso@mit.edu \
--cc=w@1wt.eu \
--cc=zwane@arm.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox