Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8dfe4b14 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

usb-storage: implement autosuspend



This patch (as930) implements autosuspend for usb-storage.  It is
adapted from a patch by Oliver Neukum.  Autosuspend is allowed except
during LUN scanning, resets, and command execution.

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b0e2a705
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -285,10 +285,15 @@ static int device_reset(struct scsi_cmnd *srb)

	US_DEBUGP("%s called\n", __FUNCTION__);

	result = usb_autopm_get_interface(us->pusb_intf);
	if (result == 0) {

		/* lock the device pointers and do the reset */
		mutex_lock(&(us->dev_mutex));
		result = us->transport_reset(us);
		mutex_unlock(&us->dev_mutex);
		usb_autopm_put_interface(us->pusb_intf);
	}

	return result < 0 ? FAILED : SUCCESS;
}
+20 −7
Original line number Diff line number Diff line
@@ -191,16 +191,14 @@ 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);

	/* 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;
}
@@ -209,13 +207,11 @@ static int storage_resume(struct usb_interface *iface)
{
	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);

	mutex_unlock(&us->dev_mutex);
	return 0;
}

@@ -313,6 +309,7 @@ static int usb_stor_control_thread(void * __us)
{
	struct us_data *us = (struct us_data *)__us;
	struct Scsi_Host *host = us_to_host(us);
	int autopm_rc;

	current->flags |= PF_NOFREEZE;

@@ -323,6 +320,9 @@ static int usb_stor_control_thread(void * __us)
			
		US_DEBUGP("*** thread awakened.\n");

		/* Autoresume the device */
		autopm_rc = usb_autopm_get_interface(us->pusb_intf);

		/* lock the device pointers */
		mutex_lock(&(us->dev_mutex));

@@ -381,6 +381,12 @@ static int usb_stor_control_thread(void * __us)
			us->srb->result = SAM_STAT_GOOD;
		}

		/* Did the autoresume fail? */
		else if (autopm_rc < 0) {
			US_DEBUGP("Could not wake device\n");
			us->srb->result = DID_ERROR << 16;
		}

		/* we've got a command, let's do it! */
		else {
			US_DEBUG(usb_stor_show_command(us->srb));
@@ -423,6 +429,10 @@ static int usb_stor_control_thread(void * __us)

		/* unlock the device pointers */
		mutex_unlock(&us->dev_mutex);

		/* Start an autosuspend */
		if (autopm_rc == 0)
			usb_autopm_put_interface(us->pusb_intf);
	} /* for (;;) */

	/* Wait until we are told to stop */
@@ -939,6 +949,7 @@ static int usb_stor_scan_thread(void * __us)
	}

	scsi_host_put(us_to_host(us));
	usb_autopm_put_interface(us->pusb_intf);
	complete_and_exit(&threads_gone, 0);
}

@@ -1028,6 +1039,7 @@ static int storage_probe(struct usb_interface *intf,
	 * 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;
@@ -1065,6 +1077,7 @@ static struct usb_driver usb_storage_driver = {
	.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)