aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShaohua Li <shaohua.li@intel.com>2007-10-11 17:53:58 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-10-11 17:53:58 -0400
commit5e32132befa5d2cefadf3141fee0bbb40cd11f0e (patch)
tree7bf2002e49b169d24b87a8fe71364875e04d1e90
parent8cb1f567f4c0a2fde9cbf77c2af888a28cab3423 (diff)
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 <shaohua.li@intel.com> Acked-by: Len Brown <len.brown@intel.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r--drivers/acpi/bus.c4
-rw-r--r--drivers/ide/ide-acpi.c42
-rw-r--r--drivers/ide/ide.c14
-rw-r--r--include/linux/ide.h2
4 files changed, 59 insertions, 3 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 9ba778a2b484..feab124d8e05 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)
262 printk(KERN_WARNING PREFIX 262 printk(KERN_WARNING PREFIX
263 "Transitioning device [%s] to D%d\n", 263 "Transitioning device [%s] to D%d\n",
264 device->pnp.bus_id, state); 264 device->pnp.bus_id, state);
265 else 265 else {
266 device->power.state = state;
266 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 267 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
267 "Device [%s] transitioned to D%d\n", 268 "Device [%s] transitioned to D%d\n",
268 device->pnp.bus_id, state)); 269 device->pnp.bus_id, state));
270 }
269 271
270 return result; 272 return result;
271} 273}
diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
index 17aea65d7dd2..6bff81a58bf3 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)
612EXPORT_SYMBOL_GPL(ide_acpi_push_timing); 612EXPORT_SYMBOL_GPL(ide_acpi_push_timing);
613 613
614/** 614/**
615 * ide_acpi_set_state - set the channel power state
616 * @hwif: target IDE interface
617 * @on: state, on/off
618 *
619 * This function executes the _PS0/_PS3 ACPI method to set the power state.
620 * ACPI spec requires _PS0 when IDE power on and _PS3 when power off
621 */
622void ide_acpi_set_state(ide_hwif_t *hwif, int on)
623{
624 int unit;
625
626 if (ide_noacpi)
627 return;
628
629 DEBPRINT("ENTER:\n");
630
631 if (!hwif->acpidata) {
632 DEBPRINT("no ACPI data for %s\n", hwif->name);
633 return;
634 }
635 /* channel first and then drives for power on and verse versa for power off */
636 if (on)
637 acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0);
638 for (unit = 0; unit < MAX_DRIVES; ++unit) {
639 ide_drive_t *drive = &hwif->drives[unit];
640
641 if (!drive->acpidata->obj_handle)
642 drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive);
643
644 if (drive->acpidata->obj_handle && drive->present) {
645 acpi_bus_set_power(drive->acpidata->obj_handle,
646 on? ACPI_STATE_D0: ACPI_STATE_D3);
647 }
648 }
649 if (!on)
650 acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3);
651}
652EXPORT_SYMBOL_GPL(ide_acpi_set_state);
653
654/**
615 * ide_acpi_init - initialize the ACPI link for an IDE interface 655 * ide_acpi_init - initialize the ACPI link for an IDE interface
616 * @hwif: target IDE interface (channel) 656 * @hwif: target IDE interface (channel)
617 * 657 *
@@ -679,6 +719,8 @@ void ide_acpi_init(ide_hwif_t *hwif)
679 return; 719 return;
680 } 720 }
681 721
722 /* ACPI _PS0 before _STM */
723 ide_acpi_set_state(hwif, 1);
682 /* 724 /*
683 * ACPI requires us to call _STM on startup 725 * ACPI requires us to call _STM on startup
684 */ 726 */
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index de54306789a1..9fdc1fe1b299 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)
915 struct request rq; 915 struct request rq;
916 struct request_pm_state rqpm; 916 struct request_pm_state rqpm;
917 ide_task_t args; 917 ide_task_t args;
918 int ret;
918 919
919 /* Call ACPI _GTM only once */ 920 /* Call ACPI _GTM only once */
920 if (!(drive->dn % 2)) 921 if (!(drive->dn % 2))
@@ -931,7 +932,14 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
931 mesg.event = PM_EVENT_FREEZE; 932 mesg.event = PM_EVENT_FREEZE;
932 rqpm.pm_state = mesg.event; 933 rqpm.pm_state = mesg.event;
933 934
934 return ide_do_drive_cmd(drive, &rq, ide_wait); 935 ret = ide_do_drive_cmd(drive, &rq, ide_wait);
936 /* only call ACPI _PS3 after both drivers are suspended */
937 if (!ret && (((drive->dn % 2) && hwif->drives[0].present
938 && hwif->drives[1].present)
939 || !hwif->drives[0].present
940 || !hwif->drives[1].present))
941 ide_acpi_set_state(hwif, 0);
942 return ret;
935} 943}
936 944
937static int generic_ide_resume(struct device *dev) 945static int generic_ide_resume(struct device *dev)
@@ -944,8 +952,10 @@ static int generic_ide_resume(struct device *dev)
944 int err; 952 int err;
945 953
946 /* Call ACPI _STM only once */ 954 /* Call ACPI _STM only once */
947 if (!(drive->dn % 2)) 955 if (!(drive->dn % 2)) {
956 ide_acpi_set_state(hwif, 1);
948 ide_acpi_push_timing(hwif); 957 ide_acpi_push_timing(hwif);
958 }
949 959
950 ide_acpi_exec_tfs(drive); 960 ide_acpi_exec_tfs(drive);
951 961
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 0665428356d3..80ea946282d7 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);
1338extern void ide_acpi_get_timing(ide_hwif_t *hwif); 1338extern void ide_acpi_get_timing(ide_hwif_t *hwif);
1339extern void ide_acpi_push_timing(ide_hwif_t *hwif); 1339extern void ide_acpi_push_timing(ide_hwif_t *hwif);
1340extern void ide_acpi_init(ide_hwif_t *hwif); 1340extern void ide_acpi_init(ide_hwif_t *hwif);
1341extern void ide_acpi_set_state(ide_hwif_t *hwif, int on);
1341#else 1342#else
1342static inline int ide_acpi_exec_tfs(ide_drive_t *drive) { return 0; } 1343static inline int ide_acpi_exec_tfs(ide_drive_t *drive) { return 0; }
1343static inline void ide_acpi_get_timing(ide_hwif_t *hwif) { ; } 1344static inline void ide_acpi_get_timing(ide_hwif_t *hwif) { ; }
1344static inline void ide_acpi_push_timing(ide_hwif_t *hwif) { ; } 1345static inline void ide_acpi_push_timing(ide_hwif_t *hwif) { ; }
1345static inline void ide_acpi_init(ide_hwif_t *hwif) { ; } 1346static inline void ide_acpi_init(ide_hwif_t *hwif) { ; }
1347static inline void ide_acpi_set_state(ide_hwif_t *hwif, int on) {}
1346#endif 1348#endif
1347 1349
1348extern int ide_hwif_request_regions(ide_hwif_t *hwif); 1350extern int ide_hwif_request_regions(ide_hwif_t *hwif);