]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Fix IDE-CD command failure re-play
authorJens Axboe <axboe@suse.de>
Sat, 12 Jul 2003 02:27:18 +0000 (19:27 -0700)
committerJens Axboe <axboe@suse.de>
Sat, 12 Jul 2003 02:27:18 +0000 (19:27 -0700)
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.

drivers/ide/ide-cd.c

index fede3d71bc515cdce39da1e25a59817ce7ed9d50..ea211467f65241a97e24685f76c696fad5d4923e 100644 (file)
@@ -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;