diff options
| author | Jens Axboe <axboe@suse.de> | 2003-07-11 19:27:18 -0700 |
|---|---|---|
| committer | Jens Axboe <axboe@suse.de> | 2003-07-11 19:27:18 -0700 |
| commit | 963436f3a5a06c2be3cbb5e8a33e355fbec2216b (patch) | |
| tree | 6b9f81ebf813188e59803c1c3de6e31c2f06440a | |
| parent | e9f1867d14040e846838731163eba69034a3ca51 (diff) | |
[PATCH] Fix IDE-CD command failure re-play
Every failed SG_IO request is replayed second time without data
transfer. Fix the problem by immediately purging the failed SG_IO
request from the request queue.
It fixes (among others)
http://marc.theaimsgroup.com/?t=105634805100001&r=1&w=2
where induced kernel crash occurs upon packet replay.
| -rw-r--r-- | drivers/ide/ide-cd.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index fede3d71bc51..ea211467f652 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -749,12 +749,17 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) by transferring the semaphore from the packet command request to the request sense request. */ + rq->flags |= REQ_FAILED; if ((stat & ERR_STAT) != 0) { wait = rq->waiting; rq->waiting = NULL; + if ((rq->flags & REQ_BLOCK_PC) != 0) { + cdrom_queue_request_sense(drive, wait, + rq->sense, rq); + return 1; /* REQ_BLOCK_PC self-cares */ + } } - rq->flags |= REQ_FAILED; cdrom_end_request(drive, 0); if ((stat & ERR_STAT) != 0) @@ -1657,13 +1662,14 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) dma = info->dma; if (dma) { info->dma = 0; - if ((dma_error = HWIF(drive)->ide_dma_end(drive))) { - printk("ide-cd: dma error\n"); - HWIF(drive)->ide_dma_off(drive); - } + dma_error = HWIF(drive)->ide_dma_end(drive); } if (cdrom_decode_status(drive, 0, &stat)) { + if ((stat & ERR_STAT) != 0) { + end_that_request_chunk(rq, 0, rq->data_len); + goto end_request; /* purge the whole thing... */ + } end_that_request_chunk(rq, 1, rq->data_len); return ide_stopped; } @@ -1672,8 +1678,11 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) * using dma, transfer is complete now */ if (dma) { - if (dma_error) + if (dma_error) { + printk("ide-cd: dma error\n"); + HWIF(drive)->ide_dma_off(drive); return DRIVER(drive)->error(drive, "dma error", stat); + } end_that_request_chunk(rq, 1, rq->data_len); rq->data_len = 0; |
