aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <petkovbb@gmail.com>2009-06-26 14:22:37 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-26 14:22:37 -0400
commit9c72ebef5aabf3532469d602a9d87beceea268b1 (patch)
tree9f3106fb47e0a8125254f2331dbd8f034793c131
parent5e955245d6cf49c5ed26c7add7392ff5a6762bf4 (diff)
ide-cd: handle fragmented packet commands gracefully
There are some devices in the wild that clear the DRQ bit during the last word of a packet command and therefore could use a "second chance" for that last word of data to be xferred instead of simply failing the request. Do that by attempting to suck in those last bytes in PIO mode. In addition, the ATA_ERR bit has to be cleared for we cannot be sure the data is valid otherwise. See http://bugzilla.kernel.org/show_bug.cgi?id=13399 for details. Signed-off-by: Borislav Petkov <petkovbb@gmail.com> Acked-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/ide/ide-cd.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index f0ede5953af8..6a9a769bffc1 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -592,9 +592,19 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
592 } 592 }
593 } else if (!blk_pc_request(rq)) { 593 } else if (!blk_pc_request(rq)) {
594 ide_cd_request_sense_fixup(drive, cmd); 594 ide_cd_request_sense_fixup(drive, cmd);
595 /* complain if we still have data left to transfer */ 595
596 uptodate = cmd->nleft ? 0 : 1; 596 uptodate = cmd->nleft ? 0 : 1;
597 if (uptodate == 0) 597
598 /*
599 * suck out the remaining bytes from the drive in an
600 * attempt to complete the data xfer. (see BZ#13399)
601 */
602 if (!(stat & ATA_ERR) && !uptodate && thislen) {
603 ide_pio_bytes(drive, cmd, write, thislen);
604 uptodate = cmd->nleft ? 0 : 1;
605 }
606
607 if (!uptodate)
598 rq->cmd_flags |= REQ_FAILED; 608 rq->cmd_flags |= REQ_FAILED;
599 } 609 }
600 goto out_end; 610 goto out_end;