[patch]autosuspend for usb storage
Oliver Neukum <[email protected]>
| Newsgroups | gmane.linux.usb.devel |
|---|---|
| Organization | Novell |
| Message-ID | <[email protected]> |
Hi, this patch implements autosuspend for usb-storage. The device may autosuspend except while 1. a scsi request is being processed 2. a bus is scanned for devices 3. a scsi reset is in progress Regards Oliver Signed-off-by: Oliver Neukum <[email protected]> -- --- linux-2.6.21-rc7/drivers/usb/storage/scsiglue.c 2007-04-25 08:48:23.000000000 +0200 +++ linux-2.6.21-rc7-auto/drivers/usb/storage/scsiglue.c 2007-04-25 08:56:08.000000000 +0200 @@ -287,7 +287,11 @@ static int device_reset(struct scsi_cmnd /* lock the device pointers and do the reset */ mutex_lock(&(us->dev_mutex)); - result = us->transport_reset(us); + result = usb_autopm_get_interface(us->pusb_intf); + if (!result) { + result = us->transport_reset(us); + usb_autopm_put_interface(us->pusb_intf); + } mutex_unlock(&us->dev_mutex); return result < 0 ? FAILED : SUCCESS; --- linux-2.6.21-rc7/drivers/usb/storage/usb.c 2007-04-25 08:48:23.000000000 +0200 +++ linux-2.6.21-rc7-auto/drivers/usb/storage/usb.c 2007-04-24 14:03:56.000000000 +0200 @@ -68,6 +68,8 @@ #include "debug.h" #include "initializers.h" +#include "../core/usb.h" + #ifdef CONFIG_USB_STORAGE_USBAT #include "shuttle_usbat.h" #endif @@ -190,19 +192,19 @@ static struct us_unusual_dev us_unusual_ static int storage_suspend(struct usb_interface *iface, pm_message_t message) { struct us_data *us = usb_get_intfdata(iface); + US_DEBUGP("%s\n", __FUNCTION__); /* Wait until no command is running */ mutex_lock(&us->dev_mutex); - US_DEBUGP("%s\n", __FUNCTION__); if (us->suspend_resume_hook) (us->suspend_resume_hook)(us, US_SUSPEND); iface->dev.power.power_state.event = message.event; /* When runtime PM is working, we'll set a flag to indicate * whether we should autoresume when a SCSI request arrives. */ - mutex_unlock(&us->dev_mutex); + return 0; } @@ -210,14 +212,12 @@ static int storage_resume(struct usb_int { struct us_data *us = usb_get_intfdata(iface); - mutex_lock(&us->dev_mutex); - US_DEBUGP("%s\n", __FUNCTION__); + if (us->suspend_resume_hook) (us->suspend_resume_hook)(us, US_RESUME); iface->dev.power.power_state.event = PM_EVENT_ON; - mutex_unlock(&us->dev_mutex); return 0; } @@ -300,6 +300,7 @@ static int usb_stor_control_thread(void { struct us_data *us = (struct us_data *)__us; struct Scsi_Host *host = us_to_host(us); + int res; current->flags |= PF_NOFREEZE; @@ -311,6 +312,7 @@ static int usb_stor_control_thread(void US_DEBUGP("*** thread awakened.\n"); /* lock the device pointers */ + usb_pm_lock(us->pusb_dev); mutex_lock(&(us->dev_mutex)); /* if the device has disconnected, we are free to exit */ @@ -370,8 +372,15 @@ static int usb_stor_control_thread(void /* we've got a command, let's do it! */ else { - US_DEBUG(usb_stor_show_command(us->srb)); - us->proto_handler(us->srb, us); + res = __usb_autopm_do_interface(us->pusb_intf, 1); + if (!res) { + US_DEBUG(usb_stor_show_command(us->srb)); + us->proto_handler(us->srb, us); + __usb_autopm_do_interface(us->pusb_intf, -1); + } else { + us->srb->result = DID_ERROR << 16; + US_DEBUGP("Could not wake device\n"); + } } /* lock access to the state */ @@ -410,6 +419,7 @@ SkipForAbort: /* unlock the device pointers */ mutex_unlock(&us->dev_mutex); + usb_pm_unlock(us->pusb_dev); } /* for (;;) */ scsi_host_put(host); @@ -938,6 +948,7 @@ retry: } scsi_host_put(us_to_host(us)); + usb_autopm_put_interface(us->pusb_intf); complete_and_exit(&threads_gone, 0); } @@ -1027,6 +1038,7 @@ static int storage_probe(struct usb_inte * start it up. */ scsi_host_get(us_to_host(us)); atomic_inc(&total_threads); + usb_autopm_get_interface(intf); /* dropped in the scanning thread */ wake_up_process(th); return 0; @@ -1063,6 +1075,7 @@ static struct usb_driver usb_storage_dri .pre_reset = storage_pre_reset, .post_reset = storage_post_reset, .id_table = storage_usb_ids, + .supports_autosuspend = 1, }; static int __init usb_stor_init(void) ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ [email protected] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel