diff options
| -rw-r--r-- | drivers/ide/Makefile | 2 | ||||
| -rw-r--r-- | drivers/ide/ide-io.c | 159 | ||||
| -rw-r--r-- | drivers/ide/ide-pm.c | 235 | ||||
| -rw-r--r-- | drivers/ide/ide.c | 74 | ||||
| -rw-r--r-- | include/linux/ide.h | 8 |
5 files changed, 244 insertions, 234 deletions
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 7818d402b188..bdc7b81bc044 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | EXTRA_CFLAGS += -Idrivers/ide | 5 | EXTRA_CFLAGS += -Idrivers/ide |
| 6 | 6 | ||
| 7 | ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ | 7 | ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ |
| 8 | ide-taskfile.o ide-park.o ide-pio-blacklist.o | 8 | ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o |
| 9 | 9 | ||
| 10 | # core IDE code | 10 | # core IDE code |
| 11 | ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o | 11 | ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o |
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 26d3f3cacc8a..ecacc008fdaf 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
| @@ -120,98 +120,6 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) | |||
| 120 | } | 120 | } |
| 121 | EXPORT_SYMBOL(ide_end_request); | 121 | EXPORT_SYMBOL(ide_end_request); |
| 122 | 122 | ||
| 123 | static void ide_complete_power_step(ide_drive_t *drive, struct request *rq) | ||
| 124 | { | ||
| 125 | struct request_pm_state *pm = rq->data; | ||
| 126 | |||
| 127 | #ifdef DEBUG_PM | ||
| 128 | printk(KERN_INFO "%s: complete_power_step(step: %d)\n", | ||
| 129 | drive->name, pm->pm_step); | ||
| 130 | #endif | ||
| 131 | if (drive->media != ide_disk) | ||
| 132 | return; | ||
| 133 | |||
| 134 | switch (pm->pm_step) { | ||
| 135 | case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ | ||
| 136 | if (pm->pm_state == PM_EVENT_FREEZE) | ||
| 137 | pm->pm_step = IDE_PM_COMPLETED; | ||
| 138 | else | ||
| 139 | pm->pm_step = IDE_PM_STANDBY; | ||
| 140 | break; | ||
| 141 | case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ | ||
| 142 | pm->pm_step = IDE_PM_COMPLETED; | ||
| 143 | break; | ||
| 144 | case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ | ||
| 145 | pm->pm_step = IDE_PM_IDLE; | ||
| 146 | break; | ||
| 147 | case IDE_PM_IDLE: /* Resume step 2 (idle)*/ | ||
| 148 | pm->pm_step = IDE_PM_RESTORE_DMA; | ||
| 149 | break; | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) | ||
| 154 | { | ||
| 155 | struct request_pm_state *pm = rq->data; | ||
| 156 | ide_task_t *args = rq->special; | ||
| 157 | |||
| 158 | memset(args, 0, sizeof(*args)); | ||
| 159 | |||
| 160 | switch (pm->pm_step) { | ||
| 161 | case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ | ||
| 162 | if (drive->media != ide_disk) | ||
| 163 | break; | ||
| 164 | /* Not supported? Switch to next step now. */ | ||
| 165 | if (ata_id_flush_enabled(drive->id) == 0 || | ||
| 166 | (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) { | ||
| 167 | ide_complete_power_step(drive, rq); | ||
| 168 | return ide_stopped; | ||
| 169 | } | ||
| 170 | if (ata_id_flush_ext_enabled(drive->id)) | ||
| 171 | args->tf.command = ATA_CMD_FLUSH_EXT; | ||
| 172 | else | ||
| 173 | args->tf.command = ATA_CMD_FLUSH; | ||
| 174 | goto out_do_tf; | ||
| 175 | case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ | ||
| 176 | args->tf.command = ATA_CMD_STANDBYNOW1; | ||
| 177 | goto out_do_tf; | ||
| 178 | case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ | ||
| 179 | ide_set_max_pio(drive); | ||
| 180 | /* | ||
| 181 | * skip IDE_PM_IDLE for ATAPI devices | ||
| 182 | */ | ||
| 183 | if (drive->media != ide_disk) | ||
| 184 | pm->pm_step = IDE_PM_RESTORE_DMA; | ||
| 185 | else | ||
| 186 | ide_complete_power_step(drive, rq); | ||
| 187 | return ide_stopped; | ||
| 188 | case IDE_PM_IDLE: /* Resume step 2 (idle) */ | ||
| 189 | args->tf.command = ATA_CMD_IDLEIMMEDIATE; | ||
| 190 | goto out_do_tf; | ||
| 191 | case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */ | ||
| 192 | /* | ||
| 193 | * Right now, all we do is call ide_set_dma(drive), | ||
| 194 | * we could be smarter and check for current xfer_speed | ||
| 195 | * in struct drive etc... | ||
| 196 | */ | ||
| 197 | if (drive->hwif->dma_ops == NULL) | ||
| 198 | break; | ||
| 199 | /* | ||
| 200 | * TODO: respect IDE_DFLAG_USING_DMA | ||
| 201 | */ | ||
| 202 | ide_set_dma(drive); | ||
| 203 | break; | ||
| 204 | } | ||
| 205 | |||
| 206 | pm->pm_step = IDE_PM_COMPLETED; | ||
| 207 | return ide_stopped; | ||
| 208 | |||
| 209 | out_do_tf: | ||
| 210 | args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | ||
| 211 | args->data_phase = TASKFILE_NO_DATA; | ||
| 212 | return do_rw_taskfile(drive, args); | ||
| 213 | } | ||
| 214 | |||
| 215 | /** | 123 | /** |
| 216 | * ide_end_dequeued_request - complete an IDE I/O | 124 | * ide_end_dequeued_request - complete an IDE I/O |
| 217 | * @drive: IDE device for the I/O | 125 | * @drive: IDE device for the I/O |
| @@ -236,39 +144,6 @@ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, | |||
| 236 | } | 144 | } |
| 237 | EXPORT_SYMBOL_GPL(ide_end_dequeued_request); | 145 | EXPORT_SYMBOL_GPL(ide_end_dequeued_request); |
| 238 | 146 | ||
| 239 | |||
| 240 | /** | ||
| 241 | * ide_complete_pm_request - end the current Power Management request | ||
| 242 | * @drive: target drive | ||
| 243 | * @rq: request | ||
| 244 | * | ||
| 245 | * This function cleans up the current PM request and stops the queue | ||
| 246 | * if necessary. | ||
| 247 | */ | ||
| 248 | static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) | ||
| 249 | { | ||
| 250 | struct request_queue *q = drive->queue; | ||
| 251 | unsigned long flags; | ||
| 252 | |||
| 253 | #ifdef DEBUG_PM | ||
| 254 | printk("%s: completing PM request, %s\n", drive->name, | ||
| 255 | blk_pm_suspend_request(rq) ? "suspend" : "resume"); | ||
| 256 | #endif | ||
| 257 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 258 | if (blk_pm_suspend_request(rq)) { | ||
| 259 | blk_stop_queue(q); | ||
| 260 | } else { | ||
| 261 | drive->dev_flags &= ~IDE_DFLAG_BLOCKED; | ||
| 262 | blk_start_queue(q); | ||
| 263 | } | ||
| 264 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 265 | |||
| 266 | drive->hwif->hwgroup->rq = NULL; | ||
| 267 | |||
| 268 | if (blk_end_request(rq, 0, 0)) | ||
| 269 | BUG(); | ||
| 270 | } | ||
| 271 | |||
| 272 | /** | 147 | /** |
| 273 | * ide_end_drive_cmd - end an explicit drive command | 148 | * ide_end_drive_cmd - end an explicit drive command |
| 274 | * @drive: command | 149 | * @drive: command |
| @@ -697,40 +572,6 @@ static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) | |||
| 697 | } | 572 | } |
| 698 | } | 573 | } |
| 699 | 574 | ||
| 700 | static void ide_check_pm_state(ide_drive_t *drive, struct request *rq) | ||
| 701 | { | ||
| 702 | struct request_pm_state *pm = rq->data; | ||
| 703 | |||
| 704 | if (blk_pm_suspend_request(rq) && | ||
| 705 | pm->pm_step == IDE_PM_START_SUSPEND) | ||
| 706 | /* Mark drive blocked when starting the suspend sequence. */ | ||
| 707 | drive->dev_flags |= IDE_DFLAG_BLOCKED; | ||
| 708 | else if (blk_pm_resume_request(rq) && | ||
| 709 | pm->pm_step == IDE_PM_START_RESUME) { | ||
| 710 | /* | ||
| 711 | * The first thing we do on wakeup is to wait for BSY bit to | ||
| 712 | * go away (with a looong timeout) as a drive on this hwif may | ||
| 713 | * just be POSTing itself. | ||
| 714 | * We do that before even selecting as the "other" device on | ||
| 715 | * the bus may be broken enough to walk on our toes at this | ||
| 716 | * point. | ||
| 717 | */ | ||
| 718 | ide_hwif_t *hwif = drive->hwif; | ||
| 719 | int rc; | ||
| 720 | #ifdef DEBUG_PM | ||
| 721 | printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); | ||
| 722 | #endif | ||
| 723 | rc = ide_wait_not_busy(hwif, 35000); | ||
| 724 | if (rc) | ||
| 725 | printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); | ||
| 726 | SELECT_DRIVE(drive); | ||
| 727 | hwif->tp_ops->set_irq(hwif, 1); | ||
| 728 | rc = ide_wait_not_busy(hwif, 100000); | ||
| 729 | if (rc) | ||
| 730 | printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); | ||
| 731 | } | ||
| 732 | } | ||
| 733 | |||
| 734 | /** | 575 | /** |
| 735 | * start_request - start of I/O and command issuing for IDE | 576 | * start_request - start of I/O and command issuing for IDE |
| 736 | * | 577 | * |
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c new file mode 100644 index 000000000000..8282c6086e6a --- /dev/null +++ b/drivers/ide/ide-pm.c | |||
| @@ -0,0 +1,235 @@ | |||
| 1 | #include <linux/kernel.h> | ||
| 2 | #include <linux/ide.h> | ||
| 3 | #include <linux/hdreg.h> | ||
| 4 | |||
| 5 | int generic_ide_suspend(struct device *dev, pm_message_t mesg) | ||
| 6 | { | ||
| 7 | ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); | ||
| 8 | ide_hwif_t *hwif = HWIF(drive); | ||
| 9 | struct request *rq; | ||
| 10 | struct request_pm_state rqpm; | ||
| 11 | ide_task_t args; | ||
| 12 | int ret; | ||
| 13 | |||
| 14 | /* call ACPI _GTM only once */ | ||
| 15 | if ((drive->dn & 1) == 0 || pair == NULL) | ||
| 16 | ide_acpi_get_timing(hwif); | ||
| 17 | |||
| 18 | memset(&rqpm, 0, sizeof(rqpm)); | ||
| 19 | memset(&args, 0, sizeof(args)); | ||
| 20 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | ||
| 21 | rq->cmd_type = REQ_TYPE_PM_SUSPEND; | ||
| 22 | rq->special = &args; | ||
| 23 | rq->data = &rqpm; | ||
| 24 | rqpm.pm_step = IDE_PM_START_SUSPEND; | ||
| 25 | if (mesg.event == PM_EVENT_PRETHAW) | ||
| 26 | mesg.event = PM_EVENT_FREEZE; | ||
| 27 | rqpm.pm_state = mesg.event; | ||
| 28 | |||
| 29 | ret = blk_execute_rq(drive->queue, NULL, rq, 0); | ||
| 30 | blk_put_request(rq); | ||
| 31 | |||
| 32 | /* call ACPI _PS3 only after both devices are suspended */ | ||
| 33 | if (ret == 0 && ((drive->dn & 1) || pair == NULL)) | ||
| 34 | ide_acpi_set_state(hwif, 0); | ||
| 35 | |||
| 36 | return ret; | ||
| 37 | } | ||
| 38 | |||
| 39 | int generic_ide_resume(struct device *dev) | ||
| 40 | { | ||
| 41 | ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); | ||
| 42 | ide_hwif_t *hwif = HWIF(drive); | ||
| 43 | struct request *rq; | ||
| 44 | struct request_pm_state rqpm; | ||
| 45 | ide_task_t args; | ||
| 46 | int err; | ||
| 47 | |||
| 48 | /* call ACPI _PS0 / _STM only once */ | ||
| 49 | if ((drive->dn & 1) == 0 || pair == NULL) { | ||
| 50 | ide_acpi_set_state(hwif, 1); | ||
| 51 | ide_acpi_push_timing(hwif); | ||
| 52 | } | ||
| 53 | |||
| 54 | ide_acpi_exec_tfs(drive); | ||
| 55 | |||
| 56 | memset(&rqpm, 0, sizeof(rqpm)); | ||
| 57 | memset(&args, 0, sizeof(args)); | ||
| 58 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | ||
| 59 | rq->cmd_type = REQ_TYPE_PM_RESUME; | ||
| 60 | rq->cmd_flags |= REQ_PREEMPT; | ||
| 61 | rq->special = &args; | ||
| 62 | rq->data = &rqpm; | ||
| 63 | rqpm.pm_step = IDE_PM_START_RESUME; | ||
| 64 | rqpm.pm_state = PM_EVENT_ON; | ||
| 65 | |||
| 66 | err = blk_execute_rq(drive->queue, NULL, rq, 1); | ||
| 67 | blk_put_request(rq); | ||
| 68 | |||
| 69 | if (err == 0 && dev->driver) { | ||
| 70 | ide_driver_t *drv = to_ide_driver(dev->driver); | ||
| 71 | |||
| 72 | if (drv->resume) | ||
| 73 | drv->resume(drive); | ||
| 74 | } | ||
| 75 | |||
| 76 | return err; | ||
| 77 | } | ||
| 78 | |||
| 79 | void ide_complete_power_step(ide_drive_t *drive, struct request *rq) | ||
| 80 | { | ||
| 81 | struct request_pm_state *pm = rq->data; | ||
| 82 | |||
| 83 | #ifdef DEBUG_PM | ||
| 84 | printk(KERN_INFO "%s: complete_power_step(step: %d)\n", | ||
| 85 | drive->name, pm->pm_step); | ||
| 86 | #endif | ||
| 87 | if (drive->media != ide_disk) | ||
| 88 | return; | ||
| 89 | |||
| 90 | switch (pm->pm_step) { | ||
| 91 | case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ | ||
| 92 | if (pm->pm_state == PM_EVENT_FREEZE) | ||
| 93 | pm->pm_step = IDE_PM_COMPLETED; | ||
| 94 | else | ||
| 95 | pm->pm_step = IDE_PM_STANDBY; | ||
| 96 | break; | ||
| 97 | case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ | ||
| 98 | pm->pm_step = IDE_PM_COMPLETED; | ||
| 99 | break; | ||
| 100 | case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ | ||
| 101 | pm->pm_step = IDE_PM_IDLE; | ||
| 102 | break; | ||
| 103 | case IDE_PM_IDLE: /* Resume step 2 (idle)*/ | ||
| 104 | pm->pm_step = IDE_PM_RESTORE_DMA; | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) | ||
| 110 | { | ||
| 111 | struct request_pm_state *pm = rq->data; | ||
| 112 | ide_task_t *args = rq->special; | ||
| 113 | |||
| 114 | memset(args, 0, sizeof(*args)); | ||
| 115 | |||
| 116 | switch (pm->pm_step) { | ||
| 117 | case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ | ||
| 118 | if (drive->media != ide_disk) | ||
| 119 | break; | ||
| 120 | /* Not supported? Switch to next step now. */ | ||
| 121 | if (ata_id_flush_enabled(drive->id) == 0 || | ||
| 122 | (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) { | ||
| 123 | ide_complete_power_step(drive, rq); | ||
| 124 | return ide_stopped; | ||
| 125 | } | ||
| 126 | if (ata_id_flush_ext_enabled(drive->id)) | ||
| 127 | args->tf.command = ATA_CMD_FLUSH_EXT; | ||
| 128 | else | ||
| 129 | args->tf.command = ATA_CMD_FLUSH; | ||
| 130 | goto out_do_tf; | ||
| 131 | case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ | ||
| 132 | args->tf.command = ATA_CMD_STANDBYNOW1; | ||
| 133 | goto out_do_tf; | ||
| 134 | case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ | ||
| 135 | ide_set_max_pio(drive); | ||
| 136 | /* | ||
| 137 | * skip IDE_PM_IDLE for ATAPI devices | ||
| 138 | */ | ||
| 139 | if (drive->media != ide_disk) | ||
| 140 | pm->pm_step = IDE_PM_RESTORE_DMA; | ||
| 141 | else | ||
| 142 | ide_complete_power_step(drive, rq); | ||
| 143 | return ide_stopped; | ||
| 144 | case IDE_PM_IDLE: /* Resume step 2 (idle) */ | ||
| 145 | args->tf.command = ATA_CMD_IDLEIMMEDIATE; | ||
| 146 | goto out_do_tf; | ||
| 147 | case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */ | ||
| 148 | /* | ||
| 149 | * Right now, all we do is call ide_set_dma(drive), | ||
| 150 | * we could be smarter and check for current xfer_speed | ||
| 151 | * in struct drive etc... | ||
| 152 | */ | ||
| 153 | if (drive->hwif->dma_ops == NULL) | ||
| 154 | break; | ||
| 155 | /* | ||
| 156 | * TODO: respect IDE_DFLAG_USING_DMA | ||
| 157 | */ | ||
| 158 | ide_set_dma(drive); | ||
| 159 | break; | ||
| 160 | } | ||
| 161 | |||
| 162 | pm->pm_step = IDE_PM_COMPLETED; | ||
| 163 | return ide_stopped; | ||
| 164 | |||
| 165 | out_do_tf: | ||
| 166 | args->tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; | ||
| 167 | args->data_phase = TASKFILE_NO_DATA; | ||
| 168 | return do_rw_taskfile(drive, args); | ||
| 169 | } | ||
| 170 | |||
| 171 | /** | ||
| 172 | * ide_complete_pm_request - end the current Power Management request | ||
| 173 | * @drive: target drive | ||
| 174 | * @rq: request | ||
| 175 | * | ||
| 176 | * This function cleans up the current PM request and stops the queue | ||
| 177 | * if necessary. | ||
| 178 | */ | ||
| 179 | void ide_complete_pm_request(ide_drive_t *drive, struct request *rq) | ||
| 180 | { | ||
| 181 | struct request_queue *q = drive->queue; | ||
| 182 | unsigned long flags; | ||
| 183 | |||
| 184 | #ifdef DEBUG_PM | ||
| 185 | printk("%s: completing PM request, %s\n", drive->name, | ||
| 186 | blk_pm_suspend_request(rq) ? "suspend" : "resume"); | ||
| 187 | #endif | ||
| 188 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 189 | if (blk_pm_suspend_request(rq)) { | ||
| 190 | blk_stop_queue(q); | ||
| 191 | } else { | ||
| 192 | drive->dev_flags &= ~IDE_DFLAG_BLOCKED; | ||
| 193 | blk_start_queue(q); | ||
| 194 | } | ||
| 195 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 196 | |||
| 197 | drive->hwif->hwgroup->rq = NULL; | ||
| 198 | |||
| 199 | if (blk_end_request(rq, 0, 0)) | ||
| 200 | BUG(); | ||
| 201 | } | ||
| 202 | |||
| 203 | void ide_check_pm_state(ide_drive_t *drive, struct request *rq) | ||
| 204 | { | ||
| 205 | struct request_pm_state *pm = rq->data; | ||
| 206 | |||
| 207 | if (blk_pm_suspend_request(rq) && | ||
| 208 | pm->pm_step == IDE_PM_START_SUSPEND) | ||
| 209 | /* Mark drive blocked when starting the suspend sequence. */ | ||
| 210 | drive->dev_flags |= IDE_DFLAG_BLOCKED; | ||
| 211 | else if (blk_pm_resume_request(rq) && | ||
| 212 | pm->pm_step == IDE_PM_START_RESUME) { | ||
| 213 | /* | ||
| 214 | * The first thing we do on wakeup is to wait for BSY bit to | ||
| 215 | * go away (with a looong timeout) as a drive on this hwif may | ||
| 216 | * just be POSTing itself. | ||
| 217 | * We do that before even selecting as the "other" device on | ||
| 218 | * the bus may be broken enough to walk on our toes at this | ||
| 219 | * point. | ||
| 220 | */ | ||
| 221 | ide_hwif_t *hwif = drive->hwif; | ||
| 222 | int rc; | ||
| 223 | #ifdef DEBUG_PM | ||
| 224 | printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); | ||
| 225 | #endif | ||
| 226 | rc = ide_wait_not_busy(hwif, 35000); | ||
| 227 | if (rc) | ||
| 228 | printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); | ||
| 229 | SELECT_DRIVE(drive); | ||
| 230 | hwif->tp_ops->set_irq(hwif, 1); | ||
| 231 | rc = ide_wait_not_busy(hwif, 100000); | ||
| 232 | if (rc) | ||
| 233 | printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); | ||
| 234 | } | ||
| 235 | } | ||
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 41d042053548..f0f09f702e9c 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
| @@ -388,80 +388,6 @@ ide_ext_devset_rw_sync(unmaskirq, unmaskirq); | |||
| 388 | ide_ext_devset_rw_sync(using_dma, using_dma); | 388 | ide_ext_devset_rw_sync(using_dma, using_dma); |
| 389 | __IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); | 389 | __IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); |
| 390 | 390 | ||
| 391 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) | ||
| 392 | { | ||
| 393 | ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); | ||
| 394 | ide_hwif_t *hwif = HWIF(drive); | ||
| 395 | struct request *rq; | ||
| 396 | struct request_pm_state rqpm; | ||
| 397 | ide_task_t args; | ||
| 398 | int ret; | ||
| 399 | |||
| 400 | /* call ACPI _GTM only once */ | ||
| 401 | if ((drive->dn & 1) == 0 || pair == NULL) | ||
| 402 | ide_acpi_get_timing(hwif); | ||
| 403 | |||
| 404 | memset(&rqpm, 0, sizeof(rqpm)); | ||
| 405 | memset(&args, 0, sizeof(args)); | ||
| 406 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | ||
| 407 | rq->cmd_type = REQ_TYPE_PM_SUSPEND; | ||
| 408 | rq->special = &args; | ||
| 409 | rq->data = &rqpm; | ||
| 410 | rqpm.pm_step = IDE_PM_START_SUSPEND; | ||
| 411 | if (mesg.event == PM_EVENT_PRETHAW) | ||
| 412 | mesg.event = PM_EVENT_FREEZE; | ||
| 413 | rqpm.pm_state = mesg.event; | ||
| 414 | |||
| 415 | ret = blk_execute_rq(drive->queue, NULL, rq, 0); | ||
| 416 | blk_put_request(rq); | ||
| 417 | |||
| 418 | /* call ACPI _PS3 only after both devices are suspended */ | ||
| 419 | if (ret == 0 && ((drive->dn & 1) || pair == NULL)) | ||
| 420 | ide_acpi_set_state(hwif, 0); | ||
| 421 | |||
| 422 | return ret; | ||
| 423 | } | ||
| 424 | |||
| 425 | static int generic_ide_resume(struct device *dev) | ||
| 426 | { | ||
| 427 | ide_drive_t *drive = dev->driver_data, *pair = ide_get_pair_dev(drive); | ||
| 428 | ide_hwif_t *hwif = HWIF(drive); | ||
| 429 | struct request *rq; | ||
| 430 | struct request_pm_state rqpm; | ||
| 431 | ide_task_t args; | ||
| 432 | int err; | ||
| 433 | |||
| 434 | /* call ACPI _PS0 / _STM only once */ | ||
| 435 | if ((drive->dn & 1) == 0 || pair == NULL) { | ||
| 436 | ide_acpi_set_state(hwif, 1); | ||
| 437 | ide_acpi_push_timing(hwif); | ||
| 438 | } | ||
| 439 | |||
| 440 | ide_acpi_exec_tfs(drive); | ||
| 441 | |||
| 442 | memset(&rqpm, 0, sizeof(rqpm)); | ||
| 443 | memset(&args, 0, sizeof(args)); | ||
| 444 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | ||
| 445 | rq->cmd_type = REQ_TYPE_PM_RESUME; | ||
| 446 | rq->cmd_flags |= REQ_PREEMPT; | ||
| 447 | rq->special = &args; | ||
| 448 | rq->data = &rqpm; | ||
| 449 | rqpm.pm_step = IDE_PM_START_RESUME; | ||
| 450 | rqpm.pm_state = PM_EVENT_ON; | ||
| 451 | |||
| 452 | err = blk_execute_rq(drive->queue, NULL, rq, 1); | ||
| 453 | blk_put_request(rq); | ||
| 454 | |||
| 455 | if (err == 0 && dev->driver) { | ||
| 456 | ide_driver_t *drv = to_ide_driver(dev->driver); | ||
| 457 | |||
| 458 | if (drv->resume) | ||
| 459 | drv->resume(drive); | ||
| 460 | } | ||
| 461 | |||
| 462 | return err; | ||
| 463 | } | ||
| 464 | |||
| 465 | /** | 391 | /** |
| 466 | * ide_device_get - get an additional reference to a ide_drive_t | 392 | * ide_device_get - get an additional reference to a ide_drive_t |
| 467 | * @drive: device to get a reference to | 393 | * @drive: device to get a reference to |
diff --git a/include/linux/ide.h b/include/linux/ide.h index 9b89cab6d493..e99c56de7f56 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
| @@ -1116,6 +1116,14 @@ enum { | |||
| 1116 | IDE_PM_COMPLETED, | 1116 | IDE_PM_COMPLETED, |
| 1117 | }; | 1117 | }; |
| 1118 | 1118 | ||
| 1119 | int generic_ide_suspend(struct device *, pm_message_t); | ||
| 1120 | int generic_ide_resume(struct device *); | ||
| 1121 | |||
| 1122 | void ide_complete_power_step(ide_drive_t *, struct request *); | ||
| 1123 | ide_startstop_t ide_start_power_step(ide_drive_t *, struct request *); | ||
| 1124 | void ide_complete_pm_request(ide_drive_t *, struct request *); | ||
| 1125 | void ide_check_pm_state(ide_drive_t *, struct request *); | ||
| 1126 | |||
| 1119 | /* | 1127 | /* |
| 1120 | * Subdrivers support. | 1128 | * Subdrivers support. |
| 1121 | * | 1129 | * |
