diff options
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/hcd-pci.c | 3 | ||||
-rw-r--r-- | drivers/usb/core/hcd.c | 15 | ||||
-rw-r--r-- | drivers/usb/core/hcd.h | 7 |
3 files changed, 18 insertions, 7 deletions
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 5131d88e8c5b..29b5b2a6e183 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -219,6 +219,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) | |||
219 | goto done; | 219 | goto done; |
220 | } | 220 | } |
221 | } | 221 | } |
222 | synchronize_irq(dev->irq); | ||
222 | 223 | ||
223 | /* FIXME until the generic PM interfaces change a lot more, this | 224 | /* FIXME until the generic PM interfaces change a lot more, this |
224 | * can't use PCI D1 and D2 states. For example, the confusion | 225 | * can't use PCI D1 and D2 states. For example, the confusion |
@@ -392,7 +393,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev) | |||
392 | 393 | ||
393 | dev->dev.power.power_state = PMSG_ON; | 394 | dev->dev.power.power_state = PMSG_ON; |
394 | 395 | ||
395 | hcd->saw_irq = 0; | 396 | clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); |
396 | 397 | ||
397 | if (hcd->driver->resume) { | 398 | if (hcd->driver->resume) { |
398 | retval = hcd->driver->resume(hcd); | 399 | retval = hcd->driver->resume(hcd); |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 5e5f65a475ab..da24c31ee00d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1315,11 +1315,12 @@ static int hcd_unlink_urb (struct urb *urb, int status) | |||
1315 | * finish unlinking the initial failed usb_set_address() | 1315 | * finish unlinking the initial failed usb_set_address() |
1316 | * or device descriptor fetch. | 1316 | * or device descriptor fetch. |
1317 | */ | 1317 | */ |
1318 | if (!hcd->saw_irq && hcd->self.root_hub != urb->dev) { | 1318 | if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) |
1319 | && hcd->self.root_hub != urb->dev) { | ||
1319 | dev_warn (hcd->self.controller, "Unlink after no-IRQ? " | 1320 | dev_warn (hcd->self.controller, "Unlink after no-IRQ? " |
1320 | "Controller is probably using the wrong IRQ." | 1321 | "Controller is probably using the wrong IRQ." |
1321 | "\n"); | 1322 | "\n"); |
1322 | hcd->saw_irq = 1; | 1323 | set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); |
1323 | } | 1324 | } |
1324 | 1325 | ||
1325 | urb->status = status; | 1326 | urb->status = status; |
@@ -1649,13 +1650,15 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r) | |||
1649 | struct usb_hcd *hcd = __hcd; | 1650 | struct usb_hcd *hcd = __hcd; |
1650 | int start = hcd->state; | 1651 | int start = hcd->state; |
1651 | 1652 | ||
1652 | if (start == HC_STATE_HALT) | 1653 | if (unlikely(start == HC_STATE_HALT || |
1654 | !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) | ||
1653 | return IRQ_NONE; | 1655 | return IRQ_NONE; |
1654 | if (hcd->driver->irq (hcd, r) == IRQ_NONE) | 1656 | if (hcd->driver->irq (hcd, r) == IRQ_NONE) |
1655 | return IRQ_NONE; | 1657 | return IRQ_NONE; |
1656 | 1658 | ||
1657 | hcd->saw_irq = 1; | 1659 | set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); |
1658 | if (hcd->state == HC_STATE_HALT) | 1660 | |
1661 | if (unlikely(hcd->state == HC_STATE_HALT)) | ||
1659 | usb_hc_died (hcd); | 1662 | usb_hc_died (hcd); |
1660 | return IRQ_HANDLED; | 1663 | return IRQ_HANDLED; |
1661 | } | 1664 | } |
@@ -1768,6 +1771,8 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
1768 | 1771 | ||
1769 | dev_info(hcd->self.controller, "%s\n", hcd->product_desc); | 1772 | dev_info(hcd->self.controller, "%s\n", hcd->product_desc); |
1770 | 1773 | ||
1774 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
1775 | |||
1771 | /* till now HC has been in an indeterminate state ... */ | 1776 | /* till now HC has been in an indeterminate state ... */ |
1772 | if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { | 1777 | if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) { |
1773 | dev_err(hcd->self.controller, "can't reset\n"); | 1778 | dev_err(hcd->self.controller, "can't reset\n"); |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 24a62a2ff86d..c8a1b350e2cf 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -72,7 +72,12 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */ | |||
72 | * hardware info/state | 72 | * hardware info/state |
73 | */ | 73 | */ |
74 | const struct hc_driver *driver; /* hw-specific hooks */ | 74 | const struct hc_driver *driver; /* hw-specific hooks */ |
75 | unsigned saw_irq : 1; | 75 | |
76 | /* Flags that need to be manipulated atomically */ | ||
77 | unsigned long flags; | ||
78 | #define HCD_FLAG_HW_ACCESSIBLE 0x00000001 | ||
79 | #define HCD_FLAG_SAW_IRQ 0x00000002 | ||
80 | |||
76 | unsigned can_wakeup:1; /* hw supports wakeup? */ | 81 | unsigned can_wakeup:1; /* hw supports wakeup? */ |
77 | unsigned remote_wakeup:1;/* sw should use wakeup? */ | 82 | unsigned remote_wakeup:1;/* sw should use wakeup? */ |
78 | unsigned rh_registered:1;/* is root hub registered? */ | 83 | unsigned rh_registered:1;/* is root hub registered? */ |