diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2006-06-25 05:47:44 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 10:01:06 -0700 |
commit | dbe217af3be08346f4b1abb885c2d9ec29c98fac (patch) | |
tree | 493ee2547ba3095d7aa468d6ddffc1a82f18ce56 /drivers/ide/ide-io.c | |
parent | 8e3a67a99231f9f3f476bc3449e93c9a6a17f2e0 (diff) | |
download | talos-obmc-linux-dbe217af3be08346f4b1abb885c2d9ec29c98fac.tar.gz talos-obmc-linux-dbe217af3be08346f4b1abb885c2d9ec29c98fac.zip |
[PATCH] IDE CD end-of media error fix
This is a patch from Alan that fixes a real ide-cd.c regression causing
bogus "Media Check" failures for perfectly valid Fedora install ISOs, on
certain CD-ROM drives.
This is a forward port to 2.6.16 (from RHEL) of the minimal changes for the
end of media problem. It may not be sufficient for some controllers
(promise notably) and it does not touch the locking so the error path
locking is as horked as in mainstream.
From: Ingo Molnar <mingo@elte.hu>
I have ported the patch to 2.6.17-rc4 and tested it by provoking
end-of-media IO errors with an unaligned ISO image. Unlike the vanilla
kernel, the patched kernel interpreted the error condition correctly with
512 byte granularity:
hdc: command error: status=0x51 { DriveReady SeekComplete Error }
hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 }
ide: failed opcode was: unknown
ATAPI device hdc:
Error: Illegal request -- (Sense key=0x05)
Illegal mode for this track or incompatible medium -- (asc=0x64, ascq=0x00)
The failed "Read 10" packet command was:
"28 00 00 04 fb 78 00 00 06 00 00 00 00 00 00 00 "
end_request: I/O error, dev hdc, sector 1306080
Buffer I/O error on device hdc, logical block 163260
Buffer I/O error on device hdc, logical block 163261
Buffer I/O error on device hdc, logical block 163262
the unpatched kernel produces an incorrect error dump:
hdc: command error: status=0x51 { DriveReady SeekComplete Error }
hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 }
ide: failed opcode was: unknown
end_request: I/O error, dev hdc, sector 1306080
Buffer I/O error on device hdc, logical block 163260
hdc: command error: status=0x51 { DriveReady SeekComplete Error }
hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 }
ide: failed opcode was: unknown
end_request: I/O error, dev hdc, sector 1306088
Buffer I/O error on device hdc, logical block 163261
hdc: command error: status=0x51 { DriveReady SeekComplete Error }
hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 }
ide: failed opcode was: unknown
end_request: I/O error, dev hdc, sector 1306096
Buffer I/O error on device hdc, logical block 163262
I do not have the right type of CD-ROM drive to reproduce the end-of-media
data corruption bug myself, but this same patch in RHEL solved it.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Bartlomiej Zolnierkiewicz <B.Zolnierkiewicz@elka.pw.edu.pl>
Cc: Jens Axboe <axboe@suse.de>
Cc: Matt Mackall <mpm@selenic.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/ide/ide-io.c')
-rw-r--r-- | drivers/ide/ide-io.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 4f2f138de2ca..622a55c72f03 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -223,6 +223,63 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * } /** + * ide_end_dequeued_request - complete an IDE I/O + * @drive: IDE device for the I/O + * @uptodate: + * @nr_sectors: number of sectors completed + * + * Complete an I/O that is no longer on the request queue. This + * typically occurs when we pull the request and issue a REQUEST_SENSE. + * We must still finish the old request but we must not tamper with the + * queue in the meantime. + * + * NOTE: This path does not handle barrier, but barrier is not supported + * on ide-cd anyway. + */ + +int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, + int uptodate, int nr_sectors) +{ + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&ide_lock, flags); + + BUG_ON(!(rq->flags & REQ_STARTED)); + + /* + * if failfast is set on a request, override number of sectors and + * complete the whole request right now + */ + if (blk_noretry_request(rq) && end_io_error(uptodate)) + nr_sectors = rq->hard_nr_sectors; + + if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors) + rq->errors = -EIO; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->ide_dma_on(drive); + } + + if (!end_that_request_first(rq, uptodate, nr_sectors)) { + add_disk_randomness(rq->rq_disk); + if (blk_rq_tagged(rq)) + blk_queue_end_tag(drive->queue, rq); + end_that_request_last(rq, uptodate); + ret = 0; + } + spin_unlock_irqrestore(&ide_lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(ide_end_dequeued_request); + + +/** * ide_complete_pm_request - end the current Power Management request * @drive: target drive * @rq: request |