diff options
author | Jason Lunz <lunz@falooley.org> | 2006-10-03 04:14:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-03 11:04:08 -0400 |
commit | 8c2c0118b86183bf4826db990cae5c8a8d6c6746 (patch) | |
tree | 71f7e806eccec4ef2d41fc6490395cc01bcb8123 /drivers/ide | |
parent | 3f63c5e88a5ce45b423f3712293f1664115b09c0 (diff) |
[PATCH] ide: reprogram disk pio timings on resume
Add a step to the IDE PM state machine that reprograms disk PIO timings
as the first step on resume. This prevents ide deadlock on
resume-from-ram on my nforce3-based laptop.
An earlier implementation was written entirely within the amd74xx ide
driver, but Alan helpfully pointed out that this is the correct thing to
do globally. Still, I'm only calling hwif->tuneproc() for disks, based
on two things:
- The existing state machine is already passed over for non-disk drives
- Previous testing on my laptop shows that the hangs are related only
to the disk - suspend/resume from a livecd showed that there's no
need for this on the cdrom.
Signed-off-by: Jason Lunz <lunz@falooley.org>
Cc: Bartlomiej Zolnierkiewicz <B.Zolnierkiewicz@elka.pw.edu.pl>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Brad Campbell <brad@wasp.net.au>
Cc: David Brownell <david-b@pacbell.net>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/ide-io.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 8d26619ba16b..ba6039b55b41 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -134,7 +134,8 @@ enum { | |||
134 | ide_pm_flush_cache = ide_pm_state_start_suspend, | 134 | ide_pm_flush_cache = ide_pm_state_start_suspend, |
135 | idedisk_pm_standby, | 135 | idedisk_pm_standby, |
136 | 136 | ||
137 | idedisk_pm_idle = ide_pm_state_start_resume, | 137 | idedisk_pm_restore_pio = ide_pm_state_start_resume, |
138 | idedisk_pm_idle, | ||
138 | ide_pm_restore_dma, | 139 | ide_pm_restore_dma, |
139 | }; | 140 | }; |
140 | 141 | ||
@@ -155,7 +156,10 @@ static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 s | |||
155 | case idedisk_pm_standby: /* Suspend step 2 (standby) complete */ | 156 | case idedisk_pm_standby: /* Suspend step 2 (standby) complete */ |
156 | pm->pm_step = ide_pm_state_completed; | 157 | pm->pm_step = ide_pm_state_completed; |
157 | break; | 158 | break; |
158 | case idedisk_pm_idle: /* Resume step 1 (idle) complete */ | 159 | case idedisk_pm_restore_pio: /* Resume step 1 complete */ |
160 | pm->pm_step = idedisk_pm_idle; | ||
161 | break; | ||
162 | case idedisk_pm_idle: /* Resume step 2 (idle) complete */ | ||
159 | pm->pm_step = ide_pm_restore_dma; | 163 | pm->pm_step = ide_pm_restore_dma; |
160 | break; | 164 | break; |
161 | } | 165 | } |
@@ -169,8 +173,11 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * | |||
169 | memset(args, 0, sizeof(*args)); | 173 | memset(args, 0, sizeof(*args)); |
170 | 174 | ||
171 | if (drive->media != ide_disk) { | 175 | if (drive->media != ide_disk) { |
172 | /* skip idedisk_pm_idle for ATAPI devices */ | 176 | /* |
173 | if (pm->pm_step == idedisk_pm_idle) | 177 | * skip idedisk_pm_restore_pio and idedisk_pm_idle for ATAPI |
178 | * devices | ||
179 | */ | ||
180 | if (pm->pm_step == idedisk_pm_restore_pio) | ||
174 | pm->pm_step = ide_pm_restore_dma; | 181 | pm->pm_step = ide_pm_restore_dma; |
175 | } | 182 | } |
176 | 183 | ||
@@ -197,13 +204,19 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * | |||
197 | args->handler = &task_no_data_intr; | 204 | args->handler = &task_no_data_intr; |
198 | return do_rw_taskfile(drive, args); | 205 | return do_rw_taskfile(drive, args); |
199 | 206 | ||
200 | case idedisk_pm_idle: /* Resume step 1 (idle) */ | 207 | case idedisk_pm_restore_pio: /* Resume step 1 (restore PIO) */ |
208 | if (drive->hwif->tuneproc != NULL) | ||
209 | drive->hwif->tuneproc(drive, 255); | ||
210 | ide_complete_power_step(drive, rq, 0, 0); | ||
211 | return ide_stopped; | ||
212 | |||
213 | case idedisk_pm_idle: /* Resume step 2 (idle) */ | ||
201 | args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE; | 214 | args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE; |
202 | args->command_type = IDE_DRIVE_TASK_NO_DATA; | 215 | args->command_type = IDE_DRIVE_TASK_NO_DATA; |
203 | args->handler = task_no_data_intr; | 216 | args->handler = task_no_data_intr; |
204 | return do_rw_taskfile(drive, args); | 217 | return do_rw_taskfile(drive, args); |
205 | 218 | ||
206 | case ide_pm_restore_dma: /* Resume step 2 (restore DMA) */ | 219 | case ide_pm_restore_dma: /* Resume step 3 (restore DMA) */ |
207 | /* | 220 | /* |
208 | * Right now, all we do is call hwif->ide_dma_check(drive), | 221 | * Right now, all we do is call hwif->ide_dma_check(drive), |
209 | * we could be smarter and check for current xfer_speed | 222 | * we could be smarter and check for current xfer_speed |