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-atapi.c
index c6e0348..afe5a43 100644 (file)
@@ -80,34 +80,6 @@ void ide_init_pc(struct ide_atapi_pc *pc)
 EXPORT_SYMBOL_GPL(ide_init_pc);
 
 /*
- * Generate a new packet command request in front of the request queue, before
- * the current request, so that it will be processed immediately, on the next
- * pass through the driver.
- */
-static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
-                             struct ide_atapi_pc *pc, struct request *rq)
-{
-       blk_rq_init(NULL, rq);
-       rq->cmd_type = REQ_TYPE_SPECIAL;
-       rq->cmd_flags |= REQ_PREEMPT;
-       rq->special = (char *)pc;
-       rq->rq_disk = disk;
-
-       if (pc->req_xfer) {
-               rq->data = pc->buf;
-               rq->data_len = pc->req_xfer;
-       }
-
-       memcpy(rq->cmd, pc->c, 12);
-       if (drive->media == ide_tape)
-               rq->cmd[13] = REQ_IDETAPE_PC1;
-
-       drive->hwif->rq = NULL;
-
-       elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
-}
-
-/*
  * Add a special packet command request to the tail of the request queue,
  * and wait for it to be serviced.
  */
@@ -122,16 +94,18 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
        rq->special = (char *)pc;
 
        if (pc->req_xfer) {
-               rq->data = pc->buf;
-               rq->data_len = pc->req_xfer;
+               error = blk_rq_map_kern(drive->queue, rq, pc->buf, pc->req_xfer,
+                                       GFP_NOIO);
+               if (error)
+                       goto put_req;
        }
 
        memcpy(rq->cmd, pc->c, 12);
        if (drive->media == ide_tape)
                rq->cmd[13] = REQ_IDETAPE_PC1;
        error = blk_execute_rq(drive->queue, disk, rq, 0);
+put_req:
        blk_put_request(rq);
-
        return error;
 }
 EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
@@ -196,6 +170,7 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
        struct request_sense *sense = &drive->sense_data;
        struct request *sense_rq = &drive->sense_rq;
        unsigned int cmd_len, sense_len;
+       int err;
 
        debug_log("%s: enter\n", __func__);
 
@@ -221,13 +196,19 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
        memset(sense, 0, sizeof(*sense));
 
        blk_rq_init(rq->q, sense_rq);
-       sense_rq->rq_disk = rq->rq_disk;
 
-       sense_rq->data = sense;
+       err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len,
+                             GFP_NOIO);
+       if (unlikely(err)) {
+               if (printk_ratelimit())
+                       printk(KERN_WARNING "%s: failed to map sense buffer\n",
+                              drive->name);
+               return;
+       }
+
+       sense_rq->rq_disk = rq->rq_disk;
        sense_rq->cmd[0] = GPCMD_REQUEST_SENSE;
        sense_rq->cmd[4] = cmd_len;
-       sense_rq->data_len = sense_len;
-
        sense_rq->cmd_type = REQ_TYPE_SENSE;
        sense_rq->cmd_flags |= REQ_PREEMPT;
 
@@ -238,9 +219,14 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
 }
 EXPORT_SYMBOL_GPL(ide_prep_sense);
 
-void ide_queue_sense_rq(ide_drive_t *drive, void *special)
+int ide_queue_sense_rq(ide_drive_t *drive, void *special)
 {
-       BUG_ON(!drive->sense_rq_armed);
+       /* deferred failure from ide_prep_sense() */
+       if (!drive->sense_rq_armed) {
+               printk(KERN_WARNING "%s: failed queue sense request\n",
+                      drive->name);
+               return -ENOMEM;
+       }
 
        drive->sense_rq.special = special;
        drive->sense_rq_armed = false;
@@ -249,23 +235,33 @@ void ide_queue_sense_rq(ide_drive_t *drive, void *special)
 
        elv_add_request(drive->queue, &drive->sense_rq,
                        ELEVATOR_INSERT_FRONT, 0);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
 
 /*
  * Called when an error was detected during the last packet command.
- * We queue a request sense packet command in the head of the request list.
+ * We queue a request sense packet command at the head of the request
+ * queue.
  */
-void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk)
+void ide_retry_pc(ide_drive_t *drive)
 {
-       struct request *rq = &drive->request_sense_rq;
+       struct request *sense_rq = &drive->sense_rq;
        struct ide_atapi_pc *pc = &drive->request_sense_pc;
 
        (void)ide_read_error(drive);
-       ide_create_request_sense_cmd(drive, pc);
+
+       /* init pc from sense_rq */
+       ide_init_pc(pc);
+       memcpy(pc->c, sense_rq->cmd, 12);
+       pc->buf = bio_data(sense_rq->bio);      /* pointer to mapped address */
+       pc->req_xfer = sense_rq->data_len;
+
        if (drive->media == ide_tape)
                set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
-       ide_queue_pc_head(drive, disk, pc, rq);
+
+       if (ide_queue_sense_rq(drive, pc))
+               ide_complete_rq(drive, -EIO, blk_rq_bytes(drive->hwif->rq));
 }
 EXPORT_SYMBOL_GPL(ide_retry_pc);
 
@@ -337,7 +333,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
        struct ide_cmd *cmd = &hwif->cmd;
        struct request *rq = hwif->rq;
        const struct ide_tp_ops *tp_ops = hwif->tp_ops;
-       xfer_func_t *xferfunc;
        unsigned int timeout, done;
        u16 bcount;
        u8 stat, ireason, dsc = 0;
@@ -364,11 +359,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
                                        drive->name, rq_data_dir(pc->rq)
                                                     ? "write" : "read");
                        pc->flags |= PC_FLAG_DMA_ERROR;
-               } else {
+               } else
                        pc->xferred = pc->req_xfer;
-                       if (drive->pc_update_buffers)
-                               drive->pc_update_buffers(drive, pc);
-               }
                debug_log("%s: DMA finished\n", drive->name);
        }
 
@@ -404,7 +396,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
                        debug_log("[cmd %x]: check condition\n", rq->cmd[0]);
 
                        /* Retry operation */
-                       ide_retry_pc(drive, rq->rq_disk);
+                       ide_retry_pc(drive);
 
                        /* queued, but not started */
                        return ide_stopped;
@@ -414,6 +406,12 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
                if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
                        dsc = 1;
 
+               /*
+                * ->pc_callback() might change rq->data_len for
+                * residual count, cache total length.
+                */
+               done = blk_rq_bytes(rq);
+
                /* Command finished - Call the callback function */
                uptodate = drive->pc_callback(drive, dsc);
 
@@ -422,7 +420,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
 
                if (blk_special_request(rq)) {
                        rq->errors = 0;
-                       done = blk_rq_bytes(rq);
                        error = 0;
                } else {
 
@@ -431,11 +428,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
                                        rq->errors = -EIO;
                        }
 
-                       if (drive->media == ide_tape)
-                               done = ide_rq_bytes(rq); /* FIXME */
-                       else
-                               done = blk_rq_bytes(rq);
-
                        error = uptodate ? 0 : -EIO;
                }
 
@@ -468,21 +460,11 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
                return ide_do_reset(drive);
        }
 
-       xferfunc = write ? tp_ops->output_data : tp_ops->input_data;
-
-       if (drive->media == ide_floppy && pc->buf == NULL) {
-               done = min_t(unsigned int, bcount, cmd->nleft);
-               ide_pio_bytes(drive, cmd, write, done);
-       } else if (drive->media == ide_tape && pc->bh) {
-               done = drive->pc_io_buffers(drive, pc, bcount, write);
-       } else {
-               done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred);
-               xferfunc(drive, NULL, pc->cur_pos, done);
-       }
+       done = min_t(unsigned int, bcount, cmd->nleft);
+       ide_pio_bytes(drive, cmd, write, done);
 
-       /* Update the current position */
+       /* Update transferred byte count */
        pc->xferred += done;
-       pc->cur_pos += done;
 
        bcount -= done;
 
@@ -660,7 +642,6 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
 
                /* We haven't transferred any data yet */
                pc->xferred = 0;
-               pc->cur_pos = pc->buf;
 
                valid_tf = IDE_VALID_DEVICE;
                bcount = ((drive->media == ide_tape) ?