aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2005-04-09 17:30:08 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-06-27 17:43:44 -0400
commit4daaa87c8f19c5f1978470e9e91b74d9e0fb0f8e (patch)
treeee4ea0e8f4d9912c246916f08f2b50fbc5b42a6a /drivers/usb/host
parenta8bed8b6be75bc5a46aa599ab360d5f1db291c8f (diff)
[PATCH] USB UHCI: Fix up loose ends
This patch tidies up a few loose ends left by the preceding patches. It indicates the controller supports remote wakeup whenever the PM capability is present -- which shouldn't cause any harm if the assumption turns out to be wrong. It refuses to suspend the controller if the root hub is still active, and it refuses to resume the root hub if the controller is suspended. It adds checks for a dead controller in several spots, and it adds memory barriers as needed to insure that I/O operations are completed before moving on. Actually I'm not certain the last part is being done correctly. With code like this: outw(..., ...); mb(); udelay(5); do we know for certain that the outw() will complete _before_ the delay begins? If not, how should this be written? 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.c86
1 files changed, 65 insertions, 21 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 730ba3a621ae..82e608a4bbd0 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -13,18 +13,13 @@
13 * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface 13 * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
14 * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). 14 * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
15 * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) 15 * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
16 * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu 16 * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu
17 * 17 *
18 * Intel documents this fairly well, and as far as I know there 18 * Intel documents this fairly well, and as far as I know there
19 * are no royalties or anything like that, but even so there are 19 * are no royalties or anything like that, but even so there are
20 * people who decided that they want to do the same thing in a 20 * people who decided that they want to do the same thing in a
21 * completely different way. 21 * completely different way.
22 * 22 *
23 * WARNING! The USB documentation is downright evil. Most of it
24 * is just crap, written by a committee. You're better off ignoring
25 * most of it, the important stuff is:
26 * - the low-level protocol (fairly simple but lots of small details)
27 * - working around the horridness of the rest
28 */ 23 */
29 24
30#include <linux/config.h> 25#include <linux/config.h>
@@ -147,6 +142,15 @@ static void reset_hc(struct uhci_hcd *uhci)
147} 142}
148 143
149/* 144/*
145 * Last rites for a defunct/nonfunctional controller
146 */
147static void hc_died(struct uhci_hcd *uhci)
148{
149 reset_hc(uhci);
150 uhci->hc_inaccessible = 1;
151}
152
153/*
150 * Initialize a controller that was newly discovered or has just been 154 * Initialize a controller that was newly discovered or has just been
151 * resumed. In either case we can't be sure of its previous state. 155 * resumed. In either case we can't be sure of its previous state.
152 */ 156 */
@@ -287,6 +291,8 @@ __acquires(uhci->lock)
287 spin_unlock_irq(&uhci->lock); 291 spin_unlock_irq(&uhci->lock);
288 msleep(1); 292 msleep(1);
289 spin_lock_irq(&uhci->lock); 293 spin_lock_irq(&uhci->lock);
294 if (uhci->hc_inaccessible) /* Died */
295 return;
290 } 296 }
291 if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) 297 if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
292 dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); 298 dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
@@ -335,6 +341,8 @@ __acquires(uhci->lock)
335 spin_unlock_irq(&uhci->lock); 341 spin_unlock_irq(&uhci->lock);
336 msleep(20); 342 msleep(20);
337 spin_lock_irq(&uhci->lock); 343 spin_lock_irq(&uhci->lock);
344 if (uhci->hc_inaccessible) /* Died */
345 return;
338 346
339 /* End Global Resume and wait for EOP to be sent */ 347 /* End Global Resume and wait for EOP to be sent */
340 outw(USBCMD_CF, uhci->io_addr + USBCMD); 348 outw(USBCMD_CF, uhci->io_addr + USBCMD);
@@ -387,9 +395,11 @@ static void stall_callback(unsigned long _uhci)
387 check_fsbr(uhci); 395 check_fsbr(uhci);
388 396
389 /* Poll for and perform state transitions */ 397 /* Poll for and perform state transitions */
390 rh_state_transitions(uhci); 398 if (!uhci->hc_inaccessible) {
391 if (uhci->suspended_ports && !uhci->hc_inaccessible) 399 rh_state_transitions(uhci);
392 uhci_check_ports(uhci); 400 if (uhci->suspended_ports)
401 uhci_check_ports(uhci);
402 }
393 403
394 restart_timer(uhci); 404 restart_timer(uhci);
395 spin_unlock_irqrestore(&uhci->lock, flags); 405 spin_unlock_irqrestore(&uhci->lock, flags);
@@ -399,6 +409,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
399{ 409{
400 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 410 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
401 unsigned short status; 411 unsigned short status;
412 unsigned long flags;
402 413
403 /* 414 /*
404 * Read the interrupt status, and write it back to clear the 415 * Read the interrupt status, and write it back to clear the
@@ -417,20 +428,26 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
417 if (status & USBSTS_HCPE) 428 if (status & USBSTS_HCPE)
418 dev_err(uhci_dev(uhci), "host controller process " 429 dev_err(uhci_dev(uhci), "host controller process "
419 "error, something bad happened!\n"); 430 "error, something bad happened!\n");
420 if ((status & USBSTS_HCH) && 431 if (status & USBSTS_HCH) {
421 uhci->rh_state >= UHCI_RH_RUNNING) { 432 spin_lock_irqsave(&uhci->lock, flags);
422 dev_err(uhci_dev(uhci), "host controller halted, " 433 if (uhci->rh_state >= UHCI_RH_RUNNING) {
434 dev_err(uhci_dev(uhci),
435 "host controller halted, "
423 "very bad!\n"); 436 "very bad!\n");
424 /* FIXME: Reset the controller, fix the offending TD */ 437 hc_died(uhci);
438 spin_unlock_irqrestore(&uhci->lock, flags);
439 return IRQ_HANDLED;
440 }
441 spin_unlock_irqrestore(&uhci->lock, flags);
425 } 442 }
426 } 443 }
427 444
428 if (status & USBSTS_RD) 445 if (status & USBSTS_RD)
429 uhci->resume_detect = 1; 446 uhci->resume_detect = 1;
430 447
431 spin_lock(&uhci->lock); 448 spin_lock_irqsave(&uhci->lock, flags);
432 uhci_scan_schedule(uhci, regs); 449 uhci_scan_schedule(uhci, regs);
433 spin_unlock(&uhci->lock); 450 spin_unlock_irqrestore(&uhci->lock, flags);
434 451
435 return IRQ_HANDLED; 452 return IRQ_HANDLED;
436} 453}
@@ -525,10 +542,15 @@ static int uhci_start(struct usb_hcd *hcd)
525 struct dentry *dentry; 542 struct dentry *dentry;
526 543
527 io_size = (unsigned) hcd->rsrc_len; 544 io_size = (unsigned) hcd->rsrc_len;
545 if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
546 hcd->can_wakeup = 1; /* Assume it supports PME# */
528 547
529 dentry = debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, &uhci_debug_operations); 548 dentry = debugfs_create_file(hcd->self.bus_name,
549 S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci,
550 &uhci_debug_operations);
530 if (!dentry) { 551 if (!dentry) {
531 dev_err(uhci_dev(uhci), "couldn't create uhci debugfs entry\n"); 552 dev_err(uhci_dev(uhci),
553 "couldn't create uhci debugfs entry\n");
532 retval = -ENOMEM; 554 retval = -ENOMEM;
533 goto err_create_debug_entry; 555 goto err_create_debug_entry;
534 } 556 }
@@ -765,7 +787,8 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
765 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 787 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
766 788
767 spin_lock_irq(&uhci->lock); 789 spin_lock_irq(&uhci->lock);
768 suspend_rh(uhci, UHCI_RH_SUSPENDED); 790 if (!uhci->hc_inaccessible) /* Not dead */
791 suspend_rh(uhci, UHCI_RH_SUSPENDED);
769 spin_unlock_irq(&uhci->lock); 792 spin_unlock_irq(&uhci->lock);
770 return 0; 793 return 0;
771} 794}
@@ -773,26 +796,44 @@ static int uhci_rh_suspend(struct usb_hcd *hcd)
773static int uhci_rh_resume(struct usb_hcd *hcd) 796static int uhci_rh_resume(struct usb_hcd *hcd)
774{ 797{
775 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 798 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
799 int rc = 0;
776 800
777 spin_lock_irq(&uhci->lock); 801 spin_lock_irq(&uhci->lock);
778 wakeup_rh(uhci); 802 if (uhci->hc_inaccessible) {
803 if (uhci->rh_state == UHCI_RH_SUSPENDED) {
804 dev_warn(uhci_dev(uhci), "HC isn't running!\n");
805 rc = -ENODEV;
806 }
807 /* Otherwise the HC is dead */
808 } else
809 wakeup_rh(uhci);
779 spin_unlock_irq(&uhci->lock); 810 spin_unlock_irq(&uhci->lock);
780 return 0; 811 return rc;
781} 812}
782 813
783static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) 814static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
784{ 815{
785 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 816 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
817 int rc = 0;
786 818
787 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); 819 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
788 820
789 spin_lock_irq(&uhci->lock); 821 spin_lock_irq(&uhci->lock);
822 if (uhci->hc_inaccessible) /* Dead or already suspended */
823 goto done;
790 824
791#ifndef CONFIG_USB_SUSPEND 825#ifndef CONFIG_USB_SUSPEND
792 /* Otherwise this would never happen */ 826 /* Otherwise this would never happen */
793 suspend_rh(uhci, UHCI_RH_SUSPENDED); 827 suspend_rh(uhci, UHCI_RH_SUSPENDED);
794#endif 828#endif
795 829
830 if (uhci->rh_state > UHCI_RH_SUSPENDED) {
831 dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
832 hcd->state = HC_STATE_RUNNING;
833 rc = -EBUSY;
834 goto done;
835 };
836
796 /* All PCI host controllers are required to disable IRQ generation 837 /* All PCI host controllers are required to disable IRQ generation
797 * at the source, so we must turn off PIRQ. 838 * at the source, so we must turn off PIRQ.
798 */ 839 */
@@ -801,8 +842,9 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
801 842
802 /* FIXME: Enable non-PME# remote wakeup? */ 843 /* FIXME: Enable non-PME# remote wakeup? */
803 844
845done:
804 spin_unlock_irq(&uhci->lock); 846 spin_unlock_irq(&uhci->lock);
805 return 0; 847 return rc;
806} 848}
807 849
808static int uhci_resume(struct usb_hcd *hcd) 850static int uhci_resume(struct usb_hcd *hcd)
@@ -811,6 +853,8 @@ static int uhci_resume(struct usb_hcd *hcd)
811 853
812 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); 854 dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
813 855
856 if (uhci->rh_state == UHCI_RH_RESET) /* Dead */
857 return 0;
814 spin_lock_irq(&uhci->lock); 858 spin_lock_irq(&uhci->lock);
815 859
816 /* FIXME: Disable non-PME# remote wakeup? */ 860 /* FIXME: Disable non-PME# remote wakeup? */