diff options
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index ac4c8ddde20a..e44ca5453aa2 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -343,6 +343,7 @@ static void ehci_shutdown(struct usb_hcd *hcd) | |||
343 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 343 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
344 | 344 | ||
345 | spin_lock_irq(&ehci->lock); | 345 | spin_lock_irq(&ehci->lock); |
346 | ehci->shutdown = true; | ||
346 | ehci->rh_state = EHCI_RH_STOPPING; | 347 | ehci->rh_state = EHCI_RH_STOPPING; |
347 | ehci->enabled_hrtimer_events = 0; | 348 | ehci->enabled_hrtimer_events = 0; |
348 | spin_unlock_irq(&ehci->lock); | 349 | spin_unlock_irq(&ehci->lock); |
@@ -823,6 +824,7 @@ dead: | |||
823 | usb_hc_died(hcd); | 824 | usb_hc_died(hcd); |
824 | 825 | ||
825 | /* Don't let the controller do anything more */ | 826 | /* Don't let the controller do anything more */ |
827 | ehci->shutdown = true; | ||
826 | ehci->rh_state = EHCI_RH_STOPPING; | 828 | ehci->rh_state = EHCI_RH_STOPPING; |
827 | ehci->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE); | 829 | ehci->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE); |
828 | ehci_writel(ehci, ehci->command, &ehci->regs->command); | 830 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
@@ -1129,6 +1131,9 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated) | |||
1129 | /* Mark hardware accessible again as we are back to full power by now */ | 1131 | /* Mark hardware accessible again as we are back to full power by now */ |
1130 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 1132 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
1131 | 1133 | ||
1134 | if (ehci->shutdown) | ||
1135 | return 0; /* Controller is dead */ | ||
1136 | |||
1132 | /* | 1137 | /* |
1133 | * If CF is still set and we aren't resuming from hibernation | 1138 | * If CF is still set and we aren't resuming from hibernation |
1134 | * then we maintained suspend power. | 1139 | * then we maintained suspend power. |
@@ -1139,10 +1144,17 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated) | |||
1139 | int mask = INTR_MASK; | 1144 | int mask = INTR_MASK; |
1140 | 1145 | ||
1141 | ehci_prepare_ports_for_controller_resume(ehci); | 1146 | ehci_prepare_ports_for_controller_resume(ehci); |
1147 | |||
1148 | spin_lock_irq(&ehci->lock); | ||
1149 | if (ehci->shutdown) | ||
1150 | goto skip; | ||
1151 | |||
1142 | if (!hcd->self.root_hub->do_remote_wakeup) | 1152 | if (!hcd->self.root_hub->do_remote_wakeup) |
1143 | mask &= ~STS_PCD; | 1153 | mask &= ~STS_PCD; |
1144 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); | 1154 | ehci_writel(ehci, mask, &ehci->regs->intr_enable); |
1145 | ehci_readl(ehci, &ehci->regs->intr_enable); | 1155 | ehci_readl(ehci, &ehci->regs->intr_enable); |
1156 | skip: | ||
1157 | spin_unlock_irq(&ehci->lock); | ||
1146 | return 0; | 1158 | return 0; |
1147 | } | 1159 | } |
1148 | 1160 | ||
@@ -1154,14 +1166,20 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated) | |||
1154 | (void) ehci_halt(ehci); | 1166 | (void) ehci_halt(ehci); |
1155 | (void) ehci_reset(ehci); | 1167 | (void) ehci_reset(ehci); |
1156 | 1168 | ||
1169 | spin_lock_irq(&ehci->lock); | ||
1170 | if (ehci->shutdown) | ||
1171 | goto skip; | ||
1172 | |||
1157 | ehci_writel(ehci, ehci->command, &ehci->regs->command); | 1173 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
1158 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | 1174 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); |
1159 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | 1175 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ |
1160 | 1176 | ||
1177 | ehci->rh_state = EHCI_RH_SUSPENDED; | ||
1178 | spin_unlock_irq(&ehci->lock); | ||
1179 | |||
1161 | /* here we "know" root ports should always stay powered */ | 1180 | /* here we "know" root ports should always stay powered */ |
1162 | ehci_port_power(ehci, 1); | 1181 | ehci_port_power(ehci, 1); |
1163 | 1182 | ||
1164 | ehci->rh_state = EHCI_RH_SUSPENDED; | ||
1165 | return 1; | 1183 | return 1; |
1166 | } | 1184 | } |
1167 | 1185 | ||