diff options
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 178 |
1 files changed, 51 insertions, 127 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 0c024898cbea..15e0a511069b 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -101,37 +101,16 @@ static void uhci_get_current_frame_number(struct uhci_hcd *uhci); | |||
101 | #include "uhci-q.c" | 101 | #include "uhci-q.c" |
102 | #include "uhci-hub.c" | 102 | #include "uhci-hub.c" |
103 | 103 | ||
104 | extern void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); | ||
105 | extern int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); | ||
106 | |||
104 | /* | 107 | /* |
105 | * Make sure the controller is completely inactive, unable to | 108 | * Finish up a host controller reset and update the recorded state. |
106 | * generate interrupts or do DMA. | ||
107 | */ | 109 | */ |
108 | static void reset_hc(struct uhci_hcd *uhci) | 110 | static void finish_reset(struct uhci_hcd *uhci) |
109 | { | 111 | { |
110 | int port; | 112 | int port; |
111 | 113 | ||
112 | /* Turn off PIRQ enable and SMI enable. (This also turns off the | ||
113 | * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. | ||
114 | */ | ||
115 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, | ||
116 | USBLEGSUP_RWC); | ||
117 | |||
118 | /* Reset the HC - this will force us to get a | ||
119 | * new notification of any already connected | ||
120 | * ports due to the virtual disconnect that it | ||
121 | * implies. | ||
122 | */ | ||
123 | outw(USBCMD_HCRESET, uhci->io_addr + USBCMD); | ||
124 | mb(); | ||
125 | udelay(5); | ||
126 | if (inw(uhci->io_addr + USBCMD) & USBCMD_HCRESET) | ||
127 | dev_warn(uhci_dev(uhci), "HCRESET not completed yet!\n"); | ||
128 | |||
129 | /* Just to be safe, disable interrupt requests and | ||
130 | * make sure the controller is stopped. | ||
131 | */ | ||
132 | outw(0, uhci->io_addr + USBINTR); | ||
133 | outw(0, uhci->io_addr + USBCMD); | ||
134 | |||
135 | /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect | 114 | /* HCRESET doesn't affect the Suspend, Reset, and Resume Detect |
136 | * bits in the port status and control registers. | 115 | * bits in the port status and control registers. |
137 | * We have to clear them by hand. | 116 | * We have to clear them by hand. |
@@ -153,7 +132,8 @@ static void reset_hc(struct uhci_hcd *uhci) | |||
153 | */ | 132 | */ |
154 | static void hc_died(struct uhci_hcd *uhci) | 133 | static void hc_died(struct uhci_hcd *uhci) |
155 | { | 134 | { |
156 | reset_hc(uhci); | 135 | uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); |
136 | finish_reset(uhci); | ||
157 | uhci->hc_inaccessible = 1; | 137 | uhci->hc_inaccessible = 1; |
158 | } | 138 | } |
159 | 139 | ||
@@ -163,44 +143,8 @@ static void hc_died(struct uhci_hcd *uhci) | |||
163 | */ | 143 | */ |
164 | static void check_and_reset_hc(struct uhci_hcd *uhci) | 144 | static void check_and_reset_hc(struct uhci_hcd *uhci) |
165 | { | 145 | { |
166 | u16 legsup; | 146 | if (uhci_check_and_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr)) |
167 | unsigned int cmd, intr; | 147 | finish_reset(uhci); |
168 | |||
169 | /* | ||
170 | * When restarting a suspended controller, we expect all the | ||
171 | * settings to be the same as we left them: | ||
172 | * | ||
173 | * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP; | ||
174 | * Controller is stopped and configured with EGSM set; | ||
175 | * No interrupts enabled except possibly Resume Detect. | ||
176 | * | ||
177 | * If any of these conditions are violated we do a complete reset. | ||
178 | */ | ||
179 | pci_read_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, &legsup); | ||
180 | if (legsup & ~(USBLEGSUP_RO | USBLEGSUP_RWC)) { | ||
181 | dev_dbg(uhci_dev(uhci), "%s: legsup = 0x%04x\n", | ||
182 | __FUNCTION__, legsup); | ||
183 | goto reset_needed; | ||
184 | } | ||
185 | |||
186 | cmd = inw(uhci->io_addr + USBCMD); | ||
187 | if ((cmd & USBCMD_RS) || !(cmd & USBCMD_CF) || !(cmd & USBCMD_EGSM)) { | ||
188 | dev_dbg(uhci_dev(uhci), "%s: cmd = 0x%04x\n", | ||
189 | __FUNCTION__, cmd); | ||
190 | goto reset_needed; | ||
191 | } | ||
192 | |||
193 | intr = inw(uhci->io_addr + USBINTR); | ||
194 | if (intr & (~USBINTR_RESUME)) { | ||
195 | dev_dbg(uhci_dev(uhci), "%s: intr = 0x%04x\n", | ||
196 | __FUNCTION__, intr); | ||
197 | goto reset_needed; | ||
198 | } | ||
199 | return; | ||
200 | |||
201 | reset_needed: | ||
202 | dev_dbg(uhci_dev(uhci), "Performing full reset\n"); | ||
203 | reset_hc(uhci); | ||
204 | } | 148 | } |
205 | 149 | ||
206 | /* | 150 | /* |
@@ -212,13 +156,13 @@ static void configure_hc(struct uhci_hcd *uhci) | |||
212 | outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); | 156 | outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); |
213 | 157 | ||
214 | /* Store the frame list base address */ | 158 | /* Store the frame list base address */ |
215 | outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); | 159 | outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD); |
216 | 160 | ||
217 | /* Set the current frame number */ | 161 | /* Set the current frame number */ |
218 | outw(uhci->frame_number, uhci->io_addr + USBFRNUM); | 162 | outw(uhci->frame_number, uhci->io_addr + USBFRNUM); |
219 | 163 | ||
220 | /* Mark controller as running before we enable interrupts */ | 164 | /* Mark controller as not halted before we enable interrupts */ |
221 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; | 165 | uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; |
222 | mb(); | 166 | mb(); |
223 | 167 | ||
224 | /* Enable PIRQ */ | 168 | /* Enable PIRQ */ |
@@ -319,6 +263,7 @@ __acquires(uhci->lock) | |||
319 | 263 | ||
320 | static void start_rh(struct uhci_hcd *uhci) | 264 | static void start_rh(struct uhci_hcd *uhci) |
321 | { | 265 | { |
266 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; | ||
322 | uhci->is_stopped = 0; | 267 | uhci->is_stopped = 0; |
323 | smp_wmb(); | 268 | smp_wmb(); |
324 | 269 | ||
@@ -437,36 +382,21 @@ static void release_uhci(struct uhci_hcd *uhci) | |||
437 | int i; | 382 | int i; |
438 | 383 | ||
439 | for (i = 0; i < UHCI_NUM_SKELQH; i++) | 384 | for (i = 0; i < UHCI_NUM_SKELQH; i++) |
440 | if (uhci->skelqh[i]) { | 385 | uhci_free_qh(uhci, uhci->skelqh[i]); |
441 | uhci_free_qh(uhci, uhci->skelqh[i]); | ||
442 | uhci->skelqh[i] = NULL; | ||
443 | } | ||
444 | 386 | ||
445 | if (uhci->term_td) { | 387 | uhci_free_td(uhci, uhci->term_td); |
446 | uhci_free_td(uhci, uhci->term_td); | ||
447 | uhci->term_td = NULL; | ||
448 | } | ||
449 | 388 | ||
450 | if (uhci->qh_pool) { | 389 | dma_pool_destroy(uhci->qh_pool); |
451 | dma_pool_destroy(uhci->qh_pool); | ||
452 | uhci->qh_pool = NULL; | ||
453 | } | ||
454 | 390 | ||
455 | if (uhci->td_pool) { | 391 | dma_pool_destroy(uhci->td_pool); |
456 | dma_pool_destroy(uhci->td_pool); | ||
457 | uhci->td_pool = NULL; | ||
458 | } | ||
459 | 392 | ||
460 | if (uhci->fl) { | 393 | kfree(uhci->frame_cpu); |
461 | dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | ||
462 | uhci->fl, uhci->fl->dma_handle); | ||
463 | uhci->fl = NULL; | ||
464 | } | ||
465 | 394 | ||
466 | if (uhci->dentry) { | 395 | dma_free_coherent(uhci_dev(uhci), |
467 | debugfs_remove(uhci->dentry); | 396 | UHCI_NUMFRAMES * sizeof(*uhci->frame), |
468 | uhci->dentry = NULL; | 397 | uhci->frame, uhci->frame_dma_handle); |
469 | } | 398 | |
399 | debugfs_remove(uhci->dentry); | ||
470 | } | 400 | } |
471 | 401 | ||
472 | static int uhci_reset(struct usb_hcd *hcd) | 402 | static int uhci_reset(struct usb_hcd *hcd) |
@@ -545,7 +475,6 @@ static int uhci_start(struct usb_hcd *hcd) | |||
545 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 475 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
546 | int retval = -EBUSY; | 476 | int retval = -EBUSY; |
547 | int i; | 477 | int i; |
548 | dma_addr_t dma_handle; | ||
549 | struct dentry *dentry; | 478 | struct dentry *dentry; |
550 | 479 | ||
551 | hcd->uses_new_polling = 1; | 480 | hcd->uses_new_polling = 1; |
@@ -579,17 +508,23 @@ static int uhci_start(struct usb_hcd *hcd) | |||
579 | 508 | ||
580 | init_waitqueue_head(&uhci->waitqh); | 509 | init_waitqueue_head(&uhci->waitqh); |
581 | 510 | ||
582 | uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | 511 | uhci->frame = dma_alloc_coherent(uhci_dev(uhci), |
583 | &dma_handle, 0); | 512 | UHCI_NUMFRAMES * sizeof(*uhci->frame), |
584 | if (!uhci->fl) { | 513 | &uhci->frame_dma_handle, 0); |
514 | if (!uhci->frame) { | ||
585 | dev_err(uhci_dev(uhci), "unable to allocate " | 515 | dev_err(uhci_dev(uhci), "unable to allocate " |
586 | "consistent memory for frame list\n"); | 516 | "consistent memory for frame list\n"); |
587 | goto err_alloc_fl; | 517 | goto err_alloc_frame; |
588 | } | 518 | } |
519 | memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame)); | ||
589 | 520 | ||
590 | memset((void *)uhci->fl, 0, sizeof(*uhci->fl)); | 521 | uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu), |
591 | 522 | GFP_KERNEL); | |
592 | uhci->fl->dma_handle = dma_handle; | 523 | if (!uhci->frame_cpu) { |
524 | dev_err(uhci_dev(uhci), "unable to allocate " | ||
525 | "memory for frame pointers\n"); | ||
526 | goto err_alloc_frame_cpu; | ||
527 | } | ||
593 | 528 | ||
594 | uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci), | 529 | uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci), |
595 | sizeof(struct uhci_td), 16, 0); | 530 | sizeof(struct uhci_td), 16, 0); |
@@ -672,7 +607,7 @@ static int uhci_start(struct usb_hcd *hcd) | |||
672 | irq = 7; | 607 | irq = 7; |
673 | 608 | ||
674 | /* Only place we don't use the frame list routines */ | 609 | /* Only place we don't use the frame list routines */ |
675 | uhci->fl->frame[i] = UHCI_PTR_QH | | 610 | uhci->frame[i] = UHCI_PTR_QH | |
676 | cpu_to_le32(uhci->skelqh[irq]->dma_handle); | 611 | cpu_to_le32(uhci->skelqh[irq]->dma_handle); |
677 | } | 612 | } |
678 | 613 | ||
@@ -690,31 +625,29 @@ static int uhci_start(struct usb_hcd *hcd) | |||
690 | * error exits: | 625 | * error exits: |
691 | */ | 626 | */ |
692 | err_alloc_skelqh: | 627 | err_alloc_skelqh: |
693 | for (i = 0; i < UHCI_NUM_SKELQH; i++) | 628 | for (i = 0; i < UHCI_NUM_SKELQH; i++) { |
694 | if (uhci->skelqh[i]) { | 629 | if (uhci->skelqh[i]) |
695 | uhci_free_qh(uhci, uhci->skelqh[i]); | 630 | uhci_free_qh(uhci, uhci->skelqh[i]); |
696 | uhci->skelqh[i] = NULL; | 631 | } |
697 | } | ||
698 | 632 | ||
699 | uhci_free_td(uhci, uhci->term_td); | 633 | uhci_free_td(uhci, uhci->term_td); |
700 | uhci->term_td = NULL; | ||
701 | 634 | ||
702 | err_alloc_term_td: | 635 | err_alloc_term_td: |
703 | dma_pool_destroy(uhci->qh_pool); | 636 | dma_pool_destroy(uhci->qh_pool); |
704 | uhci->qh_pool = NULL; | ||
705 | 637 | ||
706 | err_create_qh_pool: | 638 | err_create_qh_pool: |
707 | dma_pool_destroy(uhci->td_pool); | 639 | dma_pool_destroy(uhci->td_pool); |
708 | uhci->td_pool = NULL; | ||
709 | 640 | ||
710 | err_create_td_pool: | 641 | err_create_td_pool: |
711 | dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl), | 642 | kfree(uhci->frame_cpu); |
712 | uhci->fl, uhci->fl->dma_handle); | 643 | |
713 | uhci->fl = NULL; | 644 | err_alloc_frame_cpu: |
645 | dma_free_coherent(uhci_dev(uhci), | ||
646 | UHCI_NUMFRAMES * sizeof(*uhci->frame), | ||
647 | uhci->frame, uhci->frame_dma_handle); | ||
714 | 648 | ||
715 | err_alloc_fl: | 649 | err_alloc_frame: |
716 | debugfs_remove(uhci->dentry); | 650 | debugfs_remove(uhci->dentry); |
717 | uhci->dentry = NULL; | ||
718 | 651 | ||
719 | err_create_debug_entry: | 652 | err_create_debug_entry: |
720 | return retval; | 653 | return retval; |
@@ -726,7 +659,7 @@ static void uhci_stop(struct usb_hcd *hcd) | |||
726 | 659 | ||
727 | spin_lock_irq(&uhci->lock); | 660 | spin_lock_irq(&uhci->lock); |
728 | if (!uhci->hc_inaccessible) | 661 | if (!uhci->hc_inaccessible) |
729 | reset_hc(uhci); | 662 | hc_died(uhci); |
730 | uhci_scan_schedule(uhci, NULL); | 663 | uhci_scan_schedule(uhci, NULL); |
731 | spin_unlock_irq(&uhci->lock); | 664 | spin_unlock_irq(&uhci->lock); |
732 | 665 | ||
@@ -774,14 +707,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
774 | if (uhci->hc_inaccessible) /* Dead or already suspended */ | 707 | if (uhci->hc_inaccessible) /* Dead or already suspended */ |
775 | goto done; | 708 | goto done; |
776 | 709 | ||
777 | #ifndef CONFIG_USB_SUSPEND | ||
778 | /* Otherwise this would never happen */ | ||
779 | suspend_rh(uhci, UHCI_RH_SUSPENDED); | ||
780 | #endif | ||
781 | |||
782 | if (uhci->rh_state > UHCI_RH_SUSPENDED) { | 710 | if (uhci->rh_state > UHCI_RH_SUSPENDED) { |
783 | dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); | 711 | dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); |
784 | hcd->state = HC_STATE_RUNNING; | ||
785 | rc = -EBUSY; | 712 | rc = -EBUSY; |
786 | goto done; | 713 | goto done; |
787 | }; | 714 | }; |
@@ -820,10 +747,6 @@ static int uhci_resume(struct usb_hcd *hcd) | |||
820 | check_and_reset_hc(uhci); | 747 | check_and_reset_hc(uhci); |
821 | configure_hc(uhci); | 748 | configure_hc(uhci); |
822 | 749 | ||
823 | #ifndef CONFIG_USB_SUSPEND | ||
824 | /* Otherwise this would never happen */ | ||
825 | wakeup_rh(uhci); | ||
826 | #endif | ||
827 | if (uhci->rh_state == UHCI_RH_RESET) | 750 | if (uhci->rh_state == UHCI_RH_RESET) |
828 | suspend_rh(uhci, UHCI_RH_SUSPENDED); | 751 | suspend_rh(uhci, UHCI_RH_SUSPENDED); |
829 | 752 | ||
@@ -881,8 +804,8 @@ static const struct hc_driver uhci_driver = { | |||
881 | #ifdef CONFIG_PM | 804 | #ifdef CONFIG_PM |
882 | .suspend = uhci_suspend, | 805 | .suspend = uhci_suspend, |
883 | .resume = uhci_resume, | 806 | .resume = uhci_resume, |
884 | .hub_suspend = uhci_rh_suspend, | 807 | .bus_suspend = uhci_rh_suspend, |
885 | .hub_resume = uhci_rh_resume, | 808 | .bus_resume = uhci_rh_resume, |
886 | #endif | 809 | #endif |
887 | .stop = uhci_stop, | 810 | .stop = uhci_stop, |
888 | 811 | ||
@@ -908,6 +831,7 @@ MODULE_DEVICE_TABLE(pci, uhci_pci_ids); | |||
908 | static struct pci_driver uhci_pci_driver = { | 831 | static struct pci_driver uhci_pci_driver = { |
909 | .name = (char *)hcd_name, | 832 | .name = (char *)hcd_name, |
910 | .id_table = uhci_pci_ids, | 833 | .id_table = uhci_pci_ids, |
834 | .owner = THIS_MODULE, | ||
911 | 835 | ||
912 | .probe = usb_hcd_pci_probe, | 836 | .probe = usb_hcd_pci_probe, |
913 | .remove = usb_hcd_pci_remove, | 837 | .remove = usb_hcd_pci_remove, |