Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 304091 Details for
Bug 435787
RHEL4.7: USB stress test failure on AMD SBX00
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
all in one patch for the stress test failure
all_in_one.patch (text/plain), 15.53 KB, created by
henry su
on 2008-04-29 10:28:13 UTC
(
hide
)
Description:
all in one patch for the stress test failure
Filename:
MIME Type:
Creator:
henry su
Created:
2008-04-29 10:28:13 UTC
Size:
15.53 KB
patch
obsolete
>diff -Nur linux-2.6.9.orig/drivers/usb/host/ehci-dbg.c linux-2.6.9/drivers/usb/host/ehci-dbg.c >--- linux-2.6.9.orig/drivers/usb/host/ehci-dbg.c 2008-04-29 17:02:05.000000000 +0800 >+++ linux-2.6.9/drivers/usb/host/ehci-dbg.c 2008-04-29 11:31:12.000000000 +0800 >@@ -704,9 +704,7 @@ > } > > if (ehci->reclaim) { >- temp = scnprintf (next, size, "reclaim qh %p%s\n", >- ehci->reclaim, >- ehci->reclaim_ready ? " ready" : ""); >+ temp = scnprintf(next, size, "reclaim qh %p\n", ehci->reclaim); > size -= temp; > next += temp; > } >diff -Nur linux-2.6.9.orig/drivers/usb/host/ehci.h linux-2.6.9/drivers/usb/host/ehci.h >--- linux-2.6.9.orig/drivers/usb/host/ehci.h 2008-04-29 17:02:05.000000000 +0800 >+++ linux-2.6.9/drivers/usb/host/ehci.h 2008-04-29 11:31:12.000000000 +0800 >@@ -52,7 +52,6 @@ > /* async schedule support */ > struct ehci_qh *async; > struct ehci_qh *reclaim; >- unsigned reclaim_ready : 1; > unsigned scanning : 1; > > /* periodic schedule support */ >@@ -81,6 +80,7 @@ > struct dma_pool *itd_pool; /* itd per iso urb */ > struct dma_pool *sitd_pool; /* sitd per split iso urb */ > >+ struct timer_list iaa_watchdog; > struct timer_list watchdog; > struct notifier_block reboot_notifier; > unsigned long actions; >@@ -103,9 +103,21 @@ > #define hcd_to_ehci(hcd_ptr) container_of(hcd_ptr, struct ehci_hcd, hcd) > > >+static inline void >+iaa_watchdog_start(struct ehci_hcd *ehci) >+{ >+ WARN_ON(timer_pending(&ehci->iaa_watchdog)); >+ mod_timer(&ehci->iaa_watchdog, >+ jiffies + msecs_to_jiffies(EHCI_IAA_MSECS)); >+} >+ >+static inline void iaa_watchdog_done(struct ehci_hcd *ehci) >+{ >+ del_timer(&ehci->iaa_watchdog); >+} >+ > enum ehci_timer_action { > TIMER_IO_WATCHDOG, >- TIMER_IAA_WATCHDOG, > TIMER_ASYNC_SHRINK, > TIMER_ASYNC_OFF, > }; >@@ -123,9 +135,6 @@ > unsigned long t; > > switch (action) { >- case TIMER_IAA_WATCHDOG: >- t = EHCI_IAA_JIFFIES; >- break; > case TIMER_IO_WATCHDOG: > t = EHCI_IO_JIFFIES; > break; >@@ -142,8 +151,7 @@ > // 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 (action != TIMER_IAA_WATCHDOG >- && t > ehci->watchdog.expires >+ if (time_before_eq(t, ehci->watchdog.expires) > && timer_pending (&ehci->watchdog)) > return; > mod_timer (&ehci->watchdog, t); >diff -Nur linux-2.6.9.orig/drivers/usb/host/ehci-hcd.c linux-2.6.9/drivers/usb/host/ehci-hcd.c >--- linux-2.6.9.orig/drivers/usb/host/ehci-hcd.c 2008-04-29 17:02:05.000000000 +0800 >+++ linux-2.6.9/drivers/usb/host/ehci-hcd.c 2008-04-29 14:42:21.000000000 +0800 >@@ -119,7 +119,7 @@ > #define EHCI_TUNE_MULT_TT 1 > #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ > >-#define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ >+#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 */ >@@ -246,6 +246,7 @@ > > /*-------------------------------------------------------------------------*/ > >+static void end_unlink_async(struct ehci_hcd *ehci, struct pt_regs *regs); > static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs); > > #include "ehci-hub.c" >@@ -255,26 +256,62 @@ > > /*-------------------------------------------------------------------------*/ > >-static void ehci_watchdog (unsigned long param) >+static void ehci_iaa_watchdog(unsigned long param) > { > struct ehci_hcd *ehci = (struct ehci_hcd *) param; > unsigned long flags; > > spin_lock_irqsave (&ehci->lock, flags); > >- /* lost IAA irqs wedge things badly; seen with a vt8235 */ >- if (ehci->reclaim) { >- u32 status = readl (&ehci->regs->status); >- >- if (status & STS_IAA) { >- ehci_vdbg (ehci, "lost IAA\n"); >+ /* Lost IAA irqs wedge things badly; seen first with a vt8235. >+ * So we need this watchdog, but must protect it against both >+ * (a) SMP races against real IAA firing and retriggering, and >+ * (b) clean HC shutdown, when IAA watchdog was pending. >+ */ >+ if (ehci->reclaim >+ && !timer_pending(&ehci->iaa_watchdog) >+ && HCD_IS_RUNNING(ehci->hcd.state)) { >+ u32 cmd, status; >+ >+ /* If we get here, IAA is *REALLY* late. It's barely >+ * conceivable that the system is so busy that CMD_IAAD >+ * is still legitimately set, so let's be sure it's >+ * clear before we read STS_IAA. (The HC should clear >+ * CMD_IAAD when it sets STS_IAA.) >+ */ >+ cmd = readl(&ehci->regs->command); >+ if (cmd & CMD_IAAD) >+ writel(cmd & ~CMD_IAAD, >+ &ehci->regs->command); >+ >+ /* If IAA is set here it either legitimately triggered >+ * before we cleared IAAD above (but _way_ late, so we'll >+ * still count it as lost) ... or a silicon erratum: >+ * - VIA seems to set IAA without triggering the IRQ; >+ * - IAAD potentially cleared without setting IAA. >+ */ >+ status = readl(&ehci->regs->status); >+ if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { > COUNT (ehci->stats.lost_iaa); > writel (STS_IAA, &ehci->regs->status); >- ehci->reclaim_ready = 1; > } >+ >+ ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n", >+ status, cmd); >+ end_unlink_async(ehci, NULL); > } > >- /* stop async processing after it's idled a bit */ >+ spin_unlock_irqrestore(&ehci->lock, flags); >+} >+ >+static void ehci_watchdog(unsigned long param) >+{ >+ struct ehci_hcd *ehci = (struct ehci_hcd *) param; >+ unsigned long flags; >+ >+ spin_lock_irqsave(&ehci->lock, flags); >+ >+ /* stop async processing after it's idled a bit */ > if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) > start_unlink_async (ehci, ehci->async); > >@@ -412,6 +449,10 @@ > ehci->watchdog.function = ehci_watchdog; > ehci->watchdog.data = (unsigned long) ehci; > >+ init_timer(&ehci->iaa_watchdog); >+ ehci->iaa_watchdog.function = ehci_iaa_watchdog; >+ ehci->iaa_watchdog.data = (unsigned long) ehci; >+ > #ifdef CONFIG_PCI > /* > * The mask of consistent DMA must be set before we dig into DMA pool. >@@ -630,6 +671,7 @@ > return; > } > del_timer_sync (&ehci->watchdog); >+ del_timer_sync(&ehci->iaa_watchdog); > > /* Turn off port power on all root hub ports. */ > rh_ports = HCS_N_PORTS (ehci->hcs_params); >@@ -733,8 +775,6 @@ > static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) > { > timer_action_done (ehci, TIMER_IO_WATCHDOG); >- if (ehci->reclaim_ready) >- end_unlink_async (ehci, regs); > > /* another CPU may drop ehci->lock during a schedule scan while > * it reports urb completions. this flag guards against bogus >@@ -761,7 +801,7 @@ > static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) > { > struct ehci_hcd *ehci = hcd_to_ehci (hcd); >- u32 status; >+ u32 status, cmd; > int bh; > > spin_lock (&ehci->lock); >@@ -782,7 +822,7 @@ > > /* clear (just) interrupts */ > writel (status, &ehci->regs->status); >- readl (&ehci->regs->command); /* unblock posted write */ >+ cmd = readl(&ehci->regs->command); > bh = 0; > > #ifdef EHCI_VERBOSE_DEBUG >@@ -803,9 +843,17 @@ > > /* complete the unlinking of some qh [4.15.2.3] */ > if (status & STS_IAA) { >- COUNT (ehci->stats.reclaim); >- ehci->reclaim_ready = 1; >- bh = 1; >+ /* guard against (alleged) silicon errata */ >+ if (cmd & CMD_IAAD) { >+ writel(cmd & ~CMD_IAAD, >+ &ehci->regs->command); >+ ehci_dbg(ehci, "IAA with IAAD still set?\n"); >+ } >+ if (ehci->reclaim) { >+ COUNT(ehci->stats.reclaim); >+ end_unlink_async(ehci, NULL); >+ } else >+ ehci_dbg(ehci, "IAA with nothing to reclaim?\n"); > } > > /* remote wakeup [4.3.1] */ >@@ -898,6 +946,32 @@ > } > } > >+static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) >+{ >+ /* failfast */ >+ if (!HCD_IS_RUNNING(ehci->hcd.state) && ehci->reclaim) >+ end_unlink_async(ehci, NULL); >+ >+ /* if it's not linked then there's nothing to do */ >+ if (qh->qh_state != QH_STATE_LINKED) >+ ; >+ >+ /* defer till later if busy */ >+ else if (ehci->reclaim) { >+ struct ehci_qh *last; >+ >+ for (last = ehci->reclaim; >+ last->reclaim; >+ last = last->reclaim) >+ continue; >+ qh->qh_state = QH_STATE_UNLINK_WAIT; >+ last->reclaim = qh; >+ >+ /* start IAA cycle */ >+ } else >+ start_unlink_async (ehci, qh); >+} >+ > /* remove from hardware lists > * completions normally happen asynchronously > */ >@@ -916,28 +990,19 @@ > qh = (struct ehci_qh *) urb->hcpriv; > if (!qh) > break; >- >- /* if we need to use IAA and it's busy, defer */ >- if (qh->qh_state == QH_STATE_LINKED >- && ehci->reclaim >- && HCD_IS_RUNNING (ehci->hcd.state) >- ) { >- struct ehci_qh *last; >- >- for (last = ehci->reclaim; >- last->reclaim; >- last = last->reclaim) >- continue; >- qh->qh_state = QH_STATE_UNLINK_WAIT; >- last->reclaim = qh; >- >- /* bypass IAA if the hc can't care */ >- } else if (!HCD_IS_RUNNING (ehci->hcd.state) && ehci->reclaim) >- end_unlink_async (ehci, NULL); >- >- /* something else might have unlinked the qh by now */ >- if (qh->qh_state == QH_STATE_LINKED) >- start_unlink_async (ehci, qh); >+ switch (qh->qh_state) { >+ case QH_STATE_LINKED: >+ case QH_STATE_COMPLETING: >+ unlink_async(ehci, qh); >+ break; >+ case QH_STATE_UNLINK: >+ case QH_STATE_UNLINK_WAIT: >+ /* already started */ >+ break; >+ case QH_STATE_IDLE: >+ WARN_ON(1); >+ break; >+ } > break; > > case PIPE_INTERRUPT: >@@ -990,7 +1055,7 @@ > struct ehci_hcd *ehci = hcd_to_ehci (hcd); > int epnum; > unsigned long flags; >- struct ehci_qh *qh; >+ struct ehci_qh *qh, *tmp; > > /* ASSERT: any requests/urbs are being unlinked */ > /* ASSERT: nobody can be submitting urbs for this any more */ >@@ -1016,7 +1081,18 @@ > if (!HCD_IS_RUNNING (ehci->hcd.state)) > qh->qh_state = QH_STATE_IDLE; > switch (qh->qh_state) { >+ case QH_STATE_LINKED: >+ for (tmp = ehci->async->qh_next.qh; >+ tmp && tmp != qh; >+ tmp = tmp->qh_next.qh) >+ continue; >+ /* periodic qh self-unlinks on empty */ >+ if (!tmp) >+ goto nogood; >+ unlink_async (ehci, qh); >+ /* FALL THROUGH */ > case QH_STATE_UNLINK: /* wait for hw to finish? */ >+ case QH_STATE_UNLINK_WAIT: > idle_timeout: > spin_unlock_irqrestore (&ehci->lock, flags); > set_current_state (TASK_UNINTERRUPTIBLE); >@@ -1029,6 +1105,7 @@ > } > /* else FALL THROUGH */ > default: >+nogood: > /* caller was supposed to have unlinked any requests; > * that's not our job. just leak this memory. > */ >diff -Nur linux-2.6.9.orig/drivers/usb/host/ehci-hub.c linux-2.6.9/drivers/usb/host/ehci-hub.c >--- linux-2.6.9.orig/drivers/usb/host/ehci-hub.c 2008-04-29 17:02:05.000000000 +0800 >+++ linux-2.6.9/drivers/usb/host/ehci-hub.c 2008-04-29 11:31:12.000000000 +0800 >@@ -41,6 +41,8 @@ > return 0; > if (time_before (jiffies, ehci->next_statechange)) > return -EAGAIN; >+ del_timer_sync(&ehci->watchdog); >+ del_timer_sync(&ehci->iaa_watchdog); > > port = HCS_N_PORTS (ehci->hcs_params); > spin_lock_irq (&ehci->lock); >@@ -71,7 +73,7 @@ > ehci->command = readl (&ehci->regs->command); > writel (ehci->command & ~CMD_RUN, &ehci->regs->command); > if (ehci->reclaim) >- ehci->reclaim_ready = 1; >+ end_unlink_async(ehci, NULL); > ehci_work(ehci, NULL); > (void) handshake (&ehci->regs->status, STS_HALT, STS_HALT, 2000); > >diff -Nur linux-2.6.9.orig/drivers/usb/host/ehci-q.c linux-2.6.9/drivers/usb/host/ehci-q.c >--- linux-2.6.9.orig/drivers/usb/host/ehci-q.c 2008-04-29 17:02:05.000000000 +0800 >+++ linux-2.6.9/drivers/usb/host/ehci-q.c 2008-04-29 16:48:33.000000000 +0800 >@@ -96,6 +96,29 @@ > qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING); > } > >+/* if it weren't for a common silicon quirk (writing the dummy into the qh >+ * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault >+ * recovery (including urb dequeue) would need software changes to a QH... >+ */ >+static void >+qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) >+{ >+ struct ehci_qtd *qtd; >+ >+ if (list_empty (&qh->qtd_list)) >+ qtd = qh->dummy; >+ else { >+ qtd = list_entry (qh->qtd_list.next, >+ struct ehci_qtd, qtd_list); >+ /* first qtd may already be partially processed */ >+ if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current) >+ qtd = NULL; >+ } >+ >+ if (qtd) >+ qh_update (ehci, qh, qtd); >+} >+ > /*-------------------------------------------------------------------------*/ > > static void qtd_copy_status ( >@@ -224,6 +247,11 @@ > spin_lock (&ehci->lock); > } > >+static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); >+static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); >+ >+static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh, int wait); >+static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); > > /* > * Process and free completed qtds for a qh, returning URBs to drivers. >@@ -368,17 +396,22 @@ > if (unlikely (stopped != 0) > /* some EHCI 0.95 impls will overlay dummy qtds */ > || qh->hw_qtd_next == EHCI_LIST_END) { >- if (list_empty (&qh->qtd_list)) >- end = qh->dummy; >- else { >- end = list_entry (qh->qtd_list.next, >- struct ehci_qtd, qtd_list); >- /* first qtd may already be partially processed */ >- if (cpu_to_le32 (end->qtd_dma) == qh->hw_current) >- end = NULL; >+ switch (state) { >+ case QH_STATE_IDLE: >+ qh_refresh(ehci, qh); >+ break; >+ case QH_STATE_LINKED: >+ /* should be rare for periodic transfers, >+ * except maybe high bandwidth ... >+ */ >+ if ((cpu_to_le32(0x00ff) & qh->hw_info2) != 0) { >+ intr_deschedule (ehci, qh, 1); >+ (void) qh_schedule (ehci, qh); >+ } else >+ unlink_async (ehci, qh); >+ break; >+ /* otherwise, unlink already started */ > } >- if (end) >- qh_update (ehci, qh, end); > } > > return count; >@@ -712,6 +745,7 @@ > qh->hw_info2 = cpu_to_le32 (info2); > qh_update (ehci, qh, qh->dummy); > usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); >+ qh_refresh(ehci, qh); > return qh; > } > >@@ -739,7 +773,10 @@ > /* posted write need not be known to HC yet ... */ > } > } >- >+ /* clear halt and/or toggle; and maybe recover from silicon quirk */ >+ if (qh->qh_state == QH_STATE_IDLE) >+ qh_refresh (ehci, qh); >+ > qh->hw_token &= ~HALT_BIT; > > /* splice right after start */ >@@ -931,14 +968,15 @@ > > /* the async qh for the qtds being reclaimed are now unlinked from the HC */ > >-static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); >- > static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs) > { > struct ehci_qh *qh = ehci->reclaim; > struct ehci_qh *next; > >- timer_action_done (ehci, TIMER_IAA_WATCHDOG); >+ iaa_watchdog_done(ehci); >+ >+ if (!qh) >+ return; > > // qh->hw_next = cpu_to_le32 (qh->qh_dma); > qh->qh_state = QH_STATE_IDLE; >@@ -948,7 +986,6 @@ > /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ > next = qh->reclaim; > ehci->reclaim = next; >- ehci->reclaim_ready = 0; > qh->reclaim = NULL; > > qh_completions (ehci, qh, regs); >@@ -985,10 +1022,6 @@ > if (ehci->reclaim > || (qh->qh_state != QH_STATE_LINKED > && qh->qh_state != QH_STATE_UNLINK_WAIT) >-#ifdef CONFIG_SMP >-// this macro lies except on SMP compiles >- || !spin_is_locked (&ehci->lock) >-#endif > ) > BUG (); > #endif >@@ -996,14 +1029,15 @@ > /* stop async schedule right now? */ > if (unlikely (qh == ehci->async)) { > /* can't get here without STS_ASS set */ >- if (ehci->hcd.state != USB_STATE_HALT) { >+ if (ehci->hcd.state != USB_STATE_HALT >+ && !ehci->reclaim) { > writel (cmd & ~CMD_ASE, &ehci->regs->command); > wmb (); > // handshake later, if we need to >+ timer_action_done (ehci, TIMER_ASYNC_OFF); > } >- timer_action_done (ehci, TIMER_ASYNC_OFF); > return; >- } >+ } > > qh->qh_state = QH_STATE_UNLINK; > ehci->reclaim = qh = qh_get (qh); >@@ -1024,11 +1058,10 @@ > return; > } > >- ehci->reclaim_ready = 0; > cmd |= CMD_IAAD; > writel (cmd, &ehci->regs->command); > (void) readl (&ehci->regs->command); >- timer_action (ehci, TIMER_IAA_WATCHDOG); >+ iaa_watchdog_start(ehci); > } > > /*-------------------------------------------------------------------------*/
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 435787
:
297411
|
297591
|
301746
|
301913
|
303125
| 304091