aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ohci-hcd.c
diff options
context:
space:
mode:
authorMike Nuss <mike@terascala.com>2007-08-01 16:24:30 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-12 17:54:59 -0400
commit89a0fd18a96eb1f8732714b575073f8a8d69c009 (patch)
tree166d14fc49ad7fd646e1e7aa7decf6b3bea6d381 /drivers/usb/host/ohci-hcd.c
parente8fa0ce65c58dbb60be279c4e33534650dcacc31 (diff)
USB: OHCI handles more ZFMicro quirks
The ZF Micro OHCI controller exhibits unexpected behavior that seems to be related to high load. Under certain conditions, the controller will complete a TD, remove it from the endpoint's queue, and fail to add it to the donelist. This causes the endpoint to appear to stop responding. Worse, if the device is removed while in that state, OHCI will hang while waiting for the orphaned TD to complete. The situation is not recoverable without rebooting. This fix enhances the scope of the existing OHCI_QUIRK_ZFMICRO flag: 1. A watchdog routine periodically scans the OHCI structures to check for orphaned TDs. In these cases the TD is taken back from the controller and completed normally. 2. If a device is removed while the endpoint is hung but before the watchdog catches the situation, any outstanding TDs are taken back from the controller in the 'sanitize' phase. The ohci-hcd driver used to print "INTR_SF lossage" in this situation; this changes it to the universally accurate "ED unlink timeout". Other instances of this message presumably have different root causes. Both this Compaq quirk and a NEC quirk are now properly compiled out for non-PCI builds of this driver. Signed-off-by: Mike Nuss <mike@terascala.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ohci-hcd.c')
-rw-r--r--drivers/usb/host/ohci-hcd.c166
1 files changed, 139 insertions, 27 deletions
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 6edf4097d2d2..d673cb9c36b1 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -81,7 +81,6 @@ static void ohci_dump (struct ohci_hcd *ohci, int verbose);
81static int ohci_init (struct ohci_hcd *ohci); 81static int ohci_init (struct ohci_hcd *ohci);
82static void ohci_stop (struct usb_hcd *hcd); 82static void ohci_stop (struct usb_hcd *hcd);
83static int ohci_restart (struct ohci_hcd *ohci); 83static int ohci_restart (struct ohci_hcd *ohci);
84static void ohci_quirk_nec_worker (struct work_struct *work);
85 84
86#include "ohci-hub.c" 85#include "ohci-hub.c"
87#include "ohci-dbg.c" 86#include "ohci-dbg.c"
@@ -314,6 +313,8 @@ rescan:
314 if (!HC_IS_RUNNING (hcd->state)) { 313 if (!HC_IS_RUNNING (hcd->state)) {
315sanitize: 314sanitize:
316 ed->state = ED_IDLE; 315 ed->state = ED_IDLE;
316 if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT)
317 ohci->eds_scheduled--;
317 finish_unlinks (ohci, 0); 318 finish_unlinks (ohci, 0);
318 } 319 }
319 320
@@ -321,7 +322,12 @@ sanitize:
321 case ED_UNLINK: /* wait for hw to finish? */ 322 case ED_UNLINK: /* wait for hw to finish? */
322 /* major IRQ delivery trouble loses INTR_SF too... */ 323 /* major IRQ delivery trouble loses INTR_SF too... */
323 if (limit-- == 0) { 324 if (limit-- == 0) {
324 ohci_warn (ohci, "IRQ INTR_SF lossage\n"); 325 ohci_warn(ohci, "ED unlink timeout\n");
326 if (quirk_zfmicro(ohci)) {
327 ohci_warn(ohci, "Attempting ZF TD recovery\n");
328 ohci->ed_to_check = ed;
329 ohci->zf_delay = 2;
330 }
325 goto sanitize; 331 goto sanitize;
326 } 332 }
327 spin_unlock_irqrestore (&ohci->lock, flags); 333 spin_unlock_irqrestore (&ohci->lock, flags);
@@ -379,6 +385,93 @@ ohci_shutdown (struct usb_hcd *hcd)
379 (void) ohci_readl (ohci, &ohci->regs->control); 385 (void) ohci_readl (ohci, &ohci->regs->control);
380} 386}
381 387
388static int check_ed(struct ohci_hcd *ohci, struct ed *ed)
389{
390 return (hc32_to_cpu(ohci, ed->hwINFO) & ED_IN) != 0
391 && (hc32_to_cpu(ohci, ed->hwHeadP) & TD_MASK)
392 == (hc32_to_cpu(ohci, ed->hwTailP) & TD_MASK)
393 && !list_empty(&ed->td_list);
394}
395
396/* ZF Micro watchdog timer callback. The ZF Micro chipset sometimes completes
397 * an interrupt TD but neglects to add it to the donelist. On systems with
398 * this chipset, we need to periodically check the state of the queues to look
399 * for such "lost" TDs.
400 */
401static void unlink_watchdog_func(unsigned long _ohci)
402{
403 long flags;
404 unsigned max;
405 unsigned seen_count = 0;
406 unsigned i;
407 struct ed **seen = NULL;
408 struct ohci_hcd *ohci = (struct ohci_hcd *) _ohci;
409
410 spin_lock_irqsave(&ohci->lock, flags);
411 max = ohci->eds_scheduled;
412 if (!max)
413 goto done;
414
415 if (ohci->ed_to_check)
416 goto out;
417
418 seen = kcalloc(max, sizeof *seen, GFP_ATOMIC);
419 if (!seen)
420 goto out;
421
422 for (i = 0; i < NUM_INTS; i++) {
423 struct ed *ed = ohci->periodic[i];
424
425 while (ed) {
426 unsigned temp;
427
428 /* scan this branch of the periodic schedule tree */
429 for (temp = 0; temp < seen_count; temp++) {
430 if (seen[temp] == ed) {
431 /* we've checked it and what's after */
432 ed = NULL;
433 break;
434 }
435 }
436 if (!ed)
437 break;
438 seen[seen_count++] = ed;
439 if (!check_ed(ohci, ed)) {
440 ed = ed->ed_next;
441 continue;
442 }
443
444 /* HC's TD list is empty, but HCD sees at least one
445 * TD that's not been sent through the donelist.
446 */
447 ohci->ed_to_check = ed;
448 ohci->zf_delay = 2;
449
450 /* The HC may wait until the next frame to report the
451 * TD as done through the donelist and INTR_WDH. (We
452 * just *assume* it's not a multi-TD interrupt URB;
453 * those could defer the IRQ more than one frame, using
454 * DI...) Check again after the next INTR_SF.
455 */
456 ohci_writel(ohci, OHCI_INTR_SF,
457 &ohci->regs->intrstatus);
458 ohci_writel(ohci, OHCI_INTR_SF,
459 &ohci->regs->intrenable);
460
461 /* flush those writes */
462 (void) ohci_readl(ohci, &ohci->regs->control);
463
464 goto out;
465 }
466 }
467out:
468 kfree(seen);
469 if (ohci->eds_scheduled)
470 mod_timer(&ohci->unlink_watchdog, round_jiffies_relative(HZ));
471done:
472 spin_unlock_irqrestore(&ohci->lock, flags);
473}
474
382/*-------------------------------------------------------------------------* 475/*-------------------------------------------------------------------------*
383 * HC functions 476 * HC functions
384 *-------------------------------------------------------------------------*/ 477 *-------------------------------------------------------------------------*/
@@ -616,6 +709,15 @@ retry:
616 mdelay ((temp >> 23) & 0x1fe); 709 mdelay ((temp >> 23) & 0x1fe);
617 hcd->state = HC_STATE_RUNNING; 710 hcd->state = HC_STATE_RUNNING;
618 711
712 if (quirk_zfmicro(ohci)) {
713 /* Create timer to watch for bad queue state on ZF Micro */
714 setup_timer(&ohci->unlink_watchdog, unlink_watchdog_func,
715 (unsigned long) ohci);
716
717 ohci->eds_scheduled = 0;
718 ohci->ed_to_check = NULL;
719 }
720
619 ohci_dump (ohci, 1); 721 ohci_dump (ohci, 1);
620 722
621 return 0; 723 return 0;
@@ -629,10 +731,11 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
629{ 731{
630 struct ohci_hcd *ohci = hcd_to_ohci (hcd); 732 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
631 struct ohci_regs __iomem *regs = ohci->regs; 733 struct ohci_regs __iomem *regs = ohci->regs;
632 int ints; 734 int ints;
633 735
634 /* we can eliminate a (slow) ohci_readl() 736 /* we can eliminate a (slow) ohci_readl()
635 if _only_ WDH caused this irq */ 737 * if _only_ WDH caused this irq
738 */
636 if ((ohci->hcca->done_head != 0) 739 if ((ohci->hcca->done_head != 0)
637 && ! (hc32_to_cpup (ohci, &ohci->hcca->done_head) 740 && ! (hc32_to_cpup (ohci, &ohci->hcca->done_head)
638 & 0x01)) { 741 & 0x01)) {
@@ -651,7 +754,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
651 754
652 if (ints & OHCI_INTR_UE) { 755 if (ints & OHCI_INTR_UE) {
653 // e.g. due to PCI Master/Target Abort 756 // e.g. due to PCI Master/Target Abort
654 if (ohci->flags & OHCI_QUIRK_NEC) { 757 if (quirk_nec(ohci)) {
655 /* Workaround for a silicon bug in some NEC chips used 758 /* Workaround for a silicon bug in some NEC chips used
656 * in Apple's PowerBooks. Adapted from Darwin code. 759 * in Apple's PowerBooks. Adapted from Darwin code.
657 */ 760 */
@@ -713,6 +816,31 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
713 ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable); 816 ohci_writel (ohci, OHCI_INTR_WDH, &regs->intrenable);
714 } 817 }
715 818
819 if (quirk_zfmicro(ohci) && (ints & OHCI_INTR_SF)) {
820 spin_lock(&ohci->lock);
821 if (ohci->ed_to_check) {
822 struct ed *ed = ohci->ed_to_check;
823
824 if (check_ed(ohci, ed)) {
825 /* HC thinks the TD list is empty; HCD knows
826 * at least one TD is outstanding
827 */
828 if (--ohci->zf_delay == 0) {
829 struct td *td = list_entry(
830 ed->td_list.next,
831 struct td, td_list);
832 ohci_warn(ohci,
833 "Reclaiming orphan TD %p\n",
834 td);
835 takeback_td(ohci, td);
836 ohci->ed_to_check = NULL;
837 }
838 } else
839 ohci->ed_to_check = NULL;
840 }
841 spin_unlock(&ohci->lock);
842 }
843
716 /* could track INTR_SO to reduce available PCI/... bandwidth */ 844 /* could track INTR_SO to reduce available PCI/... bandwidth */
717 845
718 /* handle any pending URB/ED unlinks, leaving INTR_SF enabled 846 /* handle any pending URB/ED unlinks, leaving INTR_SF enabled
@@ -721,7 +849,9 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
721 spin_lock (&ohci->lock); 849 spin_lock (&ohci->lock);
722 if (ohci->ed_rm_list) 850 if (ohci->ed_rm_list)
723 finish_unlinks (ohci, ohci_frame_no(ohci)); 851 finish_unlinks (ohci, ohci_frame_no(ohci));
724 if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list 852 if ((ints & OHCI_INTR_SF) != 0
853 && !ohci->ed_rm_list
854 && !ohci->ed_to_check
725 && HC_IS_RUNNING(hcd->state)) 855 && HC_IS_RUNNING(hcd->state))
726 ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable); 856 ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
727 spin_unlock (&ohci->lock); 857 spin_unlock (&ohci->lock);
@@ -751,6 +881,9 @@ static void ohci_stop (struct usb_hcd *hcd)
751 free_irq(hcd->irq, hcd); 881 free_irq(hcd->irq, hcd);
752 hcd->irq = -1; 882 hcd->irq = -1;
753 883
884 if (quirk_zfmicro(ohci))
885 del_timer(&ohci->unlink_watchdog);
886
754 remove_debug_files (ohci); 887 remove_debug_files (ohci);
755 ohci_mem_cleanup (ohci); 888 ohci_mem_cleanup (ohci);
756 if (ohci->hcca) { 889 if (ohci->hcca) {
@@ -828,27 +961,6 @@ static int ohci_restart (struct ohci_hcd *ohci)
828 961
829/*-------------------------------------------------------------------------*/ 962/*-------------------------------------------------------------------------*/
830 963
831/* NEC workaround */
832static void ohci_quirk_nec_worker(struct work_struct *work)
833{
834 struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work);
835 int status;
836
837 status = ohci_init(ohci);
838 if (status != 0) {
839 ohci_err(ohci, "Restarting NEC controller failed "
840 "in ohci_init, %d\n", status);
841 return;
842 }
843
844 status = ohci_restart(ohci);
845 if (status != 0)
846 ohci_err(ohci, "Restarting NEC controller failed "
847 "in ohci_restart, %d\n", status);
848}
849
850/*-------------------------------------------------------------------------*/
851
852#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC 964#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
853 965
854MODULE_AUTHOR (DRIVER_AUTHOR); 966MODULE_AUTHOR (DRIVER_AUTHOR);