Merge branch 'bp-remove-pc-buf' into for-next
[pandora-kernel.git] / drivers / ide / ide-cd.c
index 925eb9e..dcd7244 100644 (file)
@@ -92,16 +92,16 @@ static void cdrom_saw_media_change(ide_drive_t *drive)
        drive->atapi_flags &= ~IDE_AFLAG_TOC_VALID;
 }
 
-static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
-                          struct request_sense *sense)
+static int cdrom_log_sense(ide_drive_t *drive, struct request *rq)
 {
+       struct request_sense *sense = &drive->sense_data;
        int log = 0;
 
-       ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key);
-
        if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
                return 0;
 
+       ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key);
+
        switch (sense->sense_key) {
        case NO_SENSE:
        case RECOVERED_ERROR:
@@ -140,12 +140,12 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
 }
 
 static void cdrom_analyze_sense_data(ide_drive_t *drive,
-                             struct request *failed_command,
-                             struct request_sense *sense)
+                                    struct request *failed_command)
 {
+       struct request_sense *sense = &drive->sense_data;
+       struct cdrom_info *info = drive->driver_data;
        unsigned long sector;
        unsigned long bio_sectors;
-       struct cdrom_info *info = drive->driver_data;
 
        ide_debug_log(IDE_DBG_SENSE, "error_code: 0x%x, sense_key: 0x%x",
                                     sense->error_code, sense->sense_key);
@@ -154,7 +154,7 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
                ide_debug_log(IDE_DBG_SENSE, "failed cmd: 0x%x",
                                             failed_command->cmd[0]);
 
-       if (!cdrom_log_sense(drive, failed_command, sense))
+       if (!cdrom_log_sense(drive, failed_command))
                return;
 
        /*
@@ -182,7 +182,7 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
                                 (sense->information[2] <<  8) |
                                 (sense->information[3]);
 
-                       if (drive->queue->hardsect_size == 2048)
+                       if (queue_logical_block_size(drive->queue) == 2048)
                                /* device sector size is 2K */
                                sector <<= 2;
 
@@ -206,63 +206,33 @@ 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 = 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);
                        failed->sense_len = rq->sense_len;
                }
-               cdrom_analyze_sense_data(drive, failed, sense);
+               cdrom_analyze_sense_data(drive, failed);
 
                if (ide_end_rq(drive, failed, -EIO, blk_rq_bytes(failed)))
                        BUG();
        } else
-               cdrom_analyze_sense_data(drive, NULL, sense);
+               cdrom_analyze_sense_data(drive, NULL);
 }
 
 
@@ -428,70 +398,17 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
 
        /* if we got a CHECK_CONDITION status, queue a request sense command */
        if (stat & ATA_ERR)
-               cdrom_queue_request_sense(drive, NULL, NULL);
+               return ide_queue_sense_rq(drive, NULL) ? 2 : 1;
        return 1;
 
 end_request:
        if (stat & ATA_ERR) {
-               struct request_queue *q = drive->queue;
-               unsigned long flags;
-
-               spin_lock_irqsave(q->queue_lock, flags);
-               blkdev_dequeue_request(rq);
-               spin_unlock_irqrestore(q->queue_lock, flags);
-
                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;
 }
 
-/*
- * Check the contents of the interrupt reason register from the cdrom
- * and attempt to recover if there are problems.  Returns  0 if everything's
- * ok; nonzero if the request has been terminated.
- */
-static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
-                               int len, int ireason, int rw)
-{
-       ide_hwif_t *hwif = drive->hwif;
-
-       ide_debug_log(IDE_DBG_FUNC, "ireason: 0x%x, rw: 0x%x", ireason, rw);
-
-       /*
-        * ireason == 0: the drive wants to receive data from us
-        * ireason == 2: the drive is expecting to transfer data to us
-        */
-       if (ireason == (!rw << 1))
-               return 0;
-       else if (ireason == (rw << 1)) {
-
-               /* whoops... */
-               printk(KERN_ERR PFX "%s: %s: wrong transfer direction!\n",
-                               drive->name, __func__);
-
-               ide_pad_transfer(drive, rw, len);
-       } else  if (rw == 0 && ireason == 1) {
-               /*
-                * Some drives (ASUS) seem to tell us that status info is
-                * available.  Just get it and ignore.
-                */
-               (void)hwif->tp_ops->read_status(hwif);
-               return 0;
-       } else {
-               /* drive wants a command packet, or invalid ireason... */
-               printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x\n",
-                               drive->name, __func__, ireason);
-       }
-
-       if (rq->cmd_type == REQ_TYPE_ATA_PC)
-               rq->cmd_flags |= REQ_FAILED;
-
-       return -1;
-}
-
 static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd)
 {
        struct request *rq = cmd->rq;
@@ -503,14 +420,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,
@@ -543,14 +454,18 @@ 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);
 
                if (buffer)
-                       *bufflen = rq->data_len;
+                       *bufflen = rq->resid_len;
 
                flags = rq->cmd_flags;
                blk_put_request(rq);
@@ -608,7 +523,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 = 0, nsectors;
+       int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0;
        int sense = blk_sense_request(rq);
        unsigned int timeout;
        u16 len;
@@ -685,8 +600,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                goto out_end;
        }
 
-       /* check which way to transfer data */
-       rc = ide_cd_check_ireason(drive, rq, len, ireason, write);
+       rc = ide_check_ireason(drive, rq, len, ireason, write);
        if (rc)
                goto out_end;
 
@@ -738,13 +652,8 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 
 out_end:
        if (blk_pc_request(rq) && rc == 0) {
-               unsigned int dlen = rq->data_len;
-
-               rq->data_len = 0;
-
-               if (blk_end_request(rq, 0, dlen))
-                       BUG();
-
+               rq->resid_len = 0;
+               blk_end_request_all(rq, 0);
                hwif->rq = NULL;
        } else {
                if (sense && uptodate)
@@ -762,21 +671,13 @@ out_end:
                        ide_cd_error_cmd(drive, cmd);
 
                /* make sure it's fully ended */
-               if (blk_pc_request(rq))
-                       nsectors = (rq->data_len + 511) >> 9;
-               else
-                       nsectors = rq->hard_nr_sectors;
-
-               if (nsectors == 0)
-                       nsectors = 1;
-
                if (blk_fs_request(rq) == 0) {
-                       rq->data_len -= (cmd->nbytes - cmd->nleft);
+                       rq->resid_len -= cmd->nbytes - cmd->nleft;
                        if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE))
-                               rq->data_len += cmd->last_xfer_len;
+                               rq->resid_len += cmd->last_xfer_len;
                }
 
-               ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9);
+               ide_complete_rq(drive, uptodate ? 0 : -EIO, blk_rq_bytes(rq));
 
                if (sense && rc == 2)
                        ide_error(drive, "request sense failure", stat);
@@ -790,7 +691,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
        struct request_queue *q = drive->queue;
        int write = rq_data_dir(rq) == WRITE;
        unsigned short sectors_per_frame =
-               queue_hardsect_size(q) >> SECTOR_BITS;
+               queue_logical_block_size(q) >> SECTOR_BITS;
 
        ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, rq->cmd_flags: 0x%x, "
                                  "secs_per_frame: %u",
@@ -809,8 +710,8 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
        }
 
        /* fs requests *must* be hardware frame aligned */
-       if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
-           (rq->sector & (sectors_per_frame - 1)))
+       if ((blk_rq_sectors(rq) & (sectors_per_frame - 1)) ||
+           (blk_rq_pos(rq) & (sectors_per_frame - 1)))
                return ide_stopped;
 
        /* use DMA, if possible */
@@ -838,15 +739,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);
 
@@ -858,7 +754,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
                 */
                alignment = queue_dma_alignment(q) | q->dma_pad_mask;
                if ((unsigned long)buf & alignment
-                   || rq->data_len & q->dma_pad_mask
+                   || blk_rq_bytes(rq) & q->dma_pad_mask
                    || object_is_on_stack(buf))
                        drive->dma = 0;
        }
@@ -896,6 +792,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))
@@ -903,15 +802,14 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
 
        cmd.rq = rq;
 
-       if (blk_fs_request(rq) || rq->data_len) {
-               ide_init_sg_cmd(&cmd, blk_fs_request(rq) ? (rq->nr_sectors << 9)
-                                                        : rq->data_len);
+       if (blk_fs_request(rq) || blk_rq_bytes(rq)) {
+               ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
                ide_map_sg(drive, &cmd);
        }
 
        return ide_issue_pc(drive, &cmd);
 out_end:
-       nsectors = rq->hard_nr_sectors;
+       nsectors = blk_rq_sectors(rq);
 
        if (nsectors == 0)
                nsectors = 1;
@@ -1077,8 +975,8 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
        /* save a private copy of the TOC capacity for error handling */
        drive->probed_capacity = toc->capacity * sectors_per_frame;
 
-       blk_queue_hardsect_size(drive->queue,
-                               sectors_per_frame << SECTOR_BITS);
+       blk_queue_logical_block_size(drive->queue,
+                                    sectors_per_frame << SECTOR_BITS);
 
        /* first read just the header, so we know how long the TOC is */
        stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
@@ -1394,9 +1292,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive)
 /* standard prep_rq_fn that builds 10 byte cmds */
 static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
 {
-       int hard_sect = queue_hardsect_size(q);
-       long block = (long)rq->hard_sector / (hard_sect >> 9);
-       unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);
+       int hard_sect = queue_logical_block_size(q);
+       long block = (long)blk_rq_pos(rq) / (hard_sect >> 9);
+       unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9);
 
        memset(rq->cmd, 0, BLK_MAX_CDB);
 
@@ -1599,7 +1497,7 @@ static int ide_cdrom_setup(ide_drive_t *drive)
 
        nslots = ide_cdrom_probe_capabilities(drive);
 
-       blk_queue_hardsect_size(q, CD_FRAMESIZE);
+       blk_queue_logical_block_size(q, CD_FRAMESIZE);
 
        if (ide_cdrom_register(drive, nslots)) {
                printk(KERN_ERR PFX "%s: %s failed to register device with the"