diff options
Diffstat (limited to 'drivers/usb/host/isp116x-hcd.c')
-rw-r--r-- | drivers/usb/host/isp116x-hcd.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 82f64986bc22..5f56c4a42f52 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c | |||
@@ -1201,11 +1201,14 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd) | |||
1201 | return ret; | 1201 | return ret; |
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | /* Get rid of these declarations later in cleanup */ | ||
1205 | static int isp116x_reset(struct usb_hcd *hcd); | ||
1206 | static int isp116x_start(struct usb_hcd *hcd); | ||
1207 | |||
1204 | static int isp116x_bus_resume(struct usb_hcd *hcd) | 1208 | static int isp116x_bus_resume(struct usb_hcd *hcd) |
1205 | { | 1209 | { |
1206 | struct isp116x *isp116x = hcd_to_isp116x(hcd); | 1210 | struct isp116x *isp116x = hcd_to_isp116x(hcd); |
1207 | u32 val; | 1211 | u32 val; |
1208 | int ret = -EINPROGRESS; | ||
1209 | 1212 | ||
1210 | msleep(5); | 1213 | msleep(5); |
1211 | spin_lock_irq(&isp116x->lock); | 1214 | spin_lock_irq(&isp116x->lock); |
@@ -1219,20 +1222,27 @@ static int isp116x_bus_resume(struct usb_hcd *hcd) | |||
1219 | case HCCONTROL_USB_RESUME: | 1222 | case HCCONTROL_USB_RESUME: |
1220 | break; | 1223 | break; |
1221 | case HCCONTROL_USB_OPER: | 1224 | case HCCONTROL_USB_OPER: |
1225 | spin_unlock_irq(&isp116x->lock); | ||
1222 | /* Without setting power_state here the | 1226 | /* Without setting power_state here the |
1223 | SUSPENDED state won't be removed from | 1227 | SUSPENDED state won't be removed from |
1224 | sysfs/usbN/power.state as a response to remote | 1228 | sysfs/usbN/power.state as a response to remote |
1225 | wakeup. Maybe in the future. */ | 1229 | wakeup. Maybe in the future. */ |
1226 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | 1230 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; |
1227 | ret = 0; | 1231 | return 0; |
1228 | break; | ||
1229 | default: | 1232 | default: |
1230 | ret = -EBUSY; | 1233 | /* HCCONTROL_USB_RESET: this may happen, when during |
1231 | } | 1234 | suspension the HC lost power. Reinitialize completely */ |
1232 | |||
1233 | if (ret != -EINPROGRESS) { | ||
1234 | spin_unlock_irq(&isp116x->lock); | 1235 | spin_unlock_irq(&isp116x->lock); |
1235 | return ret; | 1236 | DBG("Chip has been reset while suspended. Reinit from scratch.\n"); |
1237 | isp116x_reset(hcd); | ||
1238 | isp116x_start(hcd); | ||
1239 | isp116x_hub_control(hcd, SetPortFeature, | ||
1240 | USB_PORT_FEAT_POWER, 1, NULL, 0); | ||
1241 | if ((isp116x->rhdesca & RH_A_NDP) == 2) | ||
1242 | isp116x_hub_control(hcd, SetPortFeature, | ||
1243 | USB_PORT_FEAT_POWER, 2, NULL, 0); | ||
1244 | hcd->self.root_hub->dev.power.power_state = PMSG_ON; | ||
1245 | return 0; | ||
1236 | } | 1246 | } |
1237 | 1247 | ||
1238 | val = isp116x->rhdesca & RH_A_NDP; | 1248 | val = isp116x->rhdesca & RH_A_NDP; |