Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=5e32132befa5d2cefadf3141fee0bbb40cd11f0e
Commit:     5e32132befa5d2cefadf3141fee0bbb40cd11f0e
Parent:     8cb1f567f4c0a2fde9cbf77c2af888a28cab3423
Author:     Shaohua Li <[EMAIL PROTECTED]>
AuthorDate: Thu Oct 11 23:53:58 2007 +0200
Committer:  Bartlomiej Zolnierkiewicz <[EMAIL PROTECTED]>
CommitDate: Thu Oct 11 23:53:58 2007 +0200

    ide: hook ACPI _PSx method to IDE power on/off
    
    ACPI spec defines the sequence of IDE power on/off:
    Powering down:
        Call _GTM.
        Power down drive (calls _PS3 method and turns off power planes).
    Powering up:
        Power up drive (calls _PS0 method if present and turns on power planes).
        Call _STM passing info from _GTM (possibly modified), with ID data from
        each drive.
        Initialize the channel.
        May modify the results of _GTF.
        For each drive:
                Call _GTF.
                Execute task file (possibly modified).
    This patch adds the missed _PS0/_PS3 methods call.
    
    Signed-off-by: Shaohua Li <[EMAIL PROTECTED]>
    Acked-by: Len Brown <[EMAIL PROTECTED]>
    Signed-off-by: Bartlomiej Zolnierkiewicz <[EMAIL PROTECTED]>
---
 drivers/acpi/bus.c     |    4 +++-
 drivers/ide/ide-acpi.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 drivers/ide/ide.c      |   14 ++++++++++++--
 include/linux/ide.h    |    2 ++
 4 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 9ba778a..feab124 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -262,10 +262,12 @@ int acpi_bus_set_power(acpi_handle handle, int state)
                printk(KERN_WARNING PREFIX
                              "Transitioning device [%s] to D%d\n",
                              device->pnp.bus_id, state);
-       else
+       else {
+               device->power.state = state;
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Device [%s] transitioned to D%d\n",
                                  device->pnp.bus_id, state));
+       }
 
        return result;
 }
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index 17aea65..6bff81a 100644
--- a/drivers/ide/ide-acpi.c
+++ b/drivers/ide/ide-acpi.c
@@ -612,6 +612,46 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
 EXPORT_SYMBOL_GPL(ide_acpi_push_timing);
 
 /**
+ * ide_acpi_set_state - set the channel power state
+ * @hwif: target IDE interface
+ * @on: 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 ide_acpi_set_state(ide_hwif_t *hwif, int on)
+{
+       int unit;
+
+       if (ide_noacpi)
+               return;
+
+       DEBPRINT("ENTER:\n");
+
+       if (!hwif->acpidata) {
+               DEBPRINT("no ACPI data for %s\n", hwif->name);
+               return;
+       }
+       /* channel first and then drives for power on and verse versa for power 
off */
+       if (on)
+               acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0);
+       for (unit = 0; unit < MAX_DRIVES; ++unit) {
+               ide_drive_t *drive = &hwif->drives[unit];
+
+               if (!drive->acpidata->obj_handle)
+                       drive->acpidata->obj_handle = 
ide_acpi_drive_get_handle(drive);
+
+               if (drive->acpidata->obj_handle && drive->present) {
+                       acpi_bus_set_power(drive->acpidata->obj_handle,
+                               on? ACPI_STATE_D0: ACPI_STATE_D3);
+               }
+       }
+       if (!on)
+               acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3);
+}
+EXPORT_SYMBOL_GPL(ide_acpi_set_state);
+
+/**
  * ide_acpi_init - initialize the ACPI link for an IDE interface
  * @hwif: target IDE interface (channel)
  *
@@ -679,6 +719,8 @@ void ide_acpi_init(ide_hwif_t *hwif)
                return;
        }
 
+       /* ACPI _PS0 before _STM */
+       ide_acpi_set_state(hwif, 1);
        /*
         * ACPI requires us to call _STM on startup
         */
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index de54306..9fdc1fe 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -915,6 +915,7 @@ static int generic_ide_suspend(struct device *dev, 
pm_message_t mesg)
        struct request rq;
        struct request_pm_state rqpm;
        ide_task_t args;
+       int ret;
 
        /* Call ACPI _GTM only once */
        if (!(drive->dn % 2))
@@ -931,7 +932,14 @@ static int generic_ide_suspend(struct device *dev, 
pm_message_t mesg)
                mesg.event = PM_EVENT_FREEZE;
        rqpm.pm_state = mesg.event;
 
-       return ide_do_drive_cmd(drive, &rq, ide_wait);
+       ret = ide_do_drive_cmd(drive, &rq, ide_wait);
+       /* only call ACPI _PS3 after both drivers are suspended */
+       if (!ret && (((drive->dn % 2) && hwif->drives[0].present
+                && hwif->drives[1].present)
+                || !hwif->drives[0].present
+                || !hwif->drives[1].present))
+               ide_acpi_set_state(hwif, 0);
+       return ret;
 }
 
 static int generic_ide_resume(struct device *dev)
@@ -944,8 +952,10 @@ static int generic_ide_resume(struct device *dev)
        int err;
 
        /* Call ACPI _STM only once */
-       if (!(drive->dn % 2))
+       if (!(drive->dn % 2)) {
+               ide_acpi_set_state(hwif, 1);
                ide_acpi_push_timing(hwif);
+       }
 
        ide_acpi_exec_tfs(drive);
 
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 0665428..80ea946 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1338,11 +1338,13 @@ extern int ide_acpi_exec_tfs(ide_drive_t *drive);
 extern void ide_acpi_get_timing(ide_hwif_t *hwif);
 extern void ide_acpi_push_timing(ide_hwif_t *hwif);
 extern void ide_acpi_init(ide_hwif_t *hwif);
+extern void ide_acpi_set_state(ide_hwif_t *hwif, int on);
 #else
 static inline int ide_acpi_exec_tfs(ide_drive_t *drive) { return 0; }
 static inline void ide_acpi_get_timing(ide_hwif_t *hwif) { ; }
 static inline void ide_acpi_push_timing(ide_hwif_t *hwif) { ; }
 static inline void ide_acpi_init(ide_hwif_t *hwif) { ; }
+static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {}
 #endif
 
 extern int ide_hwif_request_regions(ide_hwif_t *hwif);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to