]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-tape.c
ide-tape: make __idetape_discard_read_pipeline() of type void
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-tape.c
index dc7abb25a8ebf3d87f85c8795add3cc7d93f1aba..3c61770020ef75f843eb68a83e3eec2db995a781 100644 (file)
@@ -308,15 +308,14 @@ typedef struct ide_tape_obj {
         */
 
        /* Data buffer size chosen based on the tape's recommendation */
-       int stage_size;
+       int buffer_size;
        idetape_stage_t *merge_stage;
        int merge_stage_size;
        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,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;
@@ -1168,7 +1169,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 +1189,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;
 }
 
@@ -1291,7 +1292,7 @@ out:
 
 /*
  * The function below uses __get_free_pages to allocate a data buffer of size
- * tape->stage_size (or a bit more). We attempt to combine sequential pages as
+ * tape->buffer_size (or a bit more). We attempt to combine sequential pages as
  * much as possible.
  *
  * It returns a pointer to the newly allocated buffer, or NULL in case of
@@ -1302,7 +1303,7 @@ static idetape_stage_t *ide_tape_kmalloc_buffer(idetape_tape_t *tape, int full,
 {
        idetape_stage_t *stage;
        struct idetape_bh *prev_bh, *bh;
-       int pages = tape->pages_per_stage;
+       int pages = tape->pages_per_buffer;
        unsigned int order, b_allocd;
        char *b_data = NULL;
 
@@ -1374,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;
 }
 
@@ -1640,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 __idetape_discard_read_pipeline(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;
 }
 
 /*
@@ -1688,13 +1687,12 @@ static void idetape_discard_read_pipeline(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);
+       __idetape_discard_read_pipeline(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);
@@ -1792,9 +1790,9 @@ static void idetape_empty_write_pipeline(ide_drive_t *drive)
                                " but we are not writing.\n");
                return;
        }
-       if (tape->merge_stage_size > tape->stage_size) {
+       if (tape->merge_stage_size > tape->buffer_size) {
                printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
-               tape->merge_stage_size = tape->stage_size;
+               tape->merge_stage_size = tape->buffer_size;
        }
        if (tape->merge_stage_size) {
                blocks = tape->merge_stage_size / tape->blk_size;
@@ -1829,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;
@@ -1867,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;
@@ -1905,7 +1903,7 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
                unsigned int count;
 
                bh = tape->merge_stage->bh;
-               count = min(tape->stage_size, bcount);
+               count = min(tape->buffer_size, bcount);
                bcount -= count;
                blocks = count / tape->blk_size;
                while (count) {
@@ -2074,7 +2072,7 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
                tape->merge_stage_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;
@@ -2146,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;
@@ -2156,12 +2154,12 @@ 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_stage_size >= tape->buffer_size) {
                        printk(KERN_ERR "ide-tape: bug: merge buf too big\n");
                        tape->merge_stage_size = 0;
                }
                actually_written = min((unsigned int)
-                               (tape->stage_size - tape->merge_stage_size),
+                               (tape->buffer_size - tape->merge_stage_size),
                                (unsigned int)count);
                if (idetape_copy_stage_from_user(tape, buf, actually_written))
                                ret = -EFAULT;
@@ -2169,7 +2167,7 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
                tape->merge_stage_size += actually_written;
                count -= actually_written;
 
-               if (tape->merge_stage_size == tape->stage_size) {
+               if (tape->merge_stage_size == tape->buffer_size) {
                        ssize_t retval;
                        tape->merge_stage_size = 0;
                        retval = idetape_add_chrdev_write_request(drive, ctl);
@@ -2177,14 +2175,14 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
                                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);
        }
@@ -2513,7 +2511,7 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
        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);
@@ -2678,8 +2676,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);
@@ -2709,7 +2707,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];
 
@@ -2739,23 +2737,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
@@ -2767,8 +2765,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":"");