diff options
Diffstat (limited to 'drivers/usb/host')
| -rw-r--r-- | drivers/usb/host/ehci-pci.c | 46 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-q.c | 24 | ||||
| -rw-r--r-- | drivers/usb/host/ehci-sched.c | 18 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-hcd.c | 6 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-hub.c | 24 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-pci.c | 27 | ||||
| -rw-r--r-- | drivers/usb/host/uhci-hcd.c | 6 |
7 files changed, 126 insertions, 25 deletions
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 441c26064b..13f73a836e 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
| @@ -121,8 +121,8 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) | |||
| 121 | return 0; | 121 | return 0; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | /* called by khubd or root hub (re)init threads; leaves HC in halt state */ | 124 | /* called during probe() after chip reset completes */ |
| 125 | static int ehci_pci_reset(struct usb_hcd *hcd) | 125 | static int ehci_pci_setup(struct usb_hcd *hcd) |
| 126 | { | 126 | { |
| 127 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 127 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 128 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | 128 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); |
| @@ -141,6 +141,11 @@ static int ehci_pci_reset(struct usb_hcd *hcd) | |||
| 141 | if (retval) | 141 | if (retval) |
| 142 | return retval; | 142 | return retval; |
| 143 | 143 | ||
| 144 | /* data structure init */ | ||
| 145 | retval = ehci_init(hcd); | ||
| 146 | if (retval) | ||
| 147 | return retval; | ||
| 148 | |||
| 144 | /* NOTE: only the parts below this line are PCI-specific */ | 149 | /* NOTE: only the parts below this line are PCI-specific */ |
| 145 | 150 | ||
| 146 | switch (pdev->vendor) { | 151 | switch (pdev->vendor) { |
| @@ -154,7 +159,8 @@ static int ehci_pci_reset(struct usb_hcd *hcd) | |||
| 154 | /* AMD8111 EHCI doesn't work, according to AMD errata */ | 159 | /* AMD8111 EHCI doesn't work, according to AMD errata */ |
| 155 | if (pdev->device == 0x7463) { | 160 | if (pdev->device == 0x7463) { |
| 156 | ehci_info(ehci, "ignoring AMD8111 (errata)\n"); | 161 | ehci_info(ehci, "ignoring AMD8111 (errata)\n"); |
| 157 | return -EIO; | 162 | retval = -EIO; |
| 163 | goto done; | ||
| 158 | } | 164 | } |
| 159 | break; | 165 | break; |
| 160 | case PCI_VENDOR_ID_NVIDIA: | 166 | case PCI_VENDOR_ID_NVIDIA: |
| @@ -207,9 +213,8 @@ static int ehci_pci_reset(struct usb_hcd *hcd) | |||
| 207 | /* REVISIT: per-port wake capability (PCI 0x62) currently unused */ | 213 | /* REVISIT: per-port wake capability (PCI 0x62) currently unused */ |
| 208 | 214 | ||
| 209 | retval = ehci_pci_reinit(ehci, pdev); | 215 | retval = ehci_pci_reinit(ehci, pdev); |
| 210 | 216 | done: | |
| 211 | /* finish init */ | 217 | return retval; |
| 212 | return ehci_init(hcd); | ||
| 213 | } | 218 | } |
| 214 | 219 | ||
| 215 | /*-------------------------------------------------------------------------*/ | 220 | /*-------------------------------------------------------------------------*/ |
| @@ -228,14 +233,36 @@ static int ehci_pci_reset(struct usb_hcd *hcd) | |||
| 228 | static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) | 233 | static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) |
| 229 | { | 234 | { |
| 230 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 235 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
| 236 | unsigned long flags; | ||
| 237 | int rc = 0; | ||
| 231 | 238 | ||
| 232 | if (time_before(jiffies, ehci->next_statechange)) | 239 | if (time_before(jiffies, ehci->next_statechange)) |
| 233 | msleep(10); | 240 | msleep(10); |
| 234 | 241 | ||
| 242 | /* Root hub was already suspended. Disable irq emission and | ||
| 243 | * mark HW unaccessible, bail out if RH has been resumed. Use | ||
| 244 | * the spinlock to properly synchronize with possible pending | ||
| 245 | * RH suspend or resume activity. | ||
| 246 | * | ||
| 247 | * This is still racy as hcd->state is manipulated outside of | ||
| 248 | * any locks =P But that will be a different fix. | ||
| 249 | */ | ||
| 250 | spin_lock_irqsave (&ehci->lock, flags); | ||
| 251 | if (hcd->state != HC_STATE_SUSPENDED) { | ||
| 252 | rc = -EINVAL; | ||
| 253 | goto bail; | ||
| 254 | } | ||
| 255 | writel (0, &ehci->regs->intr_enable); | ||
| 256 | (void)readl(&ehci->regs->intr_enable); | ||
| 257 | |||
| 258 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
| 259 | bail: | ||
| 260 | spin_unlock_irqrestore (&ehci->lock, flags); | ||
| 261 | |||
| 235 | // could save FLADJ in case of Vaux power loss | 262 | // could save FLADJ in case of Vaux power loss |
| 236 | // ... we'd only use it to handle clock skew | 263 | // ... we'd only use it to handle clock skew |
| 237 | 264 | ||
| 238 | return 0; | 265 | return rc; |
| 239 | } | 266 | } |
| 240 | 267 | ||
| 241 | static int ehci_pci_resume(struct usb_hcd *hcd) | 268 | static int ehci_pci_resume(struct usb_hcd *hcd) |
| @@ -251,6 +278,9 @@ static int ehci_pci_resume(struct usb_hcd *hcd) | |||
| 251 | if (time_before(jiffies, ehci->next_statechange)) | 278 | if (time_before(jiffies, ehci->next_statechange)) |
| 252 | msleep(100); | 279 | msleep(100); |
| 253 | 280 | ||
| 281 | /* Mark hardware accessible again as we are out of D3 state by now */ | ||
| 282 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
| 283 | |||
| 254 | /* If CF is clear, we lost PCI Vaux power and need to restart. */ | 284 | /* If CF is clear, we lost PCI Vaux power and need to restart. */ |
| 255 | if (readl(&ehci->regs->configured_flag) != FLAG_CF) | 285 | if (readl(&ehci->regs->configured_flag) != FLAG_CF) |
| 256 | goto restart; | 286 | goto restart; |
| @@ -319,7 +349,7 @@ static const struct hc_driver ehci_pci_hc_driver = { | |||
| 319 | /* | 349 | /* |
| 320 | * basic lifecycle operations | 350 | * basic lifecycle operations |
| 321 | */ | 351 | */ |
| 322 | .reset = ehci_pci_reset, | 352 | .reset = ehci_pci_setup, |
| 323 | .start = ehci_run, | 353 | .start = ehci_run, |
| 324 | #ifdef CONFIG_PM | 354 | #ifdef CONFIG_PM |
| 325 | .suspend = ehci_pci_suspend, | 355 | .suspend = ehci_pci_suspend, |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 5bb872c349..bf03ec0d8e 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
| @@ -912,6 +912,7 @@ submit_async ( | |||
| 912 | int epnum; | 912 | int epnum; |
| 913 | unsigned long flags; | 913 | unsigned long flags; |
| 914 | struct ehci_qh *qh = NULL; | 914 | struct ehci_qh *qh = NULL; |
| 915 | int rc = 0; | ||
| 915 | 916 | ||
| 916 | qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); | 917 | qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list); |
| 917 | epnum = ep->desc.bEndpointAddress; | 918 | epnum = ep->desc.bEndpointAddress; |
| @@ -926,21 +927,28 @@ submit_async ( | |||
| 926 | #endif | 927 | #endif |
| 927 | 928 | ||
| 928 | spin_lock_irqsave (&ehci->lock, flags); | 929 | spin_lock_irqsave (&ehci->lock, flags); |
| 930 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | ||
| 931 | &ehci_to_hcd(ehci)->flags))) { | ||
| 932 | rc = -ESHUTDOWN; | ||
| 933 | goto done; | ||
| 934 | } | ||
| 935 | |||
| 929 | qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv); | 936 | qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv); |
| 937 | if (unlikely(qh == NULL)) { | ||
| 938 | rc = -ENOMEM; | ||
| 939 | goto done; | ||
| 940 | } | ||
| 930 | 941 | ||
| 931 | /* Control/bulk operations through TTs don't need scheduling, | 942 | /* Control/bulk operations through TTs don't need scheduling, |
| 932 | * the HC and TT handle it when the TT has a buffer ready. | 943 | * the HC and TT handle it when the TT has a buffer ready. |
| 933 | */ | 944 | */ |
| 934 | if (likely (qh != NULL)) { | 945 | if (likely (qh->qh_state == QH_STATE_IDLE)) |
| 935 | if (likely (qh->qh_state == QH_STATE_IDLE)) | 946 | qh_link_async (ehci, qh_get (qh)); |
| 936 | qh_link_async (ehci, qh_get (qh)); | 947 | done: |
| 937 | } | ||
| 938 | spin_unlock_irqrestore (&ehci->lock, flags); | 948 | spin_unlock_irqrestore (&ehci->lock, flags); |
| 939 | if (unlikely (qh == NULL)) { | 949 | if (unlikely (qh == NULL)) |
| 940 | qtd_list_free (ehci, urb, qtd_list); | 950 | qtd_list_free (ehci, urb, qtd_list); |
| 941 | return -ENOMEM; | 951 | return rc; |
| 942 | } | ||
| 943 | return 0; | ||
| 944 | } | 952 | } |
| 945 | 953 | ||
| 946 | /*-------------------------------------------------------------------------*/ | 954 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index f0c8aa1ccd..57e77374d2 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
| @@ -602,6 +602,12 @@ static int intr_submit ( | |||
| 602 | 602 | ||
| 603 | spin_lock_irqsave (&ehci->lock, flags); | 603 | spin_lock_irqsave (&ehci->lock, flags); |
| 604 | 604 | ||
| 605 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | ||
| 606 | &ehci_to_hcd(ehci)->flags))) { | ||
| 607 | status = -ESHUTDOWN; | ||
| 608 | goto done; | ||
| 609 | } | ||
| 610 | |||
| 605 | /* get qh and force any scheduling errors */ | 611 | /* get qh and force any scheduling errors */ |
| 606 | INIT_LIST_HEAD (&empty); | 612 | INIT_LIST_HEAD (&empty); |
| 607 | qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv); | 613 | qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv); |
| @@ -1456,7 +1462,11 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
| 1456 | 1462 | ||
| 1457 | /* schedule ... need to lock */ | 1463 | /* schedule ... need to lock */ |
| 1458 | spin_lock_irqsave (&ehci->lock, flags); | 1464 | spin_lock_irqsave (&ehci->lock, flags); |
| 1459 | status = iso_stream_schedule (ehci, urb, stream); | 1465 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, |
| 1466 | &ehci_to_hcd(ehci)->flags))) | ||
| 1467 | status = -ESHUTDOWN; | ||
| 1468 | else | ||
| 1469 | status = iso_stream_schedule (ehci, urb, stream); | ||
| 1460 | if (likely (status == 0)) | 1470 | if (likely (status == 0)) |
| 1461 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); | 1471 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
| 1462 | spin_unlock_irqrestore (&ehci->lock, flags); | 1472 | spin_unlock_irqrestore (&ehci->lock, flags); |
| @@ -1815,7 +1825,11 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
| 1815 | 1825 | ||
| 1816 | /* schedule ... need to lock */ | 1826 | /* schedule ... need to lock */ |
| 1817 | spin_lock_irqsave (&ehci->lock, flags); | 1827 | spin_lock_irqsave (&ehci->lock, flags); |
| 1818 | status = iso_stream_schedule (ehci, urb, stream); | 1828 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, |
| 1829 | &ehci_to_hcd(ehci)->flags))) | ||
| 1830 | status = -ESHUTDOWN; | ||
| 1831 | else | ||
| 1832 | status = iso_stream_schedule (ehci, urb, stream); | ||
| 1819 | if (status == 0) | 1833 | if (status == 0) |
| 1820 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); | 1834 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
| 1821 | spin_unlock_irqrestore (&ehci->lock, flags); | 1835 | spin_unlock_irqrestore (&ehci->lock, flags); |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5c0c6c8a7a..bf1d9abc07 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
| @@ -115,7 +115,7 @@ | |||
| 115 | 115 | ||
| 116 | /*-------------------------------------------------------------------------*/ | 116 | /*-------------------------------------------------------------------------*/ |
| 117 | 117 | ||
| 118 | // #define OHCI_VERBOSE_DEBUG /* not always helpful */ | 118 | #undef OHCI_VERBOSE_DEBUG /* not always helpful */ |
| 119 | 119 | ||
| 120 | /* For initializing controller (mask in an HCFS mode too) */ | 120 | /* For initializing controller (mask in an HCFS mode too) */ |
| 121 | #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR | 121 | #define OHCI_CONTROL_INIT OHCI_CTRL_CBSR |
| @@ -253,6 +253,10 @@ static int ohci_urb_enqueue ( | |||
| 253 | spin_lock_irqsave (&ohci->lock, flags); | 253 | spin_lock_irqsave (&ohci->lock, flags); |
| 254 | 254 | ||
| 255 | /* don't submit to a dead HC */ | 255 | /* don't submit to a dead HC */ |
| 256 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | ||
| 257 | retval = -ENODEV; | ||
| 258 | goto fail; | ||
| 259 | } | ||
| 256 | if (!HC_IS_RUNNING(hcd->state)) { | 260 | if (!HC_IS_RUNNING(hcd->state)) { |
| 257 | retval = -ENODEV; | 261 | retval = -ENODEV; |
| 258 | goto fail; | 262 | goto fail; |
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index e01e77bc32..72e3b12a19 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
| @@ -53,6 +53,11 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) | |||
| 53 | 53 | ||
| 54 | spin_lock_irqsave (&ohci->lock, flags); | 54 | spin_lock_irqsave (&ohci->lock, flags); |
| 55 | 55 | ||
| 56 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { | ||
| 57 | spin_unlock_irqrestore (&ohci->lock, flags); | ||
| 58 | return -ESHUTDOWN; | ||
| 59 | } | ||
| 60 | |||
| 56 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); | 61 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); |
| 57 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { | 62 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { |
| 58 | case OHCI_USB_RESUME: | 63 | case OHCI_USB_RESUME: |
| @@ -140,11 +145,19 @@ static int ohci_bus_resume (struct usb_hcd *hcd) | |||
| 140 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 145 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
| 141 | u32 temp, enables; | 146 | u32 temp, enables; |
| 142 | int status = -EINPROGRESS; | 147 | int status = -EINPROGRESS; |
| 148 | unsigned long flags; | ||
| 143 | 149 | ||
| 144 | if (time_before (jiffies, ohci->next_statechange)) | 150 | if (time_before (jiffies, ohci->next_statechange)) |
| 145 | msleep(5); | 151 | msleep(5); |
| 146 | 152 | ||
| 147 | spin_lock_irq (&ohci->lock); | 153 | spin_lock_irqsave (&ohci->lock, flags); |
| 154 | |||
| 155 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { | ||
| 156 | spin_unlock_irqrestore (&ohci->lock, flags); | ||
| 157 | return -ESHUTDOWN; | ||
| 158 | } | ||
| 159 | |||
| 160 | |||
| 148 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); | 161 | ohci->hc_control = ohci_readl (ohci, &ohci->regs->control); |
| 149 | 162 | ||
| 150 | if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { | 163 | if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { |
| @@ -179,7 +192,7 @@ static int ohci_bus_resume (struct usb_hcd *hcd) | |||
| 179 | ohci_dbg (ohci, "lost power\n"); | 192 | ohci_dbg (ohci, "lost power\n"); |
| 180 | status = -EBUSY; | 193 | status = -EBUSY; |
| 181 | } | 194 | } |
| 182 | spin_unlock_irq (&ohci->lock); | 195 | spin_unlock_irqrestore (&ohci->lock, flags); |
| 183 | if (status == -EBUSY) { | 196 | if (status == -EBUSY) { |
| 184 | (void) ohci_init (ohci); | 197 | (void) ohci_init (ohci); |
| 185 | return ohci_restart (ohci); | 198 | return ohci_restart (ohci); |
| @@ -297,8 +310,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
| 297 | /* handle autosuspended root: finish resuming before | 310 | /* handle autosuspended root: finish resuming before |
| 298 | * letting khubd or root hub timer see state changes. | 311 | * letting khubd or root hub timer see state changes. |
| 299 | */ | 312 | */ |
| 300 | if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER | 313 | if (unlikely((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER |
| 301 | || !HC_IS_RUNNING(hcd->state)) { | 314 | || !HC_IS_RUNNING(hcd->state))) { |
| 302 | can_suspend = 0; | 315 | can_suspend = 0; |
| 303 | goto done; | 316 | goto done; |
| 304 | } | 317 | } |
| @@ -508,6 +521,9 @@ static int ohci_hub_control ( | |||
| 508 | u32 temp; | 521 | u32 temp; |
| 509 | int retval = 0; | 522 | int retval = 0; |
| 510 | 523 | ||
| 524 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) | ||
| 525 | return -ESHUTDOWN; | ||
| 526 | |||
| 511 | switch (typeReq) { | 527 | switch (typeReq) { |
| 512 | case ClearHubFeature: | 528 | case ClearHubFeature: |
| 513 | switch (wValue) { | 529 | switch (wValue) { |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 5f22e6590c..1b09dde068 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
| @@ -105,13 +105,36 @@ ohci_pci_start (struct usb_hcd *hcd) | |||
| 105 | 105 | ||
| 106 | static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | 106 | static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) |
| 107 | { | 107 | { |
| 108 | /* root hub was already suspended */ | 108 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
| 109 | return 0; | 109 | unsigned long flags; |
| 110 | int rc = 0; | ||
| 111 | |||
| 112 | /* Root hub was already suspended. Disable irq emission and | ||
| 113 | * mark HW unaccessible, bail out if RH has been resumed. Use | ||
| 114 | * the spinlock to properly synchronize with possible pending | ||
| 115 | * RH suspend or resume activity. | ||
| 116 | * | ||
| 117 | * This is still racy as hcd->state is manipulated outside of | ||
| 118 | * any locks =P But that will be a different fix. | ||
| 119 | */ | ||
| 120 | spin_lock_irqsave (&ohci->lock, flags); | ||
| 121 | if (hcd->state != HC_STATE_SUSPENDED) { | ||
| 122 | rc = -EINVAL; | ||
| 123 | goto bail; | ||
| 124 | } | ||
| 125 | ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | ||
| 126 | (void)ohci_readl(ohci, &ohci->regs->intrdisable); | ||
| 127 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
| 128 | bail: | ||
| 129 | spin_unlock_irqrestore (&ohci->lock, flags); | ||
| 130 | |||
| 131 | return rc; | ||
| 110 | } | 132 | } |
| 111 | 133 | ||
| 112 | 134 | ||
| 113 | static int ohci_pci_resume (struct usb_hcd *hcd) | 135 | static int ohci_pci_resume (struct usb_hcd *hcd) |
| 114 | { | 136 | { |
| 137 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
| 115 | usb_hcd_resume_root_hub(hcd); | 138 | usb_hcd_resume_root_hub(hcd); |
| 116 | return 0; | 139 | return 0; |
| 117 | } | 140 | } |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index d33ce3982a..ed550132db 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
| @@ -717,6 +717,7 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message) | |||
| 717 | * at the source, so we must turn off PIRQ. | 717 | * at the source, so we must turn off PIRQ. |
| 718 | */ | 718 | */ |
| 719 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); | 719 | pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); |
| 720 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
| 720 | uhci->hc_inaccessible = 1; | 721 | uhci->hc_inaccessible = 1; |
| 721 | hcd->poll_rh = 0; | 722 | hcd->poll_rh = 0; |
| 722 | 723 | ||
| @@ -733,6 +734,11 @@ static int uhci_resume(struct usb_hcd *hcd) | |||
| 733 | 734 | ||
| 734 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); | 735 | dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); |
| 735 | 736 | ||
| 737 | /* We aren't in D3 state anymore, we do that even if dead as I | ||
| 738 | * really don't want to keep a stale HCD_FLAG_HW_ACCESSIBLE=0 | ||
| 739 | */ | ||
| 740 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
| 741 | |||
| 736 | if (uhci->rh_state == UHCI_RH_RESET) /* Dead */ | 742 | if (uhci->rh_state == UHCI_RH_RESET) /* Dead */ |
| 737 | return 0; | 743 | return 0; |
| 738 | spin_lock_irq(&uhci->lock); | 744 | spin_lock_irq(&uhci->lock); |
