Re: Power management for SCSI

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi!

> > > Add support for autosuspend/autoresume. Lowlevel driver can use it to
> > > spin the disk down and power down its SATA link, to turn off the USB
> > > interface, etc.
> > > 
> > > Spinning down the disk is useful - saves ~0.5W here. Powering down
> > > SATA controller is even better -- should save ~1W.
> > > 
> > > Now, I guess the patch will need to be split to small pieces for
> > > merge... I tried to rearrange it so that the documentation and hooks
> > > go before stuff that needs the hooks, and before Kconfig enabler. If
> > > it looks reasonably good, I'll split it into smaller pieces.
> > 
> > James had a number of objections to my original patch; you can read 
> > them here:
> > 
> > https://lists.linux-foundation.org/pipermail/linux-pm/2008-March/016849.html
> > 
> > I haven't had time yet to work on an improved version.
> 
> Ok, I see, "its done at the wrong level" sounds pretty serious.
> 
> First the general comments/questions:
...
> #2. As you say in the comment, the thing we're trying to power down is
> #the link.  In most SCSI implementations, the link has a rather complex
> #relationship to the target, what we want to do in
> #periodic_autosuspend_scan() is run over the devices on each link, and
> #if
> #they're not busy suspend the link?  What's probably needed is a set of
> #adjunct helpers for the transport classes to do this.
> 
> So the host suspend/resume stuff should go into struct
> scsi_transport_template?

Is this step in the right direction? Moved autosuspend from
scsi_host_template to scsi_transport_template...

							Pavel

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index e4864d9..2b8cf09 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -320,14 +320,14 @@ static struct device_attribute *ahci_sde
 };
 
 struct pci_dev *my_pdev;
-int autosuspend_enabled = 0;	/* HERE */
+int autosuspend_enabled = 1;	/* HERE */
 
 struct sleep_disabled_reason ahci_active = {
         "ahci"
 };
 
 /* The host and its devices are all idle so we can autosuspend */
-static int autosuspend(struct Scsi_Host *host)
+int ahci_autosuspend(struct Scsi_Host *host)
 {
 	if (my_pdev && autosuspend_enabled) {
 		printk("ahci: should autosuspend\n");
@@ -340,7 +340,7 @@ static int autosuspend(struct Scsi_Host 
 }
 
 /* The host needs to be autoresumed */
-static int autoresume(struct Scsi_Host *host)
+int ahci_autoresume(struct Scsi_Host *host)
 {
 	if (my_pdev && autosuspend_enabled) {
 		printk("ahci: should autoresume\n");
@@ -360,8 +360,8 @@ static struct scsi_host_template ahci_sh
 	.sg_tablesize		= AHCI_MAX_SG,
 	.dma_boundary		= AHCI_DMA_BOUNDARY,
 	.shost_attrs		= ahci_shost_attrs,
-	.autosuspend		= autosuspend,
-	.autoresume		= autoresume,
+//	.autosuspend		= autosuspend,
+//	.autoresume		= autoresume,
 	.sdev_attrs		= ahci_sdev_attrs,
 };
 
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b9d3ba4..d3526a0 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -103,6 +103,9 @@ static const u8 def_control_mpage[CONTRO
 	0, 30	/* extended self test time, see 05-359r1 */
 };
 
+int ahci_autosuspend(struct Scsi_Host *host);
+int ahci_autoresume(struct Scsi_Host *host);
+
 /*
  * libata transport template.  libata doesn't do real transport stuff.
  * It just needs the eh_timed_out hook.
@@ -111,6 +114,8 @@ static struct scsi_transport_template at
 	.eh_strategy_handler	= ata_scsi_error,
 	.eh_timed_out		= ata_scsi_timed_out,
 	.user_scan		= ata_scsi_user_scan,
+	.autosuspend		= ahci_autosuspend,
+	.autoresume		= ahci_autoresume,
 };
 
 
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index 5ef69c4..d2de371 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -10,6 +10,7 @@ #define DEBUG
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
 
 #include <linux/delay.h>
 
@@ -50,8 +51,8 @@ void scsi_autosuspend_host(struct Scsi_H
 	if (shost->pm_usage_cnt <= 0 && !shost->is_suspended &&
 			shost->shost_state == SHOST_RUNNING) {
 		WARN_ON(shost->host_busy);
-		if (!shost->hostt->autosuspend ||
-				shost->hostt->autosuspend(shost) == 0) {
+		if (!shost->transportt->autosuspend ||
+				shost->transportt->autosuspend(shost) == 0) {
 			shost->is_suspended = 1;
 			shost_dbg(shost, "suspended\n");
 		}
@@ -82,10 +83,10 @@ int scsi_autoresume_host(struct Scsi_Hos
 	mutex_lock(&shost->pm_mutex);
 	++shost->pm_usage_cnt;
 	if (shost->is_suspended) {
-		if (shost->hostt->autoresume &&
+		if (shost->transportt->autoresume &&
 				(shost->shost_state == SHOST_RUNNING ||
 				 shost->shost_state == SHOST_RECOVERY))
-			status = shost->hostt->autoresume(shost);
+			status = shost->transportt->autoresume(shost);
 		if (status == 0) {
 			shost->is_suspended = 0;
 			shost_dbg(shost, "resumed\n");
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index ef64fd8..c96f11f 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -499,10 +499,6 @@ struct scsi_host_template usb_stor_host_
 	.eh_device_reset_handler =	device_reset,
 	.eh_bus_reset_handler =		bus_reset,
 
-	/* dynamic power management */
-	.autosuspend =			autosuspend,
-	.autoresume =			autoresume,
-
 	/* queue commands only, only one command per LUN */
 	.can_queue =			1,
 	.cmd_per_lun =			1,
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index b60445f..0f30451 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -176,21 +176,6 @@ #endif
 	int (* eh_bus_reset_handler)(struct scsi_cmnd *);
 	int (* eh_host_reset_handler)(struct scsi_cmnd *);
 
-	/*
-	 * Power management routines.  These are optional; you should
-	 * implement them if you want your LLD to perform dynamic Power
-	 * Management.  The autosuspend method will be called whenever
-	 * all the devices below a host have been suspended (are in an
-	 * idle state), at which time the host adapter can safely be
-	 * autosuspended.  The autoresume method will be called whenever
-	 * a suspended host must be resumed for one of its devices to
-	 * carry out a command.  Both routines are always called in a
-	 * process context with interrupts enabled.
-	 *
-	 * Status: OPTIONAL
-	 */
-	int (* autosuspend)(struct Scsi_Host *);
-	int (* autoresume)(struct Scsi_Host *);
 
 	/*
 	 * Before the mid layer attempts to scan for a new device where none
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index 490bd13..15c7886 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -77,6 +77,22 @@ struct scsi_transport_template {
 	 * request for target drivers.
 	 */
 	int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int);
+
+	/*
+	 * Power management routines.  These are optional; you should
+	 * implement them if you want your LLD to perform dynamic Power
+	 * Management.  The autosuspend method will be called whenever
+	 * all the devices below a host have been suspended (are in an
+	 * idle state), at which time the host adapter can safely be
+	 * autosuspended.  The autoresume method will be called whenever
+	 * a suspended host must be resumed for one of its devices to
+	 * carry out a command.  Both routines are always called in a
+	 * process context with interrupts enabled.
+	 *
+	 * Status: OPTIONAL
+	 */
+	int (* autosuspend)(struct Scsi_Host *);
+	int (* autoresume)(struct Scsi_Host *);
 };
 
 #define transport_class_to_shost(tc) \


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux