diff options
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 159 |
1 files changed, 118 insertions, 41 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 5f2d74ed5ad7..4caa6a8b9a37 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/usb.h> | 33 | #include <linux/usb.h> |
34 | #include <linux/moduleparam.h> | 34 | #include <linux/moduleparam.h> |
35 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
36 | #include <linux/debugfs.h> | ||
36 | 37 | ||
37 | #include "../core/hcd.h" | 38 | #include "../core/hcd.h" |
38 | 39 | ||
@@ -109,7 +110,7 @@ static const char hcd_name [] = "ehci_hcd"; | |||
109 | #define EHCI_TUNE_MULT_TT 1 | 110 | #define EHCI_TUNE_MULT_TT 1 |
110 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ | 111 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ |
111 | 112 | ||
112 | #define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ | 113 | #define EHCI_IAA_MSECS 10 /* arbitrary */ |
113 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ | 114 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ |
114 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ | 115 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ |
115 | #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ | 116 | #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ |
@@ -266,6 +267,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci) | |||
266 | 267 | ||
267 | /*-------------------------------------------------------------------------*/ | 268 | /*-------------------------------------------------------------------------*/ |
268 | 269 | ||
270 | static void end_unlink_async(struct ehci_hcd *ehci); | ||
269 | static void ehci_work(struct ehci_hcd *ehci); | 271 | static void ehci_work(struct ehci_hcd *ehci); |
270 | 272 | ||
271 | #include "ehci-hub.c" | 273 | #include "ehci-hub.c" |
@@ -275,25 +277,41 @@ static void ehci_work(struct ehci_hcd *ehci); | |||
275 | 277 | ||
276 | /*-------------------------------------------------------------------------*/ | 278 | /*-------------------------------------------------------------------------*/ |
277 | 279 | ||
278 | static void ehci_watchdog (unsigned long param) | 280 | static void ehci_iaa_watchdog(unsigned long param) |
279 | { | 281 | { |
280 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; | 282 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; |
281 | unsigned long flags; | 283 | unsigned long flags; |
284 | u32 status, cmd; | ||
282 | 285 | ||
283 | spin_lock_irqsave (&ehci->lock, flags); | 286 | spin_lock_irqsave (&ehci->lock, flags); |
287 | WARN_ON(!ehci->reclaim); | ||
284 | 288 | ||
285 | /* 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 */ | ||
286 | if (ehci->reclaim) { | 294 | if (ehci->reclaim) { |
287 | u32 status = ehci_readl(ehci, &ehci->regs->status); | ||
288 | if (status & STS_IAA) { | 295 | if (status & STS_IAA) { |
289 | ehci_vdbg (ehci, "lost IAA\n"); | 296 | ehci_vdbg (ehci, "lost IAA\n"); |
290 | COUNT (ehci->stats.lost_iaa); | 297 | COUNT (ehci->stats.lost_iaa); |
291 | ehci_writel(ehci, STS_IAA, &ehci->regs->status); | 298 | ehci_writel(ehci, STS_IAA, &ehci->regs->status); |
292 | ehci->reclaim_ready = 1; | ||
293 | } | 299 | } |
300 | ehci_writel(ehci, cmd & ~CMD_IAAD, &ehci->regs->command); | ||
301 | end_unlink_async(ehci); | ||
294 | } | 302 | } |
295 | 303 | ||
296 | /* stop async processing after it's idled a bit */ | 304 | spin_unlock_irqrestore(&ehci->lock, flags); |
305 | } | ||
306 | |||
307 | static 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 */ | ||
297 | if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) | 315 | if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) |
298 | start_unlink_async (ehci, ehci->async); | 316 | start_unlink_async (ehci, ehci->async); |
299 | 317 | ||
@@ -363,8 +381,6 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) | |||
363 | static void ehci_work (struct ehci_hcd *ehci) | 381 | static void ehci_work (struct ehci_hcd *ehci) |
364 | { | 382 | { |
365 | timer_action_done (ehci, TIMER_IO_WATCHDOG); | 383 | timer_action_done (ehci, TIMER_IO_WATCHDOG); |
366 | if (ehci->reclaim_ready) | ||
367 | end_unlink_async (ehci); | ||
368 | 384 | ||
369 | /* another CPU may drop ehci->lock during a schedule scan while | 385 | /* another CPU may drop ehci->lock during a schedule scan while |
370 | * it reports urb completions. this flag guards against bogus | 386 | * it reports urb completions. this flag guards against bogus |
@@ -399,6 +415,7 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
399 | 415 | ||
400 | /* no more interrupts ... */ | 416 | /* no more interrupts ... */ |
401 | del_timer_sync (&ehci->watchdog); | 417 | del_timer_sync (&ehci->watchdog); |
418 | del_timer_sync(&ehci->iaa_watchdog); | ||
402 | 419 | ||
403 | spin_lock_irq(&ehci->lock); | 420 | spin_lock_irq(&ehci->lock); |
404 | if (HC_IS_RUNNING (hcd->state)) | 421 | if (HC_IS_RUNNING (hcd->state)) |
@@ -447,6 +464,10 @@ static int ehci_init(struct usb_hcd *hcd) | |||
447 | ehci->watchdog.function = ehci_watchdog; | 464 | ehci->watchdog.function = ehci_watchdog; |
448 | ehci->watchdog.data = (unsigned long) ehci; | 465 | ehci->watchdog.data = (unsigned long) ehci; |
449 | 466 | ||
467 | init_timer(&ehci->iaa_watchdog); | ||
468 | ehci->iaa_watchdog.function = ehci_iaa_watchdog; | ||
469 | ehci->iaa_watchdog.data = (unsigned long) ehci; | ||
470 | |||
450 | /* | 471 | /* |
451 | * hw default: 1K periodic list heads, one per frame. | 472 | * hw default: 1K periodic list heads, one per frame. |
452 | * periodic_size can shrink by USBCMD update if hcc_params allows. | 473 | * periodic_size can shrink by USBCMD update if hcc_params allows. |
@@ -463,7 +484,6 @@ static int ehci_init(struct usb_hcd *hcd) | |||
463 | ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); | 484 | ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); |
464 | 485 | ||
465 | ehci->reclaim = NULL; | 486 | ehci->reclaim = NULL; |
466 | ehci->reclaim_ready = 0; | ||
467 | ehci->next_uframe = -1; | 487 | ehci->next_uframe = -1; |
468 | 488 | ||
469 | /* | 489 | /* |
@@ -654,8 +674,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
654 | /* complete the unlinking of some qh [4.15.2.3] */ | 674 | /* complete the unlinking of some qh [4.15.2.3] */ |
655 | if (status & STS_IAA) { | 675 | if (status & STS_IAA) { |
656 | COUNT (ehci->stats.reclaim); | 676 | COUNT (ehci->stats.reclaim); |
657 | ehci->reclaim_ready = 1; | 677 | end_unlink_async(ehci); |
658 | bh = 1; | ||
659 | } | 678 | } |
660 | 679 | ||
661 | /* remote wakeup [4.3.1] */ | 680 | /* remote wakeup [4.3.1] */ |
@@ -761,10 +780,16 @@ static int ehci_urb_enqueue ( | |||
761 | 780 | ||
762 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | 781 | static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) |
763 | { | 782 | { |
764 | /* if we need to use IAA and it's busy, defer */ | 783 | /* failfast */ |
765 | if (qh->qh_state == QH_STATE_LINKED | 784 | if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) |
766 | && ehci->reclaim | 785 | end_unlink_async(ehci); |
767 | && 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) { | ||
768 | struct ehci_qh *last; | 793 | struct ehci_qh *last; |
769 | 794 | ||
770 | for (last = ehci->reclaim; | 795 | for (last = ehci->reclaim; |
@@ -774,12 +799,8 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
774 | qh->qh_state = QH_STATE_UNLINK_WAIT; | 799 | qh->qh_state = QH_STATE_UNLINK_WAIT; |
775 | last->reclaim = qh; | 800 | last->reclaim = qh; |
776 | 801 | ||
777 | /* bypass IAA if the hc can't care */ | 802 | /* start IAA cycle */ |
778 | } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) | 803 | } else |
779 | end_unlink_async (ehci); | ||
780 | |||
781 | /* something else might have unlinked the qh by now */ | ||
782 | if (qh->qh_state == QH_STATE_LINKED) | ||
783 | start_unlink_async (ehci, qh); | 804 | start_unlink_async (ehci, qh); |
784 | } | 805 | } |
785 | 806 | ||
@@ -806,7 +827,19 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
806 | qh = (struct ehci_qh *) urb->hcpriv; | 827 | qh = (struct ehci_qh *) urb->hcpriv; |
807 | if (!qh) | 828 | if (!qh) |
808 | break; | 829 | break; |
809 | 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 | } | ||
810 | break; | 843 | break; |
811 | 844 | ||
812 | case PIPE_INTERRUPT: | 845 | case PIPE_INTERRUPT: |
@@ -829,16 +862,16 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
829 | /* reschedule QH iff another request is queued */ | 862 | /* reschedule QH iff another request is queued */ |
830 | if (!list_empty (&qh->qtd_list) | 863 | if (!list_empty (&qh->qtd_list) |
831 | && HC_IS_RUNNING (hcd->state)) { | 864 | && HC_IS_RUNNING (hcd->state)) { |
832 | int status; | 865 | int schedule_status; |
833 | 866 | ||
834 | status = qh_schedule (ehci, qh); | 867 | schedule_status = qh_schedule (ehci, qh); |
835 | spin_unlock_irqrestore (&ehci->lock, flags); | 868 | spin_unlock_irqrestore (&ehci->lock, flags); |
836 | 869 | ||
837 | if (status != 0) { | 870 | if (schedule_status != 0) { |
838 | // shouldn't happen often, but ... | 871 | // shouldn't happen often, but ... |
839 | // FIXME kill those tds' urbs | 872 | // FIXME kill those tds' urbs |
840 | err ("can't reschedule qh %p, err %d", | 873 | err ("can't reschedule qh %p, err %d", |
841 | qh, status); | 874 | qh, schedule_status); |
842 | } | 875 | } |
843 | return status; | 876 | return status; |
844 | } | 877 | } |
@@ -898,6 +931,7 @@ rescan: | |||
898 | unlink_async (ehci, qh); | 931 | unlink_async (ehci, qh); |
899 | /* FALL THROUGH */ | 932 | /* FALL THROUGH */ |
900 | 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: | ||
901 | idle_timeout: | 935 | idle_timeout: |
902 | spin_unlock_irqrestore (&ehci->lock, flags); | 936 | spin_unlock_irqrestore (&ehci->lock, flags); |
903 | schedule_timeout_uninterruptible(1); | 937 | schedule_timeout_uninterruptible(1); |
@@ -959,11 +993,26 @@ MODULE_LICENSE ("GPL"); | |||
959 | #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver | 993 | #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver |
960 | #endif | 994 | #endif |
961 | 995 | ||
962 | #ifdef CONFIG_440EPX | 996 | #if defined(CONFIG_440EPX) && !defined(CONFIG_PPC_MERGE) |
963 | #include "ehci-ppc-soc.c" | 997 | #include "ehci-ppc-soc.c" |
964 | #define PLATFORM_DRIVER ehci_ppc_soc_driver | 998 | #define PLATFORM_DRIVER ehci_ppc_soc_driver |
965 | #endif | 999 | #endif |
966 | 1000 | ||
1001 | #ifdef CONFIG_USB_EHCI_HCD_PPC_OF | ||
1002 | #include "ehci-ppc-of.c" | ||
1003 | #define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver | ||
1004 | #endif | ||
1005 | |||
1006 | #ifdef CONFIG_ARCH_ORION | ||
1007 | #include "ehci-orion.c" | ||
1008 | #define PLATFORM_DRIVER ehci_orion_driver | ||
1009 | #endif | ||
1010 | |||
1011 | #ifdef CONFIG_ARCH_IXP4XX | ||
1012 | #include "ehci-ixp4xx.c" | ||
1013 | #define PLATFORM_DRIVER ixp4xx_ehci_driver | ||
1014 | #endif | ||
1015 | |||
967 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | 1016 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ |
968 | !defined(PS3_SYSTEM_BUS_DRIVER) | 1017 | !defined(PS3_SYSTEM_BUS_DRIVER) |
969 | #error "missing bus glue for ehci-hcd" | 1018 | #error "missing bus glue for ehci-hcd" |
@@ -978,41 +1027,66 @@ static int __init ehci_hcd_init(void) | |||
978 | sizeof(struct ehci_qh), sizeof(struct ehci_qtd), | 1027 | sizeof(struct ehci_qh), sizeof(struct ehci_qtd), |
979 | sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); | 1028 | sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); |
980 | 1029 | ||
1030 | #ifdef DEBUG | ||
1031 | ehci_debug_root = debugfs_create_dir("ehci", NULL); | ||
1032 | if (!ehci_debug_root) | ||
1033 | return -ENOENT; | ||
1034 | #endif | ||
1035 | |||
981 | #ifdef PLATFORM_DRIVER | 1036 | #ifdef PLATFORM_DRIVER |
982 | retval = platform_driver_register(&PLATFORM_DRIVER); | 1037 | retval = platform_driver_register(&PLATFORM_DRIVER); |
983 | if (retval < 0) | 1038 | if (retval < 0) |
984 | return retval; | 1039 | goto clean0; |
985 | #endif | 1040 | #endif |
986 | 1041 | ||
987 | #ifdef PCI_DRIVER | 1042 | #ifdef PCI_DRIVER |
988 | retval = pci_register_driver(&PCI_DRIVER); | 1043 | retval = pci_register_driver(&PCI_DRIVER); |
989 | if (retval < 0) { | 1044 | if (retval < 0) |
990 | #ifdef PLATFORM_DRIVER | 1045 | goto clean1; |
991 | platform_driver_unregister(&PLATFORM_DRIVER); | ||
992 | #endif | ||
993 | return retval; | ||
994 | } | ||
995 | #endif | 1046 | #endif |
996 | 1047 | ||
997 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1048 | #ifdef PS3_SYSTEM_BUS_DRIVER |
998 | retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); | 1049 | retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); |
999 | if (retval < 0) { | 1050 | if (retval < 0) |
1000 | #ifdef PLATFORM_DRIVER | 1051 | goto clean2; |
1001 | platform_driver_unregister(&PLATFORM_DRIVER); | 1052 | #endif |
1053 | |||
1054 | #ifdef OF_PLATFORM_DRIVER | ||
1055 | retval = of_register_platform_driver(&OF_PLATFORM_DRIVER); | ||
1056 | if (retval < 0) | ||
1057 | goto clean3; | ||
1058 | #endif | ||
1059 | return retval; | ||
1060 | |||
1061 | #ifdef OF_PLATFORM_DRIVER | ||
1062 | /* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */ | ||
1063 | clean3: | ||
1064 | #endif | ||
1065 | #ifdef PS3_SYSTEM_BUS_DRIVER | ||
1066 | ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | ||
1067 | clean2: | ||
1002 | #endif | 1068 | #endif |
1003 | #ifdef PCI_DRIVER | 1069 | #ifdef PCI_DRIVER |
1004 | pci_unregister_driver(&PCI_DRIVER); | 1070 | pci_unregister_driver(&PCI_DRIVER); |
1071 | clean1: | ||
1005 | #endif | 1072 | #endif |
1006 | return retval; | 1073 | #ifdef PLATFORM_DRIVER |
1007 | } | 1074 | platform_driver_unregister(&PLATFORM_DRIVER); |
1075 | clean0: | ||
1076 | #endif | ||
1077 | #ifdef DEBUG | ||
1078 | debugfs_remove(ehci_debug_root); | ||
1079 | ehci_debug_root = NULL; | ||
1008 | #endif | 1080 | #endif |
1009 | |||
1010 | return retval; | 1081 | return retval; |
1011 | } | 1082 | } |
1012 | module_init(ehci_hcd_init); | 1083 | module_init(ehci_hcd_init); |
1013 | 1084 | ||
1014 | static void __exit ehci_hcd_cleanup(void) | 1085 | static void __exit ehci_hcd_cleanup(void) |
1015 | { | 1086 | { |
1087 | #ifdef OF_PLATFORM_DRIVER | ||
1088 | of_unregister_platform_driver(&OF_PLATFORM_DRIVER); | ||
1089 | #endif | ||
1016 | #ifdef PLATFORM_DRIVER | 1090 | #ifdef PLATFORM_DRIVER |
1017 | platform_driver_unregister(&PLATFORM_DRIVER); | 1091 | platform_driver_unregister(&PLATFORM_DRIVER); |
1018 | #endif | 1092 | #endif |
@@ -1022,6 +1096,9 @@ static void __exit ehci_hcd_cleanup(void) | |||
1022 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1096 | #ifdef PS3_SYSTEM_BUS_DRIVER |
1023 | ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | 1097 | ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); |
1024 | #endif | 1098 | #endif |
1099 | #ifdef DEBUG | ||
1100 | debugfs_remove(ehci_debug_root); | ||
1101 | #endif | ||
1025 | } | 1102 | } |
1026 | module_exit(ehci_hcd_cleanup); | 1103 | module_exit(ehci_hcd_cleanup); |
1027 | 1104 | ||