ChangeSet 1.879.9.1, 2003/01/06 15:47:26-08:00, [EMAIL PROTECTED]
[PATCH] ehci, remove potential hangs
These don't affect the hang I'm hunting for, but paranoia
argues the patch is better integrated than not:
- prevent resubmit-from-completion looping in_irq if the
transfers complete really fast. (likely never seen, but...)
- grab ehci lock before reading irq status; should be harmless
except in one host error cleanup-after-death
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c Wed Jan 8 12:03:21 2003
+++ b/drivers/usb/host/ehci-hcd.c Wed Jan 8 12:03:21 2003
@@ -637,9 +637,13 @@
static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- u32 status = readl (&ehci->regs->status);
+ u32 status;
int bh;
+ spin_lock (&ehci->lock);
+
+ status = readl (&ehci->regs->status);
+
/* e.g. cardbus physical eject */
if (status == ~(u32) 0) {
ehci_dbg (ehci, "device removed\n");
@@ -648,9 +652,7 @@
status &= INTR_MASK;
if (!status) /* irq sharing? */
- return;
-
- spin_lock (&ehci->lock);
+ goto done;
/* clear (just) interrupts */
writel (status, &ehci->regs->status);
@@ -693,6 +695,7 @@
if (bh)
ehci_work (ehci, regs);
+done:
spin_unlock (&ehci->lock);
}
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c Wed Jan 8 12:03:21 2003
+++ b/drivers/usb/host/ehci-q.c Wed Jan 8 12:03:21 2003
@@ -222,7 +222,7 @@
static unsigned
qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
{
- struct ehci_qtd *last = 0;
+ struct ehci_qtd *last = 0, *end = qh->dummy;
struct list_head *entry, *tmp;
int stopped = 0;
unsigned count = 0;
@@ -253,6 +253,10 @@
last = 0;
}
+ /* ignore urbs submitted during completions we reported */
+ if (qtd == end)
+ break;
+
/* hardware copies qtd out of qh overlay */
rmb ();
token = le32_to_cpu (qtd->hw_token);
@@ -967,25 +971,28 @@
scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
{
struct ehci_qh *qh;
- unsigned count;
+ if (!++(ehci->stamp))
+ ehci->stamp++;
rescan:
qh = ehci->async->qh_next.qh;
- count = 0;
if (likely (qh != 0)) {
do {
/* clean any finished work for this qh */
- if (!list_empty (&qh->qtd_list)) {
+ if (!list_empty (&qh->qtd_list)
+ && qh->stamp != ehci->stamp) {
int temp;
/* unlinks could happen here; completion
- * reporting drops the lock.
+ * reporting drops the lock. rescan using
+ * the latest schedule, but don't rescan
+ * qhs we already finished (no looping).
*/
qh = qh_get (qh);
+ qh->stamp = ehci->stamp;
temp = qh_completions (ehci, qh, regs);
qh_put (ehci, qh);
if (temp != 0) {
- count += temp;
goto rescan;
}
}
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h Wed Jan 8 12:03:21 2003
+++ b/drivers/usb/host/ehci.h Wed Jan 8 12:03:21 2003
@@ -81,6 +81,7 @@
struct pci_pool *sitd_pool; /* sitd per split iso urb */
struct timer_list watchdog;
+ unsigned stamp;
#ifdef EHCI_STATS
struct ehci_stats stats;
@@ -306,6 +307,7 @@
struct ehci_qtd *dummy;
atomic_t refcount;
+ unsigned stamp;
u8 qh_state;
#define QH_STATE_LINKED 1 /* HC sees this */
-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel