aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-12-11 16:05:30 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-01 17:34:55 -0500
commit07d29b63ef6b39963ab37818653284d861cf55af (patch)
tree10460d9d13ad7284b644181af66ecdbf416cc5ba /drivers/usb/host/ehci-hcd.c
parent2e2eb83ffd1aeb92bf8793eea892b5bc05a993ea (diff)
USB: EHCI: add separate IAA watchdog timer
This patch (as1028) was mostly written by David Brownell; I made only a few changes (extra log info and a small bug fix -- which might account for why David's version had to be reverted). It adds a new watchdog timer to the ehci-hcd driver to be used exclusively for detecting lost or missing IAA notifications. Previously a shared timer had been used, which may have led to some problems as reported by Christian Hoffmann. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Cc: David Brownell <david-b@pacbell.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r--drivers/usb/host/ehci-hcd.c77
1 files changed, 55 insertions, 22 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 264182654f4c..5917c6b7ce33 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -110,7 +110,7 @@ static const char hcd_name [] = "ehci_hcd";
110#define EHCI_TUNE_MULT_TT 1 110#define EHCI_TUNE_MULT_TT 1
111#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ 111#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */
112 112
113#define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ 113#define EHCI_IAA_MSECS 10 /* arbitrary */
114#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ 114#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
115#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ 115#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
116#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ 116#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */
@@ -267,6 +267,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
267 267
268/*-------------------------------------------------------------------------*/ 268/*-------------------------------------------------------------------------*/
269 269
270static void end_unlink_async(struct ehci_hcd *ehci);
270static void ehci_work(struct ehci_hcd *ehci); 271static void ehci_work(struct ehci_hcd *ehci);
271 272
272#include "ehci-hub.c" 273#include "ehci-hub.c"
@@ -276,25 +277,41 @@ static void ehci_work(struct ehci_hcd *ehci);
276 277
277/*-------------------------------------------------------------------------*/ 278/*-------------------------------------------------------------------------*/
278 279
279static void ehci_watchdog (unsigned long param) 280static void ehci_iaa_watchdog(unsigned long param)
280{ 281{
281 struct ehci_hcd *ehci = (struct ehci_hcd *) param; 282 struct ehci_hcd *ehci = (struct ehci_hcd *) param;
282 unsigned long flags; 283 unsigned long flags;
284 u32 status, cmd;
283 285
284 spin_lock_irqsave (&ehci->lock, flags); 286 spin_lock_irqsave (&ehci->lock, flags);
287 WARN_ON(!ehci->reclaim);
285 288
286 /* lost IAA irqs wedge things badly; seen with a vt8235 */ 289 status = ehci_readl(ehci, &ehci->regs->status);
290 cmd = ehci_readl(ehci, &ehci->regs->command);
291 ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
292
293 /* lost IAA irqs wedge things badly; seen first with a vt8235 */
287 if (ehci->reclaim) { 294 if (ehci->reclaim) {
288 u32 status = ehci_readl(ehci, &ehci->regs->status);
289 if (status & STS_IAA) { 295 if (status & STS_IAA) {
290 ehci_vdbg (ehci, "lost IAA\n"); 296 ehci_vdbg (ehci, "lost IAA\n");
291 COUNT (ehci->stats.lost_iaa); 297 COUNT (ehci->stats.lost_iaa);
292 ehci_writel(ehci, STS_IAA, &ehci->regs->status); 298 ehci_writel(ehci, STS_IAA, &ehci->regs->status);
293 ehci->reclaim_ready = 1;
294 } 299 }
300 ehci_writel(ehci, cmd & ~CMD_IAAD, &ehci->regs->command);
301 end_unlink_async(ehci);
295 } 302 }
296 303
297 /* stop async processing after it's idled a bit */ 304 spin_unlock_irqrestore(&ehci->lock, flags);
305}
306
307static void ehci_watchdog(unsigned long param)
308{
309 struct ehci_hcd *ehci = (struct ehci_hcd *) param;
310 unsigned long flags;
311
312 spin_lock_irqsave(&ehci->lock, flags);
313
314 /* stop async processing after it's idled a bit */
298 if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) 315 if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
299 start_unlink_async (ehci, ehci->async); 316 start_unlink_async (ehci, ehci->async);
300 317
@@ -364,8 +381,6 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
364static void ehci_work (struct ehci_hcd *ehci) 381static void ehci_work (struct ehci_hcd *ehci)
365{ 382{
366 timer_action_done (ehci, TIMER_IO_WATCHDOG); 383 timer_action_done (ehci, TIMER_IO_WATCHDOG);
367 if (ehci->reclaim_ready)
368 end_unlink_async (ehci);
369 384
370 /* another CPU may drop ehci->lock during a schedule scan while 385 /* another CPU may drop ehci->lock during a schedule scan while
371 * it reports urb completions. this flag guards against bogus 386 * it reports urb completions. this flag guards against bogus
@@ -400,6 +415,7 @@ static void ehci_stop (struct usb_hcd *hcd)
400 415
401 /* no more interrupts ... */ 416 /* no more interrupts ... */
402 del_timer_sync (&ehci->watchdog); 417 del_timer_sync (&ehci->watchdog);
418 del_timer_sync(&ehci->iaa_watchdog);
403 419
404 spin_lock_irq(&ehci->lock); 420 spin_lock_irq(&ehci->lock);
405 if (HC_IS_RUNNING (hcd->state)) 421 if (HC_IS_RUNNING (hcd->state))
@@ -448,6 +464,10 @@ static int ehci_init(struct usb_hcd *hcd)
448 ehci->watchdog.function = ehci_watchdog; 464 ehci->watchdog.function = ehci_watchdog;
449 ehci->watchdog.data = (unsigned long) ehci; 465 ehci->watchdog.data = (unsigned long) ehci;
450 466
467 init_timer(&ehci->iaa_watchdog);
468 ehci->iaa_watchdog.function = ehci_iaa_watchdog;
469 ehci->iaa_watchdog.data = (unsigned long) ehci;
470
451 /* 471 /*
452 * hw default: 1K periodic list heads, one per frame. 472 * hw default: 1K periodic list heads, one per frame.
453 * periodic_size can shrink by USBCMD update if hcc_params allows. 473 * periodic_size can shrink by USBCMD update if hcc_params allows.
@@ -464,7 +484,6 @@ static int ehci_init(struct usb_hcd *hcd)
464 ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); 484 ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
465 485
466 ehci->reclaim = NULL; 486 ehci->reclaim = NULL;
467 ehci->reclaim_ready = 0;
468 ehci->next_uframe = -1; 487 ehci->next_uframe = -1;
469 488
470 /* 489 /*
@@ -655,8 +674,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
655 /* complete the unlinking of some qh [4.15.2.3] */ 674 /* complete the unlinking of some qh [4.15.2.3] */
656 if (status & STS_IAA) { 675 if (status & STS_IAA) {
657 COUNT (ehci->stats.reclaim); 676 COUNT (ehci->stats.reclaim);
658 ehci->reclaim_ready = 1; 677 end_unlink_async(ehci);
659 bh = 1;
660 } 678 }
661 679
662 /* remote wakeup [4.3.1] */ 680 /* remote wakeup [4.3.1] */
@@ -762,10 +780,16 @@ static int ehci_urb_enqueue (
762 780
763static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) 781static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
764{ 782{
765 /* if we need to use IAA and it's busy, defer */ 783 /* failfast */
766 if (qh->qh_state == QH_STATE_LINKED 784 if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
767 && ehci->reclaim 785 end_unlink_async(ehci);
768 && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { 786
787 /* if it's not linked then there's nothing to do */
788 if (qh->qh_state != QH_STATE_LINKED)
789 ;
790
791 /* defer till later if busy */
792 else if (ehci->reclaim) {
769 struct ehci_qh *last; 793 struct ehci_qh *last;
770 794
771 for (last = ehci->reclaim; 795 for (last = ehci->reclaim;
@@ -775,12 +799,8 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
775 qh->qh_state = QH_STATE_UNLINK_WAIT; 799 qh->qh_state = QH_STATE_UNLINK_WAIT;
776 last->reclaim = qh; 800 last->reclaim = qh;
777 801
778 /* bypass IAA if the hc can't care */ 802 /* start IAA cycle */
779 } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) 803 } else
780 end_unlink_async (ehci);
781
782 /* something else might have unlinked the qh by now */
783 if (qh->qh_state == QH_STATE_LINKED)
784 start_unlink_async (ehci, qh); 804 start_unlink_async (ehci, qh);
785} 805}
786 806
@@ -807,7 +827,19 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
807 qh = (struct ehci_qh *) urb->hcpriv; 827 qh = (struct ehci_qh *) urb->hcpriv;
808 if (!qh) 828 if (!qh)
809 break; 829 break;
810 unlink_async (ehci, qh); 830 switch (qh->qh_state) {
831 case QH_STATE_LINKED:
832 case QH_STATE_COMPLETING:
833 unlink_async(ehci, qh);
834 break;
835 case QH_STATE_UNLINK:
836 case QH_STATE_UNLINK_WAIT:
837 /* already started */
838 break;
839 case QH_STATE_IDLE:
840 WARN_ON(1);
841 break;
842 }
811 break; 843 break;
812 844
813 case PIPE_INTERRUPT: 845 case PIPE_INTERRUPT:
@@ -899,6 +931,7 @@ rescan:
899 unlink_async (ehci, qh); 931 unlink_async (ehci, qh);
900 /* FALL THROUGH */ 932 /* FALL THROUGH */
901 case QH_STATE_UNLINK: /* wait for hw to finish? */ 933 case QH_STATE_UNLINK: /* wait for hw to finish? */
934 case QH_STATE_UNLINK_WAIT:
902idle_timeout: 935idle_timeout:
903 spin_unlock_irqrestore (&ehci->lock, flags); 936 spin_unlock_irqrestore (&ehci->lock, flags);
904 schedule_timeout_uninterruptible(1); 937 schedule_timeout_uninterruptible(1);