Loading drivers/usb/host/ehci-dbg.c +3 −1 Original line number Diff line number Diff line Loading @@ -754,7 +754,9 @@ show_registers (struct class_device *class_dev, char *buf) } if (ehci->reclaim) { temp = scnprintf (next, size, "reclaim qh %p\n", ehci->reclaim); temp = scnprintf (next, size, "reclaim qh %p%s\n", ehci->reclaim, ehci->reclaim_ready ? " ready" : ""); size -= temp; next += temp; } Loading drivers/usb/host/ehci-hcd.c +21 −49 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ static const char hcd_name [] = "ehci_hcd"; #define EHCI_TUNE_MULT_TT 1 #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ #define EHCI_IAA_MSECS 10 /* arbitrary */ #define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ #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 */ Loading Loading @@ -254,7 +254,6 @@ static void ehci_quiesce (struct ehci_hcd *ehci) /*-------------------------------------------------------------------------*/ static void end_unlink_async (struct ehci_hcd *ehci); static void ehci_work(struct ehci_hcd *ehci); #include "ehci-hub.c" Loading @@ -264,36 +263,24 @@ static void ehci_work(struct ehci_hcd *ehci); /*-------------------------------------------------------------------------*/ static void ehci_iaa_watchdog (unsigned long param) static void ehci_watchdog (unsigned long param) { struct ehci_hcd *ehci = (struct ehci_hcd *) param; unsigned long flags; u32 status; spin_lock_irqsave (&ehci->lock, flags); WARN_ON(!ehci->reclaim); /* lost IAA irqs wedge things badly; seen first with a vt8235 */ /* lost IAA irqs wedge things badly; seen with a vt8235 */ if (ehci->reclaim) { status = readl (&ehci->regs->status); u32 status = readl (&ehci->regs->status); if (status & STS_IAA) { ehci_vdbg (ehci, "lost IAA\n"); COUNT (ehci->stats.lost_iaa); writel (STS_IAA, &ehci->regs->status); end_unlink_async (ehci); ehci->reclaim_ready = 1; } } 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); Loading Loading @@ -345,6 +332,8 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) static void ehci_work (struct ehci_hcd *ehci) { timer_action_done (ehci, TIMER_IO_WATCHDOG); if (ehci->reclaim_ready) end_unlink_async (ehci); /* another CPU may drop ehci->lock during a schedule scan while * it reports urb completions. this flag guards against bogus Loading Loading @@ -379,7 +368,6 @@ static void ehci_stop (struct usb_hcd *hcd) /* no more interrupts ... */ del_timer_sync (&ehci->watchdog); del_timer_sync (&ehci->iaa_watchdog); spin_lock_irq(&ehci->lock); if (HC_IS_RUNNING (hcd->state)) Loading Loading @@ -426,10 +414,6 @@ static int ehci_init(struct usb_hcd *hcd) 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; /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. Loading @@ -446,6 +430,7 @@ static int ehci_init(struct usb_hcd *hcd) ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); ehci->reclaim = NULL; ehci->reclaim_ready = 0; ehci->next_uframe = -1; /* Loading Loading @@ -619,7 +604,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* complete the unlinking of some qh [4.15.2.3] */ if (status & STS_IAA) { COUNT (ehci->stats.reclaim); end_unlink_async (ehci); ehci->reclaim_ready = 1; bh = 1; } Loading Loading @@ -723,14 +708,10 @@ static int ehci_urb_enqueue ( static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) { // BUG_ON(qh->qh_state != QH_STATE_LINKED); /* failfast */ if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) end_unlink_async (ehci); /* defer till later if busy */ else if (ehci->reclaim) { /* if we need to use IAA and it's busy, defer */ if (qh->qh_state == QH_STATE_LINKED && ehci->reclaim && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { struct ehci_qh *last; for (last = ehci->reclaim; Loading @@ -740,8 +721,12 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) qh->qh_state = QH_STATE_UNLINK_WAIT; last->reclaim = qh; /* start IAA cycle */ } else /* bypass IAA if the hc can't care */ } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) end_unlink_async (ehci); /* something else might have unlinked the qh by now */ if (qh->qh_state == QH_STATE_LINKED) start_unlink_async (ehci, qh); } Loading @@ -763,20 +748,8 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) qh = (struct ehci_qh *) urb->hcpriv; if (!qh) break; 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: qh = (struct ehci_qh *) urb->hcpriv; Loading Loading @@ -867,7 +840,6 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) 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); schedule_timeout_uninterruptible(1); Loading drivers/usb/host/ehci-hub.c +1 −1 Original line number Diff line number Diff line Loading @@ -48,7 +48,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) } ehci->command = readl (&ehci->regs->command); if (ehci->reclaim) end_unlink_async (ehci); ehci->reclaim_ready = 1; ehci_work(ehci); /* suspend any active/unsuspended ports, maybe allow wakeup */ Loading drivers/usb/host/ehci-pci.c +1 −1 Original line number Diff line number Diff line Loading @@ -303,7 +303,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd) /* emptying the schedule aborts any urbs */ spin_lock_irq(&ehci->lock); if (ehci->reclaim) end_unlink_async (ehci); ehci->reclaim_ready = 1; ehci_work(ehci); spin_unlock_irq(&ehci->lock); Loading drivers/usb/host/ehci-q.c +4 −2 Original line number Diff line number Diff line Loading @@ -967,7 +967,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) struct ehci_qh *qh = ehci->reclaim; struct ehci_qh *next; iaa_watchdog_done (ehci); timer_action_done (ehci, TIMER_IAA_WATCHDOG); // qh->hw_next = cpu_to_le32 (qh->qh_dma); qh->qh_state = QH_STATE_IDLE; Loading @@ -977,6 +977,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) /* 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); Loading Loading @@ -1051,10 +1052,11 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) return; } ehci->reclaim_ready = 0; cmd |= CMD_IAAD; writel (cmd, &ehci->regs->command); (void) readl (&ehci->regs->command); iaa_watchdog_start (ehci); timer_action (ehci, TIMER_IAA_WATCHDOG); } /*-------------------------------------------------------------------------*/ Loading Loading
drivers/usb/host/ehci-dbg.c +3 −1 Original line number Diff line number Diff line Loading @@ -754,7 +754,9 @@ show_registers (struct class_device *class_dev, char *buf) } if (ehci->reclaim) { temp = scnprintf (next, size, "reclaim qh %p\n", ehci->reclaim); temp = scnprintf (next, size, "reclaim qh %p%s\n", ehci->reclaim, ehci->reclaim_ready ? " ready" : ""); size -= temp; next += temp; } Loading
drivers/usb/host/ehci-hcd.c +21 −49 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ static const char hcd_name [] = "ehci_hcd"; #define EHCI_TUNE_MULT_TT 1 #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ #define EHCI_IAA_MSECS 10 /* arbitrary */ #define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ #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 */ Loading Loading @@ -254,7 +254,6 @@ static void ehci_quiesce (struct ehci_hcd *ehci) /*-------------------------------------------------------------------------*/ static void end_unlink_async (struct ehci_hcd *ehci); static void ehci_work(struct ehci_hcd *ehci); #include "ehci-hub.c" Loading @@ -264,36 +263,24 @@ static void ehci_work(struct ehci_hcd *ehci); /*-------------------------------------------------------------------------*/ static void ehci_iaa_watchdog (unsigned long param) static void ehci_watchdog (unsigned long param) { struct ehci_hcd *ehci = (struct ehci_hcd *) param; unsigned long flags; u32 status; spin_lock_irqsave (&ehci->lock, flags); WARN_ON(!ehci->reclaim); /* lost IAA irqs wedge things badly; seen first with a vt8235 */ /* lost IAA irqs wedge things badly; seen with a vt8235 */ if (ehci->reclaim) { status = readl (&ehci->regs->status); u32 status = readl (&ehci->regs->status); if (status & STS_IAA) { ehci_vdbg (ehci, "lost IAA\n"); COUNT (ehci->stats.lost_iaa); writel (STS_IAA, &ehci->regs->status); end_unlink_async (ehci); ehci->reclaim_ready = 1; } } 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); Loading Loading @@ -345,6 +332,8 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) static void ehci_work (struct ehci_hcd *ehci) { timer_action_done (ehci, TIMER_IO_WATCHDOG); if (ehci->reclaim_ready) end_unlink_async (ehci); /* another CPU may drop ehci->lock during a schedule scan while * it reports urb completions. this flag guards against bogus Loading Loading @@ -379,7 +368,6 @@ static void ehci_stop (struct usb_hcd *hcd) /* no more interrupts ... */ del_timer_sync (&ehci->watchdog); del_timer_sync (&ehci->iaa_watchdog); spin_lock_irq(&ehci->lock); if (HC_IS_RUNNING (hcd->state)) Loading Loading @@ -426,10 +414,6 @@ static int ehci_init(struct usb_hcd *hcd) 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; /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. Loading @@ -446,6 +430,7 @@ static int ehci_init(struct usb_hcd *hcd) ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); ehci->reclaim = NULL; ehci->reclaim_ready = 0; ehci->next_uframe = -1; /* Loading Loading @@ -619,7 +604,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* complete the unlinking of some qh [4.15.2.3] */ if (status & STS_IAA) { COUNT (ehci->stats.reclaim); end_unlink_async (ehci); ehci->reclaim_ready = 1; bh = 1; } Loading Loading @@ -723,14 +708,10 @@ static int ehci_urb_enqueue ( static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) { // BUG_ON(qh->qh_state != QH_STATE_LINKED); /* failfast */ if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) end_unlink_async (ehci); /* defer till later if busy */ else if (ehci->reclaim) { /* if we need to use IAA and it's busy, defer */ if (qh->qh_state == QH_STATE_LINKED && ehci->reclaim && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { struct ehci_qh *last; for (last = ehci->reclaim; Loading @@ -740,8 +721,12 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) qh->qh_state = QH_STATE_UNLINK_WAIT; last->reclaim = qh; /* start IAA cycle */ } else /* bypass IAA if the hc can't care */ } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) end_unlink_async (ehci); /* something else might have unlinked the qh by now */ if (qh->qh_state == QH_STATE_LINKED) start_unlink_async (ehci, qh); } Loading @@ -763,20 +748,8 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) qh = (struct ehci_qh *) urb->hcpriv; if (!qh) break; 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: qh = (struct ehci_qh *) urb->hcpriv; Loading Loading @@ -867,7 +840,6 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) 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); schedule_timeout_uninterruptible(1); Loading
drivers/usb/host/ehci-hub.c +1 −1 Original line number Diff line number Diff line Loading @@ -48,7 +48,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) } ehci->command = readl (&ehci->regs->command); if (ehci->reclaim) end_unlink_async (ehci); ehci->reclaim_ready = 1; ehci_work(ehci); /* suspend any active/unsuspended ports, maybe allow wakeup */ Loading
drivers/usb/host/ehci-pci.c +1 −1 Original line number Diff line number Diff line Loading @@ -303,7 +303,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd) /* emptying the schedule aborts any urbs */ spin_lock_irq(&ehci->lock); if (ehci->reclaim) end_unlink_async (ehci); ehci->reclaim_ready = 1; ehci_work(ehci); spin_unlock_irq(&ehci->lock); Loading
drivers/usb/host/ehci-q.c +4 −2 Original line number Diff line number Diff line Loading @@ -967,7 +967,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) struct ehci_qh *qh = ehci->reclaim; struct ehci_qh *next; iaa_watchdog_done (ehci); timer_action_done (ehci, TIMER_IAA_WATCHDOG); // qh->hw_next = cpu_to_le32 (qh->qh_dma); qh->qh_state = QH_STATE_IDLE; Loading @@ -977,6 +977,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) /* 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); Loading Loading @@ -1051,10 +1052,11 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) return; } ehci->reclaim_ready = 0; cmd |= CMD_IAAD; writel (cmd, &ehci->regs->command); (void) readl (&ehci->regs->command); iaa_watchdog_start (ehci); timer_action (ehci, TIMER_IAA_WATCHDOG); } /*-------------------------------------------------------------------------*/ Loading