]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-tape.c
ide-tape: remove tape->merge_stage
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-tape.c
index 6752d47db2f883304e48f131c192c3238449edd8..29870c415110ad0bc3cf2d4bf76791ebfe0d5763 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;
 
@@ -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)
@@ -849,10 +846,10 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
                return ide_do_reset(drive);
        }
        /* Get the number of bytes to transfer on this interrupt. */
-       bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
-                 hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
+       bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
+                 hwif->INB(hwif->io_ports.lbam_addr);
 
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
 
        if (ireason & CD) {
                printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__);
@@ -956,12 +953,12 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
                                "yet DRQ isn't asserted\n");
                return startstop;
        }
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
        while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
                printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing "
                                "a packet command, retrying\n");
                udelay(100);
-               ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+               ireason = hwif->INB(hwif->io_ports.nsect_addr);
                if (retries == 0) {
                        printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
                                        "issuing a packet command, ignoring\n");
@@ -1058,7 +1055,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[IDE_COMMAND_OFFSET]);
+               hwif->OUTB(WIN_PACKETCMD, hwif->io_ports.command_addr);
                return idetape_transfer_pc(drive);
        }
 }
@@ -1168,7 +1165,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 +1185,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 +1287,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 +1433,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 {
@@ -1626,23 +1631,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 +1662,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 +1673,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;
                }
        }
@@ -1712,8 +1714,8 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
        if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
                return 0;
 
-       if (tape->merge_stage)
-               idetape_init_merge_stage(tape);
+       if (tape->merge_bh)
+               idetape_init_merge_buffer(tape);
        if (rq.errors == IDETAPE_ERROR_GENERAL)
                return -EIO;
        return (tape->blk_size * (blocks-rq.current_nr_sectors));
@@ -1764,31 +1766,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 +1814,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 +1831,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 +1853,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 +1880,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 +1892,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 +1904,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 +1983,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 +2049,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 +2076,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 +2107,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 +2128,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 +2139,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 +2176,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 +2232,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 +2240,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 +2260,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 +2268,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 +2293,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 +2343,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 +2379,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 +2492,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 +2521,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 +2662,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 +2693,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,23 +2723,23 @@ 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
@@ -2753,8 +2751,8 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
        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 +2776,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;