lkml.org 
[lkml]   [2008]   [Aug]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: Power management for SCSI
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


\
 
 \ /
  Last update: 2008-08-14 17:57    [W:0.071 / U:0.480 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site