aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/ehci-dbg.c4
-rw-r--r--drivers/usb/host/ehci-hcd.c73
-rw-r--r--drivers/usb/host/ehci-hub.c2
-rw-r--r--drivers/usb/host/ehci-pci.c2
-rw-r--r--drivers/usb/host/ehci-q.c6
-rw-r--r--drivers/usb/host/ehci.h22
6 files changed, 70 insertions, 39 deletions
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 34b7a31cd85b..23b95b2bfe15 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -754,9 +754,7 @@ show_registers (struct class_device *class_dev, char *buf)
754 } 754 }
755 755
756 if (ehci->reclaim) { 756 if (ehci->reclaim) {
757 temp = scnprintf (next, size, "reclaim qh %p%s\n", 757 temp = scnprintf (next, size, "reclaim qh %p\n", ehci->reclaim);
758 ehci->reclaim,
759 ehci->reclaim_ready ? " ready" : "");
760 size -= temp; 758 size -= temp;
761 next += temp; 759 next += temp;
762 } 760 }
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 4e1a8c308893..5ac918591131 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -111,7 +111,7 @@ static const char hcd_name [] = "ehci_hcd";
111#define EHCI_TUNE_MULT_TT 1 111#define EHCI_TUNE_MULT_TT 1
112#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ 112#define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */
113 113
114#define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ 114#define EHCI_IAA_MSECS 10 /* arbitrary */
115#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ 115#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */
116#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ 116#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
117#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ 117#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */
@@ -254,6 +254,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
254 254
255/*-------------------------------------------------------------------------*/ 255/*-------------------------------------------------------------------------*/
256 256
257static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs);
257static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs); 258static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
258 259
259#include "ehci-hub.c" 260#include "ehci-hub.c"
@@ -263,28 +264,39 @@ static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
263 264
264/*-------------------------------------------------------------------------*/ 265/*-------------------------------------------------------------------------*/
265 266
266static void ehci_watchdog (unsigned long param) 267static void ehci_iaa_watchdog (unsigned long param)
267{ 268{
268 struct ehci_hcd *ehci = (struct ehci_hcd *) param; 269 struct ehci_hcd *ehci = (struct ehci_hcd *) param;
269 unsigned long flags; 270 unsigned long flags;
271 u32 status;
270 272
271 spin_lock_irqsave (&ehci->lock, flags); 273 spin_lock_irqsave (&ehci->lock, flags);
274 WARN_ON(!ehci->reclaim);
272 275
273 /* lost IAA irqs wedge things badly; seen with a vt8235 */ 276 /* lost IAA irqs wedge things badly; seen first with a vt8235 */
274 if (ehci->reclaim) { 277 if (ehci->reclaim) {
275 u32 status = readl (&ehci->regs->status); 278 status = readl (&ehci->regs->status);
276
277 if (status & STS_IAA) { 279 if (status & STS_IAA) {
278 ehci_vdbg (ehci, "lost IAA\n"); 280 ehci_vdbg (ehci, "lost IAA\n");
279 COUNT (ehci->stats.lost_iaa); 281 COUNT (ehci->stats.lost_iaa);
280 writel (STS_IAA, &ehci->regs->status); 282 writel (STS_IAA, &ehci->regs->status);
281 ehci->reclaim_ready = 1; 283 end_unlink_async (ehci, NULL);
282 } 284 }
283 } 285 }
284 286
285 /* stop async processing after it's idled a bit */ 287 spin_unlock_irqrestore (&ehci->lock, flags);
288}
289
290static void ehci_watchdog (unsigned long param)
291{
292 struct ehci_hcd *ehci = (struct ehci_hcd *) param;
293 unsigned long flags;
294
295 spin_lock_irqsave (&ehci->lock, flags);
296
297 /* stop async processing after it's idled a bit */
286 if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) 298 if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
287 start_unlink_async (ehci, ehci->async); 299 start_unlink_async (ehci, ehci->async);
288 300
289 /* ehci could run by timer, without IRQs ... */ 301 /* ehci could run by timer, without IRQs ... */
290 ehci_work (ehci, NULL); 302 ehci_work (ehci, NULL);
@@ -333,8 +345,6 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
333static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) 345static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
334{ 346{
335 timer_action_done (ehci, TIMER_IO_WATCHDOG); 347 timer_action_done (ehci, TIMER_IO_WATCHDOG);
336 if (ehci->reclaim_ready)
337 end_unlink_async (ehci, regs);
338 348
339 /* another CPU may drop ehci->lock during a schedule scan while 349 /* another CPU may drop ehci->lock during a schedule scan while
340 * it reports urb completions. this flag guards against bogus 350 * it reports urb completions. this flag guards against bogus
@@ -369,6 +379,7 @@ static void ehci_stop (struct usb_hcd *hcd)
369 379
370 /* no more interrupts ... */ 380 /* no more interrupts ... */
371 del_timer_sync (&ehci->watchdog); 381 del_timer_sync (&ehci->watchdog);
382 del_timer_sync (&ehci->iaa_watchdog);
372 383
373 spin_lock_irq(&ehci->lock); 384 spin_lock_irq(&ehci->lock);
374 if (HC_IS_RUNNING (hcd->state)) 385 if (HC_IS_RUNNING (hcd->state))
@@ -415,6 +426,10 @@ static int ehci_init(struct usb_hcd *hcd)
415 ehci->watchdog.function = ehci_watchdog; 426 ehci->watchdog.function = ehci_watchdog;
416 ehci->watchdog.data = (unsigned long) ehci; 427 ehci->watchdog.data = (unsigned long) ehci;
417 428
429 init_timer(&ehci->iaa_watchdog);
430 ehci->iaa_watchdog.function = ehci_iaa_watchdog;
431 ehci->iaa_watchdog.data = (unsigned long) ehci;
432
418 /* 433 /*
419 * hw default: 1K periodic list heads, one per frame. 434 * hw default: 1K periodic list heads, one per frame.
420 * periodic_size can shrink by USBCMD update if hcc_params allows. 435 * periodic_size can shrink by USBCMD update if hcc_params allows.
@@ -431,7 +446,6 @@ static int ehci_init(struct usb_hcd *hcd)
431 ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); 446 ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
432 447
433 ehci->reclaim = NULL; 448 ehci->reclaim = NULL;
434 ehci->reclaim_ready = 0;
435 ehci->next_uframe = -1; 449 ehci->next_uframe = -1;
436 450
437 /* 451 /*
@@ -605,7 +619,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
605 /* complete the unlinking of some qh [4.15.2.3] */ 619 /* complete the unlinking of some qh [4.15.2.3] */
606 if (status & STS_IAA) { 620 if (status & STS_IAA) {
607 COUNT (ehci->stats.reclaim); 621 COUNT (ehci->stats.reclaim);
608 ehci->reclaim_ready = 1; 622 end_unlink_async (ehci, regs);
609 bh = 1; 623 bh = 1;
610 } 624 }
611 625
@@ -709,10 +723,14 @@ static int ehci_urb_enqueue (
709 723
710static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) 724static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
711{ 725{
712 /* if we need to use IAA and it's busy, defer */ 726 // BUG_ON(qh->qh_state != QH_STATE_LINKED);
713 if (qh->qh_state == QH_STATE_LINKED 727
714 && ehci->reclaim 728 /* failfast */
715 && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { 729 if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
730 end_unlink_async (ehci, NULL);
731
732 /* defer till later if busy */
733 else if (ehci->reclaim) {
716 struct ehci_qh *last; 734 struct ehci_qh *last;
717 735
718 for (last = ehci->reclaim; 736 for (last = ehci->reclaim;
@@ -722,12 +740,8 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
722 qh->qh_state = QH_STATE_UNLINK_WAIT; 740 qh->qh_state = QH_STATE_UNLINK_WAIT;
723 last->reclaim = qh; 741 last->reclaim = qh;
724 742
725 /* bypass IAA if the hc can't care */ 743 /* start IAA cycle */
726 } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) 744 } else
727 end_unlink_async (ehci, NULL);
728
729 /* something else might have unlinked the qh by now */
730 if (qh->qh_state == QH_STATE_LINKED)
731 start_unlink_async (ehci, qh); 745 start_unlink_async (ehci, qh);
732} 746}
733 747
@@ -749,7 +763,19 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
749 qh = (struct ehci_qh *) urb->hcpriv; 763 qh = (struct ehci_qh *) urb->hcpriv;
750 if (!qh) 764 if (!qh)
751 break; 765 break;
752 unlink_async (ehci, qh); 766 switch (qh->qh_state) {
767 case QH_STATE_LINKED:
768 case QH_STATE_COMPLETING:
769 unlink_async (ehci, qh);
770 break;
771 case QH_STATE_UNLINK:
772 case QH_STATE_UNLINK_WAIT:
773 /* already started */
774 break;
775 case QH_STATE_IDLE:
776 WARN_ON(1);
777 break;
778 }
753 break; 779 break;
754 780
755 case PIPE_INTERRUPT: 781 case PIPE_INTERRUPT:
@@ -841,6 +867,7 @@ rescan:
841 unlink_async (ehci, qh); 867 unlink_async (ehci, qh);
842 /* FALL THROUGH */ 868 /* FALL THROUGH */
843 case QH_STATE_UNLINK: /* wait for hw to finish? */ 869 case QH_STATE_UNLINK: /* wait for hw to finish? */
870 case QH_STATE_UNLINK_WAIT:
844idle_timeout: 871idle_timeout:
845 spin_unlock_irqrestore (&ehci->lock, flags); 872 spin_unlock_irqrestore (&ehci->lock, flags);
846 schedule_timeout_uninterruptible(1); 873 schedule_timeout_uninterruptible(1);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index a5eeb9cd6ab2..b2ee13c58517 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -48,7 +48,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
48 } 48 }
49 ehci->command = readl (&ehci->regs->command); 49 ehci->command = readl (&ehci->regs->command);
50 if (ehci->reclaim) 50 if (ehci->reclaim)
51 ehci->reclaim_ready = 1; 51 end_unlink_async (ehci, NULL);
52 ehci_work(ehci, NULL); 52 ehci_work(ehci, NULL);
53 53
54 /* suspend any active/unsuspended ports, maybe allow wakeup */ 54 /* suspend any active/unsuspended ports, maybe allow wakeup */
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index e6a3bcddd55b..08d0472d4f57 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -303,7 +303,7 @@ restart:
303 /* emptying the schedule aborts any urbs */ 303 /* emptying the schedule aborts any urbs */
304 spin_lock_irq(&ehci->lock); 304 spin_lock_irq(&ehci->lock);
305 if (ehci->reclaim) 305 if (ehci->reclaim)
306 ehci->reclaim_ready = 1; 306 end_unlink_async (ehci, NULL);
307 ehci_work(ehci, NULL); 307 ehci_work(ehci, NULL);
308 spin_unlock_irq(&ehci->lock); 308 spin_unlock_irq(&ehci->lock);
309 309
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index c0da40bbfa35..7fc25b6bd7d2 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -967,7 +967,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
967 struct ehci_qh *qh = ehci->reclaim; 967 struct ehci_qh *qh = ehci->reclaim;
968 struct ehci_qh *next; 968 struct ehci_qh *next;
969 969
970 timer_action_done (ehci, TIMER_IAA_WATCHDOG); 970 iaa_watchdog_done (ehci);
971 971
972 // qh->hw_next = cpu_to_le32 (qh->qh_dma); 972 // qh->hw_next = cpu_to_le32 (qh->qh_dma);
973 qh->qh_state = QH_STATE_IDLE; 973 qh->qh_state = QH_STATE_IDLE;
@@ -977,7 +977,6 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
977 /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ 977 /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
978 next = qh->reclaim; 978 next = qh->reclaim;
979 ehci->reclaim = next; 979 ehci->reclaim = next;
980 ehci->reclaim_ready = 0;
981 qh->reclaim = NULL; 980 qh->reclaim = NULL;
982 981
983 qh_completions (ehci, qh, regs); 982 qh_completions (ehci, qh, regs);
@@ -1052,11 +1051,10 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
1052 return; 1051 return;
1053 } 1052 }
1054 1053
1055 ehci->reclaim_ready = 0;
1056 cmd |= CMD_IAAD; 1054 cmd |= CMD_IAAD;
1057 writel (cmd, &ehci->regs->command); 1055 writel (cmd, &ehci->regs->command);
1058 (void) readl (&ehci->regs->command); 1056 (void) readl (&ehci->regs->command);
1059 timer_action (ehci, TIMER_IAA_WATCHDOG); 1057 iaa_watchdog_start (ehci);
1060} 1058}
1061 1059
1062/*-------------------------------------------------------------------------*/ 1060/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index bbc3082a73d7..6aac39f50e07 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -58,7 +58,6 @@ struct ehci_hcd { /* one per controller */
58 /* async schedule support */ 58 /* async schedule support */
59 struct ehci_qh *async; 59 struct ehci_qh *async;
60 struct ehci_qh *reclaim; 60 struct ehci_qh *reclaim;
61 unsigned reclaim_ready : 1;
62 unsigned scanning : 1; 61 unsigned scanning : 1;
63 62
64 /* periodic schedule support */ 63 /* periodic schedule support */
@@ -81,6 +80,7 @@ struct ehci_hcd { /* one per controller */
81 struct dma_pool *itd_pool; /* itd per iso urb */ 80 struct dma_pool *itd_pool; /* itd per iso urb */
82 struct dma_pool *sitd_pool; /* sitd per split iso urb */ 81 struct dma_pool *sitd_pool; /* sitd per split iso urb */
83 82
83 struct timer_list iaa_watchdog;
84 struct timer_list watchdog; 84 struct timer_list watchdog;
85 unsigned long actions; 85 unsigned long actions;
86 unsigned stamp; 86 unsigned stamp;
@@ -114,9 +114,21 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
114} 114}
115 115
116 116
117static inline void
118iaa_watchdog_start (struct ehci_hcd *ehci)
119{
120 WARN_ON(timer_pending(&ehci->iaa_watchdog));
121 mod_timer (&ehci->iaa_watchdog,
122 jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
123}
124
125static inline void iaa_watchdog_done (struct ehci_hcd *ehci)
126{
127 del_timer (&ehci->iaa_watchdog);
128}
129
117enum ehci_timer_action { 130enum ehci_timer_action {
118 TIMER_IO_WATCHDOG, 131 TIMER_IO_WATCHDOG,
119 TIMER_IAA_WATCHDOG,
120 TIMER_ASYNC_SHRINK, 132 TIMER_ASYNC_SHRINK,
121 TIMER_ASYNC_OFF, 133 TIMER_ASYNC_OFF,
122}; 134};
@@ -134,9 +146,6 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
134 unsigned long t; 146 unsigned long t;
135 147
136 switch (action) { 148 switch (action) {
137 case TIMER_IAA_WATCHDOG:
138 t = EHCI_IAA_JIFFIES;
139 break;
140 case TIMER_IO_WATCHDOG: 149 case TIMER_IO_WATCHDOG:
141 t = EHCI_IO_JIFFIES; 150 t = EHCI_IO_JIFFIES;
142 break; 151 break;
@@ -153,8 +162,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
153 // async queue SHRINK often precedes IAA. while it's ready 162 // async queue SHRINK often precedes IAA. while it's ready
154 // to go OFF neither can matter, and afterwards the IO 163 // to go OFF neither can matter, and afterwards the IO
155 // watchdog stops unless there's still periodic traffic. 164 // watchdog stops unless there's still periodic traffic.
156 if (action != TIMER_IAA_WATCHDOG 165 if (time_before_eq(t, ehci->watchdog.expires)
157 && t > ehci->watchdog.expires
158 && timer_pending (&ehci->watchdog)) 166 && timer_pending (&ehci->watchdog))
159 return; 167 return;
160 mod_timer (&ehci->watchdog, t); 168 mod_timer (&ehci->watchdog, t);