diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-03-24 18:22:47 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-03-24 18:22:47 -0400 |
commit | 327fa1c29466b8fe471a91fc11e9c6171163c81a (patch) | |
tree | 9dbbf65c886d5ec68299d563da0cd7df8b97c324 /drivers/ide/ide-io.c | |
parent | 122f06f8bce406169d61242a3eb667027e27cca7 (diff) |
ide: move error handling code to ide-eh.c (v2)
Do some CodingStyle fixups in <linux/ide.h> while at it.
v2:
Add missing <linux/delay.h> include (reported by Stephen Rothwell).
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-io.c')
-rw-r--r-- | drivers/ide/ide-io.c | 129 |
1 files changed, 1 insertions, 128 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 74d1a3e68252..2e92497b58aa 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -196,7 +196,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) | |||
196 | } | 196 | } |
197 | EXPORT_SYMBOL(ide_end_drive_cmd); | 197 | EXPORT_SYMBOL(ide_end_drive_cmd); |
198 | 198 | ||
199 | static void ide_kill_rq(ide_drive_t *drive, struct request *rq) | 199 | void ide_kill_rq(ide_drive_t *drive, struct request *rq) |
200 | { | 200 | { |
201 | if (rq->rq_disk) { | 201 | if (rq->rq_disk) { |
202 | struct ide_driver *drv; | 202 | struct ide_driver *drv; |
@@ -207,133 +207,6 @@ static void ide_kill_rq(ide_drive_t *drive, struct request *rq) | |||
207 | ide_end_request(drive, 0, 0); | 207 | ide_end_request(drive, 0, 0); |
208 | } | 208 | } |
209 | 209 | ||
210 | static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) | ||
211 | { | ||
212 | ide_hwif_t *hwif = drive->hwif; | ||
213 | |||
214 | if ((stat & ATA_BUSY) || | ||
215 | ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { | ||
216 | /* other bits are useless when BUSY */ | ||
217 | rq->errors |= ERROR_RESET; | ||
218 | } else if (stat & ATA_ERR) { | ||
219 | /* err has different meaning on cdrom and tape */ | ||
220 | if (err == ATA_ABORTED) { | ||
221 | if ((drive->dev_flags & IDE_DFLAG_LBA) && | ||
222 | /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */ | ||
223 | hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS) | ||
224 | return ide_stopped; | ||
225 | } else if ((err & BAD_CRC) == BAD_CRC) { | ||
226 | /* UDMA crc error, just retry the operation */ | ||
227 | drive->crc_count++; | ||
228 | } else if (err & (ATA_BBK | ATA_UNC)) { | ||
229 | /* retries won't help these */ | ||
230 | rq->errors = ERROR_MAX; | ||
231 | } else if (err & ATA_TRK0NF) { | ||
232 | /* help it find track zero */ | ||
233 | rq->errors |= ERROR_RECAL; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ && | ||
238 | (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) { | ||
239 | int nsect = drive->mult_count ? drive->mult_count : 1; | ||
240 | |||
241 | ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE); | ||
242 | } | ||
243 | |||
244 | if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) { | ||
245 | ide_kill_rq(drive, rq); | ||
246 | return ide_stopped; | ||
247 | } | ||
248 | |||
249 | if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) | ||
250 | rq->errors |= ERROR_RESET; | ||
251 | |||
252 | if ((rq->errors & ERROR_RESET) == ERROR_RESET) { | ||
253 | ++rq->errors; | ||
254 | return ide_do_reset(drive); | ||
255 | } | ||
256 | |||
257 | if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) | ||
258 | drive->special.b.recalibrate = 1; | ||
259 | |||
260 | ++rq->errors; | ||
261 | |||
262 | return ide_stopped; | ||
263 | } | ||
264 | |||
265 | static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) | ||
266 | { | ||
267 | ide_hwif_t *hwif = drive->hwif; | ||
268 | |||
269 | if ((stat & ATA_BUSY) || | ||
270 | ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { | ||
271 | /* other bits are useless when BUSY */ | ||
272 | rq->errors |= ERROR_RESET; | ||
273 | } else { | ||
274 | /* add decoding error stuff */ | ||
275 | } | ||
276 | |||
277 | if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) | ||
278 | /* force an abort */ | ||
279 | hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); | ||
280 | |||
281 | if (rq->errors >= ERROR_MAX) { | ||
282 | ide_kill_rq(drive, rq); | ||
283 | } else { | ||
284 | if ((rq->errors & ERROR_RESET) == ERROR_RESET) { | ||
285 | ++rq->errors; | ||
286 | return ide_do_reset(drive); | ||
287 | } | ||
288 | ++rq->errors; | ||
289 | } | ||
290 | |||
291 | return ide_stopped; | ||
292 | } | ||
293 | |||
294 | static ide_startstop_t | ||
295 | __ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) | ||
296 | { | ||
297 | if (drive->media == ide_disk) | ||
298 | return ide_ata_error(drive, rq, stat, err); | ||
299 | return ide_atapi_error(drive, rq, stat, err); | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * ide_error - handle an error on the IDE | ||
304 | * @drive: drive the error occurred on | ||
305 | * @msg: message to report | ||
306 | * @stat: status bits | ||
307 | * | ||
308 | * ide_error() takes action based on the error returned by the drive. | ||
309 | * For normal I/O that may well include retries. We deal with | ||
310 | * both new-style (taskfile) and old style command handling here. | ||
311 | * In the case of taskfile command handling there is work left to | ||
312 | * do | ||
313 | */ | ||
314 | |||
315 | ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) | ||
316 | { | ||
317 | struct request *rq; | ||
318 | u8 err; | ||
319 | |||
320 | err = ide_dump_status(drive, msg, stat); | ||
321 | |||
322 | rq = drive->hwif->rq; | ||
323 | if (rq == NULL) | ||
324 | return ide_stopped; | ||
325 | |||
326 | /* retry only "normal" I/O: */ | ||
327 | if (!blk_fs_request(rq)) { | ||
328 | rq->errors = 1; | ||
329 | ide_end_drive_cmd(drive, stat, err); | ||
330 | return ide_stopped; | ||
331 | } | ||
332 | |||
333 | return __ide_error(drive, rq, stat, err); | ||
334 | } | ||
335 | EXPORT_SYMBOL_GPL(ide_error); | ||
336 | |||
337 | static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) | 210 | static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) |
338 | { | 211 | { |
339 | tf->nsect = drive->sect; | 212 | tf->nsect = drive->sect; |