ide-tape: mv idetape_empty_write_pipeline ide_tape_flush_merge_buffer
[safe/jmp/linux-2.6] / drivers / ide / ide-tape.c
index ea46ed8..00b7e0c 100644 (file)
@@ -583,20 +583,22 @@ 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_stage_t *stage)
 {
        struct idetape_bh *prev_bh, *bh = stage->bh;
-       int size;
-
-       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;
@@ -1373,7 +1375,7 @@ static idetape_stage_t *ide_tape_kmalloc_buffer(idetape_tape_t *tape, int full,
                atomic_sub(tape->excess_bh_size, &bh->b_count);
        return stage;
 abort:
-       __idetape_kfree_stage(stage);
+       ide_tape_kfree_buffer(stage);
        return NULL;
 }
 
@@ -1639,23 +1641,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);
+               ide_tape_kfree_buffer(tape->merge_stage);
                tape->merge_stage = NULL;
        }
 
        tape->chrdev_dir = IDETAPE_DIR_NONE;
-
-       return 0;
 }
 
 /*
@@ -1672,7 +1672,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);
@@ -1683,20 +1683,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;
                }
        }
@@ -1780,7 +1779,7 @@ static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
                                     blocks, tape->merge_stage->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;
@@ -1828,7 +1827,7 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
                tape->merge_stage_size = 0;
        }
        if (tape->merge_stage != NULL) {
-               __idetape_kfree_stage(tape->merge_stage);
+               ide_tape_kfree_buffer(tape->merge_stage);
                tape->merge_stage = NULL;
        }
        tape->chrdev_dir = IDETAPE_DIR_NONE;
@@ -1842,7 +1841,7 @@ 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) {
@@ -1866,7 +1865,7 @@ static int idetape_init_read(ide_drive_t *drive)
                                                        REQ_IDETAPE_READ, 0,
                                                        tape->merge_stage->bh);
                        if (bytes_read < 0) {
-                               __idetape_kfree_stage(tape->merge_stage);
+                               ide_tape_kfree_buffer(tape->merge_stage);
                                tape->merge_stage = NULL;
                                tape->chrdev_dir = IDETAPE_DIR_NONE;
                                return bytes_read;
@@ -1997,7 +1996,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
                tape->merge_stage_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);
        }
 
        /*
@@ -2122,7 +2121,7 @@ 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);
+                       ide_tape_discard_merge_buffer(drive, 1);
                if (tape->merge_stage || tape->merge_stage_size) {
                        printk(KERN_ERR "ide-tape: merge_stage_size "
                                "should be 0 now\n");
@@ -2145,7 +2144,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
                                                        REQ_IDETAPE_WRITE, 0,
                                                        tape->merge_stage->bh);
                        if (retval < 0) {
-                               __idetape_kfree_stage(tape->merge_stage);
+                               ide_tape_kfree_buffer(tape->merge_stage);
                                tape->merge_stage = NULL;
                                tape->chrdev_dir = IDETAPE_DIR_NONE;
                                return retval;
@@ -2247,7 +2246,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)
@@ -2255,12 +2254,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);
@@ -2275,7 +2274,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);
@@ -2283,10 +2282,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);
@@ -2308,11 +2307,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:
@@ -2358,7 +2357,7 @@ 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) {
@@ -2394,7 +2393,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);
        }
 }
@@ -2507,12 +2506,12 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
 {
        idetape_tape_t *tape = drive->driver_data;
 
-       idetape_empty_write_pipeline(drive);
+       ide_tape_flush_merge_buffer(drive);
        tape->merge_stage = ide_tape_kmalloc_buffer(tape, 1, 0);
        if (tape->merge_stage != NULL) {
                idetape_pad_zeros(drive, tape->blk_size *
                                (tape->user_bs_factor - 1));
-               __idetape_kfree_stage(tape->merge_stage);
+               ide_tape_kfree_buffer(tape->merge_stage);
                tape->merge_stage = NULL;
        }
        idetape_write_filemark(drive);
@@ -2536,7 +2535,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))