]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-tape.c
ide-tape: convert ide_do_drive_cmd path to use blk_execute_rq
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-tape.c
index 2275cd22902cabdd7efb6ff70ac4f8e3d871d38f..a5f0b774527bd3898a4d2d85430992c615b46428 100644 (file)
@@ -215,13 +215,6 @@ enum {
        IDETAPE_FLAG_MEDIUM_PRESENT     = (1 << 6),
 };
 
-/* A pipeline stage. */
-typedef struct idetape_stage_s {
-       struct request rq;                      /* The corresponding request */
-       struct idetape_bh *bh;                  /* The data buffers */
-       struct idetape_stage_s *next;           /* Pointer to the next stage */
-} idetape_stage_t;
-
 /*
  * Most of our global data which we need to save even as we leave the driver due
  * to an interrupt or a timer event is stored in the struct defined below.
@@ -308,15 +301,17 @@ typedef struct ide_tape_obj {
         */
 
        /* Data buffer size chosen based on the tape's recommendation */
-       int stage_size;
-       idetape_stage_t *merge_stage;
-       int merge_stage_size;
+       int buffer_size;
+       /* merge buffer */
+       struct idetape_bh *merge_bh;
+       /* size of the merge buffer */
+       int merge_bh_size;
+       /* pointer to current buffer head within the merge buffer */
        struct idetape_bh *bh;
        char *b_data;
        int b_count;
 
-       /* Pipeline parameters. */
-       int pages_per_stage;
+       int pages_per_buffer;
        /* Wasted space in each stage */
        int excess_bh_size;
 
@@ -400,13 +395,13 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                if (bh == NULL) {
                        printk(KERN_ERR "ide-tape: bh == NULL in "
                                "idetape_input_buffers\n");
-                       ide_atapi_discard_data(drive, bcount);
+                       ide_pad_transfer(drive, 0, bcount);
                        return;
                }
                count = min(
                        (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
                        bcount);
-               HWIF(drive)->atapi_input_bytes(drive, bh->b_data +
+               drive->hwif->input_data(drive, NULL, bh->b_data +
                                        atomic_read(&bh->b_count), count);
                bcount -= count;
                atomic_add(count, &bh->b_count);
@@ -432,7 +427,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                        return;
                }
                count = min((unsigned int)pc->b_count, (unsigned int)bcount);
-               HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count);
+               drive->hwif->output_data(drive, NULL, pc->b_data, count);
                bcount -= count;
                pc->b_data += count;
                pc->b_count -= count;
@@ -543,7 +538,7 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
        if (pc->flags & PC_FLAG_DMA_ERROR) {
                pc->xferred = pc->req_xfer -
                        tape->blk_size *
-                       be32_to_cpu(get_unaligned((u32 *)&sense[3]));
+                       get_unaligned_be32(&sense[3]);
                idetape_update_buffers(pc);
        }
 
@@ -584,26 +579,28 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
        }
 }
 
-/* Free a stage along with its related buffers completely. */
-static void __idetape_kfree_stage(idetape_stage_t *stage)
+/* Free data buffers completely. */
+static void ide_tape_kfree_buffer(idetape_tape_t *tape)
 {
-       struct idetape_bh *prev_bh, *bh = stage->bh;
-       int size;
+       struct idetape_bh *prev_bh, *bh = tape->merge_bh;
 
-       while (bh != NULL) {
-               if (bh->b_data != NULL) {
-                       size = (int) bh->b_size;
-                       while (size > 0) {
-                               free_page((unsigned long) bh->b_data);
-                               size -= PAGE_SIZE;
-                               bh->b_data += PAGE_SIZE;
-                       }
+       while (bh) {
+               u32 size = bh->b_size;
+
+               while (size) {
+                       unsigned int order = fls(size >> PAGE_SHIFT)-1;
+
+                       if (bh->b_data)
+                               free_pages((unsigned long)bh->b_data, order);
+
+                       size &= (order-1);
+                       bh->b_data += (1 << order) * PAGE_SIZE;
                }
                prev_bh = bh;
                bh = bh->b_reqnext;
                kfree(prev_bh);
        }
-       kfree(stage);
+       kfree(tape->merge_bh);
 }
 
 static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
@@ -665,7 +662,7 @@ static void idetape_create_request_sense_cmd(struct ide_atapi_pc *pc)
 
 static void idetape_init_rq(struct request *rq, u8 cmd)
 {
-       memset(rq, 0, sizeof(*rq));
+       blk_rq_init(NULL, rq);
        rq->cmd_type = REQ_TYPE_SPECIAL;
        rq->cmd[0] = cmd;
 }
@@ -691,6 +688,7 @@ static void idetape_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
        struct ide_tape_obj *tape = drive->driver_data;
 
        idetape_init_rq(rq, REQ_IDETAPE_PC1);
+       rq->cmd_flags |= REQ_PREEMPT;
        rq->buffer = (char *) pc;
        rq->rq_disk = tape->disk;
        (void) ide_do_drive_cmd(drive, rq, ide_preempt);
@@ -874,7 +872,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
                                printk(KERN_ERR "ide-tape: The tape wants to "
                                        "send us more data than expected "
                                        "- discarding data\n");
-                               ide_atapi_discard_data(drive, bcount);
+                               ide_pad_transfer(drive, 0, bcount);
                                ide_set_handler(drive, &idetape_pc_intr,
                                                IDETAPE_WAIT_CMD, NULL);
                                return ide_started;
@@ -883,16 +881,16 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
                                "data than expected - allowing transfer\n");
                }
                iobuf = &idetape_input_buffers;
-               xferfunc = hwif->atapi_input_bytes;
+               xferfunc = hwif->input_data;
        } else {
                iobuf = &idetape_output_buffers;
-               xferfunc = hwif->atapi_output_bytes;
+               xferfunc = hwif->output_data;
        }
 
        if (pc->bh)
                iobuf(drive, pc, bcount);
        else
-               xferfunc(drive, pc->cur_pos, bcount);
+               xferfunc(drive, NULL, pc->cur_pos, bcount);
 
        /* Update the current position */
        pc->xferred += bcount;
@@ -982,7 +980,8 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
                hwif->dma_ops->dma_start(drive);
 #endif
        /* Send the actual packet */
-       HWIF(drive)->atapi_output_bytes(drive, pc->c, 12);
+       hwif->output_data(drive, NULL, pc->c, 12);
+
        return ide_started;
 }
 
@@ -1058,7 +1057,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
                                    IDETAPE_WAIT_CMD, NULL);
                return ide_started;
        } else {
-               hwif->OUTB(WIN_PACKETCMD, hwif->io_ports.command_addr);
+               ide_execute_pkt_cmd(drive);
                return idetape_transfer_pc(drive);
        }
 }
@@ -1168,7 +1167,7 @@ static void idetape_create_read_cmd(idetape_tape_t *tape,
        pc->buf = NULL;
        pc->buf_size = length * tape->blk_size;
        pc->req_xfer = pc->buf_size;
-       if (pc->req_xfer == tape->stage_size)
+       if (pc->req_xfer == tape->buffer_size)
                pc->flags |= PC_FLAG_DMA_RECOMMENDED;
 }
 
@@ -1188,7 +1187,7 @@ static void idetape_create_write_cmd(idetape_tape_t *tape,
        pc->buf = NULL;
        pc->buf_size = length * tape->blk_size;
        pc->req_xfer = pc->buf_size;
-       if (pc->req_xfer == tape->stage_size)
+       if (pc->req_xfer == tape->buffer_size)
                pc->flags |= PC_FLAG_DMA_RECOMMENDED;
 }
 
@@ -1290,77 +1289,85 @@ out:
 }
 
 /*
- * The function below uses __get_free_page to allocate a pipeline stage, along
- * with all the necessary small buffers which together make a buffer of size
- * tape->stage_size (or a bit more). We attempt to combine sequential pages as
+ * The function below uses __get_free_pages to allocate a data buffer of size
+ * tape->buffer_size (or a bit more). We attempt to combine sequential pages as
  * much as possible.
  *
- * It returns a pointer to the new allocated stage, or NULL if we can't (or
- * don't want to) allocate a stage.
+ * It returns a pointer to the newly allocated buffer, or NULL in case of
+ * failure.
  */
-static idetape_stage_t *__idetape_kmalloc_stage(idetape_tape_t *tape, int full,
-                                               int clear)
+static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape,
+                                                 int full, int clear)
 {
-       idetape_stage_t *stage;
-       struct idetape_bh *prev_bh, *bh;
-       int pages = tape->pages_per_stage;
+       struct idetape_bh *prev_bh, *bh, *merge_bh;
+       int pages = tape->pages_per_buffer;
+       unsigned int order, b_allocd;
        char *b_data = NULL;
 
-       stage = kmalloc(sizeof(idetape_stage_t), GFP_KERNEL);
-       if (!stage)
-               return NULL;
-       stage->next = NULL;
-
-       stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
-       bh = stage->bh;
+       merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
+       bh = merge_bh;
        if (bh == NULL)
                goto abort;
-       bh->b_reqnext = NULL;
-       bh->b_data = (char *) __get_free_page(GFP_KERNEL);
+
+       order = fls(pages) - 1;
+       bh->b_data = (char *) __get_free_pages(GFP_KERNEL, order);
        if (!bh->b_data)
                goto abort;
+       b_allocd = (1 << order) * PAGE_SIZE;
+       pages &= (order-1);
+
        if (clear)
-               memset(bh->b_data, 0, PAGE_SIZE);
-       bh->b_size = PAGE_SIZE;
+               memset(bh->b_data, 0, b_allocd);
+       bh->b_reqnext = NULL;
+       bh->b_size = b_allocd;
        atomic_set(&bh->b_count, full ? bh->b_size : 0);
 
-       while (--pages) {
-               b_data = (char *) __get_free_page(GFP_KERNEL);
+       while (pages) {
+               order = fls(pages) - 1;
+               b_data = (char *) __get_free_pages(GFP_KERNEL, order);
                if (!b_data)
                        goto abort;
+               b_allocd = (1 << order) * PAGE_SIZE;
+
                if (clear)
-                       memset(b_data, 0, PAGE_SIZE);
-               if (bh->b_data == b_data + PAGE_SIZE) {
-                       bh->b_size += PAGE_SIZE;
-                       bh->b_data -= PAGE_SIZE;
+                       memset(b_data, 0, b_allocd);
+
+               /* newly allocated page frames below buffer header or ...*/
+               if (bh->b_data == b_data + b_allocd) {
+                       bh->b_size += b_allocd;
+                       bh->b_data -= b_allocd;
                        if (full)
-                               atomic_add(PAGE_SIZE, &bh->b_count);
+                               atomic_add(b_allocd, &bh->b_count);
                        continue;
                }
+               /* they are above the header */
                if (b_data == bh->b_data + bh->b_size) {
-                       bh->b_size += PAGE_SIZE;
+                       bh->b_size += b_allocd;
                        if (full)
-                               atomic_add(PAGE_SIZE, &bh->b_count);
+                               atomic_add(b_allocd, &bh->b_count);
                        continue;
                }
                prev_bh = bh;
                bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
                if (!bh) {
-                       free_page((unsigned long) b_data);
+                       free_pages((unsigned long) b_data, order);
                        goto abort;
                }
                bh->b_reqnext = NULL;
                bh->b_data = b_data;
-               bh->b_size = PAGE_SIZE;
+               bh->b_size = b_allocd;
                atomic_set(&bh->b_count, full ? bh->b_size : 0);
                prev_bh->b_reqnext = bh;
+
+               pages &= (order-1);
        }
+
        bh->b_size -= tape->excess_bh_size;
        if (full)
                atomic_sub(tape->excess_bh_size, &bh->b_count);
-       return stage;
+       return merge_bh;
 abort:
-       __idetape_kfree_stage(stage);
+       ide_tape_kfree_buffer(tape);
        return NULL;
 }
 
@@ -1428,11 +1435,11 @@ static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
        return ret;
 }
 
-static void idetape_init_merge_stage(idetape_tape_t *tape)
+static void idetape_init_merge_buffer(idetape_tape_t *tape)
 {
-       struct idetape_bh *bh = tape->merge_stage->bh;
+       struct idetape_bh *bh = tape->merge_bh;
+       tape->bh = tape->merge_bh;
 
-       tape->bh = bh;
        if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
                atomic_set(&bh->b_count, 0);
        else {
@@ -1512,12 +1519,16 @@ static void idetape_create_test_unit_ready_cmd(struct ide_atapi_pc *pc)
 static int idetape_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
 {
        struct ide_tape_obj *tape = drive->driver_data;
-       struct request rq;
+       struct request *rq;
+       int error;
 
-       idetape_init_rq(&rq, REQ_IDETAPE_PC1);
-       rq.buffer = (char *) pc;
-       rq.rq_disk = tape->disk;
-       return ide_do_drive_cmd(drive, &rq, ide_wait);
+       rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+       rq->cmd_type = REQ_TYPE_SPECIAL;
+       rq->cmd[0] = REQ_IDETAPE_PC1;
+       rq->buffer = (char *)pc;
+       error = blk_execute_rq(drive->queue, tape->disk, rq, 0);
+       blk_put_request(rq);
+       return error;
 }
 
 static void idetape_create_load_unload_cmd(ide_drive_t *drive,
@@ -1626,23 +1637,21 @@ static int idetape_create_prevent_cmd(ide_drive_t *drive,
        return 1;
 }
 
-static int __idetape_discard_read_pipeline(ide_drive_t *drive)
+static void __ide_tape_discard_merge_buffer(ide_drive_t *drive)
 {
        idetape_tape_t *tape = drive->driver_data;
 
        if (tape->chrdev_dir != IDETAPE_DIR_READ)
-               return 0;
+               return;
 
        clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
-       tape->merge_stage_size = 0;
-       if (tape->merge_stage != NULL) {
-               __idetape_kfree_stage(tape->merge_stage);
-               tape->merge_stage = NULL;
+       tape->merge_bh_size = 0;
+       if (tape->merge_bh != NULL) {
+               ide_tape_kfree_buffer(tape);
+               tape->merge_bh = NULL;
        }
 
        tape->chrdev_dir = IDETAPE_DIR_NONE;
-
-       return 0;
 }
 
 /*
@@ -1659,7 +1668,7 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
        struct ide_atapi_pc pc;
 
        if (tape->chrdev_dir == IDETAPE_DIR_READ)
-               __idetape_discard_read_pipeline(drive);
+               __ide_tape_discard_merge_buffer(drive);
        idetape_wait_ready(drive, 60 * 5 * HZ);
        idetape_create_locate_cmd(drive, &pc, block, partition, skip);
        retval = idetape_queue_pc_tail(drive, &pc);
@@ -1670,20 +1679,19 @@ static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
        return (idetape_queue_pc_tail(drive, &pc));
 }
 
-static void idetape_discard_read_pipeline(ide_drive_t *drive,
+static void ide_tape_discard_merge_buffer(ide_drive_t *drive,
                                          int restore_position)
 {
        idetape_tape_t *tape = drive->driver_data;
-       int cnt;
        int seek, position;
 
-       cnt = __idetape_discard_read_pipeline(drive);
+       __ide_tape_discard_merge_buffer(drive);
        if (restore_position) {
                position = idetape_read_position(drive);
-               seek = position > cnt ? position - cnt : 0;
+               seek = position > 0 ? position : 0;
                if (idetape_position_tape(drive, seek, 0, 0)) {
                        printk(KERN_INFO "ide-tape: %s: position_tape failed in"
-                                        " discard_pipeline()\n", tape->name);
+                                        " %s\n", tape->name, __func__);
                        return;
                }
        }
@@ -1697,26 +1705,33 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
                                 struct idetape_bh *bh)
 {
        idetape_tape_t *tape = drive->driver_data;
-       struct request rq;
+       struct request *rq;
+       int ret, errors;
 
        debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd);
 
-       idetape_init_rq(&rq, cmd);
-       rq.rq_disk = tape->disk;
-       rq.special = (void *)bh;
-       rq.sector = tape->first_frame;
-       rq.nr_sectors           = blocks;
-       rq.current_nr_sectors   = blocks;
-       (void) ide_do_drive_cmd(drive, &rq, ide_wait);
+       rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+       rq->cmd_type = REQ_TYPE_SPECIAL;
+       rq->cmd[0] = cmd;
+       rq->rq_disk = tape->disk;
+       rq->special = (void *)bh;
+       rq->sector = tape->first_frame;
+       rq->nr_sectors = blocks;
+       rq->current_nr_sectors = blocks;
+       blk_execute_rq(drive->queue, tape->disk, rq, 0);
+
+       errors = rq->errors;
+       ret = tape->blk_size * (blocks - rq->current_nr_sectors);
+       blk_put_request(rq);
 
        if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
                return 0;
 
-       if (tape->merge_stage)
-               idetape_init_merge_stage(tape);
-       if (rq.errors == IDETAPE_ERROR_GENERAL)
+       if (tape->merge_bh)
+               idetape_init_merge_buffer(tape);
+       if (errors == IDETAPE_ERROR_GENERAL)
                return -EIO;
-       return (tape->blk_size * (blocks-rq.current_nr_sectors));
+       return ret;
 }
 
 static void idetape_create_inquiry_cmd(struct ide_atapi_pc *pc)
@@ -1764,31 +1779,31 @@ static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
        debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
 
        return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
-                                    blocks, tape->merge_stage->bh);
+                                    blocks, tape->merge_bh);
 }
 
-static void idetape_empty_write_pipeline(ide_drive_t *drive)
+static void ide_tape_flush_merge_buffer(ide_drive_t *drive)
 {
        idetape_tape_t *tape = drive->driver_data;
        int blocks, min;
        struct idetape_bh *bh;
 
        if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
-               printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline,"
+               printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer"
                                " but we are not writing.\n");
                return;
        }
-       if (tape->merge_stage_size > tape->stage_size) {
+       if (tape->merge_bh_size > tape->buffer_size) {
                printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
-               tape->merge_stage_size = tape->stage_size;
+               tape->merge_bh_size = tape->buffer_size;
        }
-       if (tape->merge_stage_size) {
-               blocks = tape->merge_stage_size / tape->blk_size;
-               if (tape->merge_stage_size % tape->blk_size) {
+       if (tape->merge_bh_size) {
+               blocks = tape->merge_bh_size / tape->blk_size;
+               if (tape->merge_bh_size % tape->blk_size) {
                        unsigned int i;
 
                        blocks++;
-                       i = tape->blk_size - tape->merge_stage_size %
+                       i = tape->blk_size - tape->merge_bh_size %
                                tape->blk_size;
                        bh = tape->bh->b_reqnext;
                        while (bh) {
@@ -1812,11 +1827,11 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
                        }
                }
                (void) idetape_add_chrdev_write_request(drive, blocks);
-               tape->merge_stage_size = 0;
+               tape->merge_bh_size = 0;
        }
-       if (tape->merge_stage != NULL) {
-               __idetape_kfree_stage(tape->merge_stage);
-               tape->merge_stage = NULL;
+       if (tape->merge_bh != NULL) {
+               ide_tape_kfree_buffer(tape);
+               tape->merge_bh = NULL;
        }
        tape->chrdev_dir = IDETAPE_DIR_NONE;
 }
@@ -1829,16 +1844,16 @@ static int idetape_init_read(ide_drive_t *drive)
        /* Initialize read operation */
        if (tape->chrdev_dir != IDETAPE_DIR_READ) {
                if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
-                       idetape_empty_write_pipeline(drive);
+                       ide_tape_flush_merge_buffer(drive);
                        idetape_flush_tape_buffers(drive);
                }
-               if (tape->merge_stage || tape->merge_stage_size) {
-                       printk(KERN_ERR "ide-tape: merge_stage_size should be"
+               if (tape->merge_bh || tape->merge_bh_size) {
+                       printk(KERN_ERR "ide-tape: merge_bh_size should be"
                                         " 0 now\n");
-                       tape->merge_stage_size = 0;
+                       tape->merge_bh_size = 0;
                }
-               tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0);
-               if (!tape->merge_stage)
+               tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
+               if (!tape->merge_bh)
                        return -ENOMEM;
                tape->chrdev_dir = IDETAPE_DIR_READ;
 
@@ -1851,10 +1866,10 @@ static int idetape_init_read(ide_drive_t *drive)
                if (drive->dsc_overlap) {
                        bytes_read = idetape_queue_rw_tail(drive,
                                                        REQ_IDETAPE_READ, 0,
-                                                       tape->merge_stage->bh);
+                                                       tape->merge_bh);
                        if (bytes_read < 0) {
-                               __idetape_kfree_stage(tape->merge_stage);
-                               tape->merge_stage = NULL;
+                               ide_tape_kfree_buffer(tape);
+                               tape->merge_bh = NULL;
                                tape->chrdev_dir = IDETAPE_DIR_NONE;
                                return bytes_read;
                        }
@@ -1878,7 +1893,7 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
        idetape_init_read(drive);
 
        return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
-                                    tape->merge_stage->bh);
+                                    tape->merge_bh);
 }
 
 static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
@@ -1890,8 +1905,8 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
        while (bcount) {
                unsigned int count;
 
-               bh = tape->merge_stage->bh;
-               count = min(tape->stage_size, bcount);
+               bh = tape->merge_bh;
+               count = min(tape->buffer_size, bcount);
                bcount -= count;
                blocks = count / tape->blk_size;
                while (count) {
@@ -1902,7 +1917,7 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
                        bh = bh->b_reqnext;
                }
                idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks,
-                                     tape->merge_stage->bh);
+                                     tape->merge_bh);
        }
 }
 
@@ -1981,16 +1996,12 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
        }
 
        if (tape->chrdev_dir == IDETAPE_DIR_READ) {
-               tape->merge_stage_size = 0;
+               tape->merge_bh_size = 0;
                if (test_and_clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags))
                        ++count;
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
        }
 
-       /*
-        * The filemark was not found in our internal pipeline; now we can issue
-        * the space command.
-        */
        switch (mt_op) {
        case MTFSF:
        case MTBSF:
@@ -2051,16 +2062,16 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
                return rc;
        if (count == 0)
                return (0);
-       if (tape->merge_stage_size) {
-               actually_read = min((unsigned int)(tape->merge_stage_size),
+       if (tape->merge_bh_size) {
+               actually_read = min((unsigned int)(tape->merge_bh_size),
                                    (unsigned int)count);
                if (idetape_copy_stage_to_user(tape, buf, actually_read))
                        ret = -EFAULT;
                buf += actually_read;
-               tape->merge_stage_size -= actually_read;
+               tape->merge_bh_size -= actually_read;
                count -= actually_read;
        }
-       while (count >= tape->stage_size) {
+       while (count >= tape->buffer_size) {
                bytes_read = idetape_add_chrdev_read_request(drive, ctl);
                if (bytes_read <= 0)
                        goto finish;
@@ -2078,7 +2089,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
                if (idetape_copy_stage_to_user(tape, buf, temp))
                        ret = -EFAULT;
                actually_read += temp;
-               tape->merge_stage_size = bytes_read-temp;
+               tape->merge_bh_size = bytes_read-temp;
        }
 finish:
        if (!actually_read && test_bit(IDETAPE_FLAG_FILEMARK, &tape->flags)) {
@@ -2109,17 +2120,17 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
        /* Initialize write operation */
        if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
                if (tape->chrdev_dir == IDETAPE_DIR_READ)
-                       idetape_discard_read_pipeline(drive, 1);
-               if (tape->merge_stage || tape->merge_stage_size) {
-                       printk(KERN_ERR "ide-tape: merge_stage_size "
+                       ide_tape_discard_merge_buffer(drive, 1);
+               if (tape->merge_bh || tape->merge_bh_size) {
+                       printk(KERN_ERR "ide-tape: merge_bh_size "
                                "should be 0 now\n");
-                       tape->merge_stage_size = 0;
+                       tape->merge_bh_size = 0;
                }
-               tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0);
-               if (!tape->merge_stage)
+               tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0);
+               if (!tape->merge_bh)
                        return -ENOMEM;
                tape->chrdev_dir = IDETAPE_DIR_WRITE;
-               idetape_init_merge_stage(tape);
+               idetape_init_merge_buffer(tape);
 
                /*
                 * Issue a write 0 command to ensure that DSC handshake is
@@ -2130,10 +2141,10 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
                if (drive->dsc_overlap) {
                        ssize_t retval = idetape_queue_rw_tail(drive,
                                                        REQ_IDETAPE_WRITE, 0,
-                                                       tape->merge_stage->bh);
+                                                       tape->merge_bh);
                        if (retval < 0) {
-                               __idetape_kfree_stage(tape->merge_stage);
-                               tape->merge_stage = NULL;
+                               ide_tape_kfree_buffer(tape);
+                               tape->merge_bh = NULL;
                                tape->chrdev_dir = IDETAPE_DIR_NONE;
                                return retval;
                        }
@@ -2141,36 +2152,36 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
        }
        if (count == 0)
                return (0);
-       if (tape->merge_stage_size) {
-               if (tape->merge_stage_size >= tape->stage_size) {
+       if (tape->merge_bh_size) {
+               if (tape->merge_bh_size >= tape->buffer_size) {
                        printk(KERN_ERR "ide-tape: bug: merge buf too big\n");
-                       tape->merge_stage_size = 0;
+                       tape->merge_bh_size = 0;
                }
                actually_written = min((unsigned int)
-                               (tape->stage_size - tape->merge_stage_size),
+                               (tape->buffer_size - tape->merge_bh_size),
                                (unsigned int)count);
                if (idetape_copy_stage_from_user(tape, buf, actually_written))
                                ret = -EFAULT;
                buf += actually_written;
-               tape->merge_stage_size += actually_written;
+               tape->merge_bh_size += actually_written;
                count -= actually_written;
 
-               if (tape->merge_stage_size == tape->stage_size) {
+               if (tape->merge_bh_size == tape->buffer_size) {
                        ssize_t retval;
-                       tape->merge_stage_size = 0;
+                       tape->merge_bh_size = 0;
                        retval = idetape_add_chrdev_write_request(drive, ctl);
                        if (retval <= 0)
                                return (retval);
                }
        }
-       while (count >= tape->stage_size) {
+       while (count >= tape->buffer_size) {
                ssize_t retval;
-               if (idetape_copy_stage_from_user(tape, buf, tape->stage_size))
+               if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size))
                        ret = -EFAULT;
-               buf += tape->stage_size;
-               count -= tape->stage_size;
+               buf += tape->buffer_size;
+               count -= tape->buffer_size;
                retval = idetape_add_chrdev_write_request(drive, ctl);
-               actually_written += tape->stage_size;
+               actually_written += tape->buffer_size;
                if (retval <= 0)
                        return (retval);
        }
@@ -2178,7 +2189,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
                actually_written += count;
                if (idetape_copy_stage_from_user(tape, buf, count))
                        ret = -EFAULT;
-               tape->merge_stage_size += count;
+               tape->merge_bh_size += count;
        }
        return ret ? ret : actually_written;
 }
@@ -2234,7 +2245,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
        case MTWEOF:
                if (tape->write_prot)
                        return -EACCES;
-               idetape_discard_read_pipeline(drive, 1);
+               ide_tape_discard_merge_buffer(drive, 1);
                for (i = 0; i < mt_count; i++) {
                        retval = idetape_write_filemark(drive);
                        if (retval)
@@ -2242,12 +2253,12 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                }
                return 0;
        case MTREW:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                if (idetape_rewind_tape(drive))
                        return -EIO;
                return 0;
        case MTLOAD:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                idetape_create_load_unload_cmd(drive, &pc,
                                               IDETAPE_LU_LOAD_MASK);
                return idetape_queue_pc_tail(drive, &pc);
@@ -2262,7 +2273,7 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                                if (!idetape_queue_pc_tail(drive, &pc))
                                        tape->door_locked = DOOR_UNLOCKED;
                }
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                idetape_create_load_unload_cmd(drive, &pc,
                                              !IDETAPE_LU_LOAD_MASK);
                retval = idetape_queue_pc_tail(drive, &pc);
@@ -2270,10 +2281,10 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                        clear_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags);
                return retval;
        case MTNOP:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                return idetape_flush_tape_buffers(drive);
        case MTRETEN:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                idetape_create_load_unload_cmd(drive, &pc,
                        IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
                return idetape_queue_pc_tail(drive, &pc);
@@ -2295,11 +2306,11 @@ static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
                        set_bit(IDETAPE_FLAG_DETECT_BS, &tape->flags);
                return 0;
        case MTSEEK:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                return idetape_position_tape(drive,
                        mt_count * tape->user_bs_factor, tape->partition, 0);
        case MTSETPART:
-               idetape_discard_read_pipeline(drive, 0);
+               ide_tape_discard_merge_buffer(drive, 0);
                return idetape_position_tape(drive, 0, mt_count, 0);
        case MTFSR:
        case MTBSR:
@@ -2345,11 +2356,11 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
        debug_log(DBG_CHRDEV, "Enter %s, cmd=%u\n", __func__, cmd);
 
        if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
-               idetape_empty_write_pipeline(drive);
+               ide_tape_flush_merge_buffer(drive);
                idetape_flush_tape_buffers(drive);
        }
        if (cmd == MTIOCGET || cmd == MTIOCPOS) {
-               block_offset = tape->merge_stage_size /
+               block_offset = tape->merge_bh_size /
                        (tape->blk_size * tape->user_bs_factor);
                position = idetape_read_position(drive);
                if (position < 0)
@@ -2381,7 +2392,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
                return 0;
        default:
                if (tape->chrdev_dir == IDETAPE_DIR_READ)
-                       idetape_discard_read_pipeline(drive, 1);
+                       ide_tape_discard_merge_buffer(drive, 1);
                return idetape_blkdev_ioctl(drive, cmd, arg);
        }
 }
@@ -2494,13 +2505,13 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
 {
        idetape_tape_t *tape = drive->driver_data;
 
-       idetape_empty_write_pipeline(drive);
-       tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0);
-       if (tape->merge_stage != NULL) {
+       ide_tape_flush_merge_buffer(drive);
+       tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0);
+       if (tape->merge_bh != NULL) {
                idetape_pad_zeros(drive, tape->blk_size *
                                (tape->user_bs_factor - 1));
-               __idetape_kfree_stage(tape->merge_stage);
-               tape->merge_stage = NULL;
+               ide_tape_kfree_buffer(tape);
+               tape->merge_bh = NULL;
        }
        idetape_write_filemark(drive);
        idetape_flush_tape_buffers(drive);
@@ -2523,7 +2534,7 @@ static int idetape_chrdev_release(struct inode *inode, struct file *filp)
                idetape_write_release(drive, minor);
        if (tape->chrdev_dir == IDETAPE_DIR_READ) {
                if (minor < 128)
-                       idetape_discard_read_pipeline(drive, 1);
+                       ide_tape_discard_merge_buffer(drive, 1);
        }
 
        if (minor < 128 && test_bit(IDETAPE_FLAG_MEDIUM_PRESENT, &tape->flags))
@@ -2664,8 +2675,8 @@ static void idetape_add_settings(ide_drive_t *drive)
                        1, 2, (u16 *)&tape->caps[16], NULL);
        ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
                        1, 1, (u16 *)&tape->caps[14], NULL);
-       ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1,
-                       1024, &tape->stage_size, NULL);
+       ide_add_setting(drive, "buffer_size", SETTING_READ, TYPE_INT, 0, 0xffff,
+                       1, 1024, &tape->buffer_size, NULL);
        ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN,
                        IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_freq,
                        NULL);
@@ -2695,7 +2706,7 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
 {
        unsigned long t;
        int speed;
-       int stage_size;
+       int buffer_size;
        u8 gcw[2];
        u16 *ctl = (u16 *)&tape->caps[12];
 
@@ -2725,36 +2736,35 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
        idetape_get_mode_sense_results(drive);
        ide_tape_get_bsize_from_bdesc(drive);
        tape->user_bs_factor = 1;
-       tape->stage_size = *ctl * tape->blk_size;
-       while (tape->stage_size > 0xffff) {
+       tape->buffer_size = *ctl * tape->blk_size;
+       while (tape->buffer_size > 0xffff) {
                printk(KERN_NOTICE "ide-tape: decreasing stage size\n");
                *ctl /= 2;
-               tape->stage_size = *ctl * tape->blk_size;
+               tape->buffer_size = *ctl * tape->blk_size;
        }
-       stage_size = tape->stage_size;
-       tape->pages_per_stage = stage_size / PAGE_SIZE;
-       if (stage_size % PAGE_SIZE) {
-               tape->pages_per_stage++;
-               tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE;
+       buffer_size = tape->buffer_size;
+       tape->pages_per_buffer = buffer_size / PAGE_SIZE;
+       if (buffer_size % PAGE_SIZE) {
+               tape->pages_per_buffer++;
+               tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE;
        }
 
        /* select the "best" DSC read/write polling freq */
        speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
 
-       t = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000);
+       t = (IDETAPE_FIFO_THRESHOLD * tape->buffer_size * HZ) / (speed * 1000);
 
        /*
         * Ensure that the number we got makes sense; limit it within
         * IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX.
         */
-       tape->best_dsc_rw_freq = max_t(unsigned long,
-                               min_t(unsigned long, t, IDETAPE_DSC_RW_MAX),
-                               IDETAPE_DSC_RW_MIN);
+       tape->best_dsc_rw_freq = clamp_t(unsigned long, t, IDETAPE_DSC_RW_MIN,
+                                        IDETAPE_DSC_RW_MAX);
        printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
                "%lums tDSC%s\n",
                drive->name, tape->name, *(u16 *)&tape->caps[14],
-               (*(u16 *)&tape->caps[16] * 512) / tape->stage_size,
-               tape->stage_size / 1024,
+               (*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
+               tape->buffer_size / 1024,
                tape->best_dsc_rw_freq * 1000 / HZ,
                drive->using_dma ? ", DMA":"");
 
@@ -2778,7 +2788,7 @@ static void ide_tape_release(struct kref *kref)
        ide_drive_t *drive = tape->drive;
        struct gendisk *g = tape->disk;
 
-       BUG_ON(tape->merge_stage_size);
+       BUG_ON(tape->merge_bh_size);
 
        drive->dsc_overlap = 0;
        drive->driver_data = NULL;