* [PATCH 0/4] SATA device runtime power off
@ 2012-08-30 6:40 Aaron Lu
2012-08-30 6:40 ` [PATCH 1/4] libata: pm: differentiate system and runtime pm for ata port Aaron Lu
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Aaron Lu @ 2012-08-30 6:40 UTC (permalink / raw)
To: Jeff Garzik, James E.J. Bottomley
Cc: linux-ide, linux-pm, linux-acpi, Aaron Lu, Aaron Lu
Add support for hard disk runtime power off and differentiate
system pm with runtime pm messages.
The patch "libata: pm: differentiate system and runtime pm for ata port"
is the same as the previously seperated sent one:
http://marc.info/?l=linux-ide&m=134614386932721&w=2
I included it into this patch set because patch "libata: acpi: respect
may_power_off flag" is based on top of it.
The patch "scsi: pm: add may_power_off flag" also appears in another
patchset intended for scsi subsystem, they are identical.
Aaron Lu (4):
libata: pm: differentiate system and runtime pm for ata port
libata: acpi: set can_power_off for both ODD and HD
scsi: pm: add may_power_off flag
libata: acpi: respect may_power_off flag
drivers/ata/libata-acpi.c | 112 +++++++++++++++++++++++++++++++--------------
drivers/ata/libata-core.c | 22 ++++++---
drivers/ata/libata-eh.c | 9 ++--
include/scsi/scsi_device.h | 1 +
4 files changed, 99 insertions(+), 45 deletions(-)
--
1.7.11.5
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/4] libata: pm: differentiate system and runtime pm for ata port
2012-08-30 6:40 [PATCH 0/4] SATA device runtime power off Aaron Lu
@ 2012-08-30 6:40 ` Aaron Lu
2012-08-30 6:40 ` [PATCH 2/4] libata: acpi: set can_power_off for both ODD and HD Aaron Lu
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Aaron Lu @ 2012-08-30 6:40 UTC (permalink / raw)
To: Jeff Garzik, James E.J. Bottomley
Cc: linux-ide, linux-pm, linux-acpi, Aaron Lu, Aaron Lu
For sata port, only runtime pm needs to be taken care of;
For IDE port, only system pm needs to be taken care of.
Currently, we use PMSG_SUSPEND for both system suspend and runtime
suspend and PMSG_ON for both system resume and runtime resume.
Change this by using PMSG_AUTO_SUSPEND for runtime suspend and
PMSG_AUTO_RESUME for runtime resume.
The ata_acpi_set_state is modified accordingly. And the sata case and
pata case is seperated for easy understanding.
Signed-off-by: Aaron Lu <aaron.lu@intel.com>
---
drivers/ata/libata-acpi.c | 83 ++++++++++++++++++++++++++++++++---------------
drivers/ata/libata-core.c | 22 +++++++++----
drivers/ata/libata-eh.c | 9 ++---
3 files changed, 78 insertions(+), 36 deletions(-)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index fd9ecf7..b67b565 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -832,50 +832,81 @@ void ata_acpi_on_resume(struct ata_port *ap)
}
}
-/**
- * ata_acpi_set_state - set the port power state
- * @ap: target ATA port
- * @state: state, on/off
- *
- * This function executes the _PS0/_PS3 ACPI method to set the power state.
- * ACPI spec requires _PS0 when IDE power on and _PS3 when power off
- */
-void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
+static void sata_acpi_set_state(struct ata_port *ap, pm_message_t state)
{
- struct ata_device *dev;
- acpi_handle handle;
int acpi_state;
+ acpi_handle handle;
+ struct ata_device *dev;
- /* channel first and then drives for power on and vica versa
- for power off */
- handle = ata_ap_acpi_handle(ap);
- if (handle && state.event == PM_EVENT_ON)
- acpi_bus_set_power(handle, ACPI_STATE_D0);
+ if (!PMSG_IS_AUTO(state))
+ return;
ata_for_each_dev(dev, &ap->link, ENABLED) {
handle = ata_dev_acpi_handle(dev);
if (!handle)
continue;
- if (state.event != PM_EVENT_ON) {
+ if (state.event == PM_EVENT_AUTO_SUSPEND) {
acpi_state = acpi_pm_device_sleep_state(
&dev->sdev->sdev_gendev, NULL, ACPI_STATE_D3);
if (acpi_state > 0)
acpi_bus_set_power(handle, acpi_state);
- /* TBD: need to check if it's runtime pm request */
- acpi_pm_device_run_wake(
- &dev->sdev->sdev_gendev, true);
+ acpi_pm_device_run_wake(&dev->sdev->sdev_gendev, true);
} else {
- /* Ditto */
- acpi_pm_device_run_wake(
- &dev->sdev->sdev_gendev, false);
+ acpi_pm_device_run_wake(&dev->sdev->sdev_gendev, false);
acpi_bus_set_power(handle, ACPI_STATE_D0);
}
}
+}
+
+/**
+ * pata_acpi_set_state - set the port power state
+ * @ap: target ATA port
+ * @state: state, on/off
+ *
+ * This function executes the _PS0/_PS3 ACPI method to set the power state.
+ * ACPI spec requires _PS0 when IDE power on and _PS3 when power off
+ */
+static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state)
+{
+ struct ata_device *dev;
+
+ if (!ata_ap_acpi_handle(ap))
+ return;
+
+ /*
+ * Channel first and then drives for power on and
+ * vica versa for power off
+ */
+ if (state.event == PM_EVENT_ON)
+ acpi_bus_set_power(ata_ap_acpi_handle(ap), ACPI_STATE_D0);
+
+ ata_for_each_dev(dev, &ap->link, ENABLED) {
+ if (ata_dev_acpi_handle(dev))
+ acpi_bus_set_power(ata_dev_acpi_handle(dev),
+ state.event == PM_EVENT_ON ?
+ ACPI_STATE_D0 : ACPI_STATE_D3);
+
+ }
- handle = ata_ap_acpi_handle(ap);
- if (handle && state.event != PM_EVENT_ON)
- acpi_bus_set_power(handle, ACPI_STATE_D3);
+ if (state.event != PM_EVENT_ON)
+ acpi_bus_set_power(ata_ap_acpi_handle(ap), ACPI_STATE_D3);
+}
+
+/**
+ * ata_acpi_set_state - set the port power state
+ * @ap: target ATA port
+ * @state: state, on/off
+ *
+ * Depends on whether the port is a PATA port or a SATA port,
+ * this function calls into different functions.
+ */
+void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
+{
+ if (ap->flags & ATA_FLAG_ACPI_SATA)
+ sata_acpi_set_state(ap, state);
+ else
+ pata_acpi_set_state(ap, state);
}
/**
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index c3fbdca..6c7d167 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5309,7 +5309,7 @@ static int ata_port_suspend_common(struct device *dev, pm_message_t mesg)
*
* http://thread.gmane.org/gmane.linux.ide/46764
*/
- if (mesg.event == PM_EVENT_SUSPEND)
+ if (mesg.event & PM_EVENT_SUSPEND)
ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY;
rc = ata_port_request_pm(ap, mesg, 0, ehi_flags, 1);
@@ -5324,6 +5324,11 @@ static int ata_port_suspend(struct device *dev)
return ata_port_suspend_common(dev, PMSG_SUSPEND);
}
+static int ata_port_runtime_suspend(struct device *dev)
+{
+ return ata_port_suspend_common(dev, PMSG_AUTO_SUSPEND);
+}
+
static int ata_port_do_freeze(struct device *dev)
{
if (pm_runtime_suspended(dev))
@@ -5340,12 +5345,12 @@ static int ata_port_poweroff(struct device *dev)
return ata_port_suspend_common(dev, PMSG_HIBERNATE);
}
-static int ata_port_resume_common(struct device *dev)
+static int ata_port_resume_common(struct device *dev, pm_message_t mesg)
{
struct ata_port *ap = to_ata_port(dev);
int rc;
- rc = ata_port_request_pm(ap, PMSG_ON, ATA_EH_RESET,
+ rc = ata_port_request_pm(ap, mesg, ATA_EH_RESET,
ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 1);
return rc;
}
@@ -5354,7 +5359,7 @@ static int ata_port_resume(struct device *dev)
{
int rc;
- rc = ata_port_resume_common(dev);
+ rc = ata_port_resume_common(dev, PMSG_ON);
if (!rc) {
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
@@ -5364,6 +5369,11 @@ static int ata_port_resume(struct device *dev)
return rc;
}
+static int ata_port_runtime_resume(struct device *dev)
+{
+ return ata_port_resume_common(dev, PMSG_AUTO_RESUME);
+}
+
static int ata_port_runtime_idle(struct device *dev)
{
return pm_runtime_suspend(dev);
@@ -5377,8 +5387,8 @@ static const struct dev_pm_ops ata_port_pm_ops = {
.poweroff = ata_port_poweroff,
.restore = ata_port_resume,
- .runtime_suspend = ata_port_suspend,
- .runtime_resume = ata_port_resume_common,
+ .runtime_suspend = ata_port_runtime_suspend,
+ .runtime_resume = ata_port_runtime_resume,
.runtime_idle = ata_port_runtime_idle,
};
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7d4535e..f3eced6 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -4021,7 +4021,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
/* are we suspending? */
spin_lock_irqsave(ap->lock, flags);
if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
- ap->pm_mesg.event == PM_EVENT_ON) {
+ !(ap->pm_mesg.event & PM_EVENT_SUSPEND)) {
spin_unlock_irqrestore(ap->lock, flags);
return;
}
@@ -4040,7 +4040,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
if (ap->ops->port_suspend)
rc = ap->ops->port_suspend(ap, ap->pm_mesg);
- ata_acpi_set_state(ap, PMSG_SUSPEND);
+ ata_acpi_set_state(ap, ap->pm_mesg);
out:
/* report result */
spin_lock_irqsave(ap->lock, flags);
@@ -4080,7 +4080,8 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
/* are we resuming? */
spin_lock_irqsave(ap->lock, flags);
if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
- ap->pm_mesg.event != PM_EVENT_ON) {
+ (ap->pm_mesg.event != PM_EVENT_ON &&
+ ap->pm_mesg.event != PM_EVENT_AUTO_RESUME)) {
spin_unlock_irqrestore(ap->lock, flags);
return;
}
@@ -4099,7 +4100,7 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
ata_for_each_dev(dev, link, ALL)
ata_ering_clear(&dev->ering);
- ata_acpi_set_state(ap, PMSG_ON);
+ ata_acpi_set_state(ap, ap->pm_mesg);
if (ap->ops->port_resume)
rc = ap->ops->port_resume(ap);
--
1.7.11.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/4] libata: acpi: set can_power_off for both ODD and HD
2012-08-30 6:40 [PATCH 0/4] SATA device runtime power off Aaron Lu
2012-08-30 6:40 ` [PATCH 1/4] libata: pm: differentiate system and runtime pm for ata port Aaron Lu
@ 2012-08-30 6:40 ` Aaron Lu
2012-08-30 6:40 ` [PATCH 3/4] scsi: pm: add may_power_off flag Aaron Lu
2012-08-30 6:40 ` [PATCH 4/4] libata: acpi: respect " Aaron Lu
3 siblings, 0 replies; 5+ messages in thread
From: Aaron Lu @ 2012-08-30 6:40 UTC (permalink / raw)
To: Jeff Garzik, James E.J. Bottomley
Cc: linux-ide, linux-pm, linux-acpi, Aaron Lu, Aaron Lu
Hard disk may also be runtime powered off, so set can_power_off flag
for it too if condition satisfies.
Signed-off-by: Aaron Lu <aaron.lu@intel.com>
---
drivers/ata/libata-acpi.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index b67b565..67a696f 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -1024,7 +1024,7 @@ static void ata_acpi_add_pm_notifier(struct ata_device *dev)
if (ACPI_FAILURE(status))
return;
- if (dev->sdev->can_power_off) {
+ if (dev->class == ATA_DEV_ATAPI && dev->sdev->can_power_off) {
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
ata_acpi_wake_dev, dev);
device_set_run_wake(&dev->sdev->sdev_gendev, true);
@@ -1045,7 +1045,7 @@ static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
if (ACPI_FAILURE(status))
return;
- if (dev->sdev->can_power_off) {
+ if (dev->class == ATA_DEV_ATAPI && dev->sdev->can_power_off) {
device_set_run_wake(&dev->sdev->sdev_gendev, false);
acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
ata_acpi_wake_dev);
@@ -1152,14 +1152,23 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
/*
* If firmware has _PS3 or _PR3 for this device,
- * and this ata ODD device support device attention,
- * it means this device can be powered off
+ * it means this device can be powered off runtime
*/
states = acpi_dev->power.states;
- if ((states[ACPI_STATE_D3_HOT].flags.valid ||
- states[ACPI_STATE_D3_COLD].flags.explicit_set) &&
- ata_dev->flags & ATA_DFLAG_DA)
- sdev->can_power_off = 1;
+ if (states[ACPI_STATE_D3_HOT].flags.valid ||
+ states[ACPI_STATE_D3_COLD].flags.explicit_set) {
+ /*
+ * For ODD, it needs to support device attention or
+ * it can't be powered up back by user
+ */
+ if (ata_dev->class == ATA_DEV_ATAPI &&
+ ata_dev->flags & ATA_DFLAG_DA)
+ sdev->can_power_off = 1;
+
+ /* No requirement for hard disk */
+ if (ata_dev->class == ATA_DEV_ATA)
+ sdev->can_power_off = 1;
+ }
return 0;
}
--
1.7.11.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/4] scsi: pm: add may_power_off flag
2012-08-30 6:40 [PATCH 0/4] SATA device runtime power off Aaron Lu
2012-08-30 6:40 ` [PATCH 1/4] libata: pm: differentiate system and runtime pm for ata port Aaron Lu
2012-08-30 6:40 ` [PATCH 2/4] libata: acpi: set can_power_off for both ODD and HD Aaron Lu
@ 2012-08-30 6:40 ` Aaron Lu
2012-08-30 6:40 ` [PATCH 4/4] libata: acpi: respect " Aaron Lu
3 siblings, 0 replies; 5+ messages in thread
From: Aaron Lu @ 2012-08-30 6:40 UTC (permalink / raw)
To: Jeff Garzik, James E.J. Bottomley
Cc: linux-ide, linux-pm, linux-acpi, Aaron Lu, Aaron Lu
Add a new flag may_power_off for scsi device, it gives the user a chance
to control when the device is runtime suspended, can we remove its power
if possible.
I'm planning using this flag for sr and sd.
For sr, if user set 0 to may_power_off, we will disable runtime suspend
for ODD, since runtime suspend for ODD is wholly for zero power ODD, if
we can't power off the ODD, there is no meaning to do runtime PM on it.
For sd, if user set 0 to may_power_off, we will not power off the device
when it is runtime suspended.
Signed-off-by: Aaron Lu <aaron.lu@intel.com>
---
include/scsi/scsi_device.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 9895f69..ad7cb68 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -156,6 +156,7 @@ struct scsi_device {
unsigned is_visible:1; /* is the device visible in sysfs */
unsigned can_power_off:1; /* Device supports runtime power off */
unsigned wce_default_on:1; /* Cache is ON by default */
+ unsigned may_power_off:1; /* power off is allowed by user */
DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
struct list_head event_list; /* asserted events */
--
1.7.11.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/4] libata: acpi: respect may_power_off flag
2012-08-30 6:40 [PATCH 0/4] SATA device runtime power off Aaron Lu
` (2 preceding siblings ...)
2012-08-30 6:40 ` [PATCH 3/4] scsi: pm: add may_power_off flag Aaron Lu
@ 2012-08-30 6:40 ` Aaron Lu
3 siblings, 0 replies; 5+ messages in thread
From: Aaron Lu @ 2012-08-30 6:40 UTC (permalink / raw)
To: Jeff Garzik, James E.J. Bottomley
Cc: linux-ide, linux-pm, linux-acpi, Aaron Lu, Aaron Lu
If user does not want the device being powered off when runtime
suspended by setting may_power_off flag to 0, we will not choose D3 cold
ACPI D-State for it in sata_acpi_set_state.
Signed-off-by: Aaron Lu <aaron.lu@intel.com>
---
drivers/ata/libata-acpi.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 67a696f..90c42a0 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -848,7 +848,9 @@ static void sata_acpi_set_state(struct ata_port *ap, pm_message_t state)
if (state.event == PM_EVENT_AUTO_SUSPEND) {
acpi_state = acpi_pm_device_sleep_state(
- &dev->sdev->sdev_gendev, NULL, ACPI_STATE_D3);
+ &dev->sdev->sdev_gendev, NULL,
+ dev->sdev->may_power_off ?
+ ACPI_STATE_D3_COLD : ACPI_STATE_D3_HOT);
if (acpi_state > 0)
acpi_bus_set_power(handle, acpi_state);
acpi_pm_device_run_wake(&dev->sdev->sdev_gendev, true);
--
1.7.11.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-08-30 6:41 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-30 6:40 [PATCH 0/4] SATA device runtime power off Aaron Lu
2012-08-30 6:40 ` [PATCH 1/4] libata: pm: differentiate system and runtime pm for ata port Aaron Lu
2012-08-30 6:40 ` [PATCH 2/4] libata: acpi: set can_power_off for both ODD and HD Aaron Lu
2012-08-30 6:40 ` [PATCH 3/4] scsi: pm: add may_power_off flag Aaron Lu
2012-08-30 6:40 ` [PATCH 4/4] libata: acpi: respect " Aaron Lu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).