Merge branch 'for-2.6.31' of git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
[safe/jmp/linux-2.6] / drivers / ide / ide-cd.c
index e946f0e..a75e4ee 100644 (file)
@@ -206,54 +206,25 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
        ide_cd_log_error(drive->name, failed_command, sense);
 }
 
-static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
-                                     struct request *failed_command)
-{
-       struct cdrom_info *info         = drive->driver_data;
-       struct request *rq              = &drive->request_sense_rq;
-
-       ide_debug_log(IDE_DBG_SENSE, "enter");
-
-       if (sense == NULL)
-               sense = &info->sense_data;
-
-       /* stuff the sense request in front of our current request */
-       blk_rq_init(NULL, rq);
-       rq->cmd_type = REQ_TYPE_ATA_PC;
-       rq->rq_disk = info->disk;
-
-       rq->data = sense;
-       rq->cmd[0] = GPCMD_REQUEST_SENSE;
-       rq->cmd[4] = 18;
-       rq->data_len = 18;
-
-       rq->cmd_type = REQ_TYPE_SENSE;
-       rq->cmd_flags |= REQ_PREEMPT;
-
-       /* NOTE! Save the failed command in "rq->buffer" */
-       rq->buffer = (void *) failed_command;
-
-       if (failed_command)
-               ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x",
-                                            failed_command->cmd[0]);
-
-       drive->hwif->rq = NULL;
-
-       elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
-}
-
 static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq)
 {
        /*
-        * For REQ_TYPE_SENSE, "rq->buffer" points to the original
-        * failed request
+        * For REQ_TYPE_SENSE, "rq->special" points to the original
+        * failed request.  Also, the sense data should be read
+        * directly from rq which might be different from the original
+        * sense buffer if it got copied during mapping.
         */
-       struct request *failed = (struct request *)rq->buffer;
-       struct cdrom_info *info = drive->driver_data;
-       void *sense = &info->sense_data;
+       struct request *failed = (struct request *)rq->special;
+       void *sense = bio_data(rq->bio);
 
        if (failed) {
                if (failed->sense) {
+                       /*
+                        * Sense is always read into drive->sense_data.
+                        * Copy back if the failed request has its
+                        * sense pointer set.
+                        */
+                       memcpy(failed->sense, sense, 18);
                        sense = failed->sense;
                        failed->sense_len = rq->sense_len;
                }
@@ -311,8 +282,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq = hwif->rq;
-       int err, sense_key;
-       u8 quiet = rq->cmd_flags & REQ_QUIET;
+       int err, sense_key, do_end_request = 0;
 
        /* get the IDE error register */
        err = ide_read_error(drive);
@@ -330,131 +300,108 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
                 */
                rq->cmd_flags |= REQ_FAILED;
                return 2;
-       } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
-               /* All other functions, except for READ. */
+       }
 
-               /*
-                * if we have an error, pass back CHECK_CONDITION as the
-                * scsi status byte
-                */
-               if (blk_pc_request(rq) && !rq->errors)
-                       rq->errors = SAM_STAT_CHECK_CONDITION;
+       /* if we have an error, pass CHECK_CONDITION as the SCSI status byte */
+       if (blk_pc_request(rq) && !rq->errors)
+               rq->errors = SAM_STAT_CHECK_CONDITION;
 
-               /* check for tray open */
-               if (sense_key == NOT_READY) {
-                       cdrom_saw_media_change(drive);
-               } else if (sense_key == UNIT_ATTENTION) {
-                       /* check for media change */
+       if (blk_noretry_request(rq))
+               do_end_request = 1;
+
+       switch (sense_key) {
+       case NOT_READY:
+               if (blk_fs_request(rq) && rq_data_dir(rq) == WRITE) {
+                       if (ide_cd_breathe(drive, rq))
+                               return 1;
+               } else {
                        cdrom_saw_media_change(drive);
-                       return 0;
-               } else if (sense_key == ILLEGAL_REQUEST &&
-                          rq->cmd[0] == GPCMD_START_STOP_UNIT) {
-                       /*
-                        * Don't print error message for this condition--
-                        * SFF8090i indicates that 5/24/00 is the correct
-                        * response to a request to close the tray if the
-                        * drive doesn't have that capability.
-                        * cdrom_log_sense() knows this!
-                        */
-               } else if (!quiet) {
-                       /* otherwise, print an error */
-                       ide_dump_status(drive, "packet command error", stat);
+
+                       if (blk_fs_request(rq) && !blk_rq_quiet(rq))
+                               printk(KERN_ERR PFX "%s: tray open\n",
+                                       drive->name);
                }
+               do_end_request = 1;
+               break;
+       case UNIT_ATTENTION:
+               cdrom_saw_media_change(drive);
 
-               rq->cmd_flags |= REQ_FAILED;
+               if (blk_fs_request(rq) == 0)
+                       return 0;
 
                /*
-                * instead of playing games with moving completions around,
-                * remove failed request completely and end it when the
-                * request sense has completed
+                * Arrange to retry the request but be sure to give up if we've
+                * retried too many times.
                 */
-               goto end_request;
-
-       } else if (blk_fs_request(rq)) {
-               int do_end_request = 0;
-
-               /* handle errors from READ and WRITE requests */
-
-               if (blk_noretry_request(rq))
-                       do_end_request = 1;
-
-               if (sense_key == NOT_READY) {
-                       /* tray open */
-                       if (rq_data_dir(rq) == READ) {
-                               cdrom_saw_media_change(drive);
-
-                               /* fail the request */
-                               if (!quiet)
-                                       printk(KERN_ERR PFX "%s: tray open\n",
-                                               drive->name);
-                       } else {
-                               if (ide_cd_breathe(drive, rq))
-                                       return 1;
-                       }
-                       do_end_request = 1;
-               } else if (sense_key == UNIT_ATTENTION) {
-                       /* media change */
-                       cdrom_saw_media_change(drive);
-
-                       /*
-                        * Arrange to retry the request but be sure to give up
-                        * if we've retried too many times.
-                        */
-                       if (++rq->errors > ERROR_MAX)
-                               do_end_request = 1;
-               } else if (sense_key == ILLEGAL_REQUEST ||
-                          sense_key == DATA_PROTECT) {
-                       /*
-                        * No point in retrying after an illegal request or data
-                        * protect error.
-                        */
-                       if (!quiet)
-                               ide_dump_status(drive, "command error", stat);
-                       do_end_request = 1;
-               } else if (sense_key == MEDIUM_ERROR) {
-                       /*
-                        * No point in re-trying a zillion times on a bad
-                        * sector. If we got here the error is not correctable.
-                        */
-                       if (!quiet)
-                               ide_dump_status(drive, "media error "
-                                               "(bad sector)", stat);
-                       do_end_request = 1;
-               } else if (sense_key == BLANK_CHECK) {
-                       /* disk appears blank ?? */
-                       if (!quiet)
-                               ide_dump_status(drive, "media error (blank)",
-                                               stat);
+               if (++rq->errors > ERROR_MAX)
                        do_end_request = 1;
-               } else if ((err & ~ATA_ABORTED) != 0) {
+               break;
+       case ILLEGAL_REQUEST:
+               /*
+                * Don't print error message for this condition -- SFF8090i
+                * indicates that 5/24/00 is the correct response to a request
+                * to close the tray if the drive doesn't have that capability.
+                *
+                * cdrom_log_sense() knows this!
+                */
+               if (rq->cmd[0] == GPCMD_START_STOP_UNIT)
+                       break;
+               /* fall-through */
+       case DATA_PROTECT:
+               /*
+                * No point in retrying after an illegal request or data
+                * protect error.
+                */
+               if (!blk_rq_quiet(rq))
+                       ide_dump_status(drive, "command error", stat);
+               do_end_request = 1;
+               break;
+       case MEDIUM_ERROR:
+               /*
+                * No point in re-trying a zillion times on a bad sector.
+                * If we got here the error is not correctable.
+                */
+               if (!blk_rq_quiet(rq))
+                       ide_dump_status(drive, "media error "
+                                       "(bad sector)", stat);
+               do_end_request = 1;
+               break;
+       case BLANK_CHECK:
+               /* disk appears blank? */
+               if (!blk_rq_quiet(rq))
+                       ide_dump_status(drive, "media error (blank)",
+                                       stat);
+               do_end_request = 1;
+               break;
+       default:
+               if (blk_fs_request(rq) == 0)
+                       break;
+               if (err & ~ATA_ABORTED) {
                        /* go to the default handler for other errors */
                        ide_error(drive, "cdrom_decode_status", stat);
                        return 1;
-               } else if ((++rq->errors > ERROR_MAX)) {
+               } else if (++rq->errors > ERROR_MAX)
                        /* we've racked up too many retries, abort */
                        do_end_request = 1;
-               }
-
-               /*
-                * End a request through request sense analysis when we have
-                * sense data. We need this in order to perform end of media
-                * processing.
-                */
-               if (do_end_request)
-                       goto end_request;
+       }
 
-               /*
-                * If we got a CHECK_CONDITION status, queue
-                * a request sense command.
-                */
-               if (stat & ATA_ERR)
-                       cdrom_queue_request_sense(drive, NULL, NULL);
-               return 1;
-       } else {
-               blk_dump_rq_flags(rq, PFX "bad rq");
-               return 2;
+       if (blk_fs_request(rq) == 0) {
+               rq->cmd_flags |= REQ_FAILED;
+               do_end_request = 1;
        }
 
+       /*
+        * End a request through request sense analysis when we have sense data.
+        * We need this in order to perform end of media processing.
+        */
+       if (do_end_request)
+               goto end_request;
+
+       /* if we got a CHECK_CONDITION status, queue a request sense command */
+       if (stat & ATA_ERR)
+               return ide_queue_sense_rq(drive, NULL) ? 2 : 1;
+       return 1;
+
 end_request:
        if (stat & ATA_ERR) {
                struct request_queue *q = drive->queue;
@@ -466,8 +413,7 @@ end_request:
 
                hwif->rq = NULL;
 
-               cdrom_queue_request_sense(drive, rq->sense, rq);
-               return 1;
+               return ide_queue_sense_rq(drive, rq) ? 2 : 1;
        } else
                return 2;
 }
@@ -527,14 +473,8 @@ static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd)
         * and some drives don't send them.  Sigh.
         */
        if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
-           cmd->nleft > 0 && cmd->nleft <= 5) {
-               unsigned int ofs = cmd->nbytes - cmd->nleft;
-
-               while (cmd->nleft > 0) {
-                       *((u8 *)rq->data + ofs++) = 0;
-                       cmd->nleft--;
-               }
-       }
+           cmd->nleft > 0 && cmd->nleft <= 5)
+               cmd->nleft = 0;
 }
 
 int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
@@ -567,8 +507,12 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
                rq->cmd_flags |= cmd_flags;
                rq->timeout = timeout;
                if (buffer) {
-                       rq->data = buffer;
-                       rq->data_len = *bufflen;
+                       error = blk_rq_map_kern(drive->queue, rq, buffer,
+                                               *bufflen, GFP_NOIO);
+                       if (error) {
+                               blk_put_request(rq);
+                               return error;
+                       }
                }
 
                error = blk_execute_rq(drive->queue, info->disk, rq, 0);
@@ -632,7 +576,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
        struct request *rq = hwif->rq;
        ide_expiry_t *expiry = NULL;
        int dma_error = 0, dma, thislen, uptodate = 0;
-       int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc, nsectors;
+       int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0, nsectors;
        int sense = blk_sense_request(rq);
        unsigned int timeout;
        u16 len;
@@ -862,15 +806,10 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
        drive->dma = 0;
 
        /* sg request */
-       if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) {
+       if (rq->bio) {
                struct request_queue *q = drive->queue;
+               char *buf = bio_data(rq->bio);
                unsigned int alignment;
-               char *buf;
-
-               if (rq->bio)
-                       buf = bio_data(rq->bio);
-               else
-                       buf = rq->data;
 
                drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
 
@@ -920,6 +859,9 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
                goto out_end;
        }
 
+       /* prepare sense request for this command */
+       ide_prep_sense(drive, rq);
+
        memset(&cmd, 0, sizeof(cmd));
 
        if (rq_data_dir(rq))