aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-06-05 12:21:30 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-21 18:04:16 -0400
commite323de46e83b6df2f330651907ac823f8d53308a (patch)
treec899168e635f967fe46acaf4873c6b29dbf7f406 /drivers/usb/host
parentbe3cbc5f87d4b1fbd714644b6824ce4eb229f372 (diff)
[PATCH] UHCI: remove hc_inaccessible flag
This patch (as706) removes the private hc_inaccessible flag from uhci-hcd. It's not needed because it conveys exactly the same information as the generic HCD_FLAG_HW_ACCESSIBLE bit. In its place goes a new flag recording whether the controller is dead. The new code allows a complete device reset to resurrect a dead controller (although usbcore doesn't yet implement such a facility). Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/uhci-hcd.c49
-rw-r--r--drivers/usb/host/uhci-hcd.h2
-rw-r--r--drivers/usb/host/uhci-hub.c4
3 files changed, 29 insertions, 26 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index dc9ed29c6175..025b969f95e8 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -110,17 +110,23 @@ static void finish_reset(struct uhci_hcd *uhci)
110 uhci->is_stopped = UHCI_IS_STOPPED; 110 uhci->is_stopped = UHCI_IS_STOPPED;
111 uhci_to_hcd(uhci)->state = HC_STATE_HALT; 111 uhci_to_hcd(uhci)->state = HC_STATE_HALT;
112 uhci_to_hcd(uhci)->poll_rh = 0; 112 uhci_to_hcd(uhci)->poll_rh = 0;
113
114 uhci->dead = 0; /* Full reset resurrects the controller */
113} 115}
114 116
115/* 117/*
116 * Last rites for a defunct/nonfunctional controller 118 * Last rites for a defunct/nonfunctional controller
117 * or one we don't want to use any more. 119 * or one we don't want to use any more.
118 */ 120 */
119static void hc_died(struct uhci_hcd *uhci) 121static void uhci_hc_died(struct uhci_hcd *uhci)
120{ 122{
123 uhci_get_current_frame_number(uhci);
121 uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr); 124 uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
122 finish_reset(uhci); 125 finish_reset(uhci);
123 uhci->hc_inaccessible = 1; 126 uhci->dead = 1;
127
128 /* The current frame may already be partway finished */
129 ++uhci->frame_number;
124} 130}
125 131
126/* 132/*
@@ -234,7 +240,7 @@ __acquires(uhci->lock)
234 spin_unlock_irq(&uhci->lock); 240 spin_unlock_irq(&uhci->lock);
235 msleep(1); 241 msleep(1);
236 spin_lock_irq(&uhci->lock); 242 spin_lock_irq(&uhci->lock);
237 if (uhci->hc_inaccessible) /* Died */ 243 if (uhci->dead)
238 return; 244 return;
239 } 245 }
240 if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) 246 if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
@@ -287,7 +293,7 @@ __acquires(uhci->lock)
287 spin_unlock_irq(&uhci->lock); 293 spin_unlock_irq(&uhci->lock);
288 msleep(20); 294 msleep(20);
289 spin_lock_irq(&uhci->lock); 295 spin_lock_irq(&uhci->lock);
290 if (uhci->hc_inaccessible) /* Died */ 296 if (uhci->dead)
291 return; 297 return;
292 298
293 /* End Global Resume and wait for EOP to be sent */ 299 /* End Global Resume and wait for EOP to be sent */
@@ -339,7 +345,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
339 errbuf, ERRBUF_LEN); 345 errbuf, ERRBUF_LEN);
340 lprintk(errbuf); 346 lprintk(errbuf);
341 } 347 }
342 hc_died(uhci); 348 uhci_hc_died(uhci);
343 349
344 /* Force a callback in case there are 350 /* Force a callback in case there are
345 * pending unlinks */ 351 * pending unlinks */
@@ -462,7 +468,7 @@ static void uhci_shutdown(struct pci_dev *pdev)
462{ 468{
463 struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev); 469 struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev);
464 470
465 hc_died(hcd_to_uhci(hcd)); 471 uhci_hc_died(hcd_to_uhci(hcd));
466} 472}
467 473
468/* 474/*
@@ -664,8 +670,8 @@ static void uhci_stop(struct usb_hcd *hcd)
664 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 670 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
665 671
666 spin_lock_irq(&uhci->lock); 672 spin_lock_irq(&uhci->lock);
667 if (!uhci->hc_inaccessible) 673 if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead)
668 hc_died(uhci); 674 uhci_hc_died(uhci);
669 uhci_scan_schedule(uhci, NULL); 675 uhci_scan_schedule(uhci, NULL);
670 spin_unlock_irq(&uhci->lock); 676 spin_unlock_irq(&uhci->lock);
671 677
@@ -681,7 +687,7 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
681 spin_lock_irq(&uhci->lock); 687 spin_lock_irq(&uhci->lock);
682 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) 688 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
683 rc = -ESHUTDOWN; 689 rc = -ESHUTDOWN;
684 else if (!uhci->hc_inaccessible) 690 else if (!uhci->dead)
685 suspend_rh(uhci, UHCI_RH_SUSPENDED); 691 suspend_rh(uhci, UHCI_RH_SUSPENDED);
686 spin_unlock_irq(&uhci->lock); 692 spin_unlock_irq(&uhci->lock);
687 return rc; 693 return rc;
@@ -696,7 +702,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd)
696 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { 702 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
697 dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n"); 703 dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
698 rc = -ESHUTDOWN; 704 rc = -ESHUTDOWN;
699 } else if (!uhci->hc_inaccessible) 705 } else if (!uhci->dead)
700 wakeup_rh(uhci); 706 wakeup_rh(uhci);
701 spin_unlock_irq(&uhci->lock); 707 spin_unlock_irq(&uhci->lock);
702 return rc; 708 return rc;
@@ -710,8 +716,8 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
710 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); 716 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
711 717
712 spin_lock_irq(&uhci->lock); 718 spin_lock_irq(&uhci->lock);
713 if (uhci->hc_inaccessible) /* Dead or already suspended */ 719 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
714 goto done; 720 goto done_okay; /* Already suspended or dead */
715 721
716 if (uhci->rh_state > UHCI_RH_SUSPENDED) { 722 if (uhci->rh_state > UHCI_RH_SUSPENDED) {
717 dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n"); 723 dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
@@ -724,12 +730,12 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
724 */ 730 */
725 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); 731 pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
726 mb(); 732 mb();
727 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
728 uhci->hc_inaccessible = 1;
729 hcd->poll_rh = 0; 733 hcd->poll_rh = 0;
730 734
731 /* FIXME: Enable non-PME# remote wakeup? */ 735 /* FIXME: Enable non-PME# remote wakeup? */
732 736
737done_okay:
738 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
733done: 739done:
734 spin_unlock_irq(&uhci->lock); 740 spin_unlock_irq(&uhci->lock);
735 return rc; 741 return rc;
@@ -742,25 +748,22 @@ static int uhci_resume(struct usb_hcd *hcd)
742 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); 748 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
743 749
744 /* Since we aren't in D3 any more, it's safe to set this flag 750 /* Since we aren't in D3 any more, it's safe to set this flag
745 * even if the controller was dead. It might not even be dead 751 * even if the controller was dead.
746 * any more, if the firmware or quirks code has reset it.
747 */ 752 */
748 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 753 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
749 mb(); 754 mb();
750 755
751 if (uhci->rh_state == UHCI_RH_RESET) /* Dead */
752 return 0;
753
754 spin_lock_irq(&uhci->lock); 756 spin_lock_irq(&uhci->lock);
755 757
756 /* FIXME: Disable non-PME# remote wakeup? */ 758 /* FIXME: Disable non-PME# remote wakeup? */
757 759
758 uhci->hc_inaccessible = 0; 760 /* The firmware or a boot kernel may have changed the controller
759 761 * settings during a system wakeup. Check it and reconfigure
760 /* The BIOS may have changed the controller settings during a 762 * to avoid problems.
761 * system wakeup. Check it and reconfigure to avoid problems.
762 */ 763 */
763 check_and_reset_hc(uhci); 764 check_and_reset_hc(uhci);
765
766 /* If the controller was dead before, it's back alive now */
764 configure_hc(uhci); 767 configure_hc(uhci);
765 768
766 if (uhci->rh_state == UHCI_RH_RESET) { 769 if (uhci->rh_state == UHCI_RH_RESET) {
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 469b4268b850..619d704f4e8f 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -395,7 +395,7 @@ struct uhci_hcd {
395 395
396 unsigned int scan_in_progress:1; /* Schedule scan is running */ 396 unsigned int scan_in_progress:1; /* Schedule scan is running */
397 unsigned int need_rescan:1; /* Redo the schedule scan */ 397 unsigned int need_rescan:1; /* Redo the schedule scan */
398 unsigned int hc_inaccessible:1; /* HC is suspended or dead */ 398 unsigned int dead:1; /* Controller has died */
399 unsigned int working_RD:1; /* Suspended root hub doesn't 399 unsigned int working_RD:1; /* Suspended root hub doesn't
400 need to be polled */ 400 need to be polled */
401 unsigned int is_initialized:1; /* Data structure is usable */ 401 unsigned int is_initialized:1; /* Data structure is usable */
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index f53c116e0dfd..c545ef92fe29 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -171,7 +171,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
171 spin_lock_irqsave(&uhci->lock, flags); 171 spin_lock_irqsave(&uhci->lock, flags);
172 172
173 uhci_scan_schedule(uhci, NULL); 173 uhci_scan_schedule(uhci, NULL);
174 if (uhci->hc_inaccessible) 174 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
175 goto done; 175 goto done;
176 uhci_check_ports(uhci); 176 uhci_check_ports(uhci);
177 177
@@ -227,7 +227,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
227 u16 wPortChange, wPortStatus; 227 u16 wPortChange, wPortStatus;
228 unsigned long flags; 228 unsigned long flags;
229 229
230 if (uhci->hc_inaccessible) 230 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
231 return -ETIMEDOUT; 231 return -ETIMEDOUT;
232 232
233 spin_lock_irqsave(&uhci->lock, flags); 233 spin_lock_irqsave(&uhci->lock, flags);