diff options
Diffstat (limited to 'drivers/usb/storage/usb.c')
| -rw-r--r-- | drivers/usb/storage/usb.c | 91 |
1 files changed, 53 insertions, 38 deletions
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 8e898e3d861e..bef8bcd9bd98 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
| @@ -191,16 +191,13 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) | |||
| 191 | { | 191 | { |
| 192 | struct us_data *us = usb_get_intfdata(iface); | 192 | struct us_data *us = usb_get_intfdata(iface); |
| 193 | 193 | ||
| 194 | US_DEBUGP("%s\n", __FUNCTION__); | ||
| 195 | |||
| 194 | /* Wait until no command is running */ | 196 | /* Wait until no command is running */ |
| 195 | mutex_lock(&us->dev_mutex); | 197 | mutex_lock(&us->dev_mutex); |
| 196 | 198 | ||
| 197 | US_DEBUGP("%s\n", __FUNCTION__); | ||
| 198 | if (us->suspend_resume_hook) | 199 | if (us->suspend_resume_hook) |
| 199 | (us->suspend_resume_hook)(us, US_SUSPEND); | 200 | (us->suspend_resume_hook)(us, US_SUSPEND); |
| 200 | iface->dev.power.power_state.event = message.event; | ||
| 201 | |||
| 202 | /* When runtime PM is working, we'll set a flag to indicate | ||
| 203 | * whether we should autoresume when a SCSI request arrives. */ | ||
| 204 | 201 | ||
| 205 | mutex_unlock(&us->dev_mutex); | 202 | mutex_unlock(&us->dev_mutex); |
| 206 | return 0; | 203 | return 0; |
| @@ -210,14 +207,25 @@ static int storage_resume(struct usb_interface *iface) | |||
| 210 | { | 207 | { |
| 211 | struct us_data *us = usb_get_intfdata(iface); | 208 | struct us_data *us = usb_get_intfdata(iface); |
| 212 | 209 | ||
| 213 | mutex_lock(&us->dev_mutex); | ||
| 214 | |||
| 215 | US_DEBUGP("%s\n", __FUNCTION__); | 210 | US_DEBUGP("%s\n", __FUNCTION__); |
| 211 | |||
| 216 | if (us->suspend_resume_hook) | 212 | if (us->suspend_resume_hook) |
| 217 | (us->suspend_resume_hook)(us, US_RESUME); | 213 | (us->suspend_resume_hook)(us, US_RESUME); |
| 218 | iface->dev.power.power_state.event = PM_EVENT_ON; | ||
| 219 | 214 | ||
| 220 | mutex_unlock(&us->dev_mutex); | 215 | return 0; |
| 216 | } | ||
| 217 | |||
| 218 | static int storage_reset_resume(struct usb_interface *iface) | ||
| 219 | { | ||
| 220 | struct us_data *us = usb_get_intfdata(iface); | ||
| 221 | |||
| 222 | US_DEBUGP("%s\n", __FUNCTION__); | ||
| 223 | |||
| 224 | /* Report the reset to the SCSI core */ | ||
| 225 | usb_stor_report_bus_reset(us); | ||
| 226 | |||
| 227 | /* FIXME: Notify the subdrivers that they need to reinitialize | ||
| 228 | * the device */ | ||
| 221 | return 0; | 229 | return 0; |
| 222 | } | 230 | } |
| 223 | 231 | ||
| @@ -228,7 +236,7 @@ static int storage_resume(struct usb_interface *iface) | |||
| 228 | * a USB port reset, whether from this driver or a different one. | 236 | * a USB port reset, whether from this driver or a different one. |
| 229 | */ | 237 | */ |
| 230 | 238 | ||
| 231 | static void storage_pre_reset(struct usb_interface *iface) | 239 | static int storage_pre_reset(struct usb_interface *iface) |
| 232 | { | 240 | { |
| 233 | struct us_data *us = usb_get_intfdata(iface); | 241 | struct us_data *us = usb_get_intfdata(iface); |
| 234 | 242 | ||
| @@ -236,22 +244,23 @@ static void storage_pre_reset(struct usb_interface *iface) | |||
| 236 | 244 | ||
| 237 | /* Make sure no command runs during the reset */ | 245 | /* Make sure no command runs during the reset */ |
| 238 | mutex_lock(&us->dev_mutex); | 246 | mutex_lock(&us->dev_mutex); |
| 247 | return 0; | ||
| 239 | } | 248 | } |
| 240 | 249 | ||
| 241 | static void storage_post_reset(struct usb_interface *iface) | 250 | static int storage_post_reset(struct usb_interface *iface) |
| 242 | { | 251 | { |
| 243 | struct us_data *us = usb_get_intfdata(iface); | 252 | struct us_data *us = usb_get_intfdata(iface); |
| 244 | 253 | ||
| 245 | US_DEBUGP("%s\n", __FUNCTION__); | 254 | US_DEBUGP("%s\n", __FUNCTION__); |
| 246 | 255 | ||
| 247 | /* Report the reset to the SCSI core */ | 256 | /* Report the reset to the SCSI core */ |
| 248 | scsi_lock(us_to_host(us)); | ||
| 249 | usb_stor_report_bus_reset(us); | 257 | usb_stor_report_bus_reset(us); |
| 250 | scsi_unlock(us_to_host(us)); | ||
| 251 | 258 | ||
| 252 | /* FIXME: Notify the subdrivers that they need to reinitialize | 259 | /* FIXME: Notify the subdrivers that they need to reinitialize |
| 253 | * the device */ | 260 | * the device */ |
| 261 | |||
| 254 | mutex_unlock(&us->dev_mutex); | 262 | mutex_unlock(&us->dev_mutex); |
| 263 | return 0; | ||
| 255 | } | 264 | } |
| 256 | 265 | ||
| 257 | /* | 266 | /* |
| @@ -300,6 +309,7 @@ static int usb_stor_control_thread(void * __us) | |||
| 300 | { | 309 | { |
| 301 | struct us_data *us = (struct us_data *)__us; | 310 | struct us_data *us = (struct us_data *)__us; |
| 302 | struct Scsi_Host *host = us_to_host(us); | 311 | struct Scsi_Host *host = us_to_host(us); |
| 312 | int autopm_rc; | ||
| 303 | 313 | ||
| 304 | current->flags |= PF_NOFREEZE; | 314 | current->flags |= PF_NOFREEZE; |
| 305 | 315 | ||
| @@ -310,6 +320,9 @@ static int usb_stor_control_thread(void * __us) | |||
| 310 | 320 | ||
| 311 | US_DEBUGP("*** thread awakened.\n"); | 321 | US_DEBUGP("*** thread awakened.\n"); |
| 312 | 322 | ||
| 323 | /* Autoresume the device */ | ||
| 324 | autopm_rc = usb_autopm_get_interface(us->pusb_intf); | ||
| 325 | |||
| 313 | /* lock the device pointers */ | 326 | /* lock the device pointers */ |
| 314 | mutex_lock(&(us->dev_mutex)); | 327 | mutex_lock(&(us->dev_mutex)); |
| 315 | 328 | ||
| @@ -368,6 +381,12 @@ static int usb_stor_control_thread(void * __us) | |||
| 368 | us->srb->result = SAM_STAT_GOOD; | 381 | us->srb->result = SAM_STAT_GOOD; |
| 369 | } | 382 | } |
| 370 | 383 | ||
| 384 | /* Did the autoresume fail? */ | ||
| 385 | else if (autopm_rc < 0) { | ||
| 386 | US_DEBUGP("Could not wake device\n"); | ||
| 387 | us->srb->result = DID_ERROR << 16; | ||
| 388 | } | ||
| 389 | |||
| 371 | /* we've got a command, let's do it! */ | 390 | /* we've got a command, let's do it! */ |
| 372 | else { | 391 | else { |
| 373 | US_DEBUG(usb_stor_show_command(us->srb)); | 392 | US_DEBUG(usb_stor_show_command(us->srb)); |
| @@ -410,25 +429,21 @@ SkipForAbort: | |||
| 410 | 429 | ||
| 411 | /* unlock the device pointers */ | 430 | /* unlock the device pointers */ |
| 412 | mutex_unlock(&us->dev_mutex); | 431 | mutex_unlock(&us->dev_mutex); |
| 413 | } /* for (;;) */ | ||
| 414 | 432 | ||
| 415 | scsi_host_put(host); | 433 | /* Start an autosuspend */ |
| 434 | if (autopm_rc == 0) | ||
| 435 | usb_autopm_put_interface(us->pusb_intf); | ||
| 436 | } /* for (;;) */ | ||
| 416 | 437 | ||
| 417 | /* notify the exit routine that we're actually exiting now | 438 | /* Wait until we are told to stop */ |
| 418 | * | 439 | for (;;) { |
| 419 | * complete()/wait_for_completion() is similar to up()/down(), | 440 | set_current_state(TASK_INTERRUPTIBLE); |
| 420 | * except that complete() is safe in the case where the structure | 441 | if (kthread_should_stop()) |
| 421 | * is getting deleted in a parallel mode of execution (i.e. just | 442 | break; |
| 422 | * after the down() -- that's necessary for the thread-shutdown | 443 | schedule(); |
| 423 | * case. | 444 | } |
| 424 | * | 445 | __set_current_state(TASK_RUNNING); |
| 425 | * complete_and_exit() goes even further than this -- it is safe in | 446 | return 0; |
| 426 | * the case that the thread of the caller is going away (not just | ||
| 427 | * the structure) -- this is necessary for the module-remove case. | ||
| 428 | * This is important in preemption kernels, which transfer the flow | ||
| 429 | * of execution immediately upon a complete(). | ||
| 430 | */ | ||
| 431 | complete_and_exit(&threads_gone, 0); | ||
| 432 | } | 447 | } |
| 433 | 448 | ||
| 434 | /*********************************************************************** | 449 | /*********************************************************************** |
| @@ -796,19 +811,13 @@ static int usb_stor_acquire_resources(struct us_data *us) | |||
| 796 | } | 811 | } |
| 797 | 812 | ||
| 798 | /* Start up our control thread */ | 813 | /* Start up our control thread */ |
| 799 | th = kthread_create(usb_stor_control_thread, us, "usb-storage"); | 814 | th = kthread_run(usb_stor_control_thread, us, "usb-storage"); |
| 800 | if (IS_ERR(th)) { | 815 | if (IS_ERR(th)) { |
| 801 | printk(KERN_WARNING USB_STORAGE | 816 | printk(KERN_WARNING USB_STORAGE |
| 802 | "Unable to start control thread\n"); | 817 | "Unable to start control thread\n"); |
| 803 | return PTR_ERR(th); | 818 | return PTR_ERR(th); |
| 804 | } | 819 | } |
| 805 | 820 | us->ctl_thread = th; | |
| 806 | /* Take a reference to the host for the control thread and | ||
| 807 | * count it among all the threads we have launched. Then | ||
| 808 | * start it up. */ | ||
| 809 | scsi_host_get(us_to_host(us)); | ||
| 810 | atomic_inc(&total_threads); | ||
| 811 | wake_up_process(th); | ||
| 812 | 821 | ||
| 813 | return 0; | 822 | return 0; |
| 814 | } | 823 | } |
| @@ -825,6 +834,8 @@ static void usb_stor_release_resources(struct us_data *us) | |||
| 825 | US_DEBUGP("-- sending exit command to thread\n"); | 834 | US_DEBUGP("-- sending exit command to thread\n"); |
| 826 | set_bit(US_FLIDX_DISCONNECTING, &us->flags); | 835 | set_bit(US_FLIDX_DISCONNECTING, &us->flags); |
| 827 | up(&us->sema); | 836 | up(&us->sema); |
| 837 | if (us->ctl_thread) | ||
| 838 | kthread_stop(us->ctl_thread); | ||
| 828 | 839 | ||
| 829 | /* Call the destructor routine, if it exists */ | 840 | /* Call the destructor routine, if it exists */ |
| 830 | if (us->extra_destructor) { | 841 | if (us->extra_destructor) { |
| @@ -938,6 +949,7 @@ retry: | |||
| 938 | } | 949 | } |
| 939 | 950 | ||
| 940 | scsi_host_put(us_to_host(us)); | 951 | scsi_host_put(us_to_host(us)); |
| 952 | usb_autopm_put_interface(us->pusb_intf); | ||
| 941 | complete_and_exit(&threads_gone, 0); | 953 | complete_and_exit(&threads_gone, 0); |
| 942 | } | 954 | } |
| 943 | 955 | ||
| @@ -1027,6 +1039,7 @@ static int storage_probe(struct usb_interface *intf, | |||
| 1027 | * start it up. */ | 1039 | * start it up. */ |
| 1028 | scsi_host_get(us_to_host(us)); | 1040 | scsi_host_get(us_to_host(us)); |
| 1029 | atomic_inc(&total_threads); | 1041 | atomic_inc(&total_threads); |
| 1042 | usb_autopm_get_interface(intf); /* dropped in the scanning thread */ | ||
| 1030 | wake_up_process(th); | 1043 | wake_up_process(th); |
| 1031 | 1044 | ||
| 1032 | return 0; | 1045 | return 0; |
| @@ -1059,10 +1072,12 @@ static struct usb_driver usb_storage_driver = { | |||
| 1059 | #ifdef CONFIG_PM | 1072 | #ifdef CONFIG_PM |
| 1060 | .suspend = storage_suspend, | 1073 | .suspend = storage_suspend, |
| 1061 | .resume = storage_resume, | 1074 | .resume = storage_resume, |
| 1075 | .reset_resume = storage_reset_resume, | ||
| 1062 | #endif | 1076 | #endif |
| 1063 | .pre_reset = storage_pre_reset, | 1077 | .pre_reset = storage_pre_reset, |
| 1064 | .post_reset = storage_post_reset, | 1078 | .post_reset = storage_post_reset, |
| 1065 | .id_table = storage_usb_ids, | 1079 | .id_table = storage_usb_ids, |
| 1080 | .supports_autosuspend = 1, | ||
| 1066 | }; | 1081 | }; |
| 1067 | 1082 | ||
| 1068 | static int __init usb_stor_init(void) | 1083 | static int __init usb_stor_init(void) |
