]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-cd.c
ide-cd: use scatterlists for PIO transfers (fs requests)
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-cd.c
index 30113e69c8bbd64c1b15161b0d0ced1a03c54fac..5f15859c2c731f65f6b5e78ae8143d4b640e497d 100644 (file)
@@ -539,64 +539,12 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
 {
        ide_debug_log(IDE_DBG_RQ, "rq->cmd_flags: 0x%x", rq->cmd_flags);
 
-       if (rq_data_dir(rq) == READ) {
-               unsigned short sectors_per_frame =
-                       queue_hardsect_size(drive->queue) >> SECTOR_BITS;
-               int nskip = rq->sector & (sectors_per_frame - 1);
-
-               /*
-                * If the requested sector doesn't start on a frame boundary,
-                * we must adjust the start of the transfer so that it does,
-                * and remember to skip the first few sectors.
-                *
-                * If the rq->current_nr_sectors field is larger than the size
-                * of the buffer, it will mean that we're to skip a number of
-                * sectors equal to the amount by which rq->current_nr_sectors
-                * is larger than the buffer size.
-                */
-               if (nskip > 0) {
-                       /* sanity check... */
-                       if (rq->current_nr_sectors !=
-                           bio_cur_sectors(rq->bio)) {
-                               printk(KERN_ERR PFX "%s: %s: buffer botch (%u)\n",
-                                               drive->name, __func__,
-                                               rq->current_nr_sectors);
-                               return ide_stopped;
-                       }
-                       rq->current_nr_sectors += nskip;
-               }
-       }
-
        /* set up the command */
        rq->timeout = ATAPI_WAIT_PC;
 
        return ide_started;
 }
 
-/*
- * Fix up a possibly partially-processed request so that we can start it over
- * entirely, or even put it back on the request queue.
- */
-static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq)
-{
-
-       ide_debug_log(IDE_DBG_FUNC, "enter");
-
-       if (rq->buffer != bio_data(rq->bio)) {
-               sector_t n =
-                       (rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE;
-
-               rq->buffer = bio_data(rq->bio);
-               rq->nr_sectors += n;
-               rq->sector -= n;
-       }
-       rq->current_nr_sectors = bio_cur_sectors(rq->bio);
-       rq->hard_cur_sectors = rq->current_nr_sectors;
-       rq->hard_nr_sectors = rq->nr_sectors;
-       rq->hard_sector = rq->sector;
-       rq->q->prep_rq_fn(rq->q, rq);
-}
-
 static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq)
 {
        ide_debug_log(IDE_DBG_FUNC, "rq->cmd[0]: 0x%x", rq->cmd[0]);
@@ -690,6 +638,17 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
        return (flags & REQ_FAILED) ? -EIO : 0;
 }
 
+static void ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
+{
+       unsigned int nr_bytes = cmd->nbytes - cmd->nleft;
+
+       if (cmd->tf_flags & IDE_TFLAG_WRITE)
+               nr_bytes -= cmd->last_xfer_len;
+
+       if (nr_bytes > 0)
+               ide_complete_rq(drive, 0, nr_bytes);
+}
+
 /*
  * Called from blk_end_request_callback() after the data of the request is
  * completed and before the request itself is completed. By returning value '1',
@@ -703,6 +662,7 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
 static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
+       struct ide_cmd *cmd = &hwif->cmd;
        struct request *rq = hwif->rq;
        xfer_func_t *xferfunc;
        ide_expiry_t *expiry = NULL;
@@ -769,11 +729,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                         * Otherwise, complete the command normally.
                         */
                        uptodate = 1;
-                       if (rq->current_nr_sectors > 0) {
+                       if (cmd->nleft > 0) {
                                printk(KERN_ERR PFX "%s: %s: data underrun "
-                                               "(%d blocks)\n",
-                                               drive->name, __func__,
-                                               rq->current_nr_sectors);
+                                       "(%u bytes)\n", drive->name, __func__,
+                                       cmd->nleft);
                                if (!write)
                                        rq->cmd_flags |= REQ_FAILED;
                                uptodate = 0;
@@ -795,24 +754,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
 
        if (blk_fs_request(rq)) {
                if (write == 0) {
-                       int nskip;
-
                        if (ide_cd_check_transfer_size(drive, len))
                                goto out_end;
-
-                       /*
-                        * First, figure out if we need to bit-bucket
-                        * any of the leading sectors.
-                        */
-                       nskip = min_t(int, rq->current_nr_sectors
-                                          - bio_cur_sectors(rq->bio),
-                                          thislen >> 9);
-                       if (nskip > 0) {
-                               ide_pad_transfer(drive, write, nskip << 9);
-                               rq->current_nr_sectors -= nskip;
-                               thislen -= (nskip << 9);
-                       }
                }
+               cmd->last_xfer_len = 0;
        }
 
        if (ireason == 0) {
@@ -835,15 +780,15 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                /* bio backed? */
                if (rq->bio) {
                        if (blk_fs_request(rq)) {
-                               ptr = rq->buffer;
-                               blen = rq->current_nr_sectors << 9;
+                               blen = min_t(int, thislen, cmd->nleft);
                        } else {
                                ptr = bio_data(rq->bio);
                                blen = bio_iovec(rq->bio)->bv_len;
                        }
                }
 
-               if (!ptr) {
+               if ((blk_fs_request(rq) && cmd->nleft == 0) ||
+                   (blk_fs_request(rq) == 0 && ptr == NULL)) {
                        if (blk_fs_request(rq) && !write)
                                /*
                                 * If the buffers are full, pipe the rest into
@@ -863,26 +808,16 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
                if (blen > thislen)
                        blen = thislen;
 
-               xferfunc(drive, NULL, ptr, blen);
+               if (blk_fs_request(rq)) {
+                       ide_pio_bytes(drive, cmd, write, blen);
+                       cmd->last_xfer_len += blen;
+               } else
+                       xferfunc(drive, NULL, ptr, blen);
 
                thislen -= blen;
                len -= blen;
 
-               if (blk_fs_request(rq)) {
-                       rq->buffer += blen;
-                       rq->nr_sectors -= (blen >> 9);
-                       rq->current_nr_sectors -= (blen >> 9);
-                       rq->sector += (blen >> 9);
-
-                       if (rq->current_nr_sectors == 0 && rq->nr_sectors) {
-                               nsectors = rq->hard_cur_sectors;
-
-                               if (nsectors == 0)
-                                       nsectors = 1;
-
-                               ide_complete_rq(drive, 0, nsectors << 9);
-                       }
-               } else {
+               if (blk_fs_request(rq) == 0) {
                        rq->data_len -= blen;
 
                        /*
@@ -933,8 +868,10 @@ out_end:
                        ide_cd_complete_failed_rq(drive, rq);
 
                if (blk_fs_request(rq)) {
-                       if (rq->current_nr_sectors == 0)
+                       if (cmd->nleft == 0)
                                uptodate = 1;
+                       if (uptodate == 0)
+                               ide_cd_error_cmd(drive, cmd);
                } else {
                        if (uptodate <= 0 && rq->errors == 0)
                                rq->errors = -EIO;
@@ -944,7 +881,7 @@ out_end:
                if (blk_pc_request(rq))
                        nsectors = (rq->data_len + 511) >> 9;
                else
-                       nsectors = rq->hard_cur_sectors;
+                       nsectors = rq->hard_nr_sectors;
 
                if (nsectors == 0)
                        nsectors = 1;
@@ -960,9 +897,10 @@ out_end:
 static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
 {
        struct cdrom_info *cd = drive->driver_data;
+       struct request_queue *q = drive->queue;
        int write = rq_data_dir(rq) == WRITE;
        unsigned short sectors_per_frame =
-               queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+               queue_hardsect_size(q) >> SECTOR_BITS;
 
        ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, write: 0x%x, "
                                  "secs_per_frame: %u",
@@ -977,17 +915,16 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
                 * We may be retrying this request after an error.  Fix up any
                 * weirdness which might be present in the request packet.
                 */
-               ide_cd_restore_request(drive, rq);
+               q->prep_rq_fn(q, rq);
        }
 
-       /* use DMA, if possible / writes *must* be hardware frame aligned */
+       /* fs requests *must* be hardware frame aligned */
        if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
-           (rq->sector & (sectors_per_frame - 1))) {
-               if (write)
-                       return ide_stopped;
-               drive->dma = 0;
-       } else
-               drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
+           (rq->sector & (sectors_per_frame - 1)))
+               return ide_stopped;
+
+       /* use DMA, if possible */
+       drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
 
        if (write)
                cd->devinfo.media_written = 1;
@@ -1050,8 +987,6 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
        if (blk_fs_request(rq)) {
                if (cdrom_start_rw(drive, rq) == ide_stopped ||
                    ide_cd_prepare_rw_request(drive, rq) == ide_stopped) {
-                       if (rq->current_nr_sectors == 0)
-                               uptodate = 1;
                        goto out_end;
                }
        } else if (blk_sense_request(rq) || blk_pc_request(rq) ||
@@ -1078,6 +1013,11 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
 
        cmd.rq = rq;
 
+       if (blk_fs_request(rq)) {
+               ide_init_sg_cmd(&cmd, rq->nr_sectors << 9);
+               ide_map_sg(drive, &cmd);
+       }
+
        return ide_issue_pc(drive, &cmd);
 out_end:
        nsectors = rq->hard_nr_sectors;