diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-10-17 16:57:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-10-17 16:57:18 -0400 |
commit | 64f89798da35f43c6ef6afda0541e25034513458 (patch) | |
tree | 419546d28bac423277b504b3a94ed7da333490ca | |
parent | 4e4bc305e16440ab38060d61fbcb7d774881d2f1 (diff) |
USB: revert EHCI VIA workaround patch
This reverts 26f953fd884ea4879585287917f855c63c6b2666 which caused
resume problems on the mac mini.
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/host/ehci-dbg.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 70 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-pci.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-q.c | 6 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 22 |
6 files changed, 37 insertions, 69 deletions
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 23b95b2bfe15..34b7a31cd85b 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -754,7 +754,9 @@ 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\n", ehci->reclaim); | 757 | temp = scnprintf (next, size, "reclaim qh %p%s\n", |
758 | ehci->reclaim, | ||
759 | ehci->reclaim_ready ? " ready" : ""); | ||
758 | size -= temp; | 760 | size -= temp; |
759 | next += temp; | 761 | next += temp; |
760 | } | 762 | } |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index aac6ec5dd7cf..9030994aba98 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_MSECS 10 /* arbitrary */ | 114 | #define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ |
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,7 +254,6 @@ static void ehci_quiesce (struct ehci_hcd *ehci) | |||
254 | 254 | ||
255 | /*-------------------------------------------------------------------------*/ | 255 | /*-------------------------------------------------------------------------*/ |
256 | 256 | ||
257 | static void end_unlink_async (struct ehci_hcd *ehci); | ||
258 | static void ehci_work(struct ehci_hcd *ehci); | 257 | static void ehci_work(struct ehci_hcd *ehci); |
259 | 258 | ||
260 | #include "ehci-hub.c" | 259 | #include "ehci-hub.c" |
@@ -264,37 +263,25 @@ static void ehci_work(struct ehci_hcd *ehci); | |||
264 | 263 | ||
265 | /*-------------------------------------------------------------------------*/ | 264 | /*-------------------------------------------------------------------------*/ |
266 | 265 | ||
267 | static void ehci_iaa_watchdog (unsigned long param) | 266 | static void ehci_watchdog (unsigned long param) |
268 | { | 267 | { |
269 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; | 268 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; |
270 | unsigned long flags; | 269 | unsigned long flags; |
271 | u32 status; | ||
272 | 270 | ||
273 | spin_lock_irqsave (&ehci->lock, flags); | 271 | spin_lock_irqsave (&ehci->lock, flags); |
274 | WARN_ON(!ehci->reclaim); | ||
275 | 272 | ||
276 | /* lost IAA irqs wedge things badly; seen first with a vt8235 */ | 273 | /* lost IAA irqs wedge things badly; seen with a vt8235 */ |
277 | if (ehci->reclaim) { | 274 | if (ehci->reclaim) { |
278 | status = readl (&ehci->regs->status); | 275 | u32 status = readl (&ehci->regs->status); |
279 | if (status & STS_IAA) { | 276 | if (status & STS_IAA) { |
280 | ehci_vdbg (ehci, "lost IAA\n"); | 277 | ehci_vdbg (ehci, "lost IAA\n"); |
281 | COUNT (ehci->stats.lost_iaa); | 278 | COUNT (ehci->stats.lost_iaa); |
282 | writel (STS_IAA, &ehci->regs->status); | 279 | writel (STS_IAA, &ehci->regs->status); |
283 | end_unlink_async (ehci); | 280 | ehci->reclaim_ready = 1; |
284 | } | 281 | } |
285 | } | 282 | } |
286 | 283 | ||
287 | spin_unlock_irqrestore (&ehci->lock, flags); | 284 | /* stop async processing after it's idled a bit */ |
288 | } | ||
289 | |||
290 | static 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 */ | ||
298 | if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) | 285 | if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) |
299 | start_unlink_async (ehci, ehci->async); | 286 | start_unlink_async (ehci, ehci->async); |
300 | 287 | ||
@@ -345,6 +332,8 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) | |||
345 | static void ehci_work (struct ehci_hcd *ehci) | 332 | static void ehci_work (struct ehci_hcd *ehci) |
346 | { | 333 | { |
347 | timer_action_done (ehci, TIMER_IO_WATCHDOG); | 334 | timer_action_done (ehci, TIMER_IO_WATCHDOG); |
335 | if (ehci->reclaim_ready) | ||
336 | end_unlink_async (ehci); | ||
348 | 337 | ||
349 | /* another CPU may drop ehci->lock during a schedule scan while | 338 | /* another CPU may drop ehci->lock during a schedule scan while |
350 | * it reports urb completions. this flag guards against bogus | 339 | * it reports urb completions. this flag guards against bogus |
@@ -379,7 +368,6 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
379 | 368 | ||
380 | /* no more interrupts ... */ | 369 | /* no more interrupts ... */ |
381 | del_timer_sync (&ehci->watchdog); | 370 | del_timer_sync (&ehci->watchdog); |
382 | del_timer_sync (&ehci->iaa_watchdog); | ||
383 | 371 | ||
384 | spin_lock_irq(&ehci->lock); | 372 | spin_lock_irq(&ehci->lock); |
385 | if (HC_IS_RUNNING (hcd->state)) | 373 | if (HC_IS_RUNNING (hcd->state)) |
@@ -426,10 +414,6 @@ static int ehci_init(struct usb_hcd *hcd) | |||
426 | ehci->watchdog.function = ehci_watchdog; | 414 | ehci->watchdog.function = ehci_watchdog; |
427 | ehci->watchdog.data = (unsigned long) ehci; | 415 | ehci->watchdog.data = (unsigned long) ehci; |
428 | 416 | ||
429 | init_timer(&ehci->iaa_watchdog); | ||
430 | ehci->iaa_watchdog.function = ehci_iaa_watchdog; | ||
431 | ehci->iaa_watchdog.data = (unsigned long) ehci; | ||
432 | |||
433 | /* | 417 | /* |
434 | * hw default: 1K periodic list heads, one per frame. | 418 | * hw default: 1K periodic list heads, one per frame. |
435 | * periodic_size can shrink by USBCMD update if hcc_params allows. | 419 | * periodic_size can shrink by USBCMD update if hcc_params allows. |
@@ -446,6 +430,7 @@ static int ehci_init(struct usb_hcd *hcd) | |||
446 | ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); | 430 | ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); |
447 | 431 | ||
448 | ehci->reclaim = NULL; | 432 | ehci->reclaim = NULL; |
433 | ehci->reclaim_ready = 0; | ||
449 | ehci->next_uframe = -1; | 434 | ehci->next_uframe = -1; |
450 | 435 | ||
451 | /* | 436 | /* |
@@ -619,7 +604,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
619 | /* complete the unlinking of some qh [4.15.2.3] */ | 604 | /* complete the unlinking of some qh [4.15.2.3] */ |
620 | if (status & STS_IAA) { | 605 | if (status & STS_IAA) { |
621 | COUNT (ehci->stats.reclaim); | 606 | COUNT (ehci->stats.reclaim); |
622 | end_unlink_async (ehci); | 607 | ehci->reclaim_ready = 1; |
623 | bh = 1; | 608 | bh = 1; |
624 | } | 609 | } |
625 | 610 | ||
@@ -723,14 +708,10 @@ static int ehci_urb_enqueue ( | |||
723 | 708 | ||
724 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | 709 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) |
725 | { | 710 | { |
726 | // BUG_ON(qh->qh_state != QH_STATE_LINKED); | 711 | /* if we need to use IAA and it's busy, defer */ |
727 | 712 | if (qh->qh_state == QH_STATE_LINKED | |
728 | /* failfast */ | 713 | && ehci->reclaim |
729 | if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) | 714 | && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { |
730 | end_unlink_async (ehci); | ||
731 | |||
732 | /* defer till later if busy */ | ||
733 | else if (ehci->reclaim) { | ||
734 | struct ehci_qh *last; | 715 | struct ehci_qh *last; |
735 | 716 | ||
736 | for (last = ehci->reclaim; | 717 | for (last = ehci->reclaim; |
@@ -740,8 +721,12 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
740 | qh->qh_state = QH_STATE_UNLINK_WAIT; | 721 | qh->qh_state = QH_STATE_UNLINK_WAIT; |
741 | last->reclaim = qh; | 722 | last->reclaim = qh; |
742 | 723 | ||
743 | /* start IAA cycle */ | 724 | /* bypass IAA if the hc can't care */ |
744 | } else | 725 | } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) |
726 | end_unlink_async (ehci); | ||
727 | |||
728 | /* something else might have unlinked the qh by now */ | ||
729 | if (qh->qh_state == QH_STATE_LINKED) | ||
745 | start_unlink_async (ehci, qh); | 730 | start_unlink_async (ehci, qh); |
746 | } | 731 | } |
747 | 732 | ||
@@ -763,19 +748,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) | |||
763 | qh = (struct ehci_qh *) urb->hcpriv; | 748 | qh = (struct ehci_qh *) urb->hcpriv; |
764 | if (!qh) | 749 | if (!qh) |
765 | break; | 750 | break; |
766 | switch (qh->qh_state) { | 751 | unlink_async (ehci, qh); |
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 | } | ||
779 | break; | 752 | break; |
780 | 753 | ||
781 | case PIPE_INTERRUPT: | 754 | case PIPE_INTERRUPT: |
@@ -867,7 +840,6 @@ rescan: | |||
867 | unlink_async (ehci, qh); | 840 | unlink_async (ehci, qh); |
868 | /* FALL THROUGH */ | 841 | /* FALL THROUGH */ |
869 | case QH_STATE_UNLINK: /* wait for hw to finish? */ | 842 | case QH_STATE_UNLINK: /* wait for hw to finish? */ |
870 | case QH_STATE_UNLINK_WAIT: | ||
871 | idle_timeout: | 843 | idle_timeout: |
872 | spin_unlock_irqrestore (&ehci->lock, flags); | 844 | spin_unlock_irqrestore (&ehci->lock, flags); |
873 | schedule_timeout_uninterruptible(1); | 845 | schedule_timeout_uninterruptible(1); |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 2012213c0a25..1b20722c102b 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 | end_unlink_async (ehci); | 51 | ehci->reclaim_ready = 1; |
52 | ehci_work(ehci); | 52 | ehci_work(ehci); |
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 35e3fab6fc4e..e51c1ed81ac4 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 | end_unlink_async (ehci); | 306 | ehci->reclaim_ready = 1; |
307 | ehci_work(ehci); | 307 | ehci_work(ehci); |
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 46327272f614..62e46dc60e86 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) | |||
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 | iaa_watchdog_done (ehci); | 970 | timer_action_done (ehci, TIMER_IAA_WATCHDOG); |
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,6 +977,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) | |||
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; | ||
980 | qh->reclaim = NULL; | 981 | qh->reclaim = NULL; |
981 | 982 | ||
982 | qh_completions (ehci, qh); | 983 | qh_completions (ehci, qh); |
@@ -1051,10 +1052,11 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1051 | return; | 1052 | return; |
1052 | } | 1053 | } |
1053 | 1054 | ||
1055 | ehci->reclaim_ready = 0; | ||
1054 | cmd |= CMD_IAAD; | 1056 | cmd |= CMD_IAAD; |
1055 | writel (cmd, &ehci->regs->command); | 1057 | writel (cmd, &ehci->regs->command); |
1056 | (void) readl (&ehci->regs->command); | 1058 | (void) readl (&ehci->regs->command); |
1057 | iaa_watchdog_start (ehci); | 1059 | timer_action (ehci, TIMER_IAA_WATCHDOG); |
1058 | } | 1060 | } |
1059 | 1061 | ||
1060 | /*-------------------------------------------------------------------------*/ | 1062 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 6aac39f50e07..bbc3082a73d7 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -58,6 +58,7 @@ 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; | ||
61 | unsigned scanning : 1; | 62 | unsigned scanning : 1; |
62 | 63 | ||
63 | /* periodic schedule support */ | 64 | /* periodic schedule support */ |
@@ -80,7 +81,6 @@ struct ehci_hcd { /* one per controller */ | |||
80 | struct dma_pool *itd_pool; /* itd per iso urb */ | 81 | struct dma_pool *itd_pool; /* itd per iso urb */ |
81 | struct dma_pool *sitd_pool; /* sitd per split iso urb */ | 82 | struct dma_pool *sitd_pool; /* sitd per split iso urb */ |
82 | 83 | ||
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,21 +114,9 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci) | |||
114 | } | 114 | } |
115 | 115 | ||
116 | 116 | ||
117 | static inline void | ||
118 | iaa_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 | |||
125 | static inline void iaa_watchdog_done (struct ehci_hcd *ehci) | ||
126 | { | ||
127 | del_timer (&ehci->iaa_watchdog); | ||
128 | } | ||
129 | |||
130 | enum ehci_timer_action { | 117 | enum ehci_timer_action { |
131 | TIMER_IO_WATCHDOG, | 118 | TIMER_IO_WATCHDOG, |
119 | TIMER_IAA_WATCHDOG, | ||
132 | TIMER_ASYNC_SHRINK, | 120 | TIMER_ASYNC_SHRINK, |
133 | TIMER_ASYNC_OFF, | 121 | TIMER_ASYNC_OFF, |
134 | }; | 122 | }; |
@@ -146,6 +134,9 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) | |||
146 | unsigned long t; | 134 | unsigned long t; |
147 | 135 | ||
148 | switch (action) { | 136 | switch (action) { |
137 | case TIMER_IAA_WATCHDOG: | ||
138 | t = EHCI_IAA_JIFFIES; | ||
139 | break; | ||
149 | case TIMER_IO_WATCHDOG: | 140 | case TIMER_IO_WATCHDOG: |
150 | t = EHCI_IO_JIFFIES; | 141 | t = EHCI_IO_JIFFIES; |
151 | break; | 142 | break; |
@@ -162,7 +153,8 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) | |||
162 | // async queue SHRINK often precedes IAA. while it's ready | 153 | // async queue SHRINK often precedes IAA. while it's ready |
163 | // to go OFF neither can matter, and afterwards the IO | 154 | // to go OFF neither can matter, and afterwards the IO |
164 | // watchdog stops unless there's still periodic traffic. | 155 | // watchdog stops unless there's still periodic traffic. |
165 | if (time_before_eq(t, ehci->watchdog.expires) | 156 | if (action != TIMER_IAA_WATCHDOG |
157 | && t > ehci->watchdog.expires | ||
166 | && timer_pending (&ehci->watchdog)) | 158 | && timer_pending (&ehci->watchdog)) |
167 | return; | 159 | return; |
168 | mod_timer (&ehci->watchdog, t); | 160 | mod_timer (&ehci->watchdog, t); |