diff options
author | Olav Kongas <ok@artecdesign.ee> | 2005-10-28 08:04:45 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-01-04 16:48:29 -0500 |
commit | 535488fcf1e4b2331e1c4a1eb67ca09468c13507 (patch) | |
tree | 285a6e02054bb5a661605649d3527a73bbdba466 | |
parent | 61a87adf2e7b410da8e41799c61c21a7b8c8b001 (diff) |
[PATCH] USB: isp116x-hcd: support reiniting HC on resume
Until now the isp116x-hcd had no support to reinitialize the HC on
resume, if the controller lost its state during suspend. This patch,
generated against your Oct 26 git tree, adds that support. The patch is
basically the same as the one tested by Ivan Kalatchev, who reported the
problem, on 2.6.13.
Please apply,
Support reinitializing the isp116x host controller from scratch on
resume, if the controller has lost its state.
Signed-off-by: Olav Kongas <ok@artecdesign.ee>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-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; |